diff options
author | Walter Bender <walter.bender@gmail.com> | 2012-06-04 23:45:15 (GMT) |
---|---|---|
committer | Walter Bender <walter.bender@gmail.com> | 2012-06-04 23:45:15 (GMT) |
commit | 449a3ae56e4d2c0f8a3bd6d86a575b2c6176640d (patch) | |
tree | 6d37a40d3c168138a443d1df8c2c08cb3f5af759 |
New activity
198 files changed, 39630 insertions, 0 deletions
diff --git a/AmazonasTortugaActivity.py b/AmazonasTortugaActivity.py new file mode 100644 index 0000000..b0fd0b5 --- /dev/null +++ b/AmazonasTortugaActivity.py @@ -0,0 +1,1061 @@ +#Copyright (c) 2007, Playful Invention Company +#Copyright (c) 2008-12, Walter Bender +#Copyright (c) 2009-10 Raul Gutierrez Segales + +#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 cairo +import gobject + +import logging +_logger = logging.getLogger('amazonas-tortuga-activity') + +from sugar.activity import activity +try: # 0.86 toolbar widgets + from sugar.activity.widgets import ActivityToolbarButton, StopButton + from sugar.graphics.toolbarbox import ToolbarBox, ToolbarButton + HAS_TOOLBARBOX = True +except ImportError: + HAS_TOOLBARBOX = False +from sugar.graphics.toolbutton import ToolButton +from sugar.graphics.radiotoolbutton import RadioToolButton +from sugar.datastore import datastore +from sugar.graphics.combobox import ComboBox +from sugar.graphics.toolcombobox import ToolComboBox +from sugar.graphics.objectchooser import ObjectChooser +from sugar import mime + +from sugar import profile +import os +import glob +import tarfile + +from gettext import gettext as _ + +from TurtleArt.tapalette import palette_names, help_strings +from TurtleArt.taconstants import ICON_SIZE, BLOCK_SCALE, XO1, XO15, XO175, XO30 +from TurtleArt.taexporthtml import save_html +from TurtleArt.taexportlogo import save_logo +from TurtleArt.tautils import data_to_file, data_to_string, data_from_string, \ + get_path, chooser, get_hardware +from TurtleArt.tawindow import TurtleArtWindow +from TurtleArt.tacollaboration import Collaboration + +if HAS_TOOLBARBOX: + from util.helpbutton import HelpButton + + +class AmazonasTortugaActivity(activity.Activity): + + def __init__(self, handle): + ''' Activity subclass for Turtle Art ''' + super(AmazonasTortugaActivity, self).__init__(handle) + + self._stop_help = False + self._check_ver_change(get_path(activity, 'data')) + + self._setup_visibility_handler() + + self.has_toolbarbox = HAS_TOOLBARBOX + + self._level = 0 + self._custom_filepath = None + + self._setup_toolbar() + + self._setup_canvas(self._setup_scrolled_window()) + # FIX ME: not sure how or why self.canvas gets overwritten + # It is set to self.sw in _setup_canvas but None here. + # We need self.canvas for generating the preview image + self.canvas = self.sw + + self._setup_palette_toolbar() + + if not self.has_toolbarbox: + self._setup_help_toolbar() + + self._setup_sharing() + + if self._stop_help: + self._load_level() + else: + self.help_animation() + + # Eye candy intro + def help_animation(self): + self._help_index = 0 + self._stop_help = False + self.stop_turtle_button.set_icon('stopiton') + self._help_next() + + def _help_next(self): + ''' Load the next frame in the animation ''' + path = os.path.join(activity.get_bundle_path(), + 'images', 'amazonas-%d.jpg' % self._help_index) + self.tw.canvas.setxy(-160, 120, pendown=False) + self.tw.lc.insert_image(center=False, resize=False, + filepath=path) + if self._stop_help: + self._load_level() + return + self._help_index += 1 + self._help_index %= 4 # FIX ME + self._help_timeout_id = gobject.timeout_add(2000, self._help_next) + + # Activity toolbar callbacks + + def do_save_as_html_cb(self, button): + ''' Write html out to datastore. ''' + self.save_as_html.set_icon('htmlon') + _logger.debug('saving HTML code') + # Until we have URLs for datastore objects, always embed images. + embed_flag = True + + # Generate HTML by processing TA code from stacks. + html = save_html(self, self.tw, embed_flag) + if len(html) == 0: + return + + # Save the HTML code to the instance directory. + datapath = get_path(activity, 'instance') + + save_type = '.html' + if len(self.tw.saved_pictures) > 0: + if self.tw.saved_pictures[0].endswith(('.svg')): + save_type = '.xml' + + html_file = os.path.join(datapath, 'portfolio' + save_type) + f = file(html_file, 'w') + f.write(html) + f.close() + + if not embed_flag: + # We need to make a tar ball that includes the images. + tar_path = os.path.join(datapath, 'portfolio.tar') + tar_fd = tarfile.open(tar_path, 'w') + try: + tar_fd.add(html_file, 'portfolio.html') + image_list = glob.glob(os.path.join(datapath, 'image*')) + for i in image_list: + tar_fd.add(i, os.path.basename(i)) + finally: + tar_fd.close() + + dsobject = datastore.create() + dsobject.metadata['title'] = self.metadata['title'] + ' ' + \ + _('presentation') + dsobject.metadata['icon-color'] = profile.get_color().to_string() + if embed_flag: + if save_type == '.xml': + dsobject.metadata['mime_type'] = 'application/xml' + else: + dsobject.metadata['mime_type'] = 'text/html' + dsobject.set_file_path(html_file) + else: + dsobject.metadata['mime_type'] = 'application/x-tar' + dsobject.set_file_path(tar_path) + dsobject.metadata['activity'] = 'org.laptop.WebActivity' + datastore.write(dsobject) + dsobject.destroy() + + gobject.timeout_add(250, self.save_as_html.set_icon, 'htmloff') + + self.tw.saved_pictures = [] # Clear queue of pictures we have viewed. + return + + def do_save_as_logo_cb(self, button): + ''' Write UCB logo code to datastore. ''' + self.save_as_logo.set_icon('logo-saveon') + logo_code_path = self._dump_logo_code() + if logo_code_path is None: + return + + dsobject = datastore.create() + dsobject.metadata['title'] = self.metadata['title'] + '.lg' + dsobject.metadata['mime_type'] = 'text/plain' + dsobject.metadata['icon-color'] = profile.get_color().to_string() + dsobject.set_file_path(logo_code_path) + datastore.write(dsobject) + dsobject.destroy() + + gobject.timeout_add(250, self.save_as_logo.set_icon, 'logo-saveoff') + return + + def do_load_image_cb(self, button): + ''' Load an image from the Journal. ''' + chooser = ObjectChooser(parent=self, + what_filter=mime.GENERIC_TYPE_IMAGE) + + if chooser is not None: + try: + result = chooser.run() + if result == gtk.RESPONSE_ACCEPT: + jobject = chooser.get_selected_object() + if jobject and jobject.file_path: + name = jobject.metadata['title'] + mime_type = jobject.metadata['mime_type'] + _logger.debug('result of choose: %s (%s)' % \ + (name, str(mime_type))) + finally: + chooser.destroy() + del chooser + + if name is not None: + _logger.debug('opening %s ' % jobject.file_path) + self._custom_filepath = jobject.file_path + self._load_level(custom=True) + + def do_load_ta_project_cb(self, button): + ''' Load a project from the Journal. ''' + chooser(self, 'org.laptop.TurtleArtActivity', self._load_ta_project) + + def _load_ta_project(self, dsobject): + ''' Load a TA project from the datastore. ''' + try: + _logger.debug('opening %s ' % dsobject.file_path) + self.read_file(dsobject.file_path, False) + except: + _logger.debug("couldn't open %s" % dsobject.file_path) + + def do_load_python_cb(self, button): + ''' Load Python code from the Journal. ''' + self.load_python.set_icon('pippy-openon') + self.tw.load_python_code_from_file(fname=None, add_new_block=True) + gobject.timeout_add(250, self.load_python.set_icon, 'pippy-openoff') + + def do_save_as_image_cb(self, button): + ''' Save the canvas to the Journal. ''' + self.save_as_image.set_icon('image-saveon') + _logger.debug('saving image to journal') + + self.tw.save_as_image() + gobject.timeout_add(250, self.save_as_image.set_icon, 'image-saveoff') + return + + def do_keep_cb(self, button): + ''' Save a snapshot of the project to the Journal. ''' + tmpfile = self._dump_ta_code() + if tmpfile is not None: + dsobject = datastore.create() + dsobject.metadata['title'] = self.metadata['title'] + ' ' + \ + _('snapshot') + dsobject.metadata['icon-color'] = profile.get_color().to_string() + dsobject.metadata['mime_type'] = 'application/x-turtle-art' + dsobject.metadata['activity'] = 'org.laptop.TurtleConfusionActivity' + dsobject.set_file_path(tmpfile) + datastore.write(dsobject) + dsobject.destroy() + os.remove(tmpfile) + return + + # Main/palette toolbar button callbacks + + def do_palette_cb(self, button): + ''' Show/hide palette ''' + if self.tw.palette: + self.tw.hideshow_palette(False) + self.do_hidepalette() + if self.has_toolbarbox and self.tw.selected_palette is not None: + self.palette_buttons[self.tw.selected_palette].set_icon( + palette_names[self.tw.selected_palette] + 'off') + else: + self.tw.hideshow_palette(True) + self.do_showpalette() + if self.has_toolbarbox: + self.palette_buttons[0].set_icon(palette_names[0] + 'on') + + def do_palette_buttons_cb(self, button, i): + ''' Palette selector buttons ''' + if self.tw.selected_palette is not None: + if not self.has_toolbarbox: + self.palette_buttons[self.tw.selected_palette].set_icon( + palette_names[self.tw.selected_palette] + 'off') + if self.tw.selected_palette == i: + # Hide the palette if it is already selected. + self.tw.hideshow_palette(False) + self.do_hidepalette() + return + + if not self.has_toolbarbox: + self.palette_buttons[i].set_icon(palette_names[i] + 'on') + ''' + else: + self._help_button.set_current_palette(palette_names[i]) + ''' + self.tw.show_palette(i) + self.do_showpalette() + + # These methods are called both from toolbar buttons and blocks. + + def _do_hover_help_toggle(self, button): + ''' Toggle hover help ''' + if self.tw.no_help: + self.tw.no_help = False + self._hover_help_toggle.set_icon('help-off') + self._hover_help_toggle.set_tooltip(_('Turn off hover help')) + else: + self.tw.no_help = True + self.tw.last_label = None + self.tw.status_spr.hide() + self._hover_help_toggle.set_icon('help-on') + self._hover_help_toggle.set_tooltip(_('Turn on hover help')) + + def do_hidepalette(self): + ''' Hide the palette. ''' + if hasattr(self, 'palette_button'): + self.palette_button.set_icon('paletteon') + self.palette_button.set_tooltip(_('Show palette')) + + def do_showpalette(self): + ''' Show the palette. ''' + if hasattr(self, 'palette_button'): + self.palette_button.set_icon('paletteoff') + self.palette_button.set_tooltip(_('Hide palette')) + + def do_hideshow_cb(self, button): + ''' Toggle visibility. ''' + self.tw.hideshow_button() + if self.tw.hide: # We just hid the blocks. + self.blocks_button.set_icon('hideshowon') + self.blocks_button.set_tooltip(_('Show blocks')) + else: + self.blocks_button.set_icon('hideshowoff') + self.blocks_button.set_tooltip(_('Hide blocks')) + # Update palette buttons too. + if not self.tw.palette: + self.do_hidepalette() + else: + self.do_showpalette() + + def do_hide_blocks(self): + ''' Hide blocks. ''' + self.blocks_button.set_icon('hideshowon') + self.blocks_button.set_tooltip(_('Show blocks')) + self.do_hidepalette() + + def do_show_blocks(self): + ''' Show blocks. ''' + if not hasattr(self, 'blocks_button'): + return + self.blocks_button.set_icon('hideshowoff') + self.blocks_button.set_tooltip(_('Hide blocks')) + self.do_showpalette() + + def do_eraser_cb(self, button): + ''' Clear the screen and recenter. ''' + self.eraser_button.set_icon('eraseroff') + self.recenter() + self.tw.eraser_button() + gobject.timeout_add(250, self.eraser_button.set_icon, 'eraseron') + + def restore_challenge(self): + ''' Restore the current challange after a clear screen ''' + if self._custom_filepath is None: + self._load_level() + else: + self._load_level(custom=True) + + def do_run_cb(self, button): + ''' Callback for run button (rabbit) ''' + self.run_button.set_icon('run-faston') + self.tw.lc.trace = 0 + self.tw.run_button(0) + gobject.timeout_add(1000, self.run_button.set_icon, 'run-fastoff') + + def do_step_cb(self, button): + ''' Callback for step button (turtle) ''' + self.step_button.set_icon('run-slowon') + self.tw.lc.trace = 1 + self.tw.run_button(3) + gobject.timeout_add(1000, self.step_button.set_icon, 'run-slowoff') + + def do_debug_cb(self, button): + ''' Callback for debug button (bug) ''' + self.debug_button.set_icon('debugon') + self.tw.lc.trace = 1 + self.tw.run_button(9) + gobject.timeout_add(1000, self.debug_button.set_icon, 'debugoff') + + def do_stop_cb(self, button): + ''' Callback for stop button. ''' + self._stop_help = True + self.stop_turtle_button.set_icon('stopitoff') + self.tw.stop_button() + self.step_button.set_icon('run-slowoff') + self.run_button.set_icon('run-fastoff') + + def do_samples_cb(self, button): + ''' Sample-projects open dialog ''' + self.tw.load_file(True) + self.tw.run_button(0) + + def recenter(self): + ''' Recenter scrolled window around canvas. ''' + hadj = self.sw.get_hadjustment() + hadj.set_value(0) + self.sw.set_hadjustment(hadj) + vadj = self.sw.get_vadjustment() + vadj.set_value(0) + self.sw.set_vadjustment(vadj) + + def do_fullscreen_cb(self, button): + ''' Hide the Sugar toolbars. ''' + self.fullscreen() + self.recenter() + + def do_grow_blocks_cb(self, button): + ''' Grow the blocks. ''' + self.do_resize_blocks(1) + + def do_shrink_blocks_cb(self, button): + ''' Shrink the blocks. ''' + self.do_resize_blocks(-1) + + def do_resize_blocks(self, inc): + ''' Scale the blocks. ''' + if self.tw.block_scale in BLOCK_SCALE: + i = BLOCK_SCALE.index(self.tw.block_scale) + inc + else: + i = BLOCK_SCALE[3] # 2.0 + if i < 0: + self.tw.block_scale = BLOCK_SCALE[0] + elif i == len(BLOCK_SCALE): + self.tw.block_scale = BLOCK_SCALE[-1] + else: + self.tw.block_scale = BLOCK_SCALE[i] + self.tw.resize_blocks() + + def do_cartesian_cb(self, button): + ''' Display Cartesian-coordinate grid. ''' + if self.tw.cartesian: + self.tw.set_cartesian(False) + else: + self.tw.set_cartesian(True) + + def do_polar_cb(self, button): + ''' Display polar-coordinate grid. ''' + if self.tw.polar: + self.tw.set_polar(False) + else: + self.tw.set_polar(True) + + def do_metric_cb(self, button): + ''' Display metric-coordinate grid. ''' + if self.tw.metric: + self.tw.set_metric(False) + else: + self.tw.set_metric(True) + + def do_rescale_cb(self, button): + ''' Rescale coordinate system (100==height/2 or 100 pixels). ''' + if self.tw.cartesian: + cartesian = True + self.tw.set_cartesian(False) + else: + cartesian = False + if self.tw.polar: + polar = True + self.tw.set_polar(False) + else: + polar = False + if self.tw.metric: + metric = True + self.tw.set_metric(False) + else: + polar = False + if self.tw.coord_scale == 1: + self.tw.coord_scale = self.tw.height / 200 + self.rescale_button.set_icon('contract-coordinates') + self.rescale_button.set_tooltip(_('Rescale coordinates down')) + else: + self.tw.coord_scale = 1 + self.rescale_button.set_icon('expand-coordinates') + self.rescale_button.set_tooltip(_('Rescale coordinates up')) + self.tw.eraser_button() + if cartesian: + self.tw.set_cartesian(True) + if polar: + self.tw.set_polar(True) + if metric: + self.tw.set_metric(True) + + def _do_help_cb(self, button): + if os.path.exists(os.path.join( + activity.get_bundle_path(), 'challenges', + 'help-' + str(self._level + 1) + '.ta')): + self.read_file(os.path.join( + activity.get_bundle_path(), 'challenges', + 'help-' + str(self._level + 1) + '.ta'), run_it=False) + ''' + else: + self.hover_help_label.set_label(_("no help available")) + ''' + + def get_document_path(self, async_cb, async_err_cb): + ''' View TA code as part of view source. ''' + ta_code_path = self._dump_ta_code() + if ta_code_path is not None: + async_cb(ta_code_path) + + def _dump_logo_code(self): + ''' Save Logo code to temporary file. ''' + datapath = get_path(activity, 'instance') + tmpfile = os.path.join(datapath, 'tmpfile.lg') + code = save_logo(self.tw) + if len(code) == 0: + _logger.debug('save_logo returned None') + return None + try: + f = file(tmpfile, 'w') + f.write(code) + f.close() + except Exception, e: + _logger.error("Couldn't save Logo code: " + str(e)) + tmpfile = None + return tmpfile + + def _dump_ta_code(self): + ''' Save TA code to temporary file. ''' + datapath = get_path(activity, 'instance') + tmpfile = os.path.join(datapath, 'tmpfile.ta') + try: + data_to_file(self.tw.assemble_data_to_save(), tmpfile) + except Exception, e: + _logger.error("Couldn't save project code: " + str(e)) + tmpfile = None + return tmpfile + + def __visibility_notify_cb(self, window, event): + ''' Callback method for when the activity's visibility changes. ''' + if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED: + self.tw.background_plugins() + elif event.state in \ + [gtk.gdk.VISIBILITY_UNOBSCURED, gtk.gdk.VISIBILITY_PARTIAL]: + self.tw.foreground_plugins() + + def _keep_clicked_cb(self, button): + ''' Keep-button clicked. ''' + self.jobject_new_patch() + + def _setup_toolbar(self): + ''' Setup toolbar according to Sugar version. ''' + if self.has_toolbarbox: + self._toolbox = ToolbarBox() + + activity_toolbar_button = ActivityToolbarButton(self) + + edit_toolbar = gtk.Toolbar() + edit_toolbar_button = ToolbarButton(label=_('Edit'), + page=edit_toolbar, + icon_name='toolbar-edit') + view_toolbar = gtk.Toolbar() + view_toolbar_button = ToolbarButton(label=_('View'), + page=view_toolbar, + icon_name='toolbar-view') + self._palette_toolbar = gtk.Toolbar() + self._palette_toolbar_button = ToolbarButton( + page=self._palette_toolbar, icon_name='palette') + + self._make_load_save_buttons(activity_toolbar_button) + + activity_toolbar_button.show() + self._toolbox.toolbar.insert(activity_toolbar_button, -1) + edit_toolbar_button.show() + self._toolbox.toolbar.insert(edit_toolbar_button, -1) + view_toolbar_button.show() + self._toolbox.toolbar.insert(view_toolbar_button, -1) + self._palette_toolbar_button.show() + self._toolbox.toolbar.insert(self._palette_toolbar_button, -1) + + self._make_project_buttons(self._toolbox.toolbar) + + self._add_separator(self._toolbox.toolbar, expand=True, + visible=False) + + self.samples_button = self._add_button( + 'ta-open', _('Load example'), self.do_samples_cb, + self._toolbox.toolbar) + + self._help_button = self._add_button( + 'help-toolbar', _('Help'), self._do_help_cb, + self._toolbox.toolbar) + + stop_button = StopButton(self) + stop_button.props.accelerator = '<Ctrl>Q' + self._toolbox.toolbar.insert(stop_button, -1) + stop_button.show() + + _logger.debug('set_toolbar_box') + self.set_toolbar_box(self._toolbox) + self._palette_toolbar_button.set_expanded(True) + else: + self._toolbox = activity.ActivityToolbox(self) + self.set_toolbox(self._toolbox) + + project_toolbar = gtk.Toolbar() + self._toolbox.add_toolbar(_('Project'), project_toolbar) + + view_toolbar = gtk.Toolbar() + self._toolbox.add_toolbar(_('View'), view_toolbar) + view_toolbar_button = view_toolbar + edit_toolbar = gtk.Toolbar() + self._toolbox.add_toolbar(_('Edit'), edit_toolbar) + edit_toolbar_button = edit_toolbar + journal_toolbar = gtk.Toolbar() + self._toolbox.add_toolbar(_('Import/Export'), journal_toolbar) + + self._make_palette_buttons(project_toolbar, palette_button=True) + + self._add_separator(project_toolbar) + + self._make_project_buttons(project_toolbar) + self._make_load_save_buttons(journal_toolbar) + + self._add_button('edit-copy', _('Copy'), self._copy_cb, + edit_toolbar_button, '<Ctrl>c') + self._add_button('edit-paste', _('Paste'), self._paste_cb, + edit_toolbar_button, '<Ctrl>v') + self._add_button('view-fullscreen', _('Fullscreen'), + self.do_fullscreen_cb, view_toolbar_button, + '<Alt>Return') + self._add_button('view-Cartesian', _('Cartesian coordinates'), + self.do_cartesian_cb, view_toolbar_button) + self._add_button('view-polar', _('Polar coordinates'), + self.do_polar_cb, view_toolbar_button) + if get_hardware() in [XO1, XO15, XO175]: + self._add_button('view-metric', _('Metric coordinates'), + self.do_metric_cb, view_toolbar_button) + self._add_separator(view_toolbar, visible=False) + self.coordinates_label = self._add_label(_('xcor') + ' = 0 ' + \ + _('ycor') + ' = 0 ' + _('heading') + ' = 0', view_toolbar) + self._add_separator(view_toolbar, expand=True, visible=False) + """ + self.rescale_button = self._add_button( + 'expand-coordinates', _('Rescale coordinates up'), + self.do_rescale_cb, view_toolbar_button) + """ + self.resize_up_button = self._add_button( + 'resize+', _('Grow blocks'), self.do_grow_blocks_cb, + view_toolbar_button) + self.resize_down_button = self._add_button( + 'resize-', _('Shrink blocks'), self.do_shrink_blocks_cb, + view_toolbar_button) + self._hover_help_toggle = self._add_button( + 'help-off', _('Turn off hover help'), + self._do_hover_help_toggle, view_toolbar) + + edit_toolbar.show() + view_toolbar.show() + self._toolbox.show() + + if not self.has_toolbarbox: + self._toolbox.set_current_toolbar(1) + + def _setup_palette_toolbar(self): + # The palette toolbar must be setup *after* plugins are loaded. + if self.has_toolbarbox: + self.palette_buttons = [] + for i, palette_name in enumerate(palette_names): + if i == 0: + palette_group = None + else: + palette_group = self.palette_buttons[0] + _logger.debug('palette_buttons.append %s', palette_name) + self.palette_buttons.append(self._radio_button_factory( + palette_name + 'off', + self._palette_toolbar_button, + self.do_palette_buttons_cb, i, + help_strings[palette_name], + palette_group)) + self._add_separator(self._palette_toolbar, expand=True, + visible=False) + self._make_palette_buttons(self._palette_toolbar_button) + self._palette_toolbar.show() + + def _make_load_save_buttons(self, toolbar): + self.save_as_image = self._add_button( + 'image-saveoff', _('Save as image'), self.do_save_as_image_cb, + toolbar) + self.save_as_logo = self._add_button( + 'logo-saveoff', _('Save as Logo'), self.do_save_as_logo_cb, + toolbar) + self.keep_button = self._add_button( + 'filesaveoff', _('Save snapshot'), self.do_keep_cb, toolbar) + if not self.has_toolbarbox: + self._add_separator(toolbar) + self.load_ta_project = self._add_button( + 'load-from-journal', _('Import project from the Journal'), + self.do_load_ta_project_cb, toolbar) + if not self.has_toolbarbox: + self.samples_button = self._add_button( + 'ta-open', _('Load example'), self.do_samples_cb, toolbar) + + def _make_palette_buttons(self, toolbar, palette_button=False): + ''' Creates the palette and block buttons for both toolbar types''' + self._levels = self._get_levels(activity.get_bundle_path()) + self._levels_combo = self._combo_factory(self._levels, + _('Select a challenge'), + toolbar, self._levels_cb) + self._add_separator(toolbar, expand=True, visible=False) + if palette_button: # old-style toolbars need this button + self.palette_button = self._add_button( + 'paletteoff', _('Hide palette'), self.do_palette_cb, + toolbar, _('<Ctrl>p')) + self.blocks_button = self._add_button( + 'hideshowoff', _('Hide blocks'), self.do_hideshow_cb, toolbar, + _('<Ctrl>b')) + + def _make_project_buttons(self, toolbar): + ''' Creates the turtle buttons for both toolbar types''' + self.eraser_button = self._add_button( + 'eraseron', _('Clean'), self.do_eraser_cb, toolbar, _('<Ctrl>e')) + self.run_button = self._add_button( + 'run-fastoff', _('Run'), self.do_run_cb, toolbar, _('<Ctrl>r')) + self.step_button = self._add_button( + 'run-slowoff', _('Step'), self.do_step_cb, toolbar, _('<Ctrl>w')) + self.stop_turtle_button = self._add_button( + 'stopitoff', _('Stop turtle'), self.do_stop_cb, toolbar, + _('<Ctrl>s')) + + def _check_ver_change(self, datapath): + ''' Check to see if the version has changed. ''' + # We don't do anything with this info at the moment. + try: + version = os.environ['SUGAR_BUNDLE_VERSION'] + except KeyError: + version = 'unknown' + + filename = 'version.dat' + version_data = [] + new_version = True + try: + file_handle = open(os.path.join(datapath, filename), 'r') + if file_handle.readline() == version: + new_version = False + file_handle.close() + except IOError: + _logger.debug("Couldn't read version number.") + + version_data.append(version) + try: + file_handle = open(os.path.join(datapath, filename), 'w') + file_handle.writelines(version_data) + file_handle.close() + except IOError: + _logger.debug("Couldn't write version number.") + + return new_version + + def _setup_scrolled_window(self): + ''' Create a scrolled window to contain the turtle canvas. ''' + self.sw = gtk.ScrolledWindow() + self.set_canvas(self.sw) + self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.sw.show() + + canvas = gtk.DrawingArea() + canvas.set_size_request(gtk.gdk.screen_width() * 2, + gtk.gdk.screen_height() * 2) + self.sw.add_with_viewport(canvas) + hadj = self.sw.get_hadjustment() + hadj.connect('value-changed', self._scroll_cb) + vadj = self.sw.get_vadjustment() + vadj.connect('value-changed', self._scroll_cb) + self.hadj_value = 0 + self.vadj_value = 0 + canvas.show() + self.sw.show() + self.show_all() + return canvas + + def _scroll_cb(self, window): + ''' The scrolling window has been changed, so move the + floating palettes. ''' + hadj = self.sw.get_hadjustment() + self.hadj_value = hadj.get_value() + vadj = self.sw.get_vadjustment() + self.vadj_value = vadj.get_value() + if not self.tw.hw in [XO1]: + gobject.idle_add(self.tw.move_palettes, self.hadj_value, + self.vadj_value) + + def _setup_canvas(self, canvas_window): + ''' Initialize the turtle art canvas. ''' + win = canvas_window.get_window() # self._canvas.get_window() + cr = win.cairo_create() + surface = cr.get_target() + self.turtle_canvas = surface.create_similar( + cairo.CONTENT_COLOR, gtk.gdk.screen_width() * 2, + gtk.gdk.screen_height() * 2) + bundle_path = activity.get_bundle_path() + self.tw = TurtleArtWindow(canvas_window, bundle_path, self, + profile.get_color().to_string(), + profile.get_nick_name(), + turtle_canvas=self.turtle_canvas) + self.tw.window.grab_focus() + path = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'], 'data') + self.tw.save_folder = path + + self.tw.lc.scale = 100 + + # Try restoring an existing project... + if self._jobject and self._jobject.file_path: + self.read_file(self._jobject.file_path) + else: # ...or else, load a Start Block onto the canvas. + self.tw.load_start() + + def _setup_sharing(self): + ''' Setup the Collabora stack. ''' + self._collaboration = Collaboration(self.tw, self) + self._collaboration.setup() + + def _setup_visibility_handler(self): + ''' Notify me when the visibility state changes. ''' + self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK) + self.connect('visibility-notify-event', self.__visibility_notify_cb) + + def write_file(self, file_path): + ''' Write the project to the Journal. ''' + _logger.debug('Write file: %s' % file_path) + self.metadata['mime_type'] = 'application/x-turtle-art' + data_to_file(self.tw.assemble_data_to_save(), file_path) + + def read_file(self, file_path, run_it=True): + ''' Read a project in and then run it. ''' + if hasattr(self, 'tw'): + _logger.debug('Read file: %s' % (file_path)) + # Could be a deprecated gtar or tar file... + if file_path.endswith(('.gtar', '.tar')): + import tempfile + import shutil + + tar_fd = tarfile.open(file_path, 'r') + tmpdir = tempfile.mkdtemp() + try: + # We'll get 'ta_code.ta' and possibly a 'ta_image.png' + # but we will ignore the .png file + # If run_it is True, we want to create a new project + tar_fd.extractall(tmpdir) + self.tw.load_files(os.path.join(tmpdir, 'ta_code.ta'), + run_it) + finally: + shutil.rmtree(tmpdir) + tar_fd.close() + # ...otherwise, assume it is a .ta file. + else: + _logger.debug('Trying to open a .ta file:' + file_path) + self.tw.load_files(file_path, run_it) + + # Finally, run the project. + if run_it: + self.tw.run_button(0) + self._stop_help = True + else: + _logger.debug('Deferring reading file %s' % (file_path)) + + def jobject_new_patch(self): + ''' Save instance to Journal. ''' + oldj = self._jobject + self._jobject = datastore.create() + self._jobject.metadata['title'] = oldj.metadata['title'] + self._jobject.metadata['title_set_by_user'] = \ + oldj.metadata['title_set_by_user'] + self._jobject.metadata['activity_id'] = self.get_id() + self._jobject.metadata['keep'] = '0' + self._jobject.metadata['preview'] = '' + self._jobject.metadata['icon-color'] = profile.get_color().to_string() + self._jobject.file_path = '' + datastore.write( + self._jobject, reply_handler=self._internal_jobject_create_cb, + error_handler=self._internal_jobject_error_cb) + self._jobject.destroy() + + def _copy_cb(self, button): + ''' Copy to the clipboard. ''' + clipboard = gtk.Clipboard() + _logger.debug('Serialize the project and copy to clipboard.') + data = self.tw.assemble_data_to_save(False, False) + if data is not []: + text = data_to_string(data) + clipboard.set_text(text) + self.tw.paste_offset = 20 + + def _paste_cb(self, button): + ''' Paste from the clipboard. ''' + clipboard = gtk.Clipboard() + _logger.debug('Paste to the project.') + text = clipboard.wait_for_text() + if text is not None: + if self.tw.selected_blk is not None and \ + self.tw.selected_blk.name == 'string': + for i in text: + self.tw.process_alphanumeric_input(i, -1) + self.tw.selected_blk.resize() + else: + self.tw.process_data(data_from_string(text), + self.tw.paste_offset) + self.tw.paste_offset += 20 + + def _add_label(self, string, toolbar, width=None): + ''' Add a label to a toolbar. ''' + label = gtk.Label(string) + label.set_line_wrap(True) + if width is not None: + label.set_size_request(width, -1) + label.show() + toolitem = gtk.ToolItem() + toolitem.add(label) + toolbar.insert(toolitem, -1) + toolitem.show() + return label + + def _add_separator(self, toolbar, expand=False, visible=True): + ''' Add a separator to a toolbar. ''' + separator = gtk.SeparatorToolItem() + separator.props.draw = visible + separator.set_expand(expand) + if hasattr(toolbar, 'insert'): + toolbar.insert(separator, -1) + else: + toolbar.props.page.insert(separator, -1) + separator.show() + + def _add_button(self, name, tooltip, callback, toolbar, accelerator=None, + arg=None): + ''' Add a button to a toolbar. ''' + button = ToolButton(name) + button.set_tooltip(tooltip) + if arg is None: + button.connect('clicked', callback) + else: + button.connect('clicked', callback, arg) + if accelerator is not None: + try: + button.props.accelerator = accelerator + except AttributeError: + pass + button.show() + if hasattr(toolbar, 'insert'): # Add button to the main toolbar... + toolbar.insert(button, -1) + else: # ...or a secondary toolbar. + toolbar.props.page.insert(button, -1) + + if not name in help_strings: + help_strings[name] = tooltip + return button + + def _combo_factory(self, options, tooltip, toolbar, callback, default=0): + ''' Combo box factory ''' + combo = ComboBox() + if hasattr(combo, 'set_tooltip_text'): + combo.set_tooltip_text(tooltip) + combo.connect('changed', callback) + for i, option in enumerate(options): + combo.append_item(i, option.replace('-', ' '), None) + combo.set_active(default) + combo.show() + tool = ToolComboBox(combo) + tool.show() + if hasattr(toolbar, 'insert'): + toolbar.insert(tool, -1) + else: + toolbar.props.page.insert(tool, -1) + return combo + + def _get_levels(self, path): + ''' Look for level files in lessons directory. ''' + levels = glob.glob(os.path.join(activity.get_bundle_path(), + 'challenges', '*.svg')) + + level_files = [] + for i in range(len(levels)): + level_files.append('amazonas-%d' % (i+1)) + + self.offsets = {} + offset_fd = open(os.path.join(activity.get_bundle_path(), 'challenges', + 'offsets')) + for line in offset_fd: + try: + idx, offsets = line.strip('\n').split(':') + xoffset, yoffset = offsets.split(',') + self.offsets[int(idx)] = (int(xoffset), int(yoffset)) + except ValueError: + pass + offset_fd.close() + return level_files + + def _levels_cb(self, combobox=None): + ''' The combo box has changed. ''' + if hasattr(self, '_levels_combo'): + i = self._levels_combo.get_active() + if i != -1: # and i != self._level: + self._level = i + self._load_level() + self._custom_filepath = None + + def _load_level(self, custom=False): + self.tw.canvas.clearscreen() + if custom: + self.tw.canvas.setxy(0, 0, pendown=False) + self.tw.lc.insert_image(center=True, + filepath=self._custom_filepath, + resize=True, offset=False) + else: + self.tw.canvas.setxy(int(-gtk.gdk.screen_width() / 2), 100, + pendown=False) + self.tw.lc.insert_image(center=False, resize=False, + filepath=os.path.join( + activity.get_bundle_path(), 'images', + 'amazonas-tortuga.png')) + # Slight offset to account for stroke width + if self._level + 1 in self.offsets: + xoffset = self.offsets[self._level + 1][0] + yoffset = self.offsets[self._level + 1][1] + else: + xoffset = 0 + yoffset = 0 + self.tw.canvas.setxy(-2.5 + xoffset, -2.5 + yoffset, pendown=False) + self.tw.lc.insert_image(center=False, + filepath=os.path.join( + activity.get_bundle_path(), 'challenges', + self._levels[self._level] + '.svg'), resize=False, + offset=True) + self.tw.canvas.setxy(0, 0, pendown=False) + + def _radio_button_factory(self, button_name, toolbar, cb, arg, tooltip, + group): + ''' Add a radio button to a toolbar ''' + button = RadioToolButton(group=group) + button.set_named_icon(button_name) + if cb is not None: + if arg is None: + button.connect('clicked', cb) + else: + button.connect('clicked', cb, arg) + if hasattr(toolbar, 'insert'): # Add button to the main toolbar... + toolbar.insert(button, -1) + else: # ...or a secondary toolbar. + toolbar.props.page.insert(button, -1) + button.show() + if tooltip is not None: + button.set_tooltip(tooltip) + return button @@ -0,0 +1,22 @@ +Copyright (c) 2007, Playful Invention Company +Copyright (c) 2008-11, Walter Bender +Copyright (c) 2009-11 Raúl Gutiérrez Segalés + +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. + @@ -0,0 +1,68 @@ +10 + +ENHANCEMENTS +* Added help for all levels +* Sync up with Turtle Blocks 139 +* New translations + +BUG FIX +* Restore challenge after 'clean' + +9 + +ENHANCEMENTS +* Added new help files written by Ignacio Rodriguez +* Sync with current Turtle Blocks +* New translations + +8 + +ENHANCEMENTS +* Cairo conversion +* New translations + +7 + +ENHANCEMENT +* new translations + +6 + +ENHANCEMENT +* Refactoring of toolbars to meet new reference design + +BUG FIX +* Fixed race-condition that sometimes prevented turtle art from + launching (#3044) + +5 + +ENHANCEMENT +* Added offset to challenge to make it easier to align the turtle to the graphic +* Added hints to the Help toolbar (with help from Ignacio Rodriguez) +* Command-line version for running from GNOME shell + +4 + +ENHANCEMENTS +* Restore challenge after running clean block +* Improved clarity of activity-icon graphics +* Show dimensions on challenge graphics + +3 + +ENHANCEMENT +* Import custom challenge from Journal + +BUG FIXES +* Fixed problem with erase button + +2 + +BUG FIXES +* Fixed problem with old-style toolbars + +1 + + New activity that combines Turtle Blocks and Barry Newell's Turtle + Confusion challenges diff --git a/TurtleArt/__init__.py b/TurtleArt/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/TurtleArt/__init__.py diff --git a/TurtleArt/sprites.py b/TurtleArt/sprites.py new file mode 100644 index 0000000..c400d88 --- /dev/null +++ b/TurtleArt/sprites.py @@ -0,0 +1,467 @@ +# -*- coding: utf-8 -*- + +#Copyright (c) 2007-8, Playful Invention Company. +#Copyright (c) 2008-11 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. + +''' + +sprites.py is a simple sprites library for managing graphics objects, +'sprites', on a gtk.DrawingArea. It manages multiple sprites with +methods such as move, hide, set_layer, etc. + +There are two classes: + +class Sprites maintains a collection of sprites +class Sprite manages individual sprites within the collection. + +Example usage: + # Import the classes into your program. + from sprites import Sprites Sprite + + # Create a new sprite collection associated with your widget + self.sprite_list = Sprites(widget) + + # Create a "pixbuf" (in this example, from SVG). + my_pixbuf = svg_str_to_pixbuf("<svg>...some svg code...</svg>") + + # Create a sprite at position x1, y1. + my_sprite = sprites.Sprite(self.sprite_list, x1, y1, my_pixbuf) + + # Move the sprite to a new position. + my_sprite.move((x1+dx, y1+dy)) + + # Create another "pixbuf". + your_pixbuf = svg_str_to_pixbuf("<svg>...some svg code...</svg>") + + # Create a sprite at position x2, y2. + your_sprite = sprites.Sprite(self.sprite_list, x2, y2, my_pixbuf) + + # Assign the sprites to layers. + # In this example, your_sprite will be on top of my_sprite. + my_sprite.set_layer(100) + your_sprite.set_layer(200) + + # Now put my_sprite on top of your_sprite. + my_sprite.set_layer(300) + + cr = self.window.cairo_create() + # In your activity's do_expose_event, put in a call to redraw_sprites + self.sprites.redraw_sprites(event.area, cairo_context) + +# method for converting SVG to a gtk pixbuf +def svg_str_to_pixbuf(svg_string): + pl = gtk.gdk.PixbufLoader('svg') + pl.write(svg_string) + pl.close() + pixbuf = pl.get_pixbuf() + return pixbuf + +''' + +import pygtk +pygtk.require('2.0') +import gtk +import pango +import pangocairo +import cairo + + +class Sprites: + ''' A class for the list of sprites and everything they share in common ''' + + def __init__(self, widget): + ''' Initialize an empty array of sprites ''' + self.widget = widget + self.list = [] + self.cr = None + + def set_cairo_context(self, cr): + ''' Cairo context may be set or reset after __init__ ''' + self.cr = cr + + def get_sprite(self, i): + ''' Return a sprint from the array ''' + if i < 0 or i > len(self.list) - 1: + return(None) + else: + return(self.list[i]) + + def length_of_list(self): + ''' How many sprites are there? ''' + return(len(self.list)) + + def append_to_list(self, spr): + ''' Append a new sprite to the end of the list. ''' + self.list.append(spr) + + def insert_in_list(self, spr, i): + ''' Insert a sprite at position i. ''' + if i < 0: + self.list.insert(0, spr) + elif i > len(self.list) - 1: + self.list.append(spr) + else: + self.list.insert(i, spr) + + def find_in_list(self, spr): + if spr in self.list: + return True + return False + + def remove_from_list(self, spr): + ''' Remove a sprite from the list. ''' + if spr in self.list: + self.list.remove(spr) + + def find_sprite(self, pos, region=False): + ''' Search based on (x, y) position. Return the 'top/first' one. ''' + list = self.list[:] + list.reverse() + for spr in list: + if spr.hit(pos, readpixel=not region): + return spr + return None + + def redraw_sprites(self, area=None, cr=None): + ''' Redraw the sprites that intersect area. ''' + # I think I need to do this to save Cairo some work + if cr is None: + cr = self.cr + else: + self.cr = cr + if cr is None: + print 'sprites.redraw_sprites: no Cairo context' + return + for spr in self.list: + if area == None: + spr.draw(cr=cr) + else: + intersection = spr.rect.intersect(area) + if intersection.width > 0 or intersection.height > 0: + spr.draw(cr=cr) + + +class Sprite: + ''' A class for the individual sprites ''' + + def __init__(self, sprites, x, y, image): + ''' Initialize an individual sprite ''' + self._sprites = sprites + self.save_xy = (x, y) # remember initial (x, y) position + self.rect = gtk.gdk.Rectangle(int(x), int(y), 0, 0) + self._scale = [12] + self._rescale = [True] + self._horiz_align = ["center"] + self._vert_align = ["middle"] + self._fd = None + self._bold = False + self._italic = False + self._color = None + self._margins = [0, 0, 0, 0] + self.layer = 100 + self.labels = [] + self.cached_surfaces = [] + self._dx = [] # image offsets + self._dy = [] + self.type = None + self.set_image(image) + self._sprites.append_to_list(self) + + def set_image(self, image, i=0, dx=0, dy=0): + ''' Add an image to the sprite. ''' + while len(self.cached_surfaces) < i + 1: + self.cached_surfaces.append(None) + self._dx.append(0) + self._dy.append(0) + self._dx[i] = dx + self._dy[i] = dy + if isinstance(image, gtk.gdk.Pixbuf) or \ + isinstance(image, cairo.ImageSurface): + w = image.get_width() + h = image.get_height() + else: + w, h = image.get_size() + if i == 0: # Always reset width and height when base image changes. + self.rect.width = w + dx + self.rect.height = h + dy + else: + if w + dx > self.rect.width: + self.rect.width = w + dx + if h + dy > self.rect.height: + self.rect.height = h + dy + if isinstance(image, cairo.ImageSurface): + self.cached_surfaces[i] = image + else: # Convert to Cairo surface + surface = cairo.ImageSurface( + cairo.FORMAT_ARGB32, self.rect.width, self.rect.height) + context = cairo.Context(surface) + context = gtk.gdk.CairoContext(context) + context.set_source_pixbuf(image, 0, 0) + context.rectangle(0, 0, self.rect.width, self.rect.height) + context.fill() + self.cached_surfaces[i] = surface + + def move(self, pos): + ''' Move to new (x, y) position ''' + self.inval() + self.rect.x, self.rect.y = int(pos[0]), int(pos[1]) + self.inval() + + def move_relative(self, pos): + ''' Move to new (x+dx, y+dy) position ''' + self.inval() + self.rect.x += int(pos[0]) + self.rect.y += int(pos[1]) + self.inval() + + def get_xy(self): + ''' Return current (x, y) position ''' + return (self.rect.x, self.rect.y) + + def get_dimensions(self): + ''' Return current size ''' + return (self.rect.width, self.rect.height) + + def get_layer(self): + ''' Return current layer ''' + return self.layer + + def set_shape(self, image, i=0): + ''' Set the current image associated with the sprite ''' + self.inval() + self.set_image(image, i) + self.inval() + + def set_layer(self, layer=None): + ''' Set the layer for a sprite ''' + self._sprites.remove_from_list(self) + if layer is not None: + self.layer = layer + for i in range(self._sprites.length_of_list()): + if layer < self._sprites.get_sprite(i).layer: + self._sprites.insert_in_list(self, i) + self.inval() + return + self._sprites.append_to_list(self) + self.inval() + + def set_label(self, new_label, i=0): + ''' Set the label drawn on the sprite ''' + self._extend_labels_array(i) + if type(new_label) is str or type(new_label) is unicode: + # pango doesn't like nulls + self.labels[i] = new_label.replace("\0", " ") + else: + self.labels[i] = str(new_label) + self.inval() + + def set_margins(self, l=0, t=0, r=0, b=0): + ''' Set the margins for drawing the label ''' + self._margins = [l, t, r, b] + + def _extend_labels_array(self, i): + ''' Append to the labels attribute list ''' + if self._fd is None: + self.set_font('Sans') + if self._color is None: + self._color = (0., 0., 0.) + while len(self.labels) < i + 1: + self.labels.append(" ") + self._scale.append(self._scale[0]) + self._rescale.append(self._rescale[0]) + self._horiz_align.append(self._horiz_align[0]) + self._vert_align.append(self._vert_align[0]) + + def set_font(self, font): + ''' Set the font for a label ''' + self._fd = pango.FontDescription(font) + + def set_label_color(self, rgb): + ''' Set the font color for a label ''' + COLORTABLE = {'black': '#000000', 'white': '#FFFFFF', + 'red': '#FF0000', 'yellow': '#FFFF00', + 'green': '#00FF00', 'cyan': '#00FFFF', + 'blue': '#0000FF', 'purple': '#FF00FF', + 'gray': '#808080'} + if rgb.lower() in COLORTABLE: + rgb = COLORTABLE[rgb.lower()] + # Convert from '#RRGGBB' to floats + self._color = (int('0x' + rgb[1:3], 16) / 256., + int('0x' + rgb[3:5], 16) / 256., + int('0x' + rgb[5:7], 16) / 256.) + return + + def set_label_attributes(self, scale, rescale=True, horiz_align="center", + vert_align="middle", i=0): + ''' Set the various label attributes ''' + self._extend_labels_array(i) + self._scale[i] = scale + self._rescale[i] = rescale + self._horiz_align[i] = horiz_align + self._vert_align[i] = vert_align + + def hide(self): + ''' Hide a sprite ''' + self.inval() + self._sprites.remove_from_list(self) + + def restore(self): + ''' Restore a hidden sprite ''' + self.set_layer() + + def inval(self): + ''' Invalidate a region for gtk ''' + self._sprites.widget.queue_draw_area(self.rect.x, + self.rect.y, + self.rect.width, + self.rect.height) + + def draw(self, cr=None): + ''' Draw the sprite (and label) ''' + if cr is None: + print 'sprite.draw: no Cairo context.' + return + for i, surface in enumerate(self.cached_surfaces): + cr.set_source_surface(surface, + self.rect.x + self._dx[i], + self.rect.y + self._dy[i]) + cr.rectangle(self.rect.x + self._dx[i], + self.rect.y + self._dy[i], + self.rect.width, + self.rect.height) + cr.fill() + if len(self.labels) > 0: + self.draw_label(cr) + + def hit(self, pos, readpixel=False): + ''' Is (x, y) on top of the sprite? ''' + x, y = pos + if x < self.rect.x: + return False + if x > self.rect.x + self.rect.width: + return False + if y < self.rect.y: + return False + if y > self.rect.y + self.rect.height: + return False + if readpixel: + r, g, b, a = self.get_pixel(pos) + if r == g == b == a == 0: + return False + if a == -1: + return False + return self._sprites.find_in_list(self) + + def draw_label(self, cr): + ''' Draw the label based on its attributes ''' + # Create a pangocairo context + cr = pangocairo.CairoContext(cr) + my_width = self.rect.width - self._margins[0] - self._margins[2] + if my_width < 0: + my_width = 0 + my_height = self.rect.height - self._margins[1] - self._margins[3] + for i in range(len(self.labels)): + pl = cr.create_layout() + pl.set_text(str(self.labels[i])) + self._fd.set_size(int(self._scale[i] * pango.SCALE)) + pl.set_font_description(self._fd) + w = pl.get_size()[0] / pango.SCALE + if w > my_width: + if self._rescale[i]: + self._fd.set_size( + int(self._scale[i] * pango.SCALE * my_width / w)) + pl.set_font_description(self._fd) + w = pl.get_size()[0] / pango.SCALE + else: + j = len(self.labels[i]) - 1 + while(w > my_width and j > 0): + pl.set_text( + "…" + self.labels[i][len(self.labels[i]) - j:]) + self._fd.set_size(int(self._scale[i] * pango.SCALE)) + pl.set_font_description(self._fd) + w = pl.get_size()[0] / pango.SCALE + j -= 1 + if self._horiz_align[i] == "center": + x = int(self.rect.x + self._margins[0] + (my_width - w) / 2) + elif self._horiz_align[i] == 'left': + x = int(self.rect.x + self._margins[0]) + else: # right + x = int(self.rect.x + self.rect.width - w - self._margins[2]) + h = pl.get_size()[1] / pango.SCALE + if self._vert_align[i] == "middle": + y = int(self.rect.y + self._margins[1] + (my_height - h) / 2) + elif self._vert_align[i] == "top": + y = int(self.rect.y + self._margins[1]) + else: # bottom + y = int(self.rect.y + self.rect.height - h - self._margins[3]) + cr.save() + cr.translate(x, y) + cr.set_source_rgb(self._color[0], self._color[1], self._color[2]) + cr.update_layout(pl) + cr.show_layout(pl) + cr.restore() + + def label_width(self): + ''' Calculate the width of a label ''' + cr = pangocairo.CairoContext(self._sprites.cr) + if cr is not None: + max = 0 + for i in range(len(self.labels)): + pl = cr.create_layout() + pl.set_text(self.labels[i]) + self._fd.set_size(int(self._scale[i] * pango.SCALE)) + pl.set_font_description(self._fd) + w = pl.get_size()[0] / pango.SCALE + if w > max: + max = w + return max + else: + return self.rect.width + + def label_safe_width(self): + ''' Return maximum width for a label ''' + return self.rect.width - self._margins[0] - self._margins[2] + + def label_safe_height(self): + ''' Return maximum height for a label ''' + return self.rect.height - self._margins[1] - self._margins[3] + + def label_left_top(self): + ''' Return the upper-left corner of the label safe zone ''' + return(self._margins[0], self._margins[1]) + + def get_pixel(self, pos, i=0): + ''' Return the pixel at (x, y) ''' + x = int(pos[0] - self.rect.x) + y = int(pos[1] - self.rect.y) + if x < 0 or x > (self.rect.width - 1) or \ + y < 0 or y > (self.rect.height - 1): + return(-1, -1, -1, -1) + # Create a new 1x1 cairo surface. + cs = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1) + cr = cairo.Context(cs) + cr.set_source_surface(self.cached_surfaces[i], -x, -y) + cr.rectangle(0, 0, 1, 1) + cr.set_operator(cairo.OPERATOR_SOURCE) + cr.fill() + cs.flush() # Ensure all the writing is done. + pixels = cs.get_data() # Read the pixel. + return (ord(pixels[2]), ord(pixels[1]), ord(pixels[0]), 0) diff --git a/TurtleArt/tabasics.py b/TurtleArt/tabasics.py new file mode 100644 index 0000000..e26950d --- /dev/null +++ b/TurtleArt/tabasics.py @@ -0,0 +1,1362 @@ +# -*- coding: utf-8 -*- +#Copyright (c) 2011, 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. + +""" +This file contains the constants that by-in-large determine the +behavior of Turtle Art. Notably, the block palettes are defined +below. If you want to add a new block to Turtle Art, you could +simply add a block of code to this file or to turtle_block_plugin.py, +which contains additional blocks. (Even better, write your own plugin!!) + + +Adding a new palette is simply a matter of: + palette = make_palette('mypalette', # the name of your palette + colors=["#00FF00", "#00A000"], + help_string=_('Palette of my custom commands')) + +For example, if we want to add a new turtle command, 'uturn', we'd use the +add_block method in the Palette class. + palette.add_block('uturn', # the name of your block + style='basic-style', # the block style + label=_('u turn'), # the label for the block + prim_name='uturn', # code reference (see below) + help_string=_('turns the turtle 180 degrees')) + + # Next, you need to define what your block will do: + # def_prim takes 3 arguments: the primitive name, the number of + # arguments -- 0 in this case -- and the function to call -- in this + # case, the canvas.seth function to set the heading. + self.tw.lc.def_prim('uturn', 0, + lambda self: self.tw.canvas.seth(self.tw.canvas.heading + 180)) + +That's it. When you next run Turtle Art, you will have a 'uturn' block +on the 'mypalette' palette. + +You will have to create icons for the palette-selector buttons. These +are kept in the icons subdirectory. You need two icons: +mypaletteoff.svg and mypaletteon.svg, where 'mypalette' is the same +string as the entry you used in instantiating the Palette class. Note +that the icons should be the same size (55x55) as the others. (This is +the default icon size for Sugar toolbars.) +""" + +from time import time +from math import sqrt +from random import uniform + +from gettext import gettext as _ + +from tapalette import make_palette, define_logo_function +from talogo import primitive_dictionary, logoerror +from tautils import convert, chr_to_ord, round_int, strtype +from taconstants import BLACK, WHITE, CONSTANTS, XO30 + +def _num_type(x): + """ Is x a number type? """ + if type(x) == int: + return True + if type(x) == float: + return True + if type(x) == ord: + return True + return False + + +def _millisecond(): + """ Current time in milliseconds """ + return time() * 1000 + + +class Palettes(): + """ a class for creating the palettes of blocks """ + + def __init__(self, parent): + self.tw = parent + + self._turtle_palette() + + self._pen_palette() + + self._color_palette() + + self._numbers_palette() + + self._flow_palette() + + self._blocks_palette() + + self._trash_palette() + + # Palette definitions + + def _turtle_palette(self): + """ The basic Turtle Art turtle palette """ + + palette = make_palette('turtle', + colors=["#00FF00", "#00A000"], + help_string=_('Palette of turtle commands')) + + primitive_dictionary['move'] = self._prim_move + palette.add_block('forward', + style='basic-style-1arg', + label=_('forward'), + prim_name='forward', + default=100, + logo_command='forward', + help_string=_('moves turtle forward')) + self.tw.lc.def_prim('forward', 1, + lambda self, x: primitive_dictionary['move']( + self.tw.canvas.forward, x)) + + palette.add_block('back', + style='basic-style-1arg', + label=_('back'), + prim_name='back', + default=100, + logo_command='back', + help_string=_('moves turtle backward')) + self.tw.lc.def_prim('back', 1, + lambda self, x: primitive_dictionary['move']( + self.tw.canvas.forward, -x)) + + primitive_dictionary['clean'] = self._prim_clean + palette.add_block('clean', + style='basic-style-extended-vertical', + label=_('clean'), + prim_name='clean', + logo_command='clean', + help_string=_('clears the screen and reset the \ +turtle')) + self.tw.lc.def_prim('clean', 0, + lambda self: primitive_dictionary['clean']()) + + primitive_dictionary['right'] = self._prim_right + palette.add_block('left', + style='basic-style-1arg', + label=_('left'), + prim_name='left', + default=90, + logo_command='left', + help_string=_('turns turtle counterclockwise (angle \ +in degrees)')) + self.tw.lc.def_prim('left', 1, + lambda self, x: primitive_dictionary['right'](-x)) + + palette.add_block('right', + style='basic-style-1arg', + label=_('right'), + prim_name='right', + default=90, + logo_command='right', + help_string=_('turns turtle clockwise (angle in \ +degrees)')) + self.tw.lc.def_prim('right', 1, + lambda self, x: primitive_dictionary['right'](x)) + + primitive_dictionary['arc'] = self._prim_arc + palette.add_block('arc', + hidden=True, + style='basic-style-2arg', + label=[_('arc'), _('angle'), _('radius')], + prim_name='arc', + default=[90, 100], + logo_command='taarc', + help_string=_('moves turtle along an arc')) + self.tw.lc.def_prim('arc', 2, + lambda self, x, y: primitive_dictionary['arc']( + self.tw.canvas.arc, x, y)) + define_logo_function('taarc', 'to taarc :a :r\rrepeat round :a \ +[right 1 forward (0.0175 * :r)]\rend\r') + + palette.add_block('setxy2', + style='basic-style-2arg', + label=[_('set xy'), _('x'), _('y')], + prim_name='setxy2', + logo_command='tasetxy', + default=[0, 0], + help_string=_('moves turtle to position xcor, ycor; \ +(0, 0) is in the center of the screen.')) + self.tw.lc.def_prim('setxy2', 2, + lambda self, x, y: primitive_dictionary['move']( + self.tw.canvas.setxy, x, y)) + define_logo_function('tasetxy', 'to tasetxy :x :y\rsetxy :x :y\rend\r') + + primitive_dictionary['set'] = self._prim_set + palette.add_block('seth', + style='basic-style-1arg', + label=_('set heading'), + prim_name='seth', + default=0, + logo_command='seth', + help_string=_('sets the heading of the turtle (0 is \ +towards the top of the screen.)')) + self.tw.lc.def_prim('seth', 1, + lambda self, x: primitive_dictionary['set']( + 'heading', self.tw.canvas.seth, x)) + + palette.add_block('xcor', + style='box-style', + label=_('xcor'), + help_string=_('holds current x-coordinate value of \ +the turtle (can be used in place of a number block)'), + value_block=True, + prim_name='xcor', + logo_command='xcor') + self.tw.lc.def_prim( + 'xcor', 0, lambda self: self.tw.canvas.xcor / self.tw.coord_scale) + + palette.add_block('ycor', + style='box-style', + label=_('ycor'), + help_string=_('holds current y-coordinate value of \ +the turtle (can be used in place of a number block)'), + value_block=True, + prim_name='ycor', + logo_command='ycor') + self.tw.lc.def_prim( + 'ycor', 0, lambda self: self.tw.canvas.ycor / self.tw.coord_scale) + + palette.add_block('heading', + style='box-style', + label=_('heading'), + help_string=_('holds current heading value of the \ +turtle (can be used in place of a number block)'), + value_block=True, + prim_name='heading', + logo_command='heading') + self.tw.lc.def_prim( + 'heading', 0, lambda self: self.tw.canvas.heading) + + palette.add_block('turtle-label', + hidden=True, + style='blank-style', + label=['turtle']) + + # Deprecated + palette.add_block('setxy', + hidden=True, + style='basic-style-2arg', + label=[_('set xy'), _('x'), _('y')], + prim_name='setxy', + default=[0, 0], + logo_command='tasetxypenup', + help_string=_('moves turtle to position xcor, ycor; \ +(0, 0) is in the center of the screen.')) + self.tw.lc.def_prim('setxy', 2, + lambda self, x, y: primitive_dictionary['move']( + self.tw.canvas.setxy, x, y, pendown=False)) + define_logo_function('tasetxypenup', 'to tasetxypenup :x :y\rpenup\r\ +setxy :x :y\rpendown\rend\r') + + def _pen_palette(self): + """ The basic Turtle Art pen palette """ + + palette = make_palette('pen', + colors=["#00FFFF", "#00A0A0"], + help_string=_('Palette of pen commands')) + + palette.add_block('penup', + style='basic-style-extended-vertical', + label=_('pen up'), + prim_name='penup', + logo_command='penup', + help_string=_('Turtle will not draw when moved.')) + self.tw.lc.def_prim('penup', 0, + lambda self: self.tw.canvas.setpen(False)) + + palette.add_block('pendown', + style='basic-style-extended-vertical', + label=_('pen down'), + prim_name='pendown', + logo_command='pendown', + help_string=_('Turtle will draw when moved.')) + self.tw.lc.def_prim('pendown', 0, + lambda self: self.tw.canvas.setpen(True)) + + palette.add_block('setpensize', + hidden=True, + style='basic-style-1arg', + label=_('set pen size'), + prim_name='setpensize', + default=5, + logo_command='setpensize', + help_string=_('sets size of the line drawn by the \ +turtle')) + self.tw.lc.def_prim('setpensize', 1, + lambda self, x: primitive_dictionary['set']( + 'pensize', self.tw.canvas.setpensize, x)) + define_logo_function('tasetpensize', 'to tasetpensize :a\rsetpensize \ +round :a\rend\r') + + palette.add_block('fillscreen', + hidden=True, + style='basic-style-2arg', + label=[_('fill screen'), _('color'), _('shade')], + prim_name='fillscreen', + default=[60, 80], + logo_command='tasetbackground', + help_string=_('fills the background with (color, \ +shade)')) + self.tw.lc.def_prim('fillscreen', 2, + lambda self, x, y: self.tw.canvas.fillscreen(x, y)) + define_logo_function('tasetbackground', 'to tasetbackground :color \ +:shade\rtasetshade :shade\rsetbackground :color\rend\r') + + palette.add_block('pensize', + hidden=True, + style='box-style', + label=_('pen size'), + help_string=_('holds current pen size (can be used \ +in place of a number block)'), + value_block=True, + prim_name='pensize', + logo_command='pensize') + self.tw.lc.def_prim('pensize', 0, lambda self: self.tw.canvas.pensize) + define_logo_function('tapensize', 'to tapensize\routput first round \ +pensize\rend\r') + + palette.add_block('startfill', + style='basic-style-extended-vertical', + label=_('start fill'), + prim_name='startfill', + help_string=_('starts filled polygon (used with end \ +fill block)')) + self.tw.lc.def_prim('startfill', 0, + lambda self: self.tw.canvas.start_fill()) + + palette.add_block('stopfill', + style='basic-style-extended-vertical', + label=_('end fill'), + prim_name='stopfill', + help_string=_('completes filled polygon (used with \ +start fill block)')) + self.tw.lc.def_prim('stopfill', 0, + lambda self: self.tw.canvas.stop_fill()) + + def _color_palette(self): + """ The basic Turtle Art color palette """ + + if self.tw.hw == XO30: + palette = make_palette('pen', + colors=["#00FFFF", "#00A0A0"], + help_string=_('Palette of pen colors')) + else: + palette = make_palette('colors', + colors=["#00FFFF", "#00A0A0"], + help_string=_('Palette of pen colors')) + + palette.add_block('setcolor', + style='basic-style-1arg', + label=_('set color'), + prim_name='setcolor', + default=0, + logo_command='tasetpencolor', + help_string=_('sets color of the line drawn by the \ +turtle')) + self.tw.lc.def_prim('setcolor', 1, + lambda self, x: primitive_dictionary['set']( + 'color', self.tw.canvas.setcolor, x)) + + palette.add_block('setshade', + hidden=True, + style='basic-style-1arg', + label=_('set shade'), + prim_name='setshade', + default=50, + logo_command='tasetshade', + help_string=_('sets shade of the line drawn by the \ +turtle')) + self.tw.lc.def_prim('setshade', 1, + lambda self, x: primitive_dictionary['set']( + 'shade', self.tw.canvas.setshade, x)) + + palette.add_block('setgray', + hidden=True, + style='basic-style-1arg', + label=_('set gray'), + prim_name='setgray', + default=100, + help_string=_('sets gray level of the line drawn by \ +the turtle')) + self.tw.lc.def_prim('setgray', 1, + lambda self, x: primitive_dictionary['set']( + 'gray', self.tw.canvas.setgray, x)) + + palette.add_block('color', + style='box-style', + label=_('color'), + help_string=_('holds current pen color (can be used \ +in place of a number block)'), + value_block=True, + prim_name='color', + logo_command='pencolor') + self.tw.lc.def_prim('color', 0, lambda self: self.tw.canvas.color) + + palette.add_block('shade', + hidden=True, + style='box-style', + label=_('shade'), + help_string=_('holds current pen shade'), + value_block=True, + prim_name='shade', + logo_command=':shade') + self.tw.lc.def_prim('shade', 0, lambda self: self.tw.canvas.shade) + + palette.add_block('gray', + hidden=True, + style='box-style', + label=_('gray'), + help_string=_('holds current gray level (can be used \ +in place of a number block)'), + value_block=True, + prim_name='gray') + self.tw.lc.def_prim('gray', 0, lambda self: self.tw.canvas.gray) + + self._make_constant(palette, 'red', _('red'), CONSTANTS['red']) + self._make_constant(palette, 'orange', _('orange'), + CONSTANTS['orange']) + self._make_constant(palette, 'yellow', _('yellow'), + CONSTANTS['yellow']) + self._make_constant(palette, 'green', _('green'), CONSTANTS['green']) + self._make_constant(palette, 'cyan', _('cyan'), CONSTANTS['cyan']) + self._make_constant(palette, 'blue', _('blue'), CONSTANTS['blue']) + self._make_constant(palette, 'purple', _('purple'), + CONSTANTS['purple']) + self._make_constant(palette, 'white', _('white'), WHITE) + self._make_constant(palette, 'black', _('black'), BLACK) + + # deprecated blocks + palette.add_block('settextcolor', + hidden=True, + style='basic-style-1arg', + label=_('set text color'), + prim_name='settextcolor', + default=0, + help_string=_('sets color of text drawn by the \ +turtle')) + self.tw.lc.def_prim('settextcolor', 1, + lambda self, x: self.tw.canvas.settextcolor(x)) + + palette.add_block('settextsize', + hidden=True, + style='basic-style-1arg', + label=_('set text size'), + prim_name='settextsize', + default=0, + help_string=_('sets size of text drawn by the \ +turtle')) + self.tw.lc.def_prim('settextsize', 1, + lambda self, x: self.tw.canvas.settextsize(x)) + + # In order to map Turtle Art colors to the standard UCB Logo palette, + # we need to define a somewhat complex set of functions. + define_logo_function('tacolor', '\ +to tasetpalette :i :r :g :b :myshade \r\ +make "s ((:myshade - 50) / 50) \r\ +ifelse lessp :s 0 [ \r\ +make "s (1 + (:s *0.8)) \r\ +make "r (:r * :s) \r\ +make "g (:g * :s) \r\ +make "b (:b * :s) \r\ +] [ \ +make "s (:s * 0.9) \r\ +make "r (:r + ((99-:r) * :s)) \r\ +make "g (:g + ((99-:g) * :s)) \r\ +make "b (:b + ((99-:b) * :s)) \r\ +] \ +setpalette :i (list :r :g :b) \r\ +end \r\ +\ +to rgb :myi :mycolors :myshade \r\ +make "myr first :mycolors \r\ +make "mycolors butfirst :mycolors \r\ +make "myg first :mycolors \r\ +make "mycolors butfirst :mycolors \r\ +make "myb first :mycolors \r\ +make "mycolors butfirst :mycolors \r\ +tasetpalette :myi :myr :myg :myb :myshade \r\ +output :mycolors \r\ +end \r\ +\ +to processcolor :mycolors :myshade \r\ +if emptyp :mycolors [stop] \r\ +make "i :i + 1 \r\ +processcolor (rgb :i :mycolors :myshade) :myshade \r\ +end \r\ +\ +to tasetshade :shade \r\ +make "myshade modulo :shade 200 \r\ +if greaterp :myshade 99 [make "myshade (199-:myshade)] \r\ +make "i 7 \r\ +make "mycolors :colors \r\ +processcolor :mycolors :myshade \r\ +end \r\ +\ +to tasetpencolor :c \r\ +make "color (modulo (round :c) 100) \r\ +setpencolor :color + 8 \r\ +end \r\ +\ +make "colors [ \ +99 0 0 99 5 0 99 10 0 99 15 0 99 20 0 \ +99 25 0 99 30 0 99 35 0 99 40 0 99 45 0 \ +99 50 0 99 55 0 99 60 0 99 65 0 99 70 0 \ +99 75 0 99 80 0 99 85 0 99 90 0 99 95 0 \ +99 99 0 90 99 0 80 99 0 70 99 0 60 99 0 \ +50 99 0 40 99 0 30 99 0 20 99 0 10 99 0 \ + 0 99 0 0 99 5 0 99 10 0 99 15 0 99 20 \ + 0 99 25 0 99 30 0 99 35 0 99 40 0 99 45 \ + 0 99 50 0 99 55 0 99 60 0 99 65 0 99 70 \ + 0 99 75 0 99 80 0 99 85 0 99 90 0 99 95 \ + 0 99 99 0 95 99 0 90 99 0 85 99 0 80 99 \ + 0 75 99 0 70 99 0 65 99 0 60 99 0 55 99 \ + 0 50 99 0 45 99 0 40 99 0 35 99 0 30 99 \ + 0 25 99 0 20 99 0 15 99 0 10 99 0 5 99 \ + 0 0 99 5 0 99 10 0 99 15 0 99 20 0 99 \ +25 0 99 30 0 99 35 0 99 40 0 99 45 0 99 \ +50 0 99 55 0 99 60 0 99 65 0 99 70 0 99 \ +75 0 99 80 0 99 85 0 99 90 0 99 95 0 99 \ +99 0 99 99 0 90 99 0 80 99 0 70 99 0 60 \ +99 0 50 99 0 40 99 0 30 99 0 20 99 0 10] \r\ +make "shade 50 \r\ +tasetshade :shade \r') + + def _numbers_palette(self): + """ The basic Turtle Art numbers palette """ + + palette = make_palette('numbers', + colors=["#FF00FF", "#A000A0"], + help_string=_('Palette of numeric operators')) + + primitive_dictionary['plus'] = self._prim_plus + palette.add_block('plus2', + style='number-style', + label='+', + special_name=_('plus'), + string_or_number=True, + prim_name='plus', + logo_command='sum', + help_string=_('adds two alphanumeric inputs')) + self.tw.lc.def_prim( + 'plus', 2, lambda self, x, y: primitive_dictionary['plus'](x, y)) + + primitive_dictionary['minus'] = self._prim_minus + palette.add_block('minus2', + style='number-style-porch', + label='–', + special_name=_('minus'), + prim_name='minus', + logo_command='taminus', + help_string=_('subtracts bottom numeric input from \ +top numeric input')) + self.tw.lc.def_prim( + 'minus', 2, lambda self, x, y: primitive_dictionary['minus'](x, y)) + define_logo_function('taminus', 'to taminus :y :x\routput sum :x minus \ +:y\rend\r') + + primitive_dictionary['product'] = self._prim_product + palette.add_block('product2', + style='number-style', + label='×', + special_name=_('multiply'), + prim_name='product', + logo_command='product', + help_string=_('multiplies two numeric inputs')) + self.tw.lc.def_prim( + 'product', 2, + lambda self, x, y: primitive_dictionary['product'](x, y)) + + primitive_dictionary['division'] = self._prim_careful_divide + palette.add_block('division2', + style='number-style-porch', + label='/', + special_name=_('divide'), + prim_name='division', + logo_command='quotient', + help_string=_('divides top numeric input (numerator) \ +by bottom numeric input (denominator)')) + self.tw.lc.def_prim( + 'division', 2, + lambda self, x, y: primitive_dictionary['division'](x, y)) + + primitive_dictionary['id'] = self._prim_identity + palette.add_block('identity2', + style='number-style-1arg', + label='←', + special_name=_('identity'), + prim_name='id', + help_string=_('identity operator used for extending \ +blocks')) + self.tw.lc.def_prim('id', 1, + lambda self, x: primitive_dictionary['id'](x)) + + primitive_dictionary['remainder'] = self._prim_mod + palette.add_block('remainder2', + style='number-style-porch', + label=_('mod'), + special_name=_('mod'), + prim_name='remainder', + logo_command='remainder', + help_string=_('modular (remainder) operator')) + self.tw.lc.def_prim('remainder', 2, + lambda self, x, y: primitive_dictionary['remainder'](x, y)) + + primitive_dictionary['sqrt'] = self._prim_sqrt + palette.add_block('sqrt', + hidden=True, + style='number-style-1arg', + label=_('√'), + special_name=_('square root'), + prim_name='sqrt', + logo_command='tasqrt', + help_string=_('calculates square root')) + self.tw.lc.def_prim('sqrt', 1, + lambda self, x: primitive_dictionary['sqrt'](x)) + + primitive_dictionary['random'] = self._prim_random + palette.add_block('random', + hidden=True, + style='number-style-block', + label=[_('random'), _('min'), _('max')], + default=[0, 100], + prim_name='random', + logo_command='tarandom', + help_string=_('returns random number between minimum \ +(top) and maximum (bottom) values')) + self.tw.lc.def_prim( + 'random', 2, lambda self, x, y: primitive_dictionary['random']( + x, y)) + define_logo_function('tarandom', 'to tarandom :min :max\r \ +output (random (:max - :min)) + :min\rend\r') + + palette.add_block('number', + style='box-style', + label='100', + default=100, + special_name=_('number'), + help_string=_('used as numeric input in mathematic \ +operators')) + + primitive_dictionary['more'] = self._prim_more + palette.add_block('greater2', + hidden=True, + style='compare-porch-style', + label='>', + special_name=_('greater than'), + string_or_number=True, + prim_name='greater?', + logo_command='greater?', + help_string=_('logical greater-than operator')) + self.tw.lc.def_prim( + 'greater?', 2, + lambda self, x, y: primitive_dictionary['more'](x, y)) + + if self.tw.canvas.width > 1024: + self._make_constant(palette, 'true', _('True'), 1) + + primitive_dictionary['less'] = self._prim_less + palette.add_block('less2', + hidden=True, + style='compare-porch-style', + label='<', + special_name=_('less than'), + string_or_number=True, + prim_name='less?', + logo_command='less?', + help_string=_('logical less-than operator')) + self.tw.lc.def_prim( + 'less?', 2, lambda self, x, y: primitive_dictionary['less'](x, y)) + + if self.tw.canvas.width > 1024: + self._make_constant(palette, 'false', _('False'), 0) + + primitive_dictionary['equal'] = self._prim_equal + palette.add_block('equal2', + hidden=True, + style='compare-style', + label='=', + string_or_number=True, + special_name=_('equal'), + prim_name='equal?', + logo_command='equal?', + help_string=_('logical equal-to operator')) + self.tw.lc.def_prim( + 'equal?', 2, lambda self, x, y: primitive_dictionary['equal'](x, y)) + + palette.add_block('not', + hidden=True, + style='not-style', + label=_('not'), + prim_name='not', + logo_command='not', + help_string=_('logical NOT operator')) + self.tw.lc.def_prim('not', 1, lambda self, x: not x) + + primitive_dictionary['and'] = self._prim_and + palette.add_block('and2', + hidden=True, + style='boolean-style', + label=_('and'), + prim_name='and', + logo_command='and', + special_name=_('and'), + help_string=_('logical AND operator')) + self.tw.lc.def_prim( + 'and', 2, lambda self, x, y: primitive_dictionary['and'](x, y)) + + primitive_dictionary['or'] = self._prim_or + palette.add_block('or2', + hidden=True, + style='boolean-style', + label=_('or'), + prim_name='or', + logo_command='or', + special_name=_('or'), + help_string=_('logical OR operator')) + self.tw.lc.def_prim( + 'or', 2, lambda self, x, y: primitive_dictionary['or'](x, y)) + + def _flow_palette(self): + """ The basic Turtle Art flow palette """ + + palette = make_palette('flow', + colors=["#FFC000", "#A08000"], + help_string=_('Palette of flow operators')) + + primitive_dictionary['wait'] = self._prim_wait + palette.add_block('wait', + hidden=True, + style='basic-style-1arg', + label=_('wait'), + prim_name='wait', + default=1, + logo_command='wait', + help_string=_('pauses program execution a specified \ +number of seconds')) + self.tw.lc.def_prim('wait', 1, primitive_dictionary['wait'], True) + + primitive_dictionary['forever'] = self._prim_forever + palette.add_block('forever', + hidden=True, + style='flow-style', + label=_('forever'), + prim_name='forever', + default=[None, 'vspace'], + logo_command='forever', + help_string=_('loops forever')) + self.tw.lc.def_prim('forever', 1, primitive_dictionary['forever'], True) + + primitive_dictionary['repeat'] = self._prim_repeat + palette.add_block('repeat', + style='flow-style-1arg', + label=[' ', _('repeat')], + prim_name='repeat', + default=[4, None, 'vspace'], + logo_command='repeat', + special_name=_('repeat'), + help_string=_('loops specified number of times')) + self.tw.lc.def_prim('repeat', 2, primitive_dictionary['repeat'], True) + + primitive_dictionary['if'] = self._prim_if + palette.add_block('if', + hidden=True, + style='flow-style-boolean', + label=[_('if'), ' ', _('then')], + prim_name='if', + default=[None, None, 'vspace'], + special_name=_('if then'), + logo_command='if', + help_string=_('if-then operator that uses boolean \ +operators from Numbers palette')) + self.tw.lc.def_prim('if', 2, primitive_dictionary['if'], True) + + primitive_dictionary['ifelse'] = self._prim_ifelse + palette.add_block('ifelse', + hidden=True, + style='flow-style-else', + label=[_('if'), ' ', _('then else')], + prim_name='ifelse', + default=[None, 'vspace', None, 'vspace'], + logo_command='ifelse', + special_name=_('if then else'), + help_string=_('if-then-else operator that uses \ +boolean operators from Numbers palette')) + self.tw.lc.def_prim('ifelse', 3, primitive_dictionary['ifelse'], True) + + palette.add_block('hspace', + style='flow-style-tail', + label=' ', + prim_name='nop', + special_name=_('horizontal space'), + help_string=_('jogs stack right')) + self.tw.lc.def_prim('nop', 0, lambda self: None) + + palette.add_block('vspace', + style='basic-style-extended-vertical', + label=' ', + prim_name='nop', + special_name=_('vertical space'), + help_string=_('jogs stack down')) + self.tw.lc.def_prim('nop', 0, lambda self: None) + + primitive_dictionary['stopstack'] = self._prim_stopstack + palette.add_block('stopstack', + hidden=True, + style='basic-style-tail', + label=_('stop action'), + prim_name='stopstack', + logo_command='stop', + help_string=_('stops current action')) + self.tw.lc.def_prim('stopstack', 0, + lambda self: primitive_dictionary['stopstack']()) + + def _blocks_palette(self): + """ The basic Turtle Art blocks palette """ + + palette = make_palette('blocks', + colors=["#FFFF00", "#A0A000"], + help_string=_('Palette of variable blocks')) + + primitive_dictionary['start'] = self._prim_start + palette.add_block('start', + style='basic-style-head', + label=_('start'), + prim_name='start', + logo_command='to start\r', + help_string=_('connects action to toolbar run \ +buttons')) + self.tw.lc.def_prim('start', 0, + lambda self: primitive_dictionary['start']()) + + primitive_dictionary['setbox'] = self._prim_setbox + palette.add_block('storeinbox1', + style='basic-style-1arg', + label=_('store in box 1'), + string_or_number=True, + prim_name='storeinbox1', + default=100, + logo_command='make "box1', + help_string=_('stores numeric value in Variable 1')) + self.tw.lc.def_prim('storeinbox1', 1, + lambda self, x: primitive_dictionary['setbox']( + 'box1', None, x)) + + palette.add_block('storeinbox2', + style='basic-style-1arg', + label=_('store in box 2'), + string_or_number=True, + prim_name='storeinbox2', + default=100, + logo_command='make "box2', + help_string=_('stores numeric value in Variable 2')) + self.tw.lc.def_prim('storeinbox2', 1, + lambda self, x: primitive_dictionary['setbox']( + 'box2', None, x)) + + palette.add_block('string', + hidden=True, + style='box-style', + label=_('text'), + default=_('text'), + special_name=_('text'), + help_string=_('string value')) + + palette.add_block('box1', + style='box-style', + label=_('box 1'), + prim_name='box1', + logo_command=':box1', + help_string=_('Variable 1 (numeric value)'), + value_block=True) + self.tw.lc.def_prim('box1', 0, lambda self: self.tw.lc.boxes['box1']) + + palette.add_block('box2', + style='box-style', + label=_('box 2'), + prim_name='box2', + logo_command=':box2', + help_string=_('Variable 2 (numeric value)'), + value_block=True) + self.tw.lc.def_prim('box2', 0, lambda self: self.tw.lc.boxes['box2']) + + primitive_dictionary['box'] = self._prim_box + palette.add_block('box', + hidden=True, + style='number-style-1strarg', + label=_('box'), + prim_name='box', + string_or_number=True, + default=_('my box'), + logo_command='box', + help_string=_('named variable (numeric value)')) + self.tw.lc.def_prim('box', 1, + lambda self, x: primitive_dictionary['box'](x)) + + palette.add_block('storein', + hidden=True, + style='basic-style-2arg', + label=[_('store in'), _('box'), _('value')], + string_or_number=True, + prim_name='storeinbox', + logo_command='storeinbox', + default=[_('my box'), 100], + help_string=_('stores numeric value in named \ +variable')) + self.tw.lc.def_prim('storeinbox', 2, + lambda self, x, y: primitive_dictionary['setbox']( + 'box3', x, y)) + + palette.add_block('hat', + hidden=True, + style='basic-style-head-1arg', + label=_('action'), + prim_name='nop3', + string_or_number=True, + default=_('action'), + logo_command='to action', + help_string=_('top of nameable action stack')) + self.tw.lc.def_prim('nop3', 1, lambda self, x: None) + + palette.add_block('hat1', + style='basic-style-head', + label=_('action 1'), + prim_name='nop1', + logo_command='to stack1\r', + help_string=_('top of Action 1 stack')) + self.tw.lc.def_prim('nop1', 0, lambda self: None) + + palette.add_block('hat2', + style='basic-style-head', + label=_('action 2'), + prim_name='nop2', + logo_command='to stack2\r', + help_string=_('top of Action 2 stack')) + self.tw.lc.def_prim('nop2', 0, lambda self: None) + + primitive_dictionary['stack'] = self._prim_stack + palette.add_block('stack', + hidden=True, + style='basic-style-1arg', + label=_('action'), + string_or_number=True, + prim_name='stack', + logo_command='action', + default=_('action'), + help_string=_('invokes named action stack')) + self.tw.lc.def_prim('stack', 1, primitive_dictionary['stack'], True) + + primitive_dictionary['stack1'] = self._prim_stack1 + palette.add_block('stack1', + style='basic-style-extended-vertical', + label=_('action 1'), + prim_name='stack1', + logo_command='stack1', + help_string=_('invokes Action 1 stack')) + self.tw.lc.def_prim('stack1', 0, primitive_dictionary['stack1'], True) + + primitive_dictionary['stack2'] = self._prim_stack2 + palette.add_block('stack2', + style='basic-style-extended-vertical', + label=_('action 2'), + prim_name='stack2', + logo_command='stack2', + help_string=_('invokes Action 2 stack')) + self.tw.lc.def_prim('stack2', 0, primitive_dictionary['stack2'], True) + + def _trash_palette(self): + """ The basic Turtle Art turtle palette """ + + palette = make_palette('trash', + colors=["#FFFF00", "#A0A000"], + help_string=_('trash')) + + palette.add_block('empty', + style='blank-style', + label=_('empty trash'), + help_string=_('permanently deletes items in trash')) + + palette.add_block('restoreall', + style='blank-style', + label=_('restore all'), + help_string=_('restore all blocks from trash')) + + palette.add_block('trashall', + style='blank-style', + label=_('clear all'), + help_string=_('move all blocks to trash')) + + # Block primitives + + def _prim_clean(self): + ''' Clean block ''' + self.tw.lc.prim_clear + self.tw.display_coordinates() + self.tw.parent.restore_challenge() + + def _prim_and(self, x, y): + """ Logical and """ + return x & y + + def _prim_arc(self, cmd, value1, value2): + """ Turtle draws an arc of degree, radius """ + cmd(float(value1), float(value2)) + self.tw.lc.update_label_value( + 'xcor', self.tw.canvas.xcor / self.tw.coord_scale) + self.tw.lc.update_label_value( + 'ycor', self.tw.canvas.ycor / self.tw.coord_scale) + self.tw.lc.update_label_value('heading', self.tw.canvas.heading) + + def _prim_box(self, x): + """ Retrieve value from named box """ + if type(convert(x, float, False)) == float: + if int(float(x)) == x: + x = int(x) + try: + return self.tw.lc.boxes['box3' + str(x)] + except KeyError: + raise logoerror("#emptybox") + + def _prim_forever(self, blklist): + """ Do list forever """ + while True: + self.tw.lc.icall(self.tw.lc.evline, blklist[:]) + yield True + if self.tw.lc.procstop: + break + self.tw.lc.ireturn() + yield True + + def _prim_if(self, boolean, blklist): + """ If bool, do list """ + if boolean: + self.tw.lc.icall(self.tw.lc.evline, blklist[:]) + yield True + self.tw.lc.ireturn() + yield True + + def _prim_ifelse(self, boolean, list1, list2): + """ If bool, do list1, else do list2 """ + if boolean: + self.tw.lc.ijmp(self.tw.lc.evline, list1[:]) + yield True + else: + self.tw.lc.ijmp(self.tw.lc.evline, list2[:]) + yield True + + def _prim_move(self, cmd, value1, value2=None, pendown=True): + """ Turtle moves by method specified in value1 """ + if value2 is None: + cmd(value1) + else: + cmd(float(value1), float(value2), pendown=pendown) + self.tw.lc.update_label_value('xcor', + self.tw.canvas.xcor / self.tw.coord_scale) + self.tw.lc.update_label_value('ycor', + self.tw.canvas.ycor / self.tw.coord_scale) + + def _prim_or(self, x, y): + """ Logical or """ + return x | y + + def _prim_repeat(self, num, blklist): + """ Repeat list num times. """ + num = self.tw.lc.int(num) + for i in range(num): + self.tw.lc.icall(self.tw.lc.evline, blklist[:]) + yield True + if self.tw.lc.procstop: + break + self.tw.lc.ireturn() + yield True + + def _prim_right(self, value): + """ Turtle rotates clockwise """ + self.tw.canvas.right(float(value)) + self.tw.lc.update_label_value('heading', self.tw.canvas.heading) + + def _prim_set(self, name, cmd, value=None): + """ Set a value and update the associated value blocks """ + if value is not None: + cmd(value) + self.tw.lc.update_label_value(name, value) + + def _prim_setbox(self, name, x, val): + """ Define value of named box """ + if x is not None: + if type(convert(x, float, False)) == float: + if int(float(x)) == x: + x = int(x) + self.tw.lc.boxes[name + str(x)] = val + return + + self.tw.lc.boxes[name] = val + self.tw.lc.update_label_value(name, val) + + def _prim_stack(self, x): + """ Process a named stack """ + if type(convert(x, float, False)) == float: + if int(float(x)) == x: + x = int(x) + if 'stack3' + str(x) not in self.tw.lc.stacks or \ + self.tw.lc.stacks['stack3' + str(x)] is None: + raise logoerror("#nostack") + self.tw.lc.icall(self.tw.lc.evline, + self.tw.lc.stacks['stack3' + str(x)][:]) + yield True + self.tw.lc.procstop = False + self.tw.lc.ireturn() + yield True + + def _prim_stack1(self): + """ Process Stack 1 """ + if self.tw.lc.stacks['stack1'] is None: + raise logoerror("#nostack") + self.tw.lc.icall(self.tw.lc.evline, + self.tw.lc.stacks['stack1'][:]) + yield True + self.tw.lc.procstop = False + self.tw.lc.ireturn() + yield True + + def _prim_stack2(self): + """ Process Stack 2 """ + if self.tw.lc.stacks['stack2'] is None: + raise logoerror("#nostack") + self.tw.lc.icall(self.tw.lc.evline, self.tw.lc.stacks['stack2'][:]) + yield True + self.tw.lc.procstop = False + self.tw.lc.ireturn() + yield True + + def _prim_start(self): + """ Start block: recenter """ + if self.tw.running_sugar: + self.tw.activity.recenter() + + def _prim_stopstack(self): + """ Stop execution of a stack """ + self.tw.lc.procstop = True + + def _prim_wait(self, wait_time): + """ Show the turtle while we wait """ + self.tw.active_turtle.show() + endtime = _millisecond() + wait_time * 1000. + while _millisecond() < endtime: + yield True + self.tw.active_turtle.hide() + self.tw.lc.ireturn() + yield True + + # Math primitivies + + def _prim_careful_divide(self, x, y): + """ Raise error on divide by zero """ + if type(x) == list and _num_type(y): + z = [] + for i in range(len(x)): + try: + z.append(x[i] / y) + except ZeroDivisionError: + raise logoerror("#zerodivide") + return z + try: + return x / y + except ZeroDivisionError: + raise logoerror("#zerodivide") + except TypeError: + try: + return self._string_to_num(x) / self._string_to_num(y) + except ZeroDivisionError: + raise logoerror("#zerodivide") + except ValueError: + raise logoerror("#syntaxerror") + except TypeError: + raise logoerror("#notanumber") + + def _prim_equal(self, x, y): + """ Numeric and logical equal """ + if type(x) == list and type(y) == list: + for i in range(len(x)): + if x[i] != y[i]: + return False + return True + try: + return float(x) == float(y) + except ValueError: + typex, typey = False, False + if strtype(x): + typex = True + if strtype(y): + typey = True + if typex and typey: + return x == y + try: + return self._string_to_num(x) == self._string_to_num(y) + except TypeError: + raise logoerror("#syntaxerror") + + def _prim_less(self, x, y): + """ Compare numbers and strings """ + try: + return float(x) < float(y) + except ValueError: + typex, typey = False, False + if strtype(x): + typex = True + if strtype(y): + typey = True + if typex and typey: + return x < y + try: + return self._string_to_num(x) < self._string_to_num(y) + except TypeError: + raise logoerror("#notanumber") + + def _prim_more(self, x, y): + """ Compare numbers and strings """ + return self._prim_less(y, x) + + def _prim_plus(self, x, y): + """ Add numbers, concat strings """ + if _num_type(x) and _num_type(y): + return(x + y) + elif type(x) == list and type(y) == list: + z = [] + for i in range(len(x)): + z.append(x[i] + y[i]) + return(z) + else: + if _num_type(x): + xx = str(round_int(x)) + else: + xx = str(x) + if _num_type(y): + yy = str(round_int(y)) + else: + yy = str(y) + return(xx + yy) + + def _prim_minus(self, x, y): + """ Numerical subtraction """ + if _num_type(x) and _num_type(y): + return(x - y) + elif type(x) == list and type(y) == list: + z = [] + for i in range(len(x)): + z.append(x[i] - y[i]) + return(z) + try: + return self._string_to_num(x) - self._string_to_num(y) + except TypeError: + raise logoerror("#notanumber") + + def _prim_product(self, x, y): + """ Numerical multiplication """ + if _num_type(x) and _num_type(y): + return(x * y) + elif type(x) == list and _num_type(y): + z = [] + for i in range(len(x)): + z.append(x[i] * y) + return(z) + elif type(y) == list and _num_type(x): + z = [] + for i in range(len(y)): + z.append(y[i] * x) + return(z) + try: + return self._string_to_num(x) * self._string_to_num(y) + except TypeError: + raise logoerror("#notanumber") + + def _prim_mod(self, x, y): + """ Numerical mod """ + if _num_type(x) and _num_type(y): + return(x % y) + try: + return self._string_to_num(x) % self._string_to_num(y) + except TypeError: + raise logoerror("#notanumber") + except ValueError: + raise logoerror("#syntaxerror") + + def _prim_sqrt(self, x): + """ Square root """ + if _num_type(x): + if x < 0: + raise logoerror("#negroot") + return sqrt(x) + try: + return sqrt(self._string_to_num(x)) + except ValueError: + raise logoerror("#negroot") + except TypeError: + raise logoerror("#notanumber") + + def _prim_random(self, x, y): + """ Random integer """ + if _num_type(x) and _num_type(y): + return(int(round(uniform(x, y), 0))) + xx, xflag = chr_to_ord(x) + yy, yflag = chr_to_ord(y) + if xflag and yflag: + return chr(int(round(uniform(xx, yy), 0))) + if not xflag: + xx = self._string_to_num(x) + if not yflag: + yy = self._string_to_num(y) + try: + return(int(round(uniform(xx, yy), 0))) + except TypeError: + raise logoerror("#notanumber") + + def _prim_identity(self, x): + """ Identity function """ + return(x) + + # Utilities + + def _string_to_num(self, x): + """ Try to comvert a string to a number """ + if type(x) is float: + return(x) + if type(x) is int: + return(x) + if type(x) is ord: + return(int(x)) + if type(x) is list: + raise logoerror("#syntaxerror") + xx = convert(x.replace(self.tw.decimal_point, '.'), float) + if type(xx) is float: + return xx + else: + xx, xflag = chr_to_ord(x) + if xflag: + return xx + else: + raise logoerror("#syntaxerror") + + def _make_constant(self, palette, block_name, label, constant): + """ Factory for constant blocks """ + palette.add_block(block_name, style='box-style', + label=label, prim_name=block_name, + logo_command=block_name) + self.tw.lc.def_prim(block_name, 0, lambda self: constant) diff --git a/TurtleArt/tablock.py b/TurtleArt/tablock.py new file mode 100644 index 0000000..f835994 --- /dev/null +++ b/TurtleArt/tablock.py @@ -0,0 +1,970 @@ +# -*- coding: utf-8 -*- +#Copyright (c) 2010,11 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 gtk +from gettext import gettext as _ + +from taconstants import EXPANDABLE, EXPANDABLE_ARGS, OLD_NAMES, CONSTANTS, \ + STANDARD_STROKE_WIDTH, BLOCK_SCALE, BOX_COLORS, GRADIENT_COLOR +from tapalette import palette_blocks, block_colors, expandable_blocks, \ + content_blocks, block_names, block_primitives, block_styles, \ + special_block_colors +from tasprite_factory import SVG, svg_str_to_pixbuf +import sprites + +from tautils import debug_output, error_output + + +class Blocks: + + """ A class for the list of blocks and everything they share in common """ + + def __init__(self, font_scale_factor=1, decimal_point='.'): + self.list = [] + self.font_scale_factor = font_scale_factor + self.decimal_point = decimal_point + + def get_block(self, i): + if i < 0 or i > len(self.list) - 1: + return(None) + else: + return(self.list[i]) + + def length_of_list(self): + return(len(self.list)) + + def append_to_list(self, block): + self.list.append(block) + + def remove_from_list(self, block): + if block in self.list: + self.list.remove(block) + + def print_list(self, block_type=None): + for i, block in enumerate(self.list): + if block_type is None or block_type == block.type: + print "%d: %s" % (i, block.name) + + def set_scale(self, scale): + for b in self.list: + for i in range(len(b._font_size)): + b._font_size[i] *= b.scale * scale / self.font_scale_factor + self.font_scale_factor = scale + + def spr_to_block(self, spr): + for b in self.list: + if spr == b.spr: + return b + return None + + def get_next_block(self, block): + if block is None: + return None + try: + i = self.list.index(block) + except ValueError: + return None + i += 1 + if i < len(self.list): + return self.list[i] + else: + return self.list[0] + + def get_next_block_of_same_type(self, block): + if block is None: + return None + type = block.type + i = 0 + while block is not None: + block = self.get_next_block(block) + if block is not None: + if block.type == type: + return block + if i == len(self.list): + break + i += 1 + return None + + def get_similar_blocks(self, block_type, name): + block_list = [] + if type(name) == type(''): + for block in self.list: + if block.type == block_type and block.name == name: + block_list.append(block) + else: + for block in self.list: + if block.type == block_type and block.name in name: + block_list.append(block) + return block_list + + +class Block: + """ A class for the individual blocks """ + + def __init__(self, block_list, sprite_list, name, x, y, type='block', + values=[], scale=BLOCK_SCALE[0], + colors=['#A0A0A0', '#808080']): + + self.block_list = block_list + self.spr = None + self.shapes = [None, None] + self.name = name + self.colors = colors + self._custom_colors = False + self.scale = scale + self.docks = None + self.connections = None + self.status = None + self.values = [] + self.primitive = None + self.type = type + self.dx = 0 + self.ex = 0 + self.ey = 0 + self._ei = 0 + self._font_size = [6.0, 4.5] + self._image = None + self._visible = True + + self.block_methods = { + 'basic-style': self._make_basic_style, + 'blank-style': self._make_blank_style, + 'basic-style-head': self._make_basic_style_head, + 'basic-style-head-1arg': self._make_basic_style_head_1arg, + 'basic-style-tail': self._make_basic_style_tail, + 'basic-style-extended': [self._make_basic_style, 16, 16], + 'basic-style-extended-vertical': [self._make_basic_style, 0, 4], + 'basic-style-1arg': self._make_basic_style_1arg, + 'basic-style-2arg': self._make_basic_style_2arg, + 'basic-style-3arg': self._make_basic_style_3arg, + 'basic-style-var-arg': self._make_basic_style_var_arg, + 'invisible': self._make_invisible_style, + 'bullet-style': self._make_bullet_style, + 'box-style': self._make_box_style, + 'box-style-media': self._make_media_style, + 'number-style': self._make_number_style, + 'number-style-block': self._make_number_style_block, + 'number-style-porch': self._make_number_style_porch, + 'number-style-1arg': self._make_number_style_1arg, + 'number-style-1strarg': self._make_number_style_1strarg, + 'number-style-var-arg': self._make_number_style_var_arg, + 'compare-style': self._make_compare_style, + 'compare-porch-style': self._make_compare_porch_style, + 'boolean-style': self._make_boolean_style, + 'not-style': self._make_not_style, + 'flow-style': self._make_flow_style, + 'flow-style-tail': self._make_flow_style_tail, + 'flow-style-1arg': self._make_flow_style_1arg, + 'flow-style-boolean': self._make_flow_style_boolean, + 'flow-style-else': self._make_flow_style_else, + 'collapsible-top': [self._make_collapsible_style_top, True, True], + 'collapsible-top-no-arm': [self._make_collapsible_style_top, + False, True], + 'collapsible-top-no-label': [self._make_collapsible_style_top, + True, False], + 'collapsible-top-no-arm-no-label': [ + self._make_collapsible_style_top, False, False], + 'collapsible-bottom': self._make_collapsible_style_bottom, + 'portfolio-style-2x2': self._make_portfolio_style_2x2, + 'portfolio-style-1x1': self._make_portfolio_style_1x1, + 'portfolio-style-2x1': self._make_portfolio_style_2x1, + 'portfolio-style-1x2': self._make_portfolio_style_1x2} + + if self.name in OLD_NAMES: + self.name = OLD_NAMES[self.name] + + for i in range(len(self._font_size)): + self._font_size[i] *= self.scale * \ + self.block_list.font_scale_factor + + for v in (values): + self.values.append(v) + + # If there is already a block with the same name, reuse it + copy_block = None + if self.cloneable(): + for b in self.block_list.list: + if b.scale == self.scale and b.name == self.name: + copy_block = b + break + self._new_block_from_factory(sprite_list, x, y, copy_block) + + if name in block_primitives: + self.primitive = block_primitives[self.name] + + self.block_list.append_to_list(self) + + def get_visibility(self): + ''' Should block be visible on the palette? ''' + return self._visible + + def set_visibility(self, state): + ''' Should block be visible? ''' + self._visible = state + if self._visible: + self.spr.restore() + else: + self.spr.hide() + + def expandable(self): + """ Can this block be expanded? """ + if self.name in EXPANDABLE: + return True + if self.name in expandable_blocks: + return True + if self.name in EXPANDABLE_ARGS: + return True + return False + + def cloneable(self): + """ Is it safe to clone this block? """ + if self.expandable(): + return False + if self.name in block_styles['box-style']: + return False + if self.name in ['sandwichtop', 'sandwichtop_no_label']: + return False + return True + + def highlight(self): + """ We may want to highlight a block... """ + if self.spr is not None: + self.spr.set_shape(self.shapes[1]) + + def unhighlight(self): + """ Or unhighlight it. """ + if self.spr is not None: + self.spr.set_shape(self.shapes[0]) + + def resize(self): + """ We need to resize some blocks on the fly so the labels fit. """ + if self.spr is None: + return + dx = (self.spr.label_width() - self.spr.label_safe_width()) / \ + self.scale + if dx != 0: + self.dx += dx + if self.dx < 0: + self.dx = 0 + self.refresh() + + def set_image(self, image, x, y): + """ Some blocks get a skin. """ + if self.spr is None: + return + self._image = image + self.spr.set_image(image, 1, x, y) + + def scale_image(self, x, y, w, h): + """ The skin might need scaling. """ + if self.spr is None: + return + if self._image is not None: + tmp = self._image.scale_simple(w, h, gtk.gdk.INTERP_NEAREST) + self.spr.set_image(tmp, 1, x, y) + + def rescale(self, scale): + """ We may want to rescale blocks as well. """ + if self.spr is None: + return + for i in range(len(self._font_size)): + self._font_size[i] /= self.scale + self.scale = scale + for i in range(len(self._font_size)): + self._font_size[i] *= self.scale + self._set_label_attributes() + self.svg.set_scale(self.scale) + self.refresh() + self.spr.inval() + + def set_colors(self, colors): + self.colors = colors[:] + self._custom_colors = True + self.refresh() + + def refresh(self): + if self.spr is None: + return + self._make_block(self.svg) + self._set_margins() + self.spr.set_shape(self.shapes[0]) + + def add_arg(self, keep_expanding=True): + """ We may want to add additional slots for arguments ("innies"). """ + if self.spr is None: + return + h = self.svg.get_height() + self._ei += 1 + if self.type == 'block' and keep_expanding: + self.svg.set_show(True) + else: + self.svg.set_show(False) + self.refresh() + return self.svg.get_height() - h + + def expand_in_y(self, dy): + """ We may want to grow a block vertically. """ + if self.spr is None: + return + self.ey += dy + if self.type == 'block': + if self.ey > 0: + self.svg.set_hide(True) + else: + self.svg.set_hide(False) + self.svg.set_show(True) + else: + self.svg.set_hide(False) + self.svg.set_show(False) + self.refresh() + + def expand_in_x(self, dx): + """ We may want to grow a block horizontally. """ + if self.spr is None: + return + self.ex += dx + if self.type == 'block': + self.svg.set_hide(True) + self.svg.set_show(True) + else: + self.svg.set_hide(False) + self.svg.set_show(False) + self.refresh() + + def reset_x(self): + if self.spr is None: + return 0 + dx = -self.ex + self.ex = 0 + self.svg.set_hide(False) + if self.type == 'block': + self.svg.set_show(True) + else: + self.svg.set_show(False) + self.refresh() + return dx + + def reset_y(self): + if self.spr is None: + return 0 + dy = -self.ey + self.ey = 0 + self.svg.set_hide(False) + if self.type == 'block': + self.svg.set_show(True) + else: # 'proto' + self.svg.set_show(False) + self.refresh() + return dy + + def get_expand_x_y(self): + if self.spr is None: + return(0, 0) + return (self.ex, self.ey) + + def _new_block_from_factory(self, sprite_list, x, y, copy_block=None): + self.svg = SVG() + self.svg.set_scale(self.scale) + self.svg.set_innie([False]) + self.svg.set_outie(False) + self.svg.set_tab(True) + self.svg.set_slot(True) + + if copy_block is not None: + self._left = copy_block._left + self._top = copy_block._top + self._right = copy_block._right + self._bottom = copy_block._bottom + self.dx = copy_block.dx + self.ex = copy_block.ex + self.ey = copy_block.ey + self.width = copy_block.width + self.height = copy_block.height + self.shapes[0] = copy_block.shapes[0] + if sprite_list is not None: + self.spr = sprites.Sprite(sprite_list, x, y, self.shapes[0]) + self.spr._margins = copy_block.spr._margins[:] + if len(copy_block.shapes) > 1: + self.shapes[1] = copy_block.shapes[1] + self.docks = copy_block.docks[:] + else: + if self.expandable() and self.type == 'block': + self.svg.set_show(True) + + self._make_block(self.svg) + + if sprite_list is not None: + self.spr = sprites.Sprite(sprite_list, x, y, self.shapes[0]) + self._set_margins() + + self._set_label_attributes() + if (self.name == 'number' or self.name == 'string') and \ + len(self.values) > 0: + for i, v in enumerate(self.values): + if v is not None: + if self.name == 'number': + self._set_labels(i, + str(v).replace('.', self.block_list.decimal_point)) + else: + self._set_labels(i, str(v)) + elif self.type == 'block' and self.name in CONSTANTS: + self._set_labels(0, block_names[self.name][0] + ' = ' + \ + str(CONSTANTS[self.name])) + + elif self.name in block_names: + for i, n in enumerate(block_names[self.name]): + self._set_labels(i, n) + + if copy_block is None and self.spr is not None: + if self.spr.label_width() > self.spr.label_safe_width(): + self.resize() + + def _set_margins(self): + if self.spr is None: + return + self.spr.set_margins(self.svg.margins[0], self.svg.margins[1], + self.svg.margins[2], self.svg.margins[3]) + + def _set_label_attributes(self): + if self.spr is None: + return + if self.name in content_blocks: + n = len(self.values) + if n == 0: + n = 1 # Force a scale to be set, even if there is no value. + else: + if self.name in block_names: + n = len(block_names[self.name]) + else: + debug_output('WARNING: unknown block name %s' % (self.name)) + n = 0 + for i in range(n): + if self.name in block_styles['compare-porch-style']: + self.spr.set_label_attributes(int(self._font_size[0] + 0.5), + True, 'center', 'bottom', i) + elif self.name in block_styles['number-style-porch']: + self.spr.set_label_attributes(int(self._font_size[0] + 0.5), + True, 'right', 'bottom', i) + + elif self.name in block_styles['flow-style-boolean'] or \ + self.name in block_styles['flow-style-else']: + self.spr.set_label_attributes(int(self._font_size[0] + 0.5), + True, 'left', 'middle', 0) + self.spr.set_label_attributes(int(self._font_size[1] + 0.5), + True, 'right', 'top', 1) + self.spr.set_label_attributes(int(self._font_size[1] + 0.5), + True, 'right', 'bottom', 2) + elif i == 1: # top + self.spr.set_label_attributes(int(self._font_size[1] + 0.5), + True, 'right', 'top', i) + elif i == 2: # bottom + self.spr.set_label_attributes(int(self._font_size[1] + 0.5), + True, 'right', 'bottom', i) + else: + self.spr.set_label_attributes(int(self._font_size[0] + 0.5), + True, 'center', 'middle', i) + + def _set_labels(self, i, label): + if self.spr is None: + return + self.spr.set_label(label, i) + + def _make_block(self, svg): + self._left = 0 + self._top = 0 + self._right = 0 + self._bottom = 0 + self.svg.set_stroke_width(STANDARD_STROKE_WIDTH) + self.svg.clear_docks() + for k in block_styles.keys(): + if self.name in block_styles[k]: + if type(self.block_methods[k]) == type([]): + self.block_methods[k][0](svg, self.block_methods[k][1], + self.block_methods[k][2]) + else: + self.block_methods[k](svg) + return + error_output('block type not found %s' % (self.name)) + self.block_methods['basic-style'](svg) + + def _set_colors(self, svg): + if self._custom_colors: + self.svg.set_colors(self.colors) + return + if self.name in BOX_COLORS: + self.colors = BOX_COLORS[self.name] + elif self.name in special_block_colors: + self.colors = special_block_colors[self.name] + else: + for p in range(len(palette_blocks)): + if self.name in palette_blocks[p]: + self.colors = block_colors[p] + self.svg.set_colors(self.colors) + + def _make_basic_style(self, svg, extend_x=0, extend_y=0): + self.svg.expand(self.dx + self.ex + extend_x, self.ey + extend_y) + self._make_block_graphics(svg, self.svg.basic_block) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], ['flow', + False, self.svg.docks[1][0], self.svg.docks[1][1]]] + + def _make_blank_style(self, svg, extend_x=0, extend_y=0): + self.svg.expand(self.dx + self.ex + extend_x, self.ey + extend_y) + self.svg.set_slot(False) + self.svg.set_tab(False) + self.svg.set_tail(False) + self._make_block_graphics(svg, self.svg.basic_block) + self.docks = [] + + def _make_basic_style_head(self, svg): + self.svg.expand(10 + self.dx + self.ex, self.ey) + self.svg.set_slot(False) + self.svg.set_cap(True) + self._make_block_graphics(svg, self.svg.basic_block) + self.docks = [['unavailable', False, 0, 0], + ['flow', False, self.svg.docks[0][0], + self.svg.docks[0][1]]] + + def _make_basic_style_head_1arg(self, svg): + self.svg.expand(10 + self.dx + self.ex, self.ey) + self.svg.set_innie([True]) + self.svg.set_slot(False) + self.svg.set_cap(True) + self._make_block_graphics(svg, self.svg.basic_block) + self.docks = [['unavailable', False, 0, 0], + ['string', False, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['flow', False, self.svg.docks[1][0], + self.svg.docks[1][1]]] + + def _make_basic_style_tail(self, svg): + self.svg.expand(10 + self.dx + self.ex, self.ey) + self.svg.set_tab(False) + self.svg.set_tail(True) + self._make_block_graphics(svg, self.svg.basic_block) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['unavailable', False, 0, 0]] + + def _make_basic_style_1arg(self, svg): + self.svg.expand(10 + self.dx + self.ex, self.ey) + self.svg.set_innie([True]) + self._make_block_graphics(svg, self.svg.basic_block) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['number', False, self.svg.docks[1][0], + self.svg.docks[1][1]], + ['flow', False, self.svg.docks[2][0], + self.svg.docks[2][1]]] + + def _make_basic_style_2arg(self, svg): + self.svg.expand(10 + self.dx + self.ex, self.ey) + self.svg.set_innie([True, True]) + self._make_block_graphics(svg, self.svg.basic_block) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['number', False, self.svg.docks[1][0], + self.svg.docks[1][1]], + ['number', False, self.svg.docks[2][0], + self.svg.docks[2][1]], + ['flow', False, self.svg.docks[3][0], + self.svg.docks[3][1]]] + + def _make_basic_style_3arg(self, svg): + self.svg.expand(10 + self.dx + self.ex, self.ey) + self.svg.set_innie([True, True, True]) + self._make_block_graphics(svg, self.svg.basic_block) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['number', False, self.svg.docks[1][0], + self.svg.docks[1][1]], + ['number', False, self.svg.docks[2][0], + self.svg.docks[2][1]], + ['number', False, self.svg.docks[3][0], + self.svg.docks[3][1]], + ['flow', False, self.svg.docks[4][0], + self.svg.docks[4][1]]] + + def _make_basic_style_var_arg(self, svg): + self.svg.expand(10 + self.dx + self.ex, self.ey) + innie = [True] + for i in range(self._ei): + innie.append(True) + self.svg.set_innie(innie) + self._make_block_graphics(svg, self.svg.basic_block) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['number', False, self.svg.docks[1][0], + self.svg.docks[1][1]]] + for i in range(self._ei): + self.docks.append(['number', False, self.svg.docks[i + 2][0], + self.svg.docks[i + 2][1]]) + self.docks.append(['flow', False, self.svg.docks[self._ei + 2][0], + self.svg.docks[self._ei + 2][1]]) + + def _make_bullet_style(self, svg): + self.svg.expand(10 + self.dx + self.ex, self.ey) + innie = [True, True] + for i in range(self._ei): + innie.append(True) + self.svg.set_innie(innie) + self._make_block_graphics(svg, self.svg.basic_block) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['string', False, self.svg.docks[1][0], + self.svg.docks[1][1], '['], + ['string', False, self.svg.docks[2][0], + self.svg.docks[2][1]]] + for i in range(self._ei): + self.docks.append(['string', False, self.svg.docks[i + 3][0], + self.svg.docks[i + 3][1]]) + self.docks.append(['flow', False, self.svg.docks[self._ei + 3][0], + self.svg.docks[self._ei + 3][1], ']']) + + def _make_box_style(self, svg): + self.svg.expand(60 + self.dx + self.ex, self.ey) + self._make_block_graphics(svg, self.svg.basic_box) + self.docks = [['number', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['unavailable', False, 0, 0]] + + def _make_media_style(self, svg): + self.svg.expand(40 + self.dx + self.ex, 10 + self.ey) + self._make_block_graphics(svg, self.svg.basic_box) + self.docks = [['number', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['unavailable', False, 0, 0]] + + def _make_number_style(self, svg): + self.svg.expand(self.dx + self.ex, self.ey) + self.svg.set_innie([True, True]) + self.svg.set_outie(True) + self.svg.set_tab(False) + self.svg.set_slot(False) + self._make_block_graphics(svg, self.svg.basic_block) + """ + NOTE: The "outie" is added last, so the dock order in NUMBER_STYLE + blocks needs to be modified. + """ + self.docks = [['number', True, self.svg.docks[2][0], + self.svg.docks[2][1]], + ['number', False, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['number', False, self.svg.docks[1][0], + self.svg.docks[1][1]]] + + def _make_number_style_var_arg(self, svg): + self.svg.expand(self.dx + self.ex, self.ey) + innie = [True] + for i in range(self._ei + 1): + innie.append(True) + self.svg.set_innie(innie) + self.svg.set_outie(True) + self.svg.set_tab(False) + self.svg.set_slot(False) + self._make_block_graphics(svg, self.svg.basic_block) + self.docks = [['number', True, self.svg.docks[2 + self._ei][0], + self.svg.docks[2 + self._ei][1]], + ['number', False, self.svg.docks[0][0], + self.svg.docks[0][1]]] + for i in range(self._ei + 1): + self.docks.append(['number', False, self.svg.docks[i + 1][0], + self.svg.docks[i + 1][1]]) + self.docks.append(['unavailable', False, 0, 0]) + + def _make_number_style_block(self, svg): + self.svg.expand(self.dx + self.ex, self.ey) + self.svg.set_innie([True, True]) + self.svg.set_outie(True) + self.svg.set_tab(False) + self.svg.set_slot(False) + self._make_block_graphics(svg, self.svg.basic_block) + self.docks = [['number', True, self.svg.docks[2][0], + self.svg.docks[2][1], '('], + ['number', False, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['number', False, self.svg.docks[1][0], + self.svg.docks[1][1]], + ['unavailable', False, 0, 0, ')']] + + def _make_number_style_1arg(self, svg): + self.svg.expand(self.dx + self.ex, self.ey) + self.svg.set_innie([True]) + self.svg.set_outie(True) + self.svg.set_tab(False) + self.svg.set_slot(False) + self._make_block_graphics(svg, self.svg.basic_block) + self.docks = [['number', True, self.svg.docks[1][0], + self.svg.docks[1][1]], + ['number', False, self.svg.docks[0][0], + self.svg.docks[0][1]]] + + def _make_number_style_1strarg(self, svg): + self.svg.expand(self.dx + self.ex, self.ey) + self.svg.set_innie([True]) + self.svg.set_outie(True) + self.svg.set_tab(False) + self.svg.set_slot(False) + self._make_block_graphics(svg, self.svg.basic_block) + self.docks = [['number', True, self.svg.docks[1][0], + self.svg.docks[1][1]], + ['string', False, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['unavailable', False, 0, 0]] + + def _make_number_style_porch(self, svg): + self.svg.expand(self.dx + self.ex, self.ey) + self.svg.set_innie([True, True]) + self.svg.set_outie(True) + self.svg.set_tab(False) + self.svg.set_slot(False) + self.svg.set_porch(True) + self._make_block_graphics(svg, self.svg.basic_block) + self.docks = [['number', True, self.svg.docks[2][0], + self.svg.docks[2][1]], + ['number', False, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['number', False, self.svg.docks[1][0], + self.svg.docks[1][1]]] + + def _make_compare_style(self, svg): + self.svg.expand(10 + self.dx + self.ex, self.ey) + self._make_block_graphics(svg, self.svg.boolean_compare) + self.docks = [['bool', True, self.svg.docks[0][0], + self.svg.docks[0][1], '('], + ['number', False, self.svg.docks[1][0], + self.svg.docks[1][1]], + ['number', False, self.svg.docks[2][0], + self.svg.docks[2][1]], + ['unavailable', False, 0, 0, ')']] + + def _make_compare_porch_style(self, svg): + self.svg.set_porch(True) + self._make_compare_style(svg) + + def _make_boolean_style(self, svg): + self.svg.expand(10 + self.dx + self.ex, self.ey) + self._make_block_graphics(svg, self.svg.boolean_and_or) + self.docks = [['bool', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['bool', False, self.svg.docks[1][0], + self.svg.docks[1][1]], + ['bool', False, self.svg.docks[2][0], + self.svg.docks[2][1]]] + + def _make_not_style(self, svg): + self.svg.expand(15 + self.dx + self.ex, self.ey) + self._make_block_graphics(svg, self.svg.boolean_not) + self.docks = [['bool', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['bool', False, self.svg.docks[1][0], + self.svg.docks[1][1]]] + + def _make_flow_style(self, svg): + self.svg.expand(10 + self.dx + self.ex, self.ey) + self.svg.set_slot(True) + self.svg.set_tab(True) + self._make_block_graphics(svg, self.svg.basic_flow) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['flow', False, self.svg.docks[1][0], + self.svg.docks[1][1], '['], + ['flow', False, self.svg.docks[2][0], + self.svg.docks[2][1], ']']] + + def _make_flow_style_tail(self, svg): + self.svg.expand(10 + self.dx + self.ex, self.ey) + self.svg.set_slot(True) + self.svg.set_tab(False) + self._make_block_graphics(svg, self.svg.basic_flow) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['flow', False, self.svg.docks[1][0], + self.svg.docks[1][1]]] + + def _make_flow_style_1arg(self, svg): + self.svg.expand(self.dx + self.ex, self.ey) + self.svg.set_slot(True) + self.svg.set_tab(True) + self.svg.set_innie([True]) + self._make_block_graphics(svg, self.svg.basic_flow) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['number', False, self.svg.docks[1][0], + self.svg.docks[1][1]], + ['flow', False, self.svg.docks[2][0], + self.svg.docks[2][1], '['], + ['flow', False, self.svg.docks[3][0], + self.svg.docks[3][1], ']']] + + def _make_flow_style_boolean(self, svg): + self.svg.expand(self.dx + self.ex, self.ey) + self.svg.set_slot(True) + self.svg.set_tab(True) + self.svg.set_boolean(True) + self._make_block_graphics(svg, self.svg.basic_flow) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['bool', False, self.svg.docks[1][0], + self.svg.docks[1][1]], + ['flow', False, self.svg.docks[2][0], + self.svg.docks[2][1], '['], + ['flow', False, self.svg.docks[3][0], + self.svg.docks[3][1], ']']] + + def _make_flow_style_else(self, svg): + self.svg.expand(self.dx + self.ex, self.ey) + self.svg.set_slot(True) + self.svg.set_tab(True) + self.svg.set_else(True) + self.svg.set_boolean(True) + self._make_block_graphics(svg, self.svg.basic_flow) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['bool', False, self.svg.docks[1][0], + self.svg.docks[1][1]], + ['flow', False, self.svg.docks[3][0], + self.svg.docks[3][1], '['], + ['flow', False, self.svg.docks[2][0], + self.svg.docks[2][1], ']['], + ['flow', False, self.svg.docks[4][0], + self.svg.docks[4][1], ']']] + + def _make_collapsible_style_top(self, svg, arm=True, label=True): + self.svg.expand(self.dx + self.ex, self.ey) + self.svg.set_arm(arm) + self.svg.set_show(not arm) + self._make_block_graphics(svg, self.svg.sandwich_top, label) + if label: + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['number', False, self.svg.docks[1][0], + self.svg.docks[1][1]], + ['flow', False, self.svg.docks[2][0], + self.svg.docks[2][1]]] + else: + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['flow', False, self.svg.docks[1][0], + self.svg.docks[1][1]]] + + def _make_collapsible_style_bottom(self, svg): + self.svg.expand(self.dx + self.ex, self.ey) + self._make_block_graphics(svg, self.svg.sandwich_bottom) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], ['flow', False, + self.svg.docks[1][0], self.svg.docks[1][1]]] + + def _make_invisible_style(self, svg): + self._make_block_graphics(svg, self.svg.invisible) + # force dock positions to be the same + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], ['flow', False, + self.svg.docks[0][0], self.svg.docks[0][1]]] + + # Depreciated block styles + + def _make_portfolio_style_2x2(self, svg): + self.svg.expand(30 + self.dx + self.ex, 10 + self.ey) + self.svg.set_slot(True) + self.svg.set_tab(True) + self.svg.set_innie([True, True, False, True]) + self._make_block_graphics(svg, self.svg.portfolio) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['string', False, self.svg.docks[6][0], + self.svg.docks[6][1]], + ['media', False, self.svg.docks[5][0], + self.svg.docks[5][1]], + ['media', False, self.svg.docks[1][0], + self.svg.docks[1][1]], + ['media', False, self.svg.docks[4][0], + self.svg.docks[4][1]], + ['media', False, self.svg.docks[2][0], + self.svg.docks[2][1]], + ['flow', False, self.svg.docks[3][0], + self.svg.docks[3][1]]] + + def _make_portfolio_style_2x1(self, svg): + self.svg.expand(30 + self.dx + self.ex, 10 + self.ey) + self.svg.set_slot(True) + self.svg.set_tab(True) + self.svg.set_innie([True, True]) + self._make_block_graphics(svg, self.svg.portfolio) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['string', False, self.svg.docks[4][0], + self.svg.docks[4][1]], + ['media', False, self.svg.docks[3][0], + self.svg.docks[3][1]], + ['media', False, self.svg.docks[1][0], + self.svg.docks[1][1]], + ['flow', False, self.svg.docks[2][0], + self.svg.docks[2][1]]] + + def _make_portfolio_style_1x2(self, svg): + self.svg.expand(30 + self.dx + self.ex, 15 + self.ey) + self.svg.set_slot(True) + self.svg.set_tab(True) + self.svg.set_innie([True, True, False, True]) + self.svg.set_draw_innies(False) + self._make_block_graphics(svg, self.svg.portfolio) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['string', False, self.svg.docks[4][0], + self.svg.docks[4][1]], + ['media', False, self.svg.docks[3][0], + self.svg.docks[3][1]], + ['media', False, self.svg.docks[2][0], + self.svg.docks[2][1]], + ['flow', False, self.svg.docks[1][0], + self.svg.docks[1][1]]] + + def _make_portfolio_style_1x1(self, svg): + self.svg.expand(30 + self.dx + self.ex, 15 + self.ey) + self.svg.set_slot(True) + self.svg.set_tab(True) + self.svg.set_innie([True, True]) + self.svg.set_draw_innies(False) + self._make_block_graphics(svg, self.svg.portfolio) + self.docks = [['flow', True, self.svg.docks[0][0], + self.svg.docks[0][1]], + ['string', False, self.svg.docks[3][0], + self.svg.docks[3][1]], + ['media', False, self.svg.docks[2][0], + self.svg.docks[2][1]], + ['flow', False, self.svg.docks[1][0], + self.svg.docks[1][1]]] + + def _make_block_graphics(self, svg, function, arg=None): + self._set_colors(svg) + self.svg.set_gradient(True, GRADIENT_COLOR) + if arg is None: + self.shapes[0] = svg_str_to_pixbuf(function()) + else: + self.shapes[0] = svg_str_to_pixbuf(function(arg)) + self.width = self.svg.get_width() + self.height = self.svg.get_height() + self.svg.set_gradient(False) + if arg is None: + self.shapes[1] = svg_str_to_pixbuf(function()) + else: + self.shapes[1] = svg_str_to_pixbuf(function(arg)) diff --git a/TurtleArt/tacanvas.py b/TurtleArt/tacanvas.py new file mode 100644 index 0000000..246fe35 --- /dev/null +++ b/TurtleArt/tacanvas.py @@ -0,0 +1,777 @@ +#Copyright (c) 2007-8, Playful Invention Company. +#Copyright (c) 2008-11, Walter Bender +#Copyright (c) 2011 Collabora Ltd. <http://www.collabora.co.uk/> + +#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 gtk +from math import sin, cos, atan, pi, sqrt +import os +import pango +import cairo +import pangocairo +import base64 +from gettext import gettext as _ + +from sprites import Sprite +from tasprite_factory import SVG +from tautils import image_to_base64, get_path, data_to_string, round_int, \ + debug_output +from taconstants import BLACK, WHITE + + +def wrap100(n): + ''' A variant on mod... 101 -> 99; 199 -> 1 ''' + n = int(n) + n %= 200 + if n > 99: + n = 199 - n + return n + + +def calc_shade(c, s, invert=False): + ''' Convert a color to the current shade (lightness/darkness). ''' + # Assumes 16 bit input values + if invert: + if s < 0: + return int(c / (1 + s * 0.8)) + return int((c - 65536 * s * 0.9) / (1 - (s * 0.9))) + else: + if s < 0: + return int(c * (1 + s * 0.8)) + return int(c + (65536 - c) * s * 0.9) + + +def calc_gray(c, g, invert=False): + ''' Gray is a psuedo saturation calculation. ''' + # Assumes 16 bit input values + if g == 100: + return c + if invert: + if g == 0: + return c + else: + return int(((c * 100) - (32768 * (100 - g))) / g) + else: + return int(((c * g) + (32768 * (100 - g))) / 100) + + +colors = {} +DEGTOR = pi / 180. +RTODEG = 180. / pi + +COLOR_TABLE = ( + 0xFF0000, 0xFF0D00, 0xFF1A00, 0xFF2600, 0xFF3300, + 0xFF4000, 0xFF4D00, 0xFF5900, 0xFF6600, 0xFF7300, + 0xFF8000, 0xFF8C00, 0xFF9900, 0xFFA600, 0xFFB300, + 0xFFBF00, 0xFFCC00, 0xFFD900, 0xFFE600, 0xFFF200, + 0xFFFF00, 0xE6FF00, 0xCCFF00, 0xB3FF00, 0x99FF00, + 0x80FF00, 0x66FF00, 0x4DFF00, 0x33FF00, 0x1AFF00, + 0x00FF00, 0x00FF0D, 0x00FF1A, 0x00FF26, 0x00FF33, + 0x00FF40, 0x00FF4D, 0x00FF59, 0x00FF66, 0x00FF73, + 0x00FF80, 0x00FF8C, 0x00FF99, 0x00FFA6, 0x00FFB3, + 0x00FFBF, 0x00FFCC, 0x00FFD9, 0x00FFE6, 0x00FFF2, + 0x00FFFF, 0x00F2FF, 0x00E6FF, 0x00D9FF, 0x00CCFF, + 0x00BFFF, 0x00B3FF, 0x00A6FF, 0x0099FF, 0x008CFF, + 0x0080FF, 0x0073FF, 0x0066FF, 0x0059FF, 0x004DFF, + 0x0040FF, 0x0033FF, 0x0026FF, 0x001AFF, 0x000DFF, + 0x0000FF, 0x0D00FF, 0x1A00FF, 0x2600FF, 0x3300FF, + 0x4000FF, 0x4D00FF, 0x5900FF, 0x6600FF, 0x7300FF, + 0x8000FF, 0x8C00FF, 0x9900FF, 0xA600FF, 0xB300FF, + 0xBF00FF, 0xCC00FF, 0xD900FF, 0xE600FF, 0xF200FF, + 0xFF00FF, 0xFF00E6, 0xFF00CC, 0xFF00B3, 0xFF0099, + 0xFF0080, 0xFF0066, 0xFF004D, 0xFF0033, 0xFF001A) + + +class TurtleGraphics: + ''' A class for the Turtle graphics canvas ''' + + def __init__(self, tw, width, height): + ''' Create a sprite to hold the canvas. ''' + self.tw = tw + self.width = width + self.height = height + + # Build a cairo.Context from a cairo.XlibSurface + self.canvas = cairo.Context(self.tw.turtle_canvas) + cr = gtk.gdk.CairoContext(self.canvas) + cr.set_line_cap(1) # Set the line cap to be round + self.cr_svg = None # Surface used for saving to SVG + self.cx = 0 + self.cy = 0 + self.fgrgb = [255, 0, 0] + self.bgrgb = [255, 255, 255] + self.textsize = 48 # deprecated + self.shade = 0 + self.pendown = False + self.xcor = 0 + self.ycor = 0 + self.heading = 0 + self.pensize = 5 + self.color = 0 + self.gray = 100 + self.fill = False + self.poly_points = [] + + def setup_svg_surface(self): + ''' Set up a surface for saving to SVG ''' + if self.tw.running_sugar: + svg_surface = cairo.SVGSurface( + os.path.join(get_path(self.tw.activity, 'instance'), + 'output.svg'), self.width, self.height) + else: + svg_surface = cairo.SVGSurface( + os.path.join(os.getcwd(), 'output.svg'), + self.width, self.height) + self.cr_svg = cairo.Context(svg_surface) + self.cr_svg.set_line_cap(1) # Set the line cap to be round + + def start_fill(self): + ''' Start accumulating points of a polygon to fill. ''' + self.fill = True + self.poly_points = [] + + def stop_fill(self): + ''' Fill the polygon. ''' + self.fill = False + if len(self.poly_points) == 0: + return + self.fill_polygon(self.poly_points) + if self.tw.sharing(): + shared_poly_points = [] + for p in self.poly_points: + shared_poly_points.append((self.screen_to_turtle_coordinates( + p[0], p[1]))) + event = 'F|%s' % (data_to_string([self._get_my_nick(), + shared_poly_points])) + self.tw.send_event(event) + self.poly_points = [] + + def fill_polygon(self, poly_points): + ''' Draw the polygon... ''' + def _fill_polygon(cr, poly_points): + cr.new_path() + for i, p in enumerate(poly_points): + if p[0] == 'move': + cr.move_to(p[1], p[2]) + elif p[0] == 'rarc': + cr.arc(p[1], p[2], p[3], p[4], p[5]) + elif p[0] == 'larc': + cr.arc_negative(p[1], p[2], p[3], p[4], p[5]) + else: # line + cr.line_to(p[1], p[2]) + cr.close_path() + cr.fill() + + _fill_polygon(self.canvas, poly_points) + self.inval() + if self.cr_svg is not None: + _fill_polygon(self.cr_svg, poly_points) + + def clearscreen(self, share=True): + '''Clear the canvas and reset most graphics attributes to defaults.''' + + def _clearscreen(cr): + cr.move_to(0, 0) + self.bgrgb = [255, 255, 255] + cr.set_source_rgb(self.bgrgb[0] / 255., + self.bgrgb[1] / 255., + self.bgrgb[2] / 255.) + cr.rectangle(0, 0, self.width * 2, self.height * 2) + cr.fill() + + _clearscreen(self.canvas) + self.inval() + if self.cr_svg is not None: + _clearscreen(self.cr_svg) + + self.setpensize(5, share) + self.setgray(100, share) + self.setcolor(0, share) + self.setshade(50, share) + self.fill = False + self.poly_points = [] + for turtle_key in iter(self.tw.turtles.dict): + # Don't reset remote turtles + if not self.tw.remote_turtle(turtle_key): + self.set_turtle(turtle_key) + self.tw.active_turtle.set_color(0) + self.tw.active_turtle.set_shade(50) + self.tw.active_turtle.set_gray(100) + self.tw.active_turtle.set_pen_size(5) + self.tw.active_turtle.reset_shapes() + self.seth(0, share) + self.setpen(False, share) + self.setxy(0, 0, share) + self.setpen(True, share) + self.tw.active_turtle.hide() + self.set_turtle(self.tw.default_turtle_name) + + def forward(self, n, share=True): + ''' Move the turtle forward.''' + nn = n * self.tw.coord_scale + self.canvas.set_source_rgb(self.fgrgb[0] / 255., self.fgrgb[1] / 255., + self.fgrgb[2] / 255.) + if self.cr_svg is not None: + debug_output('in forward', True) + self.cr_svg.set_source_rgb(self.fgrgb[0] / 255., + self.fgrgb[1] / 255., self.fgrgb[2] / 255.) + oldx, oldy = self.xcor, self.ycor + try: + self.xcor += nn * sin(self.heading * DEGTOR) + self.ycor += nn * cos(self.heading * DEGTOR) + except TypeError, ValueError: + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + if self.pendown: + self.draw_line(oldx, oldy, self.xcor, self.ycor) + + self.move_turtle() + + if self.tw.sharing() and share: + event = 'f|%s' % (data_to_string([self._get_my_nick(), int(n)])) + self.tw.send_event(event) + self.inval() + + def seth(self, n, share=True): + ''' Set the turtle heading. ''' + try: + self.heading = n + except TypeError, ValueError: + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + self.heading %= 360 + self.turn_turtle() + if self.tw.sharing() and share: + event = 'r|%s' % (data_to_string([self._get_my_nick(), + round_int(self.heading)])) + self.tw.send_event(event) + + def right(self, n, share=True): + ''' Rotate turtle clockwise ''' + try: + self.heading += n + except TypeError, ValueError: + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + self.heading %= 360 + self.turn_turtle() + if self.tw.sharing() and share: + event = 'r|%s' % (data_to_string([self._get_my_nick(), + round_int(self.heading)])) + self.tw.send_event(event) + + def arc(self, a, r, share=True): + ''' Draw an arc ''' + self.canvas.set_source_rgb(self.fgrgb[0] / 255., self.fgrgb[1] / 255., + self.fgrgb[2] / 255.) + if self.cr_svg is not None: + self.cr_svg.set_source_rgb(self.fgrgb[0] / 255., + self.fgrgb[1] / 255., self.fgrgb[2] / 255.) + try: + if a < 0: + self.larc(-a, r) + else: + self.rarc(a, r) + except TypeError, ValueError: + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + self.move_turtle() + if self.tw.sharing() and share: + event = 'a|%s' % (data_to_string([self._get_my_nick(), + [round_int(a), round_int(r)]])) + self.tw.send_event(event) + + def rarc(self, a, r): + ''' draw a clockwise arc ''' + r *= self.tw.coord_scale + if r < 0: + r = -r + a = -a + s = 0 + else: + s = 1 + oldx, oldy = self.xcor, self.ycor + cx = self.xcor + r * cos(self.heading * DEGTOR) + cy = self.ycor - r * sin(self.heading * DEGTOR) + if self.pendown: + x, y = self.turtle_to_screen_coordinates(cx, cy) + + def _rarc(cr, x, y, r, a, h): + cr.arc(x, y, r, (h - 180) * DEGTOR, (h - 180 + a) * DEGTOR) + cr.stroke() + + _rarc(self.canvas, x, y, r, a, self.heading) + self.inval() + if self.cr_svg is not None: + _rarc(self.cr_svg, x, y, r, a, self.heading) + + if self.fill: + if self.poly_points == []: + self.poly_points.append(('move', x, y)) + self.poly_points.append(('rarc', x, y, r, + (self.heading - 180) * DEGTOR, + (self.heading - 180 + a) * DEGTOR)) + + self.right(a, False) + self.xcor = cx - r * cos(self.heading * DEGTOR) + self.ycor = cy + r * sin(self.heading * DEGTOR) + + def larc(self, a, r): + ''' draw a counter-clockwise arc ''' + r *= self.tw.coord_scale + if r < 0: + r = -r + a = -a + s = 1 + else: + s = 0 + oldx, oldy = self.xcor, self.ycor + cx = self.xcor - r * cos(self.heading * DEGTOR) + cy = self.ycor + r * sin(self.heading * DEGTOR) + if self.pendown: + x, y = self.turtle_to_screen_coordinates(cx, cy) + + def _larc(cr, x, y, r, a, h): + cr.arc_negative(x, y, r, h * DEGTOR, (h - a) * DEGTOR) + cr.stroke() + + _larc(self.canvas, x, y, r, a, self.heading) + self.inval() + if self.cr_svg is not None: + _larc(self.cr_svg, x, y, r, a, self.heading) + + if self.fill: + if self.poly_points == []: + self.poly_points.append(('move', x, y)) + self.poly_points.append(('larc', x, y, r, + (self.heading) * DEGTOR, + (self.heading - a) * DEGTOR)) + + self.right(-a, False) + self.xcor = cx + r * cos(self.heading * DEGTOR) + self.ycor = cy - r * sin(self.heading * DEGTOR) + + def setxy(self, x, y, share=True, pendown=True): + ''' Move turtle to position x,y ''' + oldx, oldy = self.xcor, self.ycor + x *= self.tw.coord_scale + y *= self.tw.coord_scale + try: + self.xcor, self.ycor = x, y + except TypeError, ValueError: + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + + if self.pendown and pendown: + self.canvas.set_source_rgb(self.fgrgb[0] / 255., + self.fgrgb[1] / 255., + self.fgrgb[2] / 255.) + if self.cr_svg is not None: + self.cr_svg.set_source_rgb(self.fgrgb[0] / 255., + self.fgrgb[1] / 255., + self.fgrgb[2] / 255.) + self.draw_line(oldx, oldy, self.xcor, self.ycor) + self.inval() + self.move_turtle() + + if self.tw.sharing() and share: + event = 'x|%s' % (data_to_string([self._get_my_nick(), + [round_int(x), round_int(y)]])) + self.tw.send_event(event) + + def setpensize(self, ps, share=True): + ''' Set the pen size ''' + try: + if ps < 0: + ps = 0 + self.pensize = ps + except TypeError, ValueError: + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + self.tw.active_turtle.set_pen_size(ps) + self.canvas.set_line_width(ps) + if self.cr_svg is not None: + self.cr_svg.set_line_width(ps) + if self.tw.sharing() and share: + event = 'w|%s' % (data_to_string([self._get_my_nick(), + round_int(ps)])) + self.tw.send_event(event) + + def setcolor(self, c, share=True): + ''' Set the pen color ''' + try: + self.color = c + except TypeError, ValueError: + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + self.tw.active_turtle.set_color(c) + self.set_fgcolor() + if self.tw.sharing() and share: + event = 'c|%s' % (data_to_string([self._get_my_nick(), + round_int(c)])) + self.tw.send_event(event) + + def setgray(self, g, share=True): + ''' Set the gray level ''' + try: + self.gray = g + except TypeError, ValueError: + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + if self.gray < 0: + self.gray = 0 + if self.gray > 100: + self.gray = 100 + self.set_fgcolor() + self.tw.active_turtle.set_gray(self.gray) + if self.tw.sharing() and share: + event = 'g|%s' % (data_to_string([self._get_my_nick(), + round_int(self.gray)])) + self.tw.send_event(event) + + def set_textcolor(self): + ''' Deprecated: Set the text color to foreground color. ''' + return + + def settextcolor(self, c): # deprecated + ''' Set the text color ''' + return + + def settextsize(self, c): # deprecated + ''' Set the text size ''' + try: + self.tw.textsize = c + except TypeError, ValueError: + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + + def setshade(self, s, share=True): + ''' Set the color shade ''' + try: + self.shade = s + except TypeError, ValueError: + debug_output('bad value sent to %s' % (__name__), + self.tw.running_sugar) + return + self.tw.active_turtle.set_shade(s) + self.set_fgcolor() + if self.tw.sharing() and share: + event = 's|%s' % (data_to_string([self._get_my_nick(), + round_int(s)])) + self.tw.send_event(event) + + def fillscreen(self, c, s): + ''' Fill screen with color/shade and reset to defaults ''' + oldc, olds = self.color, self.shade + self.setcolor(c, False) + self.setshade(s, False) + self.bgrgb = self.fgrgb[:] + + def _fillscreen(cr, rgb, w, h): + cr.set_source_rgb(rgb[0] / 255., rgb[1] / 255., rgb[2] / 255.) + cr.rectangle(0, 0, w * 2, h * 2) + cr.fill() + + _fillscreen(self.canvas, self.fgrgb, self.width, self.height) + self.inval() + if self.cr_svg is not None: + _fillscreen(self.cr_svg, self.fgrgb, self.width, self.height) + self.setcolor(oldc, False) + self.setshade(olds, False) + self.fill = False + self.poly_points = [] + + def set_fgcolor(self): + ''' Set the foreground color ''' + if self.color == WHITE or self.shade == WHITE: + r = 0xFF00 + g = 0xFF00 + b = 0xFF00 + elif self.color == BLACK or self.shade == BLACK: + r = 0x0000 + g = 0x0000 + b = 0x0000 + else: + sh = (wrap100(self.shade) - 50) / 50.0 + rgb = COLOR_TABLE[wrap100(self.color)] + r = (rgb >> 8) & 0xff00 + r = calc_gray(r, self.gray) + r = calc_shade(r, sh) + g = rgb & 0xff00 + g = calc_gray(g, self.gray) + g = calc_shade(g, sh) + b = (rgb << 8) & 0xff00 + b = calc_gray(b, self.gray) + b = calc_shade(b, sh) + self.fgrgb = [r >> 8, g >> 8, b >> 8] + + def setpen(self, bool, share=True): + ''' Lower or raise the pen ''' + self.pendown = bool + self.tw.active_turtle.set_pen_state(bool) + if self.tw.sharing() and share: + event = 'p|%s' % (data_to_string([self._get_my_nick(), bool])) + self.tw.send_event(event) + + def draw_surface(self, surface, x, y, w, h): + ''' Draw a surface ''' + + def _draw_surface(cr, surface, x, y, w, h): + cc = gtk.gdk.CairoContext(cr) + cc.set_source_surface(surface, x, y) + cc.rectangle(x, y, w, h) + cc.fill() + + _draw_surface(self.canvas, surface, x, y, w, h) + self.inval() + if self.cr_svg is not None: + _draw_surface(self.cr_svg, surface, x, y, w, h) + + def draw_pixbuf(self, pixbuf, a, b, x, y, w, h, path, share=True): + ''' Draw a pixbuf ''' + + def _draw_pixbuf(cr, pixbuf, a, b, x, y, w, h, heading): + # Build a gtk.gdk.CairoContext from a cairo.Context to access + # the set_source_pixbuf attribute. + cc = gtk.gdk.CairoContext(cr) + cc.save() + # center the rotation on the center of the image + cc.translate(x + w / 2., y + h / 2.) + cc.rotate(heading * DEGTOR) + cc.translate(-x - w / 2., -y - h / 2.) + cc.set_source_pixbuf(pixbuf, x, y) + cc.rectangle(x, y, w, h) + cc.fill() + cc.restore() + + _draw_pixbuf(self.canvas, pixbuf, a, b, x, y, w, h, self.heading) + self.inval() + if self.cr_svg is not None: + _draw_pixbuf(self.cr_svg, pixbuf, a, b, x, y, w, h, self.heading) + if self.tw.sharing() and share: + if self.tw.running_sugar: + tmp_path = get_path(self.tw.activity, 'instance') + else: + tmp_path = '/tmp' + tmp_file = os.path.join(get_path(self.tw.activity, 'instance'), + 'tmpfile.png') + pixbuf.save(tmp_file, 'png', {'quality': '100'}) + data = image_to_base64(tmp_file, tmp_path) + height = pixbuf.get_height() + width = pixbuf.get_width() + x, y = self.screen_to_turtle_coordinates(x, y) + event = 'P|%s' % (data_to_string([self._get_my_nick(), + [round_int(a), round_int(b), + round_int(x), round_int(y), + round_int(w), round_int(h), + round_int(width), + round_int(height), + data]])) + self.tw.send_event(event) + os.remove(tmp_file) + + def draw_text(self, label, x, y, size, w, share=True): + ''' Draw text ''' + w *= self.tw.coord_scale + + def _draw_text(cr, label, x, y, size, w, scale, heading, rgb): + cc = pangocairo.CairoContext(cr) + pl = cc.create_layout() + fd = pango.FontDescription('Sans') + fd.set_size(int(size * scale) * pango.SCALE) + pl.set_font_description(fd) + if type(label) == str or type(label) == unicode: + pl.set_text(label.replace('\0', ' ')) + elif type(label) == float or type(label) == int: + pl.set_text(str(label)) + else: + pl.set_text(str(label)) + pl.set_width(int(w) * pango.SCALE) + cc.save() + cc.translate(x, y) + cc.rotate(heading * DEGTOR) + cr.set_source_rgb(rgb[0] / 255., rgb[1] / 255., rgb[2] / 255.) + cc.update_layout(pl) + cc.show_layout(pl) + cc.restore() + + _draw_text(self.canvas, label, x, y, size, w, self.tw.coord_scale, + self.heading, self.fgrgb) + self.inval() + if self.cr_svg is not None: # and self.pendown: + _draw_text(self.cr_svg, label, x, y, size, w, self.tw.coord_scale, + self.heading, self.fgrgb) + if self.tw.sharing() and share: + event = 'W|%s' % (data_to_string([self._get_my_nick(), + [label, round_int(x), + round_int(y), round_int(size), + round_int(w)]])) + self.tw.send_event(event) + + def turtle_to_screen_coordinates(self, x, y): + ''' The origin of turtle coordinates is the center of the screen ''' + return self.width / 2. + x, self.invert_y_coordinate(y) + + def screen_to_turtle_coordinates(self, x, y): + ''' The origin of the screen coordinates is the upper left corner ''' + return x - self.width / 2., self.invert_y_coordinate(y) + + def invert_y_coordinate(self, y): + ''' Positive y goes up in turtle coordinates, down in sceeen + coordinates ''' + return self.height / 2. - y + + def draw_line(self, x1, y1, x2, y2): + ''' Draw a line ''' + x1, y1 = self.turtle_to_screen_coordinates(x1, y1) + x2, y2 = self.turtle_to_screen_coordinates(x2, y2) + + def _draw_line(cr, x1, y1, x2, y2): + cr.move_to(x1, y1) + cr.line_to(x2, y2) + cr.stroke() + + _draw_line(self.canvas, x1, y1, x2, y2) + if self.cr_svg is not None: + _draw_line(self.cr_svg, x1, y1, x2, y2) + if self.fill: + if self.poly_points == []: + self.poly_points.append(('move', x1, y1)) + self.poly_points.append(('line', x2, y2)) + + def turn_turtle(self): + ''' Change the orientation of the turtle ''' + self.tw.active_turtle.set_heading(self.heading) + + def move_turtle(self): + ''' Move the turtle ''' + x, y = self.turtle_to_screen_coordinates(self.xcor, self.ycor) + if self.tw.interactive_mode: + self.tw.active_turtle.move( + (int(self.cx + x - self.tw.active_turtle.spr.rect.width / 2.), + int(self.cy + y - self.tw.active_turtle.spr.rect.height / 2.)) + ) + else: + self.tw.active_turtle.move((int(self.cx + x), int(self.cy + y))) + + def get_color_index(self, r, g, b, a=0): + ''' Find the closest palette entry to the rgb triplet ''' + if self.shade != 50 or self.gray != 100: + r <<= 8 + g <<= 8 + b <<= 8 + if self.shade != 50: + sh = (wrap100(self.shade) - 50) / 50. + r = calc_shade(r, sh, True) + g = calc_shade(g, sh, True) + b = calc_shade(b, sh, True) + if self.gray != 100: + r = calc_gray(r, self.gray, True) + g = calc_gray(g, self.gray, True) + b = calc_gray(b, self.gray, True) + r >>= 8 + g >>= 8 + b >>= 8 + min_distance = 1000000 + closest_color = -1 + for i, c in enumerate(COLOR_TABLE): + cr = int((c & 0xff0000) >> 16) + cg = int((c & 0x00ff00) >> 8) + cb = int((c & 0x0000ff)) + distance_squared = \ + ((cr - r) ** 2) + ((cg - g) ** 2) + ((cb - b) ** 2) + if distance_squared == 0: + return i + if distance_squared < min_distance: + min_distance = distance_squared + closest_color = i + return closest_color + + def get_pixel(self): + ''' Read the pixel at x, y ''' + if self.tw.interactive_mode: + x, y = self.turtle_to_screen_coordinates(self.xcor, self.ycor) + x = int(x) + y = int(y) + w = self.tw.turtle_canvas.get_width() + h = self.tw.turtle_canvas.get_height() + if x < 0 or x > (w - 1) or y < 0 or y > (h - 1): + return(-1, -1, -1, -1) + # create a new 1x1 cairo surface + cs = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1) + cr = cairo.Context(cs) + cr.set_source_surface(self.tw.turtle_canvas, -x, -y) + cr.rectangle(0, 0, 1, 1) + cr.set_operator(cairo.OPERATOR_SOURCE) + cr.fill() + cs.flush() # ensure all writing is done + pixels = cs.get_data() # Read the pixel + return (ord(pixels[2]), ord(pixels[1]), ord(pixels[0]), 0) + else: + return(-1, -1, -1, -1) + + def set_turtle(self, k, colors=None): + ''' Select the current turtle and associated pen status ''' + if k not in self.tw.turtles.dict: + # if it is a new turtle, start it in the center of the screen + self.tw.active_turtle = self.tw.turtles.get_turtle(k, True, colors) + self.seth(0, False) + self.setxy(0, 0, False, pendown=False) + self.tw.active_turtle.set_pen_state(True) + elif colors is not None: + self.tw.active_turtle = self.tw.turtles.get_turtle(k, False) + self.tw.active_turtle.set_turtle_colors(colors) + else: + self.tw.active_turtle = self.tw.turtles.get_turtle(k, False) + self.tw.active_turtle.show() + tx, ty = self.tw.active_turtle.get_xy() + self.xcor, self.ycor = self.screen_to_turtle_coordinates(tx, ty) + if self.tw.interactive_mode: + self.xcor += self.tw.active_turtle.spr.rect.width / 2. + self.ycor -= self.tw.active_turtle.spr.rect.height / 2. + self.heading = self.tw.active_turtle.get_heading() + self.setcolor(self.tw.active_turtle.get_color(), False) + self.setgray(self.tw.active_turtle.get_gray(), False) + self.setshade(self.tw.active_turtle.get_shade(), False) + self.setpensize(self.tw.active_turtle.get_pen_size(), False) + self.setpen(self.tw.active_turtle.get_pen_state(), False) + + def svg_close(self): + ''' Close current SVG graphic ''' + self.cr_svg.show_page() + + def svg_reset(self): + ''' Reset svg flags ''' + self.cr_svg = None + + def _get_my_nick(self): + return self.tw.nick + + def inval(self): + ''' Invalidate a region for gtk ''' + self.tw.inval_all() diff --git a/TurtleArt/tacollaboration.py b/TurtleArt/tacollaboration.py new file mode 100644 index 0000000..8316c7a --- /dev/null +++ b/TurtleArt/tacollaboration.py @@ -0,0 +1,419 @@ +#Copyright (c) 2011, Walter Bender +#Copyright (c) 2011 Collabora Ltd. <http://www.collabora.co.uk/> + +#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. + +from dbus.service import signal +from dbus.gobject_service import ExportedGObject +import telepathy + +import gtk +import base64 + +from TurtleArt.tautils import data_to_string, data_from_string, get_path, \ + base64_to_image, debug_output, error_output +from TurtleArt.taconstants import DEFAULT_TURTLE_COLORS + +try: + from sugar import profile + from sugar.presence import presenceservice + from sugar.presence.tubeconn import TubeConnection +except: + profile = None + from collaboration import presenceservice + from collaboration.tubeconn import TubeConnection + +SERVICE = 'org.laptop.TurtleArtActivity' +IFACE = SERVICE +PATH = '/org/laptop/TurtleArtActivity' + + +class Collaboration(): + def __init__(self, tw, activity): + """ A simplistic sharing model: the sharer is the master """ + self._tw = tw + self._tw.send_event = self.send_event + self._tw.remote_turtle_dictionary = {} + self._activity = activity + self._setup_dispatch_table() + + def setup(self): + # TODO: hand off role of master is sharer leaves + self.pservice = presenceservice.get_instance() + self.initiating = None # sharing (True) or joining (False) + + # Add my buddy object to the list + owner = self.pservice.get_owner() + self.owner = owner + self._tw.buddies.append(self.owner) + self._share = '' + self._activity.connect('shared', self._shared_cb) + self._activity.connect('joined', self._joined_cb) + + def _setup_dispatch_table(self): + self._processing_methods = { + 't': self._turtle_request, + 'T': self._receive_turtle_dict, + 'f': self._move_forward, + 'a': self._move_in_arc, + 'r': self._rotate_turtle, + 'x': self._setxy, + 'W': self._draw_text, + 'c': self._set_pen_color, + 'g': self._set_pen_gray_level, + 's': self._set_pen_shade, + 'w': self._set_pen_width, + 'p': self._set_pen_state, + 'F': self._fill_polygon, + 'P': self._draw_pixbuf + } + + def _shared_cb(self, activity): + self._shared_activity = self._activity._shared_activity + if self._shared_activity is None: + debug_output('Failed to share or join activity ... \ + _shared_activity is null in _shared_cb()', + self._tw.running_sugar) + return + + self._tw.set_sharing(True) + + self.initiating = True + self.waiting_for_turtles = False + self._tw.remote_turtle_dictionary = self._get_dictionary() + + debug_output('I am sharing...', self._tw.running_sugar) + + self.conn = self._shared_activity.telepathy_conn + self.tubes_chan = self._shared_activity.telepathy_tubes_chan + self.text_chan = self._shared_activity.telepathy_text_chan + + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal( + 'NewTube', self._new_tube_cb) + + debug_output('This is my activity: making a tube...', + self._tw.running_sugar) + + id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( + SERVICE, {}) + + def _joined_cb(self, activity): + self._shared_activity = self._activity._shared_activity + if self._shared_activity is None: + debug_output('Failed to share or join activity ... \ + _shared_activity is null in _shared_cb()', + self._tw.running_sugar) + return + + self._tw.set_sharing(True) + + self.initiating = False + self.conn = self._shared_activity.telepathy_conn + self.tubes_chan = self._shared_activity.telepathy_tubes_chan + self.text_chan = self._shared_activity.telepathy_text_chan + + # call back for "NewTube" signal + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal( + 'NewTube', self._new_tube_cb) + + debug_output('I am joining an activity: waiting for a tube...', + self._tw.running_sugar) + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes( + reply_handler=self._list_tubes_reply_cb, + error_handler=self._list_tubes_error_cb) + + # Joiner should request current state from sharer. + self.waiting_for_turtles = True + + def _list_tubes_reply_cb(self, tubes): + for tube_info in tubes: + self._new_tube_cb(*tube_info) + + def _list_tubes_error_cb(self, e): + error_output('ListTubes() failed: %s' % (e), self._tw.running_sugar) + + def _new_tube_cb(self, id, initiator, type, service, params, state): + """ Create a new tube. """ + debug_output('New tube: ID=%d initator=%d type=%d service=%s \ + params=%r state=%d' % (id, initiator, type, service, + params, state), self._tw.running_sugar) + + if (type == telepathy.TUBE_TYPE_DBUS and service == SERVICE): + if state == telepathy.TUBE_STATE_LOCAL_PENDING: + self.tubes_chan[ \ + telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(id) + + tube_conn = TubeConnection(self.conn, + self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES], id, \ + group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP]) + + # We'll use a chat tube to send serialized stacks back and forth. + self.chattube = ChatTube(tube_conn, self.initiating, \ + self.event_received_cb) + + # Now that we have the tube, we can ask for the turtle dictionary. + if self.waiting_for_turtles: # A joiner must wait for turtles. + debug_output('Sending a request for the turtle dictionary', + self._tw.running_sugar) + # We need to send our own nick, colors, and turtle position + colors = self._get_colors() + event = 't|' + data_to_string([self._get_nick(), colors]) + debug_output(event, self._tw.running_sugar) + self.send_event(event) + + def event_received_cb(self, event_message): + """ + Events are sent as a tuple, nick|cmd, where nick is a turle name + and cmd is a turtle event. Everyone gets the turtle dictionary from + the sharer and watches for 't' events, which indicate that a new + turtle has joined. + """ + if len(event_message) == 0: + return + + # Save active Turtle + save_active_turtle = self._tw.active_turtle + + try: + command, payload = event_message.split('|', 2) + self._processing_methods[command](payload) + except ValueError: + debug_output('Could not split event message.', + self._tw.running_sugar) + + # Restore active Turtle + self._tw.canvas.set_turtle(self._tw.turtles.get_turtle_key( + save_active_turtle)) + + def send_event(self, entry): + """ Send event through the tube. """ + if hasattr(self, 'chattube') and self.chattube is not None: + self.chattube.SendText(entry) + + def _turtle_request(self, payload): + ''' incoming turtle from a joiner ''' + if payload > 0: + [nick, colors] = data_from_string(payload) + if nick != self._tw.nick: # It is not me. + # There may not be a turtle dictionary. + if hasattr(self._tw, 'remote_turtle_dictionary'): + # Make sure it is not a "rejoin". + if not nick in self._tw.remote_turtle_dictionary: + # Add new turtle for the joiner. + self._tw.canvas.set_turtle(nick, colors) + self._tw.label_remote_turtle(nick, colors) + self._tw.remote_turtle_dictionary[nick] = colors + else: + self._tw.remote_turtle_dictionary = self._get_dictionary() + # Add new turtle for the joiner. + self._tw.canvas.set_turtle(nick, colors) + self._tw.label_remote_turtle(nick, colors) + + # Sharer should send the updated remote turtle dictionary to everyone. + if self.initiating: + if not self._tw.nick in self._tw.remote_turtle_dictionary: + self._tw.remote_turtle_dictionary[self._tw.nick] = \ + self._get_colors() + event_payload = data_to_string(self._tw.remote_turtle_dictionary) + self.send_event('T|' + event_payload) + self.send_my_xy() # And the sender should report her xy position. + + def _receive_turtle_dict(self, payload): + ''' Any time there is a new joiner, an updated turtle dictionary is + circulated. Everyone must report their turtle positions so that we + are in sync. ''' + if self.waiting_for_turtles: + if len(payload) > 0: + # Grab the new remote turtles dictionary. + remote_turtle_dictionary = data_from_string(payload) + # Add see what is new. + for nick in remote_turtle_dictionary: + if nick == self._tw.nick: + debug_output('skipping my nick %s' \ + % (nick), self._tw.running_sugar) + elif nick != self._tw.remote_turtle_dictionary: + # Add new the turtle. + colors = remote_turtle_dictionary[nick] + self._tw.remote_turtle_dictionary[nick] = colors + self._tw.canvas.set_turtle(nick, colors) + # Label the remote turtle. + self._tw.label_remote_turtle(nick, colors) + debug_output('adding %s to remote turtle dictionary' \ + % (nick), self._tw.running_sugar) + else: + debug_output('%s already in remote turtle dictionary' \ + % (nick), self._tw.running_sugar) + self.waiting_for_turtles = False + self.send_my_xy() + + def send_my_xy(self): + ''' Set xy location so joiner can sync turtle positions. Should be + used to sync positions after turtle drag. ''' + self._tw.canvas.set_turtle(self._get_nick()) + if self._tw.canvas.pendown: + self.send_event('p|%s' % (data_to_string([self._get_nick(), + False]))) + put_pen_back_down = True + else: + put_pen_back_down = False + self.send_event('x|%s' % (data_to_string([self._get_nick(), + [int(self._tw.canvas.xcor), int(self._tw.canvas.ycor)]]))) + if put_pen_back_down: + self.send_event('p|%s' % (data_to_string([self._get_nick(), + True]))) + self.send_event('r|%s' % (data_to_string([self._get_nick(), + int(self._tw.canvas.heading)]))) + + def _draw_pixbuf(self, payload): + if len(payload) > 0: + [nick, [a, b, x, y, w, h, width, height, data]] =\ + data_from_string(payload) + if nick != self._tw.nick: + if self._tw.running_sugar: + tmp_path = get_path(self._tw.activity, 'instance') + else: + tmp_path = '/tmp' + file_name = base64_to_image(data, tmp_path) + pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(file_name, + width, height) + x, y = self._tw.canvas.turtle_to_screen_coordinates(x, y) + self._tw.canvas.draw_pixbuf(pixbuf, a, b, x, y, w, h, + file_name, False) + + def _move_forward(self, payload): + if len(payload) > 0: + [nick, x] = data_from_string(payload) + if nick != self._tw.nick: + self._tw.canvas.set_turtle(nick) + self._tw.canvas.forward(x, False) + + def _move_in_arc(self, payload): + if len(payload) > 0: + [nick, [a, r]] = data_from_string(payload) + if nick != self._tw.nick: + self._tw.canvas.set_turtle(nick) + self._tw.canvas.arc(a, r, False) + + def _rotate_turtle(self, payload): + if len(payload) > 0: + [nick, h] = data_from_string(payload) + if nick != self._tw.nick: + self._tw.canvas.set_turtle(nick) + self._tw.canvas.seth(h, False) + + def _setxy(self, payload): + if len(payload) > 0: + [nick, [x, y]] = data_from_string(payload) + if nick != self._tw.nick: + self._tw.canvas.set_turtle(nick) + self._tw.canvas.setxy(x, y, False) + + def _draw_text(self, payload): + if len(payload) > 0: + [nick, [label, x, y, size, w]] = data_from_string(payload) + if nick != self._tw.nick: + self._tw.canvas.draw_text(label, x, y, size, w, False) + + def _set_pen_color(self, payload): + if len(payload) > 0: + [nick, x] = data_from_string(payload) + if nick != self._tw.nick: + self._tw.canvas.set_turtle(nick) + self._tw.canvas.setcolor(x, False) + + def _set_pen_gray_level(self, payload): + if len(payload) > 0: + [nick, x] = data_from_string(payload) + if nick != self._tw.nick: + self._tw.canvas.set_turtle(nick) + self._tw.canvas.setgray(x, False) + + def _set_pen_shade(self, payload): + if len(payload) > 0: + [nick, x] = data_from_string(payload) + if nick != self._tw.nick: + self._tw.canvas.set_turtle(nick) + self._tw.canvas.setshade(x, False) + + def _set_pen_width(self, payload): + if len(payload) > 0: + [nick, x] = data_from_string(payload) + if nick != self._tw.nick: + self._tw.canvas.set_turtle(nick) + self._tw.canvas.setpensize(x, False) + + def _set_pen_state(self, payload): + if len(payload) > 0: + [nick, x] = data_from_string(payload) + if nick != self._tw.nick: + self._tw.canvas.set_turtle(nick) + self._tw.canvas.setpen(x, False) + + def _fill_polygon(self, payload): + # Check to make sure that the poly_point array is passed properly + if len(payload) > 0: + [nick, poly_points] = data_from_string(payload) + shared_poly_points = [] + for i in range(len(poly_points)): + shared_poly_points.append(( + self._tw.canvas.turtle_to_screen_coordinates( + poly_points[i][0], poly_points[i][1]))) + self._tw.canvas.fill_polygon(shared_poly_points) + + def _get_dictionary(self): + return {self._get_nick(): self._get_colors()} + + def _get_nick(self): + return self._tw.nick + + def _get_colors(self): + colors = None + if self._tw.running_sugar: + if profile.get_color() is not None: + colors = profile.get_color().to_string() + else: + colors = self._activity.get_colors() + if colors is None: + colors = '%s,%s' % (DEFAULT_TURTLE_COLORS[0], + DEFAULT_TURTLE_COLORS[1]) + return colors.split(',') + + +class ChatTube(ExportedGObject): + + def __init__(self, tube, is_initiator, stack_received_cb): + """Class for setting up tube for sharing.""" + super(ChatTube, self).__init__(tube, PATH) + self.tube = tube + self.is_initiator = is_initiator # Are we sharing or joining activity? + self.stack_received_cb = stack_received_cb + self.stack = '' + + self.tube.add_signal_receiver(self.send_stack_cb, 'SendText', IFACE, \ + path=PATH, sender_keyword='sender') + + def send_stack_cb(self, text, sender=None): + if sender == self.tube.get_unique_name(): + return + self.stack = text + self.stack_received_cb(text) + + @signal(dbus_interface=IFACE, signature='s') + def SendText(self, text): + self.stack = text diff --git a/TurtleArt/taconstants.py b/TurtleArt/taconstants.py new file mode 100644 index 0000000..7a82a42 --- /dev/null +++ b/TurtleArt/taconstants.py @@ -0,0 +1,428 @@ +# -*- coding: utf-8 -*- +#Copyright (c) 2010-12 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. + +from gettext import gettext as _ + +# +# Sprite layers +# + +OVERLAY_LAYER = 400 +TURTLE_LAYER = 500 +BLOCK_LAYER = 600 +CATEGORY_LAYER = 700 +TAB_LAYER = 800 +PROTO_LAYER = 801 +STATUS_LAYER = 900 +TOP_LAYER = 1000 + +# Special-case some block colors +BOX_COLORS = {'red': ["#FF0000", "#A00000"], + 'orange': ["#FFD000", "#AA8000"], + 'yellow': ["#FFFF00", "#A0A000"], + 'blue': ["#0000FF", "#000080"], + 'cyan': ["#00FFFF", "#00A0A0"], + 'green': ["#00FF00", "#008000"], + 'purple': ["#FF00FF", "#A000A0"], + 'white': ["#FFFFFF", "#A0A0A0"], + 'black': ["#000000", "#000000"]} + +# +# Misc. parameters +# +PALETTE_HEIGHT = 120 +PALETTE_WIDTH = 175 +SELECTOR_WIDTH = 55 +ICON_SIZE = 55 +GRADIENT_COLOR = "#FFFFFF" +STANDARD_STROKE_WIDTH = 1.0 +BLOCK_SCALE = [0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 6.0, 8.0] +PALETTE_SCALE = 1.5 +DEFAULT_TURTLE = 'Yertle' +DEFAULT_TURTLE_COLORS = ['#008000', '#00A000'] +PALETTE_COLOR = "#FFD000" +TOOLBAR_COLOR = "#282828" +HORIZONTAL_PALETTE = 0 +VERTICAL_PALETTE = 1 +BLACK = -9999 +WHITE = -9998 +HIT_HIDE = 240 +HIT_SHOW = 224 +HIT_RED = "#F00000" +HIT_GREEN = "#00E000" +HIDE_WHITE = "#F0F0F0" +SHOW_WHITE = "#E0E0E0" +DEFAULT_SCALE = 33 +XO1 = 'xo1' +XO15 = 'xo1.5' +XO175 = 'xo1.75' +XO30 = 'xo3.0' +UNKNOWN = 'unknown' + +CONSTANTS = {'leftpos': None, 'toppos': None, 'rightpos': None, + 'bottompos': None, 'width': None, 'height': None, 'red': 0, + 'orange': 10, 'yellow': 20, 'green': 40, 'cyan': 50, 'blue': 70, + 'purple': 90, 'titlex': None, 'titley': None, 'leftx': None, + 'topy': None, 'rightx': None, 'bottomy': None} + +# +# Blocks that are expandable +# +EXPANDABLE_STYLE = ['boolean-style', 'compare-porch-style', 'compare-style', + 'number-style-porch', 'number-style', 'basic-style-2arg', + 'number-style-block', 'box-style-media'] + +EXPANDABLE = ['vspace', 'hspace', 'identity2'] + +EXPANDABLE_ARGS = ['list', 'myfunc1arg', 'myfunc2arg', 'myfunc3arg', + 'userdefined', 'userdefined2args', 'userdefined3args'] +# +# Blocks that are 'collapsible' +# +COLLAPSIBLE = ['sandwichbottom', 'sandwichcollapsed'] + +# +# Deprecated block styles that need dock adjustments +# +OLD_DOCK = ['and', 'or', 'plus', 'minus', 'division', 'product', 'remainder'] + +CONTENT_ARGS = ['show', 'showaligned', 'push', 'storein', 'storeinbox1', + 'storeinbox2'] + +PREFIX_DICTIONARY = {} + +# +# These blocks get a special skin +# +BLOCKS_WITH_SKIN = [] + +PYTHON_SKIN = [] + +SKIN_PATHS = ['images'] + +MEDIA_SHAPES = [] + +NO_IMPORT = [] + +EXPAND_SKIN = {} + +# +# Status blocks +# +OVERLAY_SHAPES = ['Cartesian', 'Cartesian_labeled', 'polar', 'metric'] + +STATUS_SHAPES = ['status', 'info', 'nostack', 'dupstack', 'noinput', + 'emptyheap', 'emptybox', 'nomedia', 'nocode', 'overflowerror', + 'negroot', 'syntaxerror', 'nofile', 'nojournal', 'zerodivide', + 'notanumber', 'incompatible', 'help', 'print'] + +# +# Emulate Sugar toolbar when running from outside of Sugar +# +TOOLBAR_SHAPES = ['hideshowoff', 'eraseron', 'run-fastoff', + 'run-slowoff', 'debugoff', 'stopiton'] + +# +# Legacy names +# +OLD_NAMES = {'product': 'product2', 'storeinbox': 'storein', 'minus': 'minus2', + 'division': 'division2', 'plus': 'plus2', 'and': 'and2', + 'or': 'or2', 'less': 'less2', 'greater': 'greater2', + 'equal': 'equal2', 'remainder': 'remainder2', + 'identity': 'identity2', 'division': 'division2', + 'audiooff': 'audio', 'endfill': 'stopfill', + 'descriptionoff': 'description', 'template3': 'templatelist', + 'template1': 'template1x1', 'template2': 'template2x1', + 'template6': 'template1x2', 'template7': 'template2x2', + 'template4': 'template1x1a', 'hres': 'width', 'vres': 'height', + 'sandwichtop2': 'sandwichtop', 'image': 'show', + 'container': 'indentity2', 'insertimage': 'show'} + +# +# Define the relative size and postion of media objects +# (w, h, x, y, dx, dy) +# +TITLEXY = (0.9375, 0.875) + +# +# Relative placement of portfolio objects (used by deprecated blocks) +# +TEMPLATES = {'t1x1': (0.5, 0.5, 0.0625, 0.125, 1.05, 0), + 't2z1': (0.5, 0.5, 0.0625, 0.125, 1.05, 1.05), + 't1x2': (0.45, 0.45, 0.0625, 0.125, 1.05, 1.05), + 't2x2': (0.45, 0.45, 0.0625, 0.125, 1.05, 1.05), + 't1x1a': (0.9, 0.9, 0.0625, 0.125, 0, 0), + 'bullet': (1, 1, 0.0625, 0.125, 0, 0.1), + 'insertimage': (0.333, 0.333)} + +# +# 'dead key' Unicode dictionaries +# + +DEAD_KEYS = ['grave', 'acute', 'circumflex', 'tilde', 'diaeresis', 'abovering'] +DEAD_DICTS = [{'A': 192, 'E': 200, 'I': 204, 'O': 210, 'U': 217, 'a': 224, + 'e': 232, 'i': 236, 'o': 242, 'u': 249}, + {'A': 193, 'E': 201, 'I': 205, 'O': 211, 'U': 218, 'a': 225, + 'e': 233, 'i': 237, 'o': 243, 'u': 250}, + {'A': 194, 'E': 202, 'I': 206, 'O': 212, 'U': 219, 'a': 226, + 'e': 234, 'i': 238, 'o': 244, 'u': 251}, + {'A': 195, 'O': 211, 'N': 209, 'U': 360, 'a': 227, 'o': 245, + 'n': 241, 'u': 361}, + {'A': 196, 'E': 203, 'I': 207, 'O': 211, 'U': 218, 'a': 228, + 'e': 235, 'i': 239, 'o': 245, 'u': 252}, + {'A': 197, 'a': 229}] +NOISE_KEYS = ['Shift_L', 'Shift_R', 'Control_L', 'Caps_Lock', 'Pause', + 'Alt_L', 'Alt_R', 'KP_Enter', 'ISO_Level3_Shift', 'KP_Divide', + 'Escape', 'Return', 'KP_Page_Up', 'Up', 'Down', 'Menu', + 'Left', 'Right', 'KP_Home', 'KP_End', 'KP_Up', 'Super_L', + 'KP_Down', 'KP_Left', 'KP_Right', 'KP_Page_Down', 'Scroll_Lock', + 'Page_Down', 'Page_Up'] +WHITE_SPACE = ['space', 'Tab'] + +CURSOR = '█' +RETURN = '⏎' + +VOICES = {'af': 'afrikaans', 'cy': 'welsh-test', 'el': 'greek', + 'es': 'spanish', 'hi': 'hindi-test', 'hy': 'armenian', + 'ku': 'kurdish', 'mk': 'macedonian-test', 'pt': 'brazil', + 'sk': 'slovak', 'sw': 'swahili', 'bs': 'bosnian', + 'da': 'danish', 'en': 'english', 'fi': 'finnish', + 'hr': 'croatian', 'id': 'indonesian-test', 'la': 'latin', + 'nl': 'dutch-test', 'sq': 'albanian', 'ta': 'tamil', + 'vi': 'vietnam-test', 'ca': 'catalan', 'de': 'german', + 'eo': 'esperanto', 'fr': 'french', 'hu': 'hungarian', + 'is': 'icelandic-test', 'lv': 'latvian', 'no': 'norwegian', + 'ro': 'romanian', 'sr': 'serbian', 'zh': 'Mandarin', + 'cs': 'czech', 'it': 'italian', 'pl': 'polish', + 'ru': 'russian_test', 'sv': 'swedish', 'tr': 'turkish'} + +# +# Macros (groups of blocks) +# +MACROS = { + 'kbinput': + [[0, 'until', 0, 0, [None, 1, 4, None]], + [1, 'greater2', 0, 0, [0, 2, 3, None]], + [2, 'keyboard', 0, 0, [1, None]], + [3, ['number', '0'], 0, 0, [1, None]], + [4, 'wait', 0, 0, [0, 5, 6]], + [5, ['number', '0.1'], 0, 0, [4, None]], + [6, 'kbinput', 0, 0, [4, None]]], + 'picturelist': + [[0, 'sandwichtop_no_label', 0, 0, [None, 1]], + [1, 'penup', 0, 0, [0, 2]], + [2, 'setxy2', 0, 0, [1, 3, 4, 5]], + [3, 'titlex', 0, 0, [2, None]], + [4, 'titley', 0, 0, [2, None]], + [5, 'pendown', 0, 0, [2, 6]], + [6, 'setscale', 0, 0, [5, 7, 8]], + [7, ['number', '100'], 0, 0, [6, None]], + [8, 'show', 0, 0, [6, 9, 10]], + [9, ['string', _('Title')], 0, 0, [8, None]], + [10, 'penup', 0, 0, [8, 11]], + [11, 'setxy2', 0, 0, [10, 12, 13, 14]], + [12, 'leftx', 0, 0, [11, None]], + [13, 'topy', 0, 0, [11, None]], + [14, 'pendown', 0, 0, [11, 15]], + [15, 'setscale', 0, 0, [14, 16, 17]], + [16, ['number', '67'], 0, 0, [15, None]], + [17, 'list', 0, 0, [15, 18, 19, 20]], + [18, ['string', '∙ '], 0, 0, [17, None]], + [19, ['string', '∙ '], 0, 0, [17, None]], + [20, 'sandwichbottom', 0, 0, [17, None]]], + 'picture1x1a': + [[0, 'sandwichtop_no_label', 0, 0, [None, 1]], + [1, 'penup', 0, 0, [0, 2]], + [2, 'setxy2', 0, 0, [1, 3, 4, 5]], + [3, 'titlex', 0, 0, [2, None]], + [4, 'titley', 0, 0, [2, None]], + [5, 'pendown', 0, 0, [2, 6]], + [6, 'setscale', 0, 0, [5, 7, 8]], + [7, ['number', '100'], 0, 0, [6, None]], + [8, 'show', 0, 0, [6, 9, 10]], + [9, ['string', _('Title')], 0, 0, [8, None]], + [10, 'penup', 0, 0, [8, 11]], + [11, 'setxy2', 0, 0, [10, 12, 13, 14]], + [12, 'leftx', 0, 0, [11, None]], + [13, 'topy', 0, 0, [11, None]], + [14, 'pendown', 0, 0, [11, 15]], + [15, 'setscale', 0, 0, [14, 16, 17]], + [16, ['number', '90'], 0, 0, [15, None]], + [17, 'showaligned', 0, 0, [15, 18, 19]], + [18, 'journal', 0, 0, [17, None]], + [19, 'sandwichbottom', 0, 0, [17, None]]], + 'picture2x2': + [[0, 'sandwichtop_no_label', 0, 0, [None, 1]], + [1, 'penup', 0, 0, [0, 2]], + [2, 'setxy2', 0, 0, [1, 3, 4, 5]], + [3, 'titlex', 0, 0, [2, None]], + [4, 'titley', 0, 0, [2, None]], + [5, 'pendown', 0, 0, [2, 6]], + [6, 'setscale', 0, 0, [5, 7, 8]], + [7, ['number', '100'], 0, 0, [6, None]], + [8, 'show', 0, 0, [6, 9, 10]], + [9, ['string', _('Title')], 0, 0, [8, None]], + [10, 'setscale', 0, 0, [8, 11, 12]], + [11, ['number', '35'], 0, 0, [10, None]], + [12, 'penup', 0, 0, [10, 13]], + [13, 'setxy2', 0, 0, [12, 14, 15, 16]], + [14, 'leftx', 0, 0, [13, None]], + [15, 'topy', 0, 0, [13, None]], + [16, 'pendown', 0, 0, [13, 17]], + [17, 'showaligned', 0, 0, [16, 18, 19]], + [18, 'journal', 0, 0, [17, None]], + [19, 'penup', 0, 0, [17, 20]], + [20, 'setxy2', 0, 0, [19, 21, 22, 23]], + [21, 'rightx', 0, 0, [20, None]], + [22, 'topy', 0, 0, [20, None]], + [23, 'pendown', 0, 0, [20, 24]], + [24, 'showaligned', 0, 0, [23, 25, 26]], + [25, 'journal', 0, 0, [24, None]], + [26, 'penup', 0, 0, [24, 27]], + [27, 'setxy2', 0, 0, [26, 28, 29, 30]], + [28, 'leftx', 0, 0, [27, None]], + [29, 'bottomy', 0, 0, [27, None]], + [30, 'pendown', 0, 0, [27, 31]], + [31, 'showaligned', 0, 0, [30, 32, 33]], + [32, 'journal', 0, 0, [31, None]], + [33, 'penup', 0, 0, [31, 34]], + [34, 'setxy2', 0, 0, [33, 35, 36, 37]], + [35, 'rightx', 0, 0, [34, None]], + [36, 'bottomy', 0, 0, [34, None]], + [37, 'pendown', 0, 0, [34, 38]], + [38, 'showaligned', 0, 0, [37, 39, 40]], + [39, 'journal', 0, 0, [38, None]], + [40, 'sandwichbottom', 0, 0, [38, None]]], + 'picture1x2': + [[0, 'sandwichtop_no_label', 0, 0, [None, 1]], + [1, 'penup', 0, 0, [0, 2]], + [2, 'setxy2', 0, 0, [1, 3, 4, 5]], + [3, 'titlex', 0, 0, [2, None]], + [4, 'titley', 0, 0, [2, None]], + [5, 'pendown', 0, 0, [2, 6]], + [6, 'setscale', 0, 0, [5, 7, 8]], + [7, ['number', '100'], 0, 0, [6, None]], + [8, 'show', 0, 0, [6, 9, 10]], + [9, ['string', _('Title')], 0, 0, [8, None]], + [10, 'setscale', 0, 0, [8, 11, 12]], + [11, ['number', '35'], 0, 0, [10, None]], + [12, 'penup', 0, 0, [10, 13]], + [13, 'setxy2', 0, 0, [12, 14, 15, 16]], + [14, 'leftx', 0, 0, [13, None]], + [15, 'topy', 0, 0, [13, None]], + [16, 'pendown', 0, 0, [13, 17]], + [17, 'showaligned', 0, 0, [16, 18, 19]], + [18, 'journal', 0, 0, [17, None]], + [19, 'penup', 0, 0, [17, 20]], + [20, 'setxy2', 0, 0, [19, 21, 22, 23]], + [21, 'rightx', 0, 0, [20, None]], + [22, 'topy', 0, 0, [20, None]], + [23, 'pendown', 0, 0, [20, 24]], + [24, 'showaligned', 0, 0, [23, 25, 26]], + [25, 'description', 0, 0, [24, None]], + [26, 'penup', 0, 0, [24, 27]], + [27, 'setxy2', 0, 0, [26, 28, 29, 30]], + [28, 'leftx', 0, 0, [27, None]], + [29, 'bottomy', 0, 0, [27, None]], + [30, 'pendown', 0, 0, [27, 31]], + [31, 'showaligned', 0, 0, [30, 32, 33]], + [32, 'journal', 0, 0, [31, None]], + [33, 'penup', 0, 0, [31, 34]], + [34, 'setxy2', 0, 0, [33, 35, 36, 37]], + [35, 'rightx', 0, 0, [34, None]], + [36, 'bottomy', 0, 0, [34, None]], + [37, 'pendown', 0, 0, [34, 38]], + [38, 'showaligned', 0, 0, [37, 39, 40]], + [39, 'description', 0, 0, [38, None]], + [40, 'sandwichbottom', 0, 0, [38, None]]], + 'picture2x1': + [[0, 'sandwichtop_no_label', 0, 0, [None, 1]], + [1, 'penup', 0, 0, [0, 2]], + [2, 'setxy2', 0, 0, [1, 3, 4, 5]], + [3, 'titlex', 0, 0, [2, None]], + [4, 'titley', 0, 0, [2, None]], + [5, 'pendown', 0, 0, [2, 6]], + [6, 'setscale', 0, 0, [5, 7, 8]], + [7, ['number', '100'], 0, 0, [6, None]], + [8, 'show', 0, 0, [6, 9, 10]], + [9, ['string', _('Title')], 0, 0, [8, None]], + [10, 'setscale', 0, 0, [8, 11, 12]], + [11, ['number', '35'], 0, 0, [10, None]], + [12, 'penup', 0, 0, [10, 13]], + [13, 'setxy2', 0, 0, [12, 14, 15, 16]], + [14, 'leftx', 0, 0, [13, None]], + [15, 'topy', 0, 0, [13, None]], + [16, 'pendown', 0, 0, [13, 17]], + [17, 'showaligned', 0, 0, [16, 18, 19]], + [18, 'journal', 0, 0, [17, None]], + [19, 'penup', 0, 0, [17, 20]], + [20, 'setxy2', 0, 0, [19, 21, 22, 23]], + [21, 'rightx', 0, 0, [20, None]], + [22, 'topy', 0, 0, [20, None]], + [23, 'pendown', 0, 0, [20, 24]], + [24, 'showaligned', 0, 0, [23, 25, 26]], + [25, 'journal', 0, 0, [24, None]], + [26, 'penup', 0, 0, [24, 27]], + [27, 'setxy2', 0, 0, [26, 28, 29, 30]], + [28, 'leftx', 0, 0, [27, None]], + [29, 'bottomy', 0, 0, [27, None]], + [30, 'pendown', 0, 0, [27, 31]], + [31, 'showaligned', 0, 0, [30, 32, 33]], + [32, 'description', 0, 0, [31, None]], + [33, 'penup', 0, 0, [31, 34]], + [34, 'setxy2', 0, 0, [33, 35, 36, 37]], + [35, 'rightx', 0, 0, [34, None]], + [36, 'bottomy', 0, 0, [34, None]], + [37, 'pendown', 0, 0, [34, 38]], + [38, 'showaligned', 0, 0, [37, 39, 40]], + [39, 'description', 0, 0, [38, None]], + [40, 'sandwichbottom', 0, 0, [38, None]]], + 'picture1x1': + [[0, 'sandwichtop_no_label', 0, 0, [None, 1]], + [1, 'penup', 0, 0, [0, 2]], + [2, 'setxy2', 0, 0, [1, 3, 4, 5]], + [3, 'titlex', 0, 0, [2, None]], + [4, 'titley', 0, 0, [2, None]], + [5, 'pendown', 0, 0, [2, 6]], + [6, 'setscale', 0, 0, [5, 7, 8]], + [7, ['number', '100'], 0, 0, [6, None]], + [8, 'show', 0, 0, [6, 9, 10]], + [9, ['string', _('Title')], 0, 0, [8, None]], + [10, 'setscale', 0, 0, [8, 11, 12]], + [11, ['number', '35'], 0, 0, [10, None]], + [12, 'penup', 0, 0, [10, 13]], + [13, 'setxy2', 0, 0, [12, 14, 15, 16]], + [14, 'leftx', 0, 0, [13, None]], + [15, 'topy', 0, 0, [13, None]], + [16, 'pendown', 0, 0, [13, 17]], + [17, 'showaligned', 0, 0, [16, 18, 19]], + [18, 'journal', 0, 0, [17, None]], + [19, 'penup', 0, 0, [17, 20]], + [20, 'setxy2', 0, 0, [19, 21, 22, 23]], + [21, 'rightx', 0, 0, [20, None]], + [22, 'topy', 0, 0, [20, None]], + [23, 'pendown', 0, 0, [20, 24]], + [24, 'showaligned', 0, 0, [23, 25, 26]], + [25, 'description', 0, 0, [24, None]], + [26, 'sandwichbottom', 0, 0, [24, None]]], + 'reskin': + [[0, 'skin', 0, 0, [None, 1, None]], + [1, 'journal', 0, 0, [0, None]]]} diff --git a/TurtleArt/taexporthtml.py b/TurtleArt/taexporthtml.py new file mode 100644 index 0000000..0e6a2f1 --- /dev/null +++ b/TurtleArt/taexporthtml.py @@ -0,0 +1,161 @@ +#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 os.path +from cgi import escape +from gettext import gettext as _ + +from tautils import data_to_string, save_picture, image_to_base64, get_path + +# A dictionary to define the HTML wrappers around template elements +HTML_GLUE = { + 'doctype': '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 ' + \ + 'Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n', + 'html': ('<html>\n', '</html>\n'), + 'html_svg': ('<html xmlns="http://www.w3.org/1999/xhtml">\n', + '</html>\n'), + 'head': ('<head>\n<!-- Created by Turtle Art -->\n', '</head>\n'), + 'meta': '<meta http-equiv="content-type" content="text/html; ' + \ + 'charset=UTF-8"/>\n', + 'title': ('<title>', '</title>\n'), + 'style': ('<style type="text/css">\n<!--\n', '-->\n</style>\n'), + 'body': ('<body>\n', '\n</body>\n'), + 'div': ('<div>\n', '</div>\n'), + 'slide': ('\n<a name="slide', '"></a>\n'), + 'h1': ('<h1>', '</h1>\n'), + 'table': ('<table cellpadding="10\'>\n', '</table>\n'), + 'tr': ('<tr>\n', '</tr>\n'), + 'td': ('<td valign="top" width="400" height="300">\n', + '\n</td>\n'), + 'img': ('<img width="400" height="300" alt="Image" ' + \ + 'src="file://"', '".png" />\n'), + 'img2': ('<img alt="Image" src="image"', '".png" />\n'), + 'img3': ('<img alt="Image" src="file://"', '"" />\n'), + 'ul': ('<table>\n', '</table>\n'), + 'li': ('<tr><td>', '</td></tr>\n')} + +COMMENT = '<!--\n\<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"' + \ + ' "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [\n\ + <!ENTITY ns_svg "http://www.w3.org/2000/svg">\n\ + <!ENTITY ns_xlink "http://www.w3.org/1999/xlink">\n\ +]>\n\ +-->\n' + + +def save_html(self, tw, embed_flag=True): + """ Either save the canvas and code or pictures to HTML """ + + if embed_flag: + HTML_GLUE['img'] = ('<img width="400" height="300" alt=' + \ + '"Image" src="data:image/png;base64,\n', + '"/>\n') + HTML_GLUE['img2'] = ('<img alt="Image" src="data:image/png;' + \ + 'base64,\n', '"/>\n') + + """ + If there are saved_pictures, put them into a .html; otherwise, + save a screendump and the turtle project code. + """ + htmlcode = '' + if len(tw.saved_pictures) > 0: + # saved_picture list is a collection of tuples of either the + # image_file or the containing dsobject and an SVG flag + for i, (image, svg_flag) in enumerate(tw.saved_pictures): + htmlcode += HTML_GLUE['slide'][0] + str(i) + htmlcode += HTML_GLUE['slide'][1] + \ + HTML_GLUE['div'][0] + \ + HTML_GLUE['h1'][0] + if tw.running_sugar: + from sugar.datastore import datastore + dobject = datastore.get(image) # dsobject.object_id + image_file = dobject.file_path + else: + image_file = image + if embed_flag: + f = open(image_file, 'r') + imgdata = f.read() + f.close() + if svg_flag: + tmp = imgdata + else: + imgdata = image_to_base64( + image_file, get_path(tw.activity, 'instance')) + tmp = HTML_GLUE['img2'][0] + tmp += imgdata + tmp += HTML_GLUE['img2'][1] + else: + if svg_flag: + f = open(image_file, 'r') + imgdata = f.read() + f.close() + tmp = imgdata + else: + tmp = HTML_GLUE['img3'][0] + tmp += image_file + tmp += HTML_GLUE['img3'][1] + htmlcode += tmp + \ + HTML_GLUE['h1'][1] + \ + HTML_GLUE['div'][1] + else: + if embed_flag: + tmp_file = os.path.join(get_path(tw.activity, 'instance'), + 'tmpfile.png') + save_picture(self.tw.canvas, tmp_file) + imgdata = image_to_base64(tmp_file, + get_path(tw.activity, 'instance')) + else: + imgdata = os.path.join(self.tw.load_save_folder, 'image') + self.tw.save_as_image(imgdata) + htmlcode += (HTML_GLUE['img'][0] + imgdata + \ + HTML_GLUE['img'][1]) + htmlcode += HTML_GLUE['div'][0] + htmlcode += escape(data_to_string( + tw.assemble_data_to_save(False, True))) + htmlcode += HTML_GLUE['div'][1] + + if tw.running_sugar: + title = _('Turtle Art') + ' ' + tw.activity.metadata['title'] + else: + title = _('Turtle Art') + + header = HTML_GLUE['doctype'] + \ + HTML_GLUE['html'][0] + style = HTML_GLUE['style'][0] + \ + HTML_GLUE['style'][1] + if len(tw.saved_pictures) > 0: + if tw.saved_pictures[0][1]: + header = HTML_GLUE['html_svg'][0] + style = COMMENT + + return header + \ + HTML_GLUE['head'][0] + \ + HTML_GLUE['meta'] + \ + HTML_GLUE['title'][0] + \ + title + \ + HTML_GLUE['title'][1] + \ + style + \ + HTML_GLUE['head'][1] + \ + HTML_GLUE['body'][0] + \ + htmlcode + \ + HTML_GLUE['body'][1] + \ + HTML_GLUE['html'][1] diff --git a/TurtleArt/taexportlogo.py b/TurtleArt/taexportlogo.py new file mode 100644 index 0000000..0d0660e --- /dev/null +++ b/TurtleArt/taexportlogo.py @@ -0,0 +1,272 @@ +#Copyright (c) 2008-11, 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. + +from gettext import gettext as _ + +try: + from sugar.datastore import datastore + HAS_DATASTORE = True +except: + HAS_DATASTORE = False + +from TurtleArt.tapalette import logo_commands, logo_functions +from TurtleArt.taconstants import TITLEXY, CONSTANTS + +def save_logo(tw): + """ Set up the Turtle Art color palette and color processing. """ + + # We need to catch several special cases: stacks, boxes, labels, etc. + dispatch_table = { + 'label': _add_label, + 'to action': _add_named_stack, + 'action': _add_reference_to_stack, + 'storeinbox': _add_named_box, + 'box': _add_reference_to_box + } + constants_table = { + 'lpos': _lpos, + 'tpos': _tpos, + 'rpos': _rpos, + 'bpos': _bpos, + 'red': _red, + 'orange': _orange, + 'yellow': _yellow, + 'green': _green, + 'cyan': _cyan, + 'blue': _blue, + 'purple': _purple, + 'white': _white, + 'black': _black, + 'titlex': _titlex, + 'titley': _titley, + 'leftx': _leftx, + 'topy': _topy, + 'rightx': _rightx, + 'bottomy': _bottomy, + 'width': _width, + 'height': _height + } + + stacks_of_blocks = tw.just_blocks() + stack_count = 0 + + logocode = '' + + """ + Walk through the code, substituting UCB Logo for Turtle Art primitives. + """ + for stack in stacks_of_blocks: + this_stack = '' + psuedocode = _walk_stack(tw, stack) + if psuedocode == []: + continue + + skip = False + for i in range(len(psuedocode)): + if skip: + skip = False + continue + blk = psuedocode[i] + if type(blk) == type((1, 2)): + (blk, _blk_no) = blk + if blk in logo_commands: + logo_command = logo_commands[blk] + else: + logo_command = None + if i == 0 and not logo_command in ['to stack1\r', 'to stack2\r', + 'to action', 'to start\r']: + this_stack = 'to turtleblocks_%d\r' % (stack_count) + stack_count += 1 + if logo_command in dispatch_table: + if i + 1 < len(psuedocode): + this_stack += dispatch_table[logo_command]( + psuedocode[i + 1]) + skip = True + else: + print 'missing arg to %s' % (logo_command) + elif logo_command in constants_table: + this_stack += str(constants_table[logo_command](tw)) + elif logo_command is not None: + this_stack += logo_command + else: # assume it is an argument + if not blk in ['nop', 'nop1', 'nop2', 'nop3']: + if type(blk) == str and blk[0:2] == '#s': + this_stack += str(blk[2:]).replace(' ', '_') + else: + this_stack += str(blk).replace(' ', '_') + this_stack += ' ' + + logocode += this_stack + logocode += '\rend\r' + + # We may need to prepend some additional procedures. + for key in logo_functions.iterkeys(): + if key in logocode: + logocode = logo_functions[key] + logocode + + if 'tasetshade' in logocode or 'tasetpencolor' in logocode or \ + 'tasetbackground' in logocode: + logocode = logo_functions['tacolor'] + logocode + + logocode = 'window\r' + logocode + return logocode + + +def _add_label(string): + if type(string) == str and string[0:8] in ['#smedia_', '#saudio_', + '#svideo_', '#sdescr_']: + string = string[8:] + if HAS_DATASTORE: + dsobject = datastore.get(string[8:]) + if 'title' in dsobject.metadata: + string = dsobject.metadata['title'] + else: + string = str(string) + if string[0:2] == '#s': + string = string[2:] + string = '"' + string + if string.count(' ') > 0: + return 'label sentence %s\r' % (string.replace(' ', ' "')) + else: + return 'label %s' % (string.replace(' ', '_')) + + +def _add_named_stack(action): + if type(action) == str and action[0:2] == '#s': + return 'to %s\r' % (str(action[2:]).replace(' ', '_')) + else: + return 'to %s\r' % (str(action).replace(' ', '_')) + + +def _add_reference_to_stack(action): + if type(action) == str and action[0:2] == '#s': + return '%s' % (str(action[2:]).replace(' ', '_')) + else: + return '%s' % (str(action).replace(' ', '_')) + + +def _add_named_box(box_name): + if type(box_name) == str and box_name[0:2] == '#s': + return 'make "%s' % (str(box_name[2:]).replace(' ', '_')) + else: + return 'make "%s' % (str(box_name).replace(' ', '_')) + + +def _add_reference_to_box(box_name): + if type(box_name) == str and box_name[0:2] == '#s': + return ':%s' % (str(box_name[2:]).replace(' ', '_')) + else: + return ':%s' % (str(box_name).replace(' ', '_')) + + +def _lpos(tw): + return int(-tw.canvas.width / (tw.coord_scale * 2)) + + +def _tpos(tw): + return int(tw.canvas.height / (tw.coord_scale * 2)) + + +def _rpos(tw): + return int(tw.canvas.width / (tw.coord_scale * 2)) + + +def _bpos(tw): + return int(-tw.canvas.height / (tw.coord_scale * 2)) + + +def _width(tw): + return int(tw.canvas.width / tw.coord_scale) + + +def _height(tw): + int(tw.canvas.height / tw.coord_scale) + + +def _titlex(tw): + return int(-(tw.canvas.width * TITLEXY[0]) / (tw.coord_scale * 2)) + + +def _titley(tw): + return int((tw.canvas.height * TITLEXY[1]) / (tw.coord_scale * 2)) + + +def _leftx(tw): + return int(-(tw.canvas.width * TITLEXY[0]) / (tw.coord_scale * 2)) + + +def _topy(tw): + return int((tw.canvas.height * (TITLEXY[1] - 0.125)) / (tw.coord_scale * 2)) + + +def _rightx(tw): + return 0 + + +def _bottomy(tw): + return 0 + + +def _red(tw): + return CONSTANTS['red'] + + +def _orange(tw): + return CONSTANTS['orange'] + + +def _yellow(tw): + return CONSTANTS['yellow'] + + +def _green(tw): + return CONSTANTS['green'] + + +def _cyan(tw): + return CONSTANTS['cyan'] + + +def _blue(tw): + return CONSTANTS['blue'] + + +def _purple(tw): + return CONSTANTS['purple'] + + +def _white(tw): + return 1 + + +def _black(tw): + return 0 + + +def _walk_stack(tw, blk_in_stack): + """ Convert blocks to logo psuedocode. """ + from tautils import find_top_block + + top = find_top_block(blk_in_stack) + if blk_in_stack == top: + psuedocode = tw.lc.run_blocks(top, tw.just_blocks(), False) + return psuedocode + else: + return [] diff --git a/TurtleArt/tagettext.py b/TurtleArt/tagettext.py new file mode 100644 index 0000000..ebeebb3 --- /dev/null +++ b/TurtleArt/tagettext.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2010-11 Walter Bender, Martin Langhoff +# License: GPLv2 + +# Defines the magic global _() with the right params so all modules +# can use it. +# +# Plugins that want to override MUST use a different technique. See +# the developer notes in the TA wikipage. +# +import gettext +import os + +# In a git checkout, locale is in the root of the project +# so one dir "up" from tagettext.py +localedir = os.path.join(os.path.dirname(os.path.dirname(__file__)), + 'locale' ) + +if os.path.exists(localedir): + # works from a git checkout + gettext.install('org.laptop.TurtleArtActivity', localedir) +else: + # fallback for packaged TA (rpm, xo) + gettext.install('org.laptop.TurtleArtActivity') diff --git a/TurtleArt/tagplay.py b/TurtleArt/tagplay.py new file mode 100644 index 0000000..72379c6 --- /dev/null +++ b/TurtleArt/tagplay.py @@ -0,0 +1,300 @@ +""" + tagplay.py + refactored based on Jukebox Activity + Copyright (C) 2007 Andy Wingo <wingo@pobox.com> + Copyright (C) 2007 Red Hat, Inc. + Copyright (C) 2008-2010 Kushal Das <kushal@fedoraproject.org> + Copyright (C) 2010 Walter Bender +""" + +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA + + +import logging +import os + +import pygtk +pygtk.require('2.0') + +import gobject +gobject.threads_init() + +import pygst +import gst +import gst.interfaces +import gtk + +import urllib + + +def play_audio_from_file(lc, file_path): + """ Called from Show block of audio media """ + if lc.gplay is not None and lc.gplay.player is not None: + if lc.gplay.player.playing: + lc.gplay.player.stop() + if lc.gplay.bin is not None: + lc.gplay.bin.destroy() + + lc.gplay = Gplay(lc, lc.tw.canvas.width, lc.tw.canvas.height, 4, 3) + lc.gplay.start(file_path) + + +def play_movie_from_file(lc, filepath, x, y, w, h): + """ Called from Show block of video media """ + if lc.gplay is not None and lc.gplay.player is not None: + if lc.gplay.player.playing: + lc.gplay.player.stop() + if lc.gplay.bin is not None: + lc.gplay.bin.destroy() + + lc.gplay = Gplay(lc, x, y, w, h) + lc.gplay.start(filepath) + + +def stop_media(lc): + """ Called from Clean block and toolbar Stop button """ + if lc.gplay == None: + return False + + if lc.gplay.player is not None: + lc.gplay.player.stop() + if lc.gplay.bin != None: + lc.gplay.bin.destroy() + + lc.gplay = None + + +def media_playing(lc): + if lc.gplay == None: + return False + return lc.gplay.player.is_playing() + + +class Gplay(): + UPDATE_INTERVAL = 500 + + def __init__(self, lc, x, y, w, h): + + self.player = None + self.uri = None + self.playlist = [] + self.jobjectlist = [] + self.playpath = None + self.only_audio = False + self.got_stream_info = False + self.currentplaying = 0 + + self.bin = gtk.Window() + + self.videowidget = VideoWidget() + self.bin.add(self.videowidget) + self.bin.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_NORMAL) + self.bin.set_decorated(False) + if lc.tw.running_sugar: + self.bin.set_transient_for(lc.tw.activity) + + self.bin.move(x, y + 108) + self.bin.resize(w, h) + self.bin.show_all() + + self._want_document = True + + def _player_eos_cb(self, widget): + logging.debug('end of stream') + + def _player_error_cb(self, widget, message, detail): + self.player.stop() + self.player.set_uri(None) + logging.debug('Error: %s - %s' % (message, detail)) + + def _player_stream_info_cb(self, widget, stream_info): + if not len(stream_info) or self.got_stream_info: + return + + GST_STREAM_TYPE_VIDEO = 2 + + only_audio = True + for item in stream_info: + if item.props.type == GST_STREAM_TYPE_VIDEO: + only_audio = False + self.only_audio = only_audio + self.got_stream_info = True + + def start(self, uri=None): + self._want_document = False + self.playpath = os.path.dirname(uri) + if not uri: + return False + self.playlist.append('file://' + urllib.quote(os.path.abspath(uri))) + if not self.player: + # lazy init the player so that videowidget is realized + # and has a valid widget allocation + self.player = GstPlayer(self.videowidget) + self.player.connect('eos', self._player_eos_cb) + self.player.connect('error', self._player_error_cb) + self.player.connect('stream-info', self._player_stream_info_cb) + + try: + if not self.currentplaying: + logging.info('Playing: ' + self.playlist[0]) + self.player.set_uri(self.playlist[0]) + self.currentplaying = 0 + self.play_toggled() + self.show_all() + else: + pass + except: + pass + return False + + def play_toggled(self): + if self.player.is_playing(): + self.player.pause() + else: + if self.player.error: + pass + else: + self.player.play() + + +class GstPlayer(gobject.GObject): + __gsignals__ = { + 'error': (gobject.SIGNAL_RUN_FIRST, None, [str, str]), + 'eos': (gobject.SIGNAL_RUN_FIRST, None, []), + 'stream-info': (gobject.SIGNAL_RUN_FIRST, None, [object])} + + def __init__(self, videowidget): + gobject.GObject.__init__(self) + + self.playing = False + self.error = False + + self.player = gst.element_factory_make('playbin', 'player') + + self.videowidget = videowidget + self._init_video_sink() + + bus = self.player.get_bus() + bus.enable_sync_message_emission() + bus.add_signal_watch() + bus.connect('sync-message::element', self.on_sync_message) + bus.connect('message', self.on_message) + + def set_uri(self, uri): + self.player.set_property('uri', uri) + + def on_sync_message(self, bus, message): + if message.structure is None: + return + if message.structure.get_name() == 'prepare-xwindow-id': + self.videowidget.set_sink(message.src) + message.src.set_property('force-aspect-ratio', True) + + def on_message(self, bus, message): + t = message.type + if t == gst.MESSAGE_ERROR: + err, debug = message.parse_error() + logging.debug('Error: %s - %s' % (err, debug)) + self.error = True + self.emit('eos') + self.playing = False + self.emit('error', str(err), str(debug)) + elif t == gst.MESSAGE_EOS: + self.emit('eos') + self.playing = False + elif t == gst.MESSAGE_STATE_CHANGED: + old, new, pen = message.parse_state_changed() + if old == gst.STATE_READY and new == gst.STATE_PAUSED: + self.emit('stream-info', + self.player.props.stream_info_value_array) + + def _init_video_sink(self): + self.bin = gst.Bin() + videoscale = gst.element_factory_make('videoscale') + self.bin.add(videoscale) + pad = videoscale.get_pad('sink') + ghostpad = gst.GhostPad('sink', pad) + self.bin.add_pad(ghostpad) + videoscale.set_property('method', 0) + + caps_string = 'video/x-raw-yuv, ' + r = self.videowidget.get_allocation() + if r.width > 500 and r.height > 500: + # Sigh... xvimagesink on the XOs will scale the video to fit + # but ximagesink in Xephyr does not. So we live with unscaled + # video in Xephyr so that the XO can work right. + w = 480 + h = float(w) / float(float(r.width) / float(r.height)) + caps_string += 'width=%d, height=%d' % (w, h) + else: + caps_string += 'width=480, height=360' + + caps = gst.Caps(caps_string) + self.filter = gst.element_factory_make('capsfilter', 'filter') + self.bin.add(self.filter) + self.filter.set_property('caps', caps) + + conv = gst.element_factory_make('ffmpegcolorspace', 'conv') + self.bin.add(conv) + videosink = gst.element_factory_make('autovideosink') + self.bin.add(videosink) + gst.element_link_many(videoscale, self.filter, conv, videosink) + self.player.set_property('video-sink', self.bin) + + def pause(self): + self.player.set_state(gst.STATE_PAUSED) + self.playing = False + logging.debug('pausing player') + + def play(self): + self.player.set_state(gst.STATE_PLAYING) + self.playing = True + self.error = False + logging.debug('playing player') + + def stop(self): + self.player.set_state(gst.STATE_NULL) + self.playing = False + logging.debug('stopped player') + return False + + def get_state(self, timeout=1): + return self.player.get_state(timeout=timeout) + + def is_playing(self): + return self.playing + + +class VideoWidget(gtk.DrawingArea): + + def __init__(self): + gtk.DrawingArea.__init__(self) + self.set_events(gtk.gdk.EXPOSURE_MASK) + self.imagesink = None + self.unset_flags(gtk.DOUBLE_BUFFERED) + self.set_flags(gtk.APP_PAINTABLE) + + def do_expose_event(self, event): + if self.imagesink: + self.imagesink.expose() + return False + else: + return True + + def set_sink(self, sink): + assert self.window.xid + self.imagesink = sink + self.imagesink.set_xwindow_id(self.window.xid) diff --git a/TurtleArt/tajail.py b/TurtleArt/tajail.py new file mode 100644 index 0000000..0444dc7 --- /dev/null +++ b/TurtleArt/tajail.py @@ -0,0 +1,60 @@ +#Copyright (c) 2009-10, Walter Bender (on behalf of 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. + +# A naive approach to running myfunc in a jail +import traceback +from time import * +from math import * + +from gettext import gettext as _ + +def myfunc(f, args): + ''' Run inline Python code ''' + # check to make sure no import calls are made + if len(args) == 1: + myf = 'def f(x): return ' + f.replace('import', '') + userdefined = {} + exec myf in globals(), userdefined + return userdefined.values()[0](args[0]) + elif len(args) == 2: + myf = 'def f(x, y): return ' + f.replace('import', '') + userdefined = {} + exec myf in globals(), userdefined + return userdefined.values()[0](args[0], args[1]) + elif len(args) == 3: + myf = 'def f(x, y, z): return ' + f.replace('import', '') + userdefined = {} + exec myf in globals(), userdefined + return userdefined.values()[0](args[0], args[1], args[2]) + + +def myfunc_import(parent, f, x): + ''' Run Python code imported from Journal ''' + if 'def myblock(lc,' in f: + base_class = parent.tw.lc # pre-v107, we passed lc + else: + base_class = parent.tw # as of v107, we pass tw + userdefined = {} + try: + exec f in globals(), userdefined + return userdefined['myblock'](base_class, x) + except: + traceback.print_exc() + return None diff --git a/TurtleArt/talogo.py b/TurtleArt/talogo.py new file mode 100644 index 0000000..1e5bf07 --- /dev/null +++ b/TurtleArt/talogo.py @@ -0,0 +1,908 @@ +# -*- coding: utf-8 -*- +#Copyright (c) 2007-8, Playful Invention Company. +#Copyright (c) 2008-12, Walter Bender +#Copyright (c) 2008-10, Raúl Gutiérrez Segalés + +#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 gtk +from time import time + +from operator import isNumberType +from UserDict import UserDict + +from taconstants import TAB_LAYER, DEFAULT_SCALE, PREFIX_DICTIONARY +from tapalette import block_names, value_blocks +from tautils import get_pixbuf_from_journal, convert, data_from_file, \ + text_media_type, round_int, debug_output + +from util.RtfParser import RtfTextOnly + +from gettext import gettext as _ + +media_blocks_dictionary = {} # new media blocks get added here +primitive_dictionary = {} # new block primitives get added here + + +class noKeyError(UserDict): + + __missing__ = lambda x, y: 0 + + +class symbol: + + def __init__(self, name): + self.name = name + self.nargs = None + self.fcn = None + + def __str__(self): + return self.name + + def __repr__(self): + return '#' + self.name + + +class logoerror(Exception): + + def __init__(self, value): + print value + self.value = value + + def __str__(self): + # return repr(self.value) + return str(self.value) + + +class HiddenBlock: + + def __init__(self, name, value=None): + self.name = name + self.values = [] + if value is not None: + self.values.append(value) + self.primitive = None + else: + self.primitive = name + self.connections = [] + self.docks = [] + +# Utility functions + + +def _just_stop(): + """ yield False to stop stack """ + yield False + + +def _millisecond(): + """ Current time in milliseconds """ + return time() * 1000 + + +class LogoCode: + """ A class for parsing Logo code """ + + def __init__(self, tw): + + self.tw = tw + self.oblist = {} + + DEFPRIM = {'(': [1, lambda self, x: self._prim_opar(x)], + 'define': [2, self._prim_define], + 'nop': [0, lambda self: None]} + + for p in iter(DEFPRIM): + if len(DEFPRIM[p]) == 2: + self.def_prim(p, DEFPRIM[p][0], DEFPRIM[p][1]) + else: + self.def_prim(p, DEFPRIM[p][0], DEFPRIM[p][1], DEFPRIM[p][2]) + + self.symtype = type(self._intern('print')) + self.listtype = type([]) + self.symnothing = self._intern('%nothing%') + self.symopar = self._intern('(') + self.iline = None + self.cfun = None + self.arglist = None + self.ufun = None + self.procstop = False + self.running = False + self.istack = [] + self.stacks = {} + self.boxes = {'box1': 0, 'box2': 0} + self.heap = [] + self.iresults = None + self.step = None + self.bindex = None + + self.hidden_turtle = None + + self.keyboard = 0 + self.trace = 0 + self.update_values = False + self.gplay = None + self.filepath = None + self.pixbuf = None + self.dsobject = None + self.start_time = None + + self.body_height = int((self.tw.canvas.height / 40) * self.tw.scale) + + self.scale = DEFAULT_SCALE + + def stop_logo(self): + """ Stop logo is called from the Stop button on the toolbar """ + self.tw.step_time = 0 + self.step = _just_stop() + for plugin in self.tw._plugins: + plugin.stop() + if self.tw.gst_available: + from tagplay import stop_media + stop_media(self) + self.tw.active_turtle.show() + + def def_prim(self, name, args, fcn, rprim=False): + """ Define the primitives associated with the blocks """ + sym = self._intern(name) + sym.nargs, sym.fcn = args, fcn + sym.rprim = rprim + + def _intern(self, string): + """ Add any new objects to the symbol list. """ + if string in self.oblist: + return self.oblist[string] + sym = symbol(string) + self.oblist[string] = sym + return sym + + def run_blocks(self, blk, blocks, run_flag): + """ Given a block to run... """ + for k in self.stacks.keys(): + self.stacks[k] = None + self.stacks['stack1'] = None + self.stacks['stack2'] = None + + # Save state in case there is a hidden macro expansion + self.save_blocks = None + self.save_blk = blk + self.save_while_blks = [] + + if self.trace > 0: + self.update_values = True + else: + self.update_values = False + + for b in blocks: + b.unhighlight() + + for b in blocks: + # Hidden macro expansions + if b.name in ['while', 'until', 'forever']: + action_blk, new_blocks = self._expand_forever(b, blk, blocks) + blocks = new_blocks[:] + if b == blk: + blk = action_blk + + for b in blocks: + if b.name == 'hat1': + code = self._blocks_to_code(b) + self.stacks['stack1'] = self._readline(code) + elif b.name == 'hat2': + code = self._blocks_to_code(b) + self.stacks['stack2'] = self._readline(code) + elif b.name == 'hat': + if b.connections is not None and len(b.connections) > 1 and \ + b.connections[1] is not None: + code = self._blocks_to_code(b) + try: + x = b.connections[1].values[0] + except IndexError: + self.tw.showlabel('#nostack') + self.tw.showblocks() + return None + if type(convert(x, float, False)) == float: + if int(float(x)) == x: + x = int(x) + self.stacks['stack3' + str(x)] = self._readline(code) + + code = self._blocks_to_code(blk) + + if self.save_blocks is not None: + # Undo any hidden macro expansion + blocks = self.save_blocks[:] + blk = self.save_blk + for b in self.save_while_blks: + if b[1] is not None: + b[0].connections[0].connections[b[1]] = b[0] + if b[2] is not None: + b[0].connections[-1].connections[b[2]] = b[0] + if b[3] is not None: + b[0].connections[-2].connections[b[3]] = b[0] + + if run_flag: + # debug_output("running code: %s" % (code), self.tw.running_sugar) + self.start_time = time() + self._setup_cmd(code) + else: + return code + + def _blocks_to_code(self, blk): + """ Convert a stack of blocks to pseudocode. """ + if blk is None: + return ['%nothing%', '%nothing%'] + code = [] + dock = blk.docks[0] + if len(dock) > 4: # There could be a '(', ')', '[' or ']'. + code.append(dock[4]) + if blk.primitive is not None: # make a tuple (prim, blk) + # special case: expand 'while' and 'until' primitives + try: + code.append((blk.primitive, + self.tw.block_list.list.index(blk))) + except ValueError: + code.append(blk.primitive) # Hidden block + elif len(blk.values) > 0: # Extract the value from content blocks. + if blk.name == 'number': + try: + code.append(float(blk.values[0])) + except ValueError: + code.append(float(ord(blk.values[0][0]))) + elif blk.name == 'string' or \ + blk.name == 'title': # deprecated block + if type(blk.values[0]) == float or \ + type(blk.values[0]) == int: + if int(blk.values[0]) == blk.values[0]: + blk.values[0] = int(blk.values[0]) + code.append('#s' + str(blk.values[0])) + else: + code.append('#s' + blk.values[0]) + elif blk.name in PREFIX_DICTIONARY: + if blk.values[0] is not None: + code.append(PREFIX_DICTIONARY[blk.name] + \ + str(blk.values[0])) + else: + code.append(PREFIX_DICTIONARY[blk.name] + 'None') + elif blk.name in media_blocks_dictionary: + code.append('#smedia_' + blk.name.upper()) + else: + return ['%nothing%'] + else: + return ['%nothing%'] + if blk.connections is not None and len(blk.connections) > 0: + for i in range(1, len(blk.connections)): + b = blk.connections[i] + dock = blk.docks[i] + if len(dock) > 4: # There could be a '(', ')', '[' or ']'. + for c in dock[4]: + code.append(c) + if b is not None: + code.extend(self._blocks_to_code(b)) + elif blk.docks[i][0] not in ['flow', 'unavailable']: + code.append('%nothing%') + return code + + def _setup_cmd(self, string): + """ Execute the psuedocode. """ + self.hidden_turtle = self.tw.active_turtle + self.hidden_turtle.hide() # Hide the turtle while we are running. + self.procstop = False + blklist = self._readline(string) + self.step = self._start_eval(blklist) + + def _readline(self, line): + """ + Convert the pseudocode into a list of commands. + The block associated with the command is stored as the second element + in a tuple, e.g., (#forward, 16) + """ + # debug_output(line, self.tw.running_sugar) + res = [] + while line: + token = line.pop(0) + bindex = None + if type(token) == tuple: + (token, bindex) = token + if isNumberType(token): + res.append(token) + elif token.isdigit(): + res.append(float(token)) + elif token[0] == '-' and token[1:].isdigit(): + res.append(-float(token[1:])) + elif token[0] == '"': + res.append(token[1:]) + elif token[0:2] == "#s": + res.append(token[2:]) + elif token == '[': + res.append(self._readline(line)) + elif token == ']': + return res + elif bindex is None or type(bindex) is not int: + res.append(self._intern(token)) + else: + res.append((self._intern(token), bindex)) + return res + + def _start_eval(self, blklist): + """ Step through the list. """ + if self.tw.running_sugar: + self.tw.activity.stop_turtle_button.set_icon("stopiton") + self.tw.activity.stop_turtle_button.set_tooltip( + _('Stop turtle')) + elif self.tw.interactive_mode: + self.tw.toolbar_shapes['stopiton'].set_layer(TAB_LAYER) + self.running = True + self.icall(self.evline, blklist) + yield True + if self.tw.running_sugar: + # self.tw.activity.stop_turtle_button.set_icon("stopitoff") + if self.tw.step_time == 0 and self.tw.selected_blk is None: + self.tw.activity.stop_turtle_button.set_icon("hideshowoff") + self.tw.activity.stop_turtle_button.set_tooltip( + _('Show blocks')) + else: + self.tw.activity.stop_turtle_button.set_icon("stopitoff") + self.tw.activity.stop_turtle_button.set_tooltip( + _('Stop turtle')) + elif self.tw.interactive_mode: + self.tw.toolbar_shapes['stopiton'].hide() + yield False + self.running = False + + def icall(self, fcn, *args): + """ Add a function and its arguments to the program stack. """ + self.istack.append(self.step) + self.step = fcn(*(args)) + + def evline(self, blklist): + """ Evaluate a line of code from the list. """ + oldiline = self.iline + self.iline = blklist[:] + self.arglist = None + while self.iline: + token = self.iline[0] + self.bindex = None + if type(token) == tuple: + (token, self.bindex) = self.iline[0] + + # If the blocks are visible, highlight the current block. + if not self.tw.hide and self.bindex is not None: + self.tw.block_list.list[self.bindex].highlight() + + # In debugging modes, we pause between steps and show the turtle. + if self.tw.step_time > 0: + self.tw.active_turtle.show() + endtime = _millisecond() + self.tw.step_time * 100. + while _millisecond() < endtime: + yield True + self.tw.active_turtle.hide() + + # 'Stand-alone' booleans are handled here. + if token == self.symopar: + token = self.iline[1] + if type(token) == tuple: + (token, self.bindex) = self.iline[1] + + # Process the token and any arguments. + self.icall(self._eval) + yield True + + # Time to unhighlight the current block. + if not self.tw.hide and self.bindex is not None: + self.tw.block_list.list[self.bindex].unhighlight() + + if self.procstop: + break + if self.iresult == None: + continue + + if self.bindex is not None: + self.tw.block_list.list[self.bindex].highlight() + self.tw.showblocks() + raise logoerror(str(self.iresult)) + self.iline = oldiline + self.ireturn() + if not self.tw.hide and self.tw.step_time > 0: + self.tw.display_coordinates() + yield True + + def _eval(self): + """ Evaluate the next token on the line of code we are processing. """ + token = self.iline.pop(0) + bindex = None + if type(token) == tuple: + (token, bindex) = token + + # Either we are processing a symbol or a value. + if type(token) == self.symtype: + # We highlight blocks here in case an error occurs... + if not self.tw.hide and bindex is not None: + self.tw.block_list.list[bindex].highlight() + self.icall(self._evalsym, token) + yield True + # and unhighlight if everything was OK. + if not self.tw.hide and bindex is not None: + self.tw.block_list.list[bindex].unhighlight() + res = self.iresult + else: + res = token + + self.ireturn(res) + yield True + + def _evalsym(self, token): + """ Process primitive associated with symbol token """ + self._undefined_check(token) + oldcfun, oldarglist = self.cfun, self.arglist + self.cfun, self.arglist = token, [] + + if token.nargs == None: + self.tw.showblocks() + raise logoerror("#noinput") + for i in range(token.nargs): + self._no_args_check() + self.icall(self._eval) + yield True + self.arglist.append(self.iresult) + if self.cfun.rprim: + if type(self.cfun.fcn) == self.listtype: + # debug_output('evalsym rprim list: %s' % (str(token)), + # self.tw.running_sugar) + self.icall(self._ufuncall, self.cfun.fcn) + yield True + else: + self.icall(self.cfun.fcn, *self.arglist) + yield True + result = None + else: + result = self.cfun.fcn(self, *self.arglist) + self.cfun, self.arglist = oldcfun, oldarglist + if self.arglist is not None and result == None: + self.tw.showblocks() + raise logoerror("%s %s %s" % \ + (oldcfun.name, _("did not output to"), self.cfun.name)) + self.ireturn(result) + yield True + + def _ufuncall(self, body): + """ ufuncall """ + self.ijmp(self.evline, body) + yield True + + def doevalstep(self): + """ evaluate one step """ + starttime = _millisecond() + try: + while (_millisecond() - starttime) < 120: + try: + if self.step is not None: + try: + self.step.next() + except ValueError: + debug_output('generator already executing', + self.tw.running_sugar) + return False + else: + return False + except StopIteration: + # self.tw.turtles.show_all() + if self.hidden_turtle is not None: + self.hidden_turtle.show() + self.hidden_turtle = None + else: + self.tw.active_turtle.show() + return False + except logoerror, e: + self.tw.showblocks() + self.tw.showlabel('syntaxerror', str(e)) + self.tw.turtles.show_all() + return False + return True + + def ireturn(self, res=None): + """ return value """ + self.step = self.istack.pop() + self.iresult = res + + def ijmp(self, fcn, *args): + """ ijmp """ + self.step = fcn(*(args)) + + def _undefined_check(self, token): + """ Make sure token has a definition """ + if token.fcn is not None: + return False + if token.name == '%nothing%': + errormsg = '' + else: + errormsg = "%s %s" % (_("I don't know how to"), _(token.name)) + self.tw.showblocks() + raise logoerror(errormsg) + + def _no_args_check(self): + """ Missing argument ? """ + if self.iline and self.iline[0] is not self.symnothing: + return + self.tw.showblocks() + raise logoerror("#noinput") + + # + # Primitives + # + + def _prim_opar(self, val): + self.iline.pop(0) + return val + + def _prim_define(self, name, body): + """ Define a primitive """ + if type(name) is not self.symtype: + name = self._intern(name) + name.nargs, name.fcn = 0, body + name.rprim = True + + def prim_clear(self): + """ Clear screen """ + self.tw.clear_plugins() + if self.tw.gst_available: + from tagplay import stop_media + # stop_media(self) # TODO: gplay variable + self.tw.canvas.clearscreen() + self.scale = DEFAULT_SCALE + self.hidden_turtle = None + self.start_time = time() + for name in value_blocks: + self.update_label_value(name) + + def int(self, n): + """ Raise an error if n doesn't convert to int. """ + if type(n) == int: + return n + elif type(n) == float: + return int(n) + elif type(n) == str: + return int(ord(n[0])) + else: + self.tw.showblocks() + raise logoerror("%s %s %s %s" \ + % (self.cfun.name, _("doesn't like"), str(n), _("as input"))) + + def find_value_blocks(self): + """ Find any value blocks that may need label updates """ + self.value_blocks_to_update = {} + for name in value_blocks: + self.value_blocks_to_update[name] = \ + self.tw.block_list.get_similar_blocks('block', name) + + def update_label_value(self, name, value=None): + """ Update the label of value blocks to reflect current value """ + if not self.tw.interactive_mode: + return + if self.tw.hide: + return + self.tw.display_coordinates() + if value is None: + for block in self.value_blocks_to_update[name]: + block.spr.set_label(block_names[name][0]) + block.resize() + elif self.update_values: + if type(value) == float: + valstring = str(round_int(value)).replace('.', + self.tw.decimal_point) + else: + valstring = str(value) + for block in self.value_blocks_to_update[name]: + block.spr.set_label(block_names[name][0] + ' = ' + valstring) + block.resize() + + def push_file_data_to_heap(self, dsobject): + """ push contents of a data store object (assuming json encoding) """ + data = data_from_file(dsobject.file_path) + if data is not None: + for val in data: + self.heap.append(val) + self.update_label_value('pop', self.heap[-1]) + + def x2tx(self): + """ Convert screen coordinates to turtle coordinates """ + return int(self.tw.canvas.width / 2) + int(self.tw.canvas.xcor) + + def y2ty(self): + """ Convert screen coordinates to turtle coordinates """ + return int(self.tw.canvas.height / 2) - int(self.tw.canvas.ycor) + + def wpercent(self): + """ width as a percentage of screen coordinates """ + return int((self.tw.canvas.width * self.scale) / 100.) + + def hpercent(self): + """ height as a percentage of screen coordinates """ + return int((self.tw.canvas.height * self.scale) / 100.) + + def insert_image(self, center=False, filepath=None, resize=True, + offset=False, pixbuf=False): + """ Image only (at current x, y) """ + if filepath is not None: + self.filepath = filepath + if not pixbuf: + self.pixbuf = None + w, h = self.wpercent(), self.hpercent() + if w < 1 or h < 1: + return + if pixbuf: # We may have to rescale the picture + if w != self.pixbuf.get_width() or h != self.pixbuf.get_height(): + self.pixbuf = self.pixbuf.scale_simple( + w, h, gtk.gdk.INTERP_BILINEAR) + elif self.dsobject is not None: + try: + self.pixbuf = get_pixbuf_from_journal(self.dsobject, w, h) + except: + debug_output("Couldn't open dsobject %s" % (self.dsobject), + self.tw.running_sugar) + if self.pixbuf is None and \ + self.filepath is not None and \ + self.filepath != '': + try: + if not resize: + self.pixbuf = gtk.gdk.pixbuf_new_from_file(self.filepath) + w = self.pixbuf.get_width() + h = self.pixbuf.get_height() + else: + self.pixbuf = gtk.gdk.pixbuf_new_from_file_at_size( + self.filepath, w, h) + except: + self.tw.showlabel('nojournal', self.filepath) + debug_output("Couldn't open filepath %s" % (self.filepath), + self.tw.running_sugar) + if self.pixbuf is not None: + x = self.tw.canvas.xcor + y = self.tw.canvas.ycor + w *= self.tw.coord_scale + h *= self.tw.coord_scale + if center: + self.tw.canvas.draw_pixbuf(self.pixbuf, 0, 0, + self.x2tx() - int(w / 2), + self.y2ty() - int(h / 2), w, h, + self.filepath) + elif offset: + self.tw.canvas.draw_pixbuf(self.pixbuf, 0, 0, + self.x2tx(), + self.y2ty() - h, + w, h, self.filepath) + else: + self.tw.canvas.draw_pixbuf(self.pixbuf, 0, 0, + self.x2tx(), + self.y2ty(), + w, h, self.filepath) + + def insert_desc(self, mimetype=None, description=None): + """ Description text only (at current x, y) """ + w = self.wpercent() + if w < 1: + return + text = None + if text_media_type(self.filepath): + if mimetype == 'application/rtf' or \ + self.filepath.endswith(('rtf')): + text_only = RtfTextOnly() + for line in open(self.filepath, 'r'): + text_only.feed(line) + text = text_only.output + else: + try: + f = open(self.filepath, 'r') + text = f.read() + f.close() + except IOError: + self.tw.showlabel('nojournal', self.filepath) + debug_output("Couldn't open %s" % (self.filepath), + self.tw.running_sugar) + else: + if description is not None: + text = str(description) + else: + text = self.filepath + if text is not None: + self.tw.canvas.draw_text(text, self.x2tx(), self.y2ty(), + self.body_height, w) + + def media_wait(self): + """ Wait for media to stop playing """ + if self.tw.gst_available: + from tagplay import media_playing + while(media_playing(self)): + yield True + self.ireturn() + yield True + + def play_sound(self): + """ Sound file from Journal """ + if self.tw.gst_available: + from tagplay import play_audio_from_file + play_audio_from_file(self, self.filepath) + + def play_video(self): + """ Movie file from Journal """ + w, h = self.wpercent(), self.hpercent() + if w < 1 or h < 1: + return + if self.tw.gst_available: + from tagplay import play_movie_from_file + play_movie_from_file(self, self.filepath, self.x2tx(), self.y2ty(), + w, h) + + def _expand_forever(self, b, blk, blocks): + """ Expand a while or until block into: forever, ifelse, stopstack + Expand a forever block to run in a separate stack """ + + # TODO: create a less brittle way of doing this; having to + # manage the connections and flows locally means we may run + # into trouble if any of these block types (forever, while, + # until. ifelse, stopstack, or stack) is changed in tablock.py + if b.name == 'while': + while_blk = True + else: + while_blk = False + if b.name == 'until': + until_blk = True + else: + until_blk = False + + # We'll restore the original blocks when we are finished + if self.save_blocks is None: + self.save_blocks = blocks[:] + + # Create an action block that will jump to the new stack + action_name = '#s_forever %d' % (len(self.save_while_blks) + 1) + action_blk = HiddenBlock('stack') + action_label_blk = HiddenBlock('string', value=action_name) + + # Create the blocks we'll put in the new stack + forever_blk = HiddenBlock('forever') + if while_blk or until_blk: + ifelse_blk = HiddenBlock('ifelse') + stopstack_blk = HiddenBlock('stopstack') + inflow = None + whileflow = None + outflow = None + boolflow = None + if b.connections is not None: + inflow = b.connections[0] + if while_blk or until_blk: + boolflow = b.connections[1] + whileflow = b.connections[-2] + outflow = b.connections[-1] + + # Create action block(s) to run the code inside the forever loop + if until_blk and whileflow is not None: # run until flow at least once + action_flow_name = '#s_flow %d' % (len(self.save_while_blks) + 1) + action_first = HiddenBlock('stack') + first_label_blk = HiddenBlock('string', value=action_flow_name) + + # Assign new connections and build the docks + if inflow is not None: + i = inflow.connections.index(b) + if until_blk and whileflow is not None: + inflow.connections[i] = action_first + else: + inflow.connections[i] = action_blk + else: + i = None + if outflow is not None: + j = outflow.connections.index(b) + outflow.connections[j] = action_blk + else: + j = None + + if until_blk and whileflow is not None: + action_first.connections.append(inflow) + action_first.docks.append(['flow', True, 0, 0]) + action_first.connections.append(first_label_blk) + action_first.docks.append(['number', False, 0, 0]) + action_first.connections.append(action_blk) + action_first.docks.append(['flow', False, 0, 0]) + first_label_blk.connections.append(action_first) + first_label_blk.docks.append(['number', True, 0, 0]) + action_blk.connections.append(action_first) + else: + action_blk.connections.append(inflow) + action_blk.docks.append(['flow', True, 0, 0]) + action_blk.connections.append(action_label_blk) + action_blk.docks.append(['number', False, 0, 0]) + action_blk.connections.append(outflow) + action_blk.docks.append(['flow', False, 0, 0]) + action_label_blk.connections.append(action_blk) + action_label_blk.docks.append(['number', True, 0, 0]) + + forever_blk.connections.append(None) + forever_blk.docks.append(['flow', True, 0, 0]) + if while_blk or until_blk: + forever_blk.connections.append(ifelse_blk) + else: + forever_blk.connections.append(whileflow) + forever_blk.docks.append(['flow', False, 0, 0, '[']) + forever_blk.connections.append(outflow) + forever_blk.docks.append(['flow', False, 0, 0, ']']) + if while_blk or until_blk: + ifelse_blk.connections.append(forever_blk) + ifelse_blk.docks.append(['flow', True, 0, 0]) + ifelse_blk.connections.append(boolflow) + ifelse_blk.docks.append(['bool', False, 0, 0]) + if while_blk: + ifelse_blk.connections.append(whileflow) + ifelse_blk.connections.append(stopstack_blk) + else: # until + ifelse_blk.connections.append(stopstack_blk) + ifelse_blk.connections.append(whileflow) + ifelse_blk.docks.append(['flow', False, 0, 0, '[']) + ifelse_blk.docks.append(['flow', False, 0, 0, '][']) + ifelse_blk.connections.append(None) + ifelse_blk.docks.append(['flow', False, 0, 0, ']']) + stopstack_blk.connections.append(ifelse_blk) + stopstack_blk.docks.append(['flow', False, 0, 0]) + + if whileflow is not None: + if while_blk or until_blk: + whileflow.connections[0] = ifelse_blk + else: + whileflow.connections[0] = forever_blk + + # Create a separate stacks for the forever loop and the whileflow + code = self._blocks_to_code(forever_blk) + self.stacks['stack3' + str(action_name)] = self._readline(code) + if until_blk and whileflow is not None: + # Create a stack from the whileflow to be called from + # action_first, but then reconnect it to the ifelse block + c = whileflow.connections[0] + whileflow.connections[0] = None + code = self._blocks_to_code(whileflow) + self.stacks['stack3' + str(action_flow_name)] = \ + self._readline(code) + whileflow.connections[0] = c + + # Save the connections so we can restore them later + if whileflow is not None: + self.save_while_blks.append([b, i, j, 0]) + else: + self.save_while_blks.append([b, i, j, None]) + + # Insert the new blocks into the stack + i = blocks.index(b) + if i == 0: + blocks_left = [] + else: + blocks_left = blocks[0:i] + if i == len(blocks) - 1: + blocks_right = [] + else: + blocks_right = blocks[i + 1:] + blocks = blocks_left[:] + if until_blk and whileflow is not None: + blocks.append(action_first) + blocks.append(action_blk) + blocks.append(forever_blk) + if while_blk or until_blk: + blocks.append(ifelse_blk) + blocks.append(stopstack_blk) + blocks.extend(blocks_right) + + if until_blk and whileflow is not None: + return action_first, blocks + else: + return action_blk, blocks diff --git a/TurtleArt/tapalette.py b/TurtleArt/tapalette.py new file mode 100644 index 0000000..ad96103 --- /dev/null +++ b/TurtleArt/tapalette.py @@ -0,0 +1,376 @@ +#!/usr/bin/env python +#Copyright (c) 2011,12 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. + +help_palettes = {} +help_windows = {} +palette_names = [] +palette_blocks = [] +block_colors = [] +expandable_blocks = [] +block_names = {} +block_primitives = {} +default_values = {} +logo_commands = {} +logo_functions = {} +special_names = {} # Names for blocks without names for popup help +content_blocks = ['number', 'string', 'description', 'audio', 'video', + 'journal'] +hidden_proto_blocks = [] # proto blocks that are (at least initially) hidden +value_blocks = [] # blocks whose labels are updated get added here +special_block_colors = {} +string_or_number_args = [] +block_styles = {'basic-style': [], + 'blank-style': [], + 'basic-style-head': [], + 'basic-style-head-1arg': [], + 'basic-style-tail': [], + 'basic-style-extended': [], + 'basic-style-extended-vertical': [], + 'basic-style-1arg': [], + 'basic-style-2arg': [], + 'basic-style-3arg': [], + 'basic-style-var-arg': [], + 'bullet-style': [], + 'invisible': [], + 'box-style': [], + 'box-style-media': [], + 'number-style': [], + 'number-style-var-arg': [], + 'number-style-block': [], + 'number-style-porch': [], + 'number-style-1arg': [], + 'number-style-1strarg': [], + 'compare-style': [], + 'compare-porch-style': [], + 'boolean-style': [], + 'not-style': [], + 'flow-style': [], + 'flow-style-tail': [], + 'flow-style-1arg': [], + 'flow-style-boolean': [], + 'flow-style-while': [], + 'flow-style-else': [], + 'collapsible-top': [], + 'collapsible-top-no-arm': [], + 'collapsible-top-no-label': [], + 'collapsible-top-no-arm-no-label': [], + 'collapsible-bottom': [], + 'portfolio-style-2x2': [], + 'portfolio-style-1x1': [], + 'portfolio-style-2x1': [], + 'portfolio-style-1x2': []} + + +import gtk + +from sugar.graphics.icon import Icon +from sugar.graphics import style + +from taconstants import EXPANDABLE_STYLE +from tautils import debug_output + +from util.helpbutton import add_section, add_paragraph + +from gettext import gettext as _ + +help_strings = { + 'next': _('displays next palette'), + 'orientation': _("changes the orientation of the palette of blocks") + } + + +class Palette(): + """ a class for defining new palettes """ + + def __init__(self, name, colors=["#00FF00", "#00A000"], position=None): + self._name = name + self._special_name = _(name) + self._colors = colors + self._max_text_width = int(gtk.gdk.screen_width() / 3) - 20 + + # Prepare a vbox for the help palette + if not self._name in help_palettes: + self._help_box = gtk.VBox() + self._help_box.set_homogeneous(False) + help_palettes[self._name] = self._help_box + help_windows[self._name] = gtk.ScrolledWindow() + help_windows[self._name].set_size_request( + int(gtk.gdk.screen_width() / 3), + gtk.gdk.screen_height() - style.GRID_CELL_SIZE * 3) + help_windows[self._name].set_policy( + gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) + help_windows[self._name].add_with_viewport( + help_palettes[self._name]) + help_palettes[self._name].show() + self._help = None + else: + self._help_box = help_palettes[self._name] + self._help = 'deja vu' + + def add_palette(self, position=None): + if self._name is None: + debug_output('You must specify a name for your palette') + return + + # Insert new palette just before the trash + if 'trash' in palette_names: + i = palette_names.index('trash') + else: + i = len(palette_names) + + if position is not None and type(position) is int and position < i: + i = position + + if self._name not in palette_names: + palette_names.insert(i, self._name) + palette_blocks.insert(i, []) + block_colors.insert(i, self._colors) + else: + return + + # Special name entry is needed for help hover mechanism + special_names[self._name] = self._special_name + if self._help is not None: + help_strings[self._name] = self._help + else: + help_strings[self._name] = '' + + def set_help(self, help): + if self._help is None: + self._help = help + if hasattr(self, '_help_box'): + add_section(self._help_box, self._help, icon=self._name + 'off') + + def set_special_name(self, name): + self._special_name = name + + def add_block(self, block_name, style='basic-block', label=None, + special_name=None, default=None, prim_name=None, + help_string=None, value_block=False, content_block=False, + logo_command=None, hidden=False, colors=None, + string_or_number=False): + """ Add a new block to the palette """ + block = Block(block_name) + block.set_style(style) + if label is not None: + block.set_label(label) + if special_name is not None: + block.set_special_name(special_name) + if default is not None: + if default == 'None': + block.set_default(None) + else: + block.set_default(default) + if prim_name is not None: + block.set_prim_name(prim_name) + if logo_command is not None: + block.set_logo_command(logo_command) + if help_string is not None: + block.set_help(help_string) + if not hidden: + first_arg = None + if special_name is None: + if type(label) == list: + first_arg = label[0] + else: + first_arg = label + else: + first_arg = special_name + if first_arg is None or first_arg == '' or first_arg == ' ': + add_paragraph(self._help_box, '%s' % (help_string)) + else: + add_paragraph(self._help_box, '%s: %s' % (first_arg, + help_string)) + if colors is not None: + block.set_colors(colors) + if string_or_number: + block.set_string_or_number() + block.set_value_block(value_block) + block.set_content_block(content_block) + block.set_palette(self._name) + if hidden: + block.set_hidden() + block.add_block() + + +def make_palette(palette_name, colors=None, help_string=None, position=None): + """ Palette helper function """ + if colors is None: + palette = Palette(palette_name) + else: + palette = Palette(palette_name, colors) + if help_string is not None: + palette.set_help(help_string) + palette.add_palette(position) + return palette + + +def palette_name_to_index(palette_name): + ''' Find the index associated with palette_name. ''' + if palette_name in palette_names: + return palette_names.index(palette_name) + else: + return None + + +def define_logo_function(key, value): + ''' Add a logo function to the table (not necessarily associated + with a block, e.g., color lookup tables) ''' + logo_functions[key] = value + + +class Block(): + """ a class for defining new block primitives """ + + def __init__(self, name): + self._name = name + self._special_name = None + self._palette = None + self._style = None + self._label = None + self._default = None + self._help = None + self._prim_name = None + self._logo_command = None + self._value_block = False + self._content_block = False + self._colors = None + self._hidden = False + self._string_or_number = False + + def add_block(self, position=None): + if self._name is None: + debug_output('You must specify a name for your block') + return + + # FIXME: Does the block already exist? A block can live on + # multiple palettes, but it can only have one set of + # atttributes. So if this is a redefinition, remove it from + # all lists except palettes before regeneration. + + if self._style is None: + debug_output('You must specify a style for your block') + return + else: + block_styles[self._style].append(self._name) + + if self._label is not None: + block_names[self._name] = self._label + + if self._palette is not None: + i = palette_names.index(self._palette) + if self._name in palette_blocks[i]: + debug_output('%s already in palette %s, skipping...' % ( + self._name, self._palette)) + else: + if position is not None and type(position) is int and \ + position < len(palette_blocks[i]): + palette_blocks[i].insert(position, self._name) + else: + palette_blocks[i].append(self._name) + if position is not None: + debug_output('Ignoring position (%s)' % (str(position))) + + if self._help is not None: + help_strings[self._name] = self._help + else: + help_strings[self._name] = '' + + if self._value_block: + value_blocks.append(self._name) + + if self._content_block: + content_blocks.append(self._name) + + if self._prim_name is not None: + block_primitives[self._name] = self._prim_name + + if self._logo_command is not None and self._prim_name is not None: + logo_commands[self._prim_name] = self._logo_command + + if self._default is not None: + default_values[self._name] = self._default + + if self._special_name is not None: + special_names[self._name] = self._special_name + + if self._style in EXPANDABLE_STYLE: + expandable_blocks.append(self._name) + + if self._colors is not None: + special_block_colors[self._name] = self._colors + + if self._string_or_number: + string_or_number_args.append(self._name) + + if self._hidden: + hidden_proto_blocks.append(self._name) + + def set_hidden(self): + self._hidden = True + + def set_colors(self, colors=None): + self._colors = colors + + def set_string_or_number(self, flag=True): + self._string_or_number = flag + + def set_value_block(self, value=True): + self._value_block = value + + def set_content_block(self, value=True): + self._content_block = value + + def set_palette(self, palette): + if not palette in palette_names: + debug_output('Could not find palette %s' % (palette)) + else: + self._palette = palette + + def set_help(self, help): + self._help = help + + def set_special_name(self, name): + self._special_name = name + + def set_label(self, label): + if type(label) == type([]): + self._label = label[:] + else: + self._label = [label] + + def set_default(self, default): + if type(default) == type([]): + self._default = default[:] + else: + self._default = [default] + + def set_style(self, style): + if style not in block_styles: + debug_output('Unknown style: %s' % (style)) + else: + self._style = style + + def set_prim_name(self, prim_name): + self._prim_name = prim_name + + def set_logo_command(self, logo_command): + self._logo_command = logo_command diff --git a/TurtleArt/tasprite_factory.py b/TurtleArt/tasprite_factory.py new file mode 100755 index 0000000..2b0e922 --- /dev/null +++ b/TurtleArt/tasprite_factory.py @@ -0,0 +1,1233 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +#Copyright (c) 2009-12 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 os + +from taconstants import HIT_RED, HIT_GREEN, HIDE_WHITE, SHOW_WHITE, \ + PALETTE_COLOR, TOOLBAR_COLOR + + +class SVG: + + def __init__(self): + self._x = 0 + self._y = 0 + self._min_x = 10000 + self._min_y = 10000 + self._max_x = -10000 + self._max_y = -10000 + self._width = 0 + self._height = 0 + self.docks = [] + self._scale = 1 + self._orientation = 0 + self._radius = 8 + self._stroke_width = 1 + self._innie = [False] + self._outie = False + self._innie_x1 = (9 - self._stroke_width) / 2 + self._innie_y1 = 3 + self._innie_x2 = (9 - self._stroke_width) / 2 + self._innie_y2 = (9 - self._stroke_width) / 2 + self._innie_spacer = 9 + self._slot = True + self._cap = False + self._tab = True + self._bool = False + self._slot_x = 10 + self._slot_y = 2 + self._tail = False + self._porch = False + self._porch_x = self._innie_x1 + self._innie_x2 + \ + 4 * self._stroke_width + self._porch_y = self._innie_y2 + self._expand_x = 0 + self._expand_y = 0 + self._arm = True + self._else = False + self._draw_innies = True + self._hide = False + self._show = False + self._show_x = 0 + self._show_y = 0 + self._hide_x = 0 + self._hide_y = 0 + self._dot_radius = 8 + self._fill = "#00FF00" + self._stroke = "#00A000" + self._gradient_color = "#FFFFFF" + self._gradient = False + self.margins = [0, 0, 0, 0] + + """ + The block construction methods typically start on the left side of + a block and proceed clockwise around the block, first constructing a + left-side connector ("outie"), a corner (1, -1), a slot or hat on along + the top, a corner (1, 1), right side connectors ("innie"), possibly a + "porch" to suggest an order of arguments, another corner (-1, 1), + a tab or tail, and the fourth corner (-1, -1). + """ + + def basic_block(self): + ''' The most common block type: used for 0, 1, 2, or 3 + argument commands, stacks, et al. ''' + self.reset_min_max() + (x, y) = self._calculate_x_y() + self.margins[2] = 0 + self.margins[3] = 0 + svg = self.new_path(x, y) + svg += self._corner(1, -1) + svg += self._do_slot() + svg += self._rline_to(self._expand_x, 0) + xx = self._x + svg += self._corner(1, 1) + for i in range(len(self._innie)): + if self._innie[i] is True: + svg += self._do_innie() + if i == 0: + svg += self._rline_to(0, self._expand_y) + if i == 0 and self._porch is True: + svg += self._do_porch(False) + elif len(self._innie) - 1 > i: + svg += self._rline_to(0, + 2 * self._innie_y2 + self._innie_spacer) + # moved expand_y to just after first innie above + # svg += self._rline_to(0, self._expand_y) + svg += self._corner(-1, 1) + svg += self.line_to(xx, self._y) + svg += self._rline_to(-self._expand_x, 0) + if self._tab: + svg += self._do_tab() + else: + svg += self._do_tail() + svg += self._corner(-1, -1) + svg += self._rline_to(0, -self._expand_y) + if True in self._innie: + svg += self.line_to(x, self._radius + self._innie_y2 + \ + self._stroke_width / 2.0) + svg += self._do_outie() + self.calc_w_h() + svg += self._close_path() + svg += self.style() + if self._show is True: + svg += self._show_dot() + if self._hide is True: + svg += self._hide_dot() + svg += self.footer() + return self.header() + svg + + def invisible(self): + ''' A block that is invisible but still has connectors: used + when collapsing stacks. ''' + self.reset_min_max() + (x, y) = self._calculate_x_y() + self.margins[2] = 0 + self.margins[3] = 0 + # calculate shape but don't include it in the svg output + self.new_path(x, y) + self._corner(1, -1) + self._do_slot() + xx = self._x + self._corner(1, 1) + self._corner(-1, 1) + self._do_tab() + self._corner(-1, -1) + self.calc_w_h() + self._close_path() + self.style() + return self.header() + self.footer() + + def basic_flow(self): + ''' A flow block includes an arm that holds a branch in the flow ''' + self.reset_min_max() + (x, y) = self._calculate_x_y() + self.margins[2] = 0 + self.margins[3] = 0 + svg = self.new_path(x, y) + svg += self._corner(1, -1) + svg += self._do_slot() + xx = self._x + svg += self._rline_to(self._expand_x, 0) + if self._bool: + svg += self._corner(1, 1, 90, 0, 1, True, False) + elif True in self._innie: + svg += self._corner(1, 1) + for i in range(len(self._innie)): + if self._innie[i] is True: + svg += self._do_innie() + svg += self._rline_to(0, self._innie_spacer) + else: + self.margins[2] = \ + int((self._x - self._stroke_width + 0.5) * self._scale) + if self._bool is True: + svg += self._rline_to(0, self._radius / 2.0) + svg += self._do_boolean() + svg += self._rline_to(0, self._stroke_width) + if self._else: + svg += self._rline_to(self._radius * 3 + self._slot_x * 2, 0) + else: + svg += self._rline_to(self._radius + self._slot_x, 0) + save_y = self._y + hh = self._x + svg += self._corner(1, 1) + svg += self._rline_to(-self._radius, 0) + if self._else: + svg += self._do_tab() + svg += self._rline_to(-self._radius * 2, 0) + svg += self._do_tab() + svg += self._inverse_corner(-1, 1, 90, 0, 0, True, False) + svg += self._rline_to(0, self._expand_y) + svg += self._corner(-1, 1, 90, 0, 1, False, True) + svg += self.line_to(xx, self._y) + if self._tab: + svg += self._do_tab() + else: + svg += self._do_tail() + svg += self._corner(-1, -1) + svg += self._rline_to(0, -self._expand_y) + if True in self._innie: + svg += self.line_to(x, self._radius + self._innie_y2 + \ + self._stroke_width) + svg += self._close_path() + self.calc_w_h() + svg += self.style() + if self._hide is True: + svg += self._hide_dot() + if self._show is True: + svg += self._show_dot() + svg += self.footer() + if self._bool is True: # move secondary labels to arm + self.margins[2] = self._radius * 1.5 * self._scale + self.margins[3] = (self._max_y - save_y - self._radius + \ + self._stroke_width) * self._scale + return self.header() + svg + + def portfolio(self): + ''' Deprecated block ''' + self.reset_min_max() + (x, y) = self._calculate_x_y() + self.margins[0] = int(x + 2 * self._stroke_width + 0.5) + self.margins[1] = int(y + self._stroke_width + 0.5 + self._slot_y) + self.margins[2] = 0 + self.margins[3] = 0 + x += self._innie_x1 + self._innie_x2 + svg = self.new_path(x, y) + svg += self._corner(1, -1) + svg += self._do_slot() + xx = self._x + svg += self._rline_to(self._expand_x, 0) + svg += self._corner(1, 1) + svg += self._rline_to(0, self._expand_y) + for i in range(len(self._innie)): + if self._innie[i] is True and i > 0 and self._draw_innies: + svg += self._do_innie() + svg += self._rline_to(0, 2 * self._innie_y2 + \ + self._innie_spacer) + else: + svg += self._rline_to(0, 2 * self._innie_y2 + \ + self._innie_spacer) + svg += self._corner(-1, 1) + svg += self.line_to(xx, self._y) + svg += self._do_tab() + svg += self._corner(-1, -1) + for i in range(len(self._innie)): + if self._innie[len(self._innie) - i - 1] is True: + svg += self._rline_to(0, -2 * self._innie_y2 - \ + self._innie_spacer) + svg += self._do_reverse_innie() + else: + svg += self._rline_to(0, -2 * self._innie_y2 - \ + self._innie_spacer) + svg += self._close_path() + self.calc_w_h() + svg += self.style() + svg += self.footer() + return self.header() + svg + + def basic_box(self): + ''' Basic argument style used for numbers, text, media ''' + self.reset_min_max() + self.set_outie(True) + x = self._stroke_width / 2.0 + self._innie_x1 + self._innie_x2 + self.margins[0] = int((x + self._stroke_width + 0.5) * self._scale) + self.margins[1] = int((self._stroke_width + 0.5) * self._scale) + self.margins[2] = 0 + self.margins[3] = 0 + svg = self.new_path(x, self._stroke_width / 2.0) + svg += self._rline_to(self._expand_x, 0) + svg += self._rline_to(0, 2 * self._radius + self._innie_y2 + \ + self._expand_y) + svg += self._rline_to(-self._expand_x, 0) + svg += self.line_to(x, self._radius + self._innie_y2 + \ + self._stroke_width / 2.0) + svg += self._do_outie() + svg += self._close_path() + self.calc_w_h() + svg += self.style() + svg += self.footer() + return self.header() + svg + + def boolean_and_or(self): + ''' Booleans are in a class of their own ''' + self.reset_min_max() + svg = self._start_boolean(self._stroke_width / 2.0, + self._radius * 5.5 + self._stroke_width / \ + 2.0 + \ + self._innie_y2 + self._innie_spacer +\ + self._expand_y) + svg += self._rline_to(0, -self._radius * 3.5 - self._innie_y2 - \ + self._innie_spacer - self._stroke_width) + + self._hide_x = self._x + self._radius / 2 + self._stroke_width + self._hide_y = self._y - self._radius / 2 + self._stroke_width + self._show_x = self._x + self._radius / 2 + self._stroke_width + + svg += self._rarc_to(1, -1) + svg += self._rline_to(self._radius / 2.0 + self._expand_x, 0) + xx = self._x + svg += self._rline_to(0, self._radius / 2.0) + svg += self._do_boolean() + svg += self._rline_to(0, self._radius * 1.5 + self._innie_y2 + \ + self._innie_spacer) + + svg += self._rline_to(0, self._expand_y) + + svg += self._do_boolean() + svg += self._rline_to(0, self._radius / 2.0) + + self._show_y = self._y + self._radius / 2 + self._show_y -= (self._innie_y1 + self._innie_y2 + self._stroke_width) + + svg += self.line_to(xx, self._y) + svg += self._rline_to(-self._expand_x, 0) + svg += self._end_boolean() + self.margins[0] = int((self._radius + self._stroke_width + 0.5) * \ + self._scale) + self.margins[1] = int(self._stroke_width * self._scale) + self.margins[2] = int(self._stroke_width * self._scale) + self.margins[3] = int(self._stroke_width * self._scale) + return self.header() + svg + + def boolean_not(self): + ''' Booleans are in a class of their own ''' + self.reset_min_max() + svg = self._start_boolean(self._stroke_width / 2.0, self._radius * \ + 2.0 + self._stroke_width / 2.0) + svg += self._rline_to(0, -self._stroke_width) + svg += self._rarc_to(1, -1) + svg += self._rline_to(self._radius / 2.0 + self._expand_x, 0) + xx = self._x + svg += self._rline_to(0, self._radius / 2.0) + svg += self._do_boolean() + svg += self._rline_to(0, self._radius / 2.0) + svg += self.line_to(xx, self._y) + svg += self._rline_to(-self._expand_x, 0) + svg += self._end_boolean() + self.margins[0] = int((self._radius + self._stroke_width + 0.5) * \ + self._scale) + self.margins[1] = int(self._stroke_width * self._scale) + self.margins[2] = int((self._radius + self._stroke_width + 0.5) * \ + self._scale) + self.margins[3] = int(self._stroke_width * self._scale) + return self.header() + svg + + def boolean_compare(self): + ''' Booleans are in a class of their own ''' + self.reset_min_max() + yoffset = self._radius * 2 + 2 * self._innie_y2 + \ + self._innie_spacer + self._stroke_width / 2.0 + \ + self._expand_y + svg = self._start_boolean(self._stroke_width / 2.0, yoffset) + yoffset = -2 * self._innie_y2 - self._innie_spacer - self._stroke_width + svg += self._rline_to(0, yoffset) + + self._hide_x = self._x + self._radius / 2 + self._stroke_width + self._hide_y = self._y - self._radius / 2 + self._stroke_width + self._show_x = self._x + self._radius / 2 + self._stroke_width + + svg += self._rarc_to(1, -1) + svg += self._rline_to(self._radius / 2.0 + self._expand_x, 0) + svg += self._rline_to(0, self._radius) + xx = self._x + svg += self._do_innie() + svg += self._rline_to(0, self._expand_y) + if self._porch is True: + svg += self._do_porch(False) + else: + svg += self._rline_to(0, 2 * self._innie_y2 + self._innie_spacer) + svg += self._do_innie() + svg += self._rline_to(0, self._radius) + svg += self.line_to(xx, self._y) + + svg += self._rline_to(-self._expand_x, 0) + + self._show_y = self._y + self._radius / 2 + self._show_y -= (self._innie_y1 + self._innie_y2 + self._stroke_width) + + svg += self._end_boolean() + self.margins[0] = int((self._radius + self._stroke_width) * \ + self._scale) + self.margins[1] = int(self._stroke_width * self._scale) + self.margins[2] = int(self._stroke_width * self._scale) + return self.header() + svg + + def triangle_up(self, colors): + ''' A triangle that points up ''' + self.reset_min_max() + self._fill, self._stroke = colors[0], colors[1] + self._width, self._height = 55 * self._scale, 55 * self._scale + svg = self.new_path(5, 50) + svg += self._rline_to(22.5, -45) + svg += self._rline_to(22.5, 45) + svg += self._close_path() + svg += self.style() + svg += self.footer() + return self.header() + svg + + def triangle_down(self, colors): + ''' A triangle that points down ''' + self.reset_min_max() + self._fill, self._stroke = colors[0], colors[1] + self._width, self._height = 55 * self._scale, 55 * self._scale + svg = self.new_path(5, 5) + svg += self._rline_to(22.5, 45) + svg += self._rline_to(22.5, -45) + svg += self._close_path() + svg += self.style() + svg += self.footer() + return self.header() + svg + + def turtle(self, colors): + ''' Turtles are just another block ''' + self.reset_min_max() + self._fill, self._stroke = colors[1], colors[0] + + svg = "%s%s%s%s%s%s%s%s" % (" <path d=\"M 27.5 48.3 ", + "C 26.9 48.3 26.4 48.2 25.9 48.2 L 27.2 50.5 L 28.6 48.2 ", + "C 28.2 48.2 27.9 48.3 27.5 48.3 Z\" stroke_width=\"3.5\" ", + "fill=\"", self._fill, ";\" stroke=\"", self._stroke, + "\" />\n") + svg += "%s%s%s%s%s%s%s%s%s%s" % (" <path d=\"M 40.2 11.7 ", + "C 38.0 11.7 36.2 13.3 35.8 15.3 ", + "C 37.7 16.7 39.3 18.4 40.5 20.5 ", + "C 42.8 20.4 44.6 18.5 44.6 16.2 ", + "C 44.6 13.7 42.6 11.7 40.2 11.7 Z\" stroke_width=\"3.5\" ", + "fill=\"", self._fill, ";\" stroke=\"", self._stroke, "\" />\n") + svg += "%s%s%s%s%s%s%s%s%s%s" % (" <path d=\"M 40.7 39.9 ", + "C 39.5 42.1 37.9 44.0 35.9 45.4 ", + "C 36.4 47.3 38.1 48.7 40.2 48.7 ", + "C 42.6 48.7 44.6 46.7 44.6 44.3 ", + "C 44.6 42.0 42.9 40.2 40.7 39.9 Z\" stroke_width=\"3.5\" ", + "fill=\"", self._fill, ";\" stroke=\"", self._stroke, "\" />\n") + svg += "%s%s%s%s%s%s%s%s%s%s" % (" <path d=\"M 14.3 39.9 ", + "C 12.0 40.1 10.2 42.0 10.2 44.3 ", + "C 10.2 46.7 12.2 48.7 14.7 48.7 ", + "C 16.7 48.7 18.5 47.3 18.9 45.4 ", + "C 17.1 43.9 15.5 42.1 14.3 39.9 Z\" stroke_width=\"3.5\" ", + "fill=\"", self._fill, ";\" stroke=\"", self._stroke, "\" />\n") + svg += "%s%s%s%s%s%s%s%s%s%s" % (" <path d=\"M 19.0 15.4 ", + "C 18.7 13.3 16.9 11.7 14.7 11.7 ", + "C 12.2 11.7 10.2 13.7 10.2 16.2 ", + "C 10.2 18.5 12.1 20.5 14.5 20.6 ", + "C 15.7 18.5 17.2 16.8 19.0 15.4 Z\" stroke_width=\"3.5\" ", + "fill=\"", self._fill, ";\" stroke=\"", self._stroke, "\" />\n") + svg += "%s%s%s%s%s%s%s%s%s%s%s%s" % (" <path d=\"M 27.5 12.6 ", + "C 29.4 12.6 31.2 13.0 32.9 13.7 ", + "C 33.7 12.6 34.1 11.3 34.1 9.9 ", + "C 34.1 6.2 31.1 3.2 27.4 3.2 ", + "C 23.7 3.2 20.7 6.2 20.7 9.9 ", + "C 20.7 11.3 21.2 12.7 22.0 13.7 ", + "C 23.7 13.0 25.5 12.6 27.5 12.6 Z\" stroke_width=\"3.5\" ", + "fill=\"", self._fill, ";\" stroke=\"", self._stroke, "\" />\n") + svg += "%s%s%s%s%s%s%s%s%s%s%s%s" % (" <path d=\"M 43.1 30.4 ", + "C 43.1 35.2 41.5 39.7 38.5 43.0 ", + "C 35.6 46.4 31.6 48.3 27.5 48.3 ", + "C 23.4 48.3 19.4 46.4 16.5 43.0 ", + "C 13.5 39.7 11.9 35.2 11.9 30.4 ", + "C 11.9 20.6 18.9 12.6 27.5 12.6 ", + "C 36.1 12.6 43.1 20.6 43.1 30.4 Z\" stroke_width=\"3.5\" ", + "fill=\"", self._fill, ";\" stroke=\"", self._stroke, "\" />\n") + svg += "%s%s%s%s%s" % (" <path d=\"M 25.9 33.8 L 24.3 29.1 ", + "L 27.5 26.5 L 31.1 29.2 L 29.6 33.8 Z\" stroke_width=\"3.5\" ", + "fill=\"", self._stroke, ";\" stroke=\"none\" />\n") + svg += "%s%s%s%s%s%s" % (" <path d=\"M 27.5 41.6 ", + "C 23.5 41.4 22.0 39.5 22.0 39.5 L 25.5 35.4 L 30.0 35.5 ", + "L 33.1 39.7 C 33.1 39.7 30.2 41.7 27.5 41.6 Z\" ", + "stroke_width=\"3.5\" fill=\"", self._stroke, + ";\" stroke=\"none\" />\n") + svg += "%s%s%s%s%s%s" % (" <path d=\"M 18.5 33.8 ", + "C 17.6 30.9 18.6 27.0 18.6 27.0 L 22.6 29.1 L 24.1 33.8 ", + "L 20.5 38.0 C 20.5 38.0 19.1 36.0 18.4 33.8 Z\" ", + "stroke_width=\"3.5\" fill=\"", self._stroke, + ";\" stroke=\"none\" />\n") + svg += "%s%s%s%s%s%s" % (" <path d=\"M 19.5 25.1 ", + "C 19.5 25.1 20.0 23.2 22.5 21.3 ", + "C 24.7 19.7 27.0 19.6 27.0 19.6 L 26.9 24.6 L 23.4 27.3 ", + "L 19.5 25.1 Z\" stroke_width=\"3.5\" fill=\"", self._stroke, + ";\" stroke=\"none\" />\n") + svg += "%s%s%s%s%s%s" % (" <path d=\"M 32.1 27.8 L 28.6 25.0 ", + "L 29 19.8 C 29 19.8 30.8 19.7 33.0 21.4 ", + "C 35.2 23.2 36.3 26.4 36.3 26.4 L 32.1 27.8 Z\" ", + "stroke_width=\"3.5\" fill=\"", self._stroke, + ";\" stroke=\"none\" />\n") + svg += "%s%s%s%s%s%s" % (" <path d=\"M 31.3 34.0 L 32.6 29.6 ", + "L 36.8 28.0 C 36.8 28.0 37.5 30.7 36.8 33.7 ", + "C 36.2 36.0 34.7 38.1 34.7 38.1 L 31.3 34.0 Z\" ", + "stroke_width=\"3.5\" fill=\"", self._stroke, + ";\" stroke=\"none\" />\n") + self._width, self._height = 55, 55 + svg += self.footer() + return self.header() + svg + + def palette(self, width, height): + ''' Just a rectangle with a hide button. ''' + self.reset_min_max() + self._width, self._height = width, height + self._fill, self._stroke = PALETTE_COLOR, "none" + svg = self._rect(width, height, 0, 0) + self._hide_x = (width - self._radius * 1.5) / 2 + self._hide_y = (height - self._radius * 1.5) / 2 + svg += self._hide_dot(True) + svg += self.footer() + return self.header() + svg + + def toolbar(self, width, height): + ''' Just a rectangle ''' + self.reset_min_max() + self._width, self._height = width, height + self._fill, self._stroke = TOOLBAR_COLOR, "none" + svg = self._rect(width, height, 0, 0) + svg += self.footer() + return self.header() + svg + + def sandwich_top(self, innie_flag=True): + ''' Special block for the top of a collapsible stack; includes + an 'arm" that extends down the left side of a stack ''' + self.reset_min_max() + x = self._stroke_width / 2.0 + y = self._stroke_width / 2.0 + self._radius + self.margins[0] = int((x + self._stroke_width + 0.5) * self._scale) + self.margins[1] = int((self._stroke_width + 0.5) * self._scale) + self.margins[2] = 0 + self.margins[3] = 0 + svg = self.new_path(x, y) + svg += self._corner(1, -1) + svg += self._rline_to(self._radius + self._stroke_width, 0) + svg += self._do_slot() + svg += self._rline_to(self._expand_x, 0) + xx = self._x + svg += self._corner(1, 1) + if innie_flag: + svg += self._do_innie() + svg += self._corner(-1, 1) + svg += self.line_to(xx, self._y) + svg += self._rline_to(-self._expand_x, 0) + svg += self._do_tab() + if self._arm: + svg += self._inverse_corner(-1, 1, 90, 0, 0) + svg += self._rline_to(0, self._expand_y) + svg += self._rline_to(-self._radius, 0) + else: + svg += self._rline_to(-self._radius - self._stroke_width, 0) + svg += self._corner(-1, -1) + svg += self._close_path() + self.calc_w_h() + svg += self.style() + if self._show is True: + svg += self._show_dot() + if self._hide is True: + svg += self._hide_dot() + svg += self.footer() + return self.header() + svg + + def sandwich_bottom(self): + ''' Special block for the bottom of a collapsible stack; + includes a connection to the 'arm" that extends down the left + side of a stack ''' + self.reset_min_max() + x = self._stroke_width / 2.0 + y = self._stroke_width / 2.0 + self.margins[0] = int((x + self._stroke_width + 0.5) * self._scale) + self.margins[1] = int((self._stroke_width + 0.5) * self._scale) + self.margins[2] = 0 + self.margins[3] = 0 + svg = self.new_path(x, y) + svg += self._rline_to(self._radius, 0) + svg += self._rline_to(0, self._expand_y) + svg += self._inverse_corner(1, 1, 90, 0, 0) + svg += self._do_slot() + svg += self._rline_to(self._radius, 0) + svg += self._corner(-1, 1) + svg += self._do_tab() + svg += self._rline_to(-self._radius - self._stroke_width, 0) + svg += self._corner(-1, -1) + svg += self._close_path() + self.calc_w_h() + svg += self.style() + self._hide_x = x + self._radius / 2 + self._hide_y = y + self._radius / 2 + if self._hide is True: + svg += self._hide_dot() + if self._show is True: + svg += self._show_dot() + svg += self.footer() + return self.header() + svg + + def status_block(self, graphic=None): + ''' Generate a status block ''' + self.reset_min_max() + (x, y) = self._calculate_x_y() + self.margins[2] = 0 + self.margins[3] = 0 + svg = self.new_path(x, y) + svg += self._corner(1, -1) + svg += self._rline_to(self._expand_x, 0) + xx = self._x + svg += self._corner(1, 1) + svg += self._rline_to(0, self._expand_y) + svg += self._corner(-1, 1) + svg += self.line_to(xx, self._y) + svg += self._rline_to(-self._expand_x, 0) + svg += self._corner(-1, -1) + svg += self._rline_to(0, -self._expand_y) + self.calc_w_h() + svg += self._close_path() + svg += self.style() + if self._hide is True: + svg += self._hide_dot() + svg += self.footer() + return self.header() + svg + + # + # Utility methods + # + def set_tail(self, flag=True): + self._tail = flag + + def set_draw_innies(self, flag=True): + self._draw_innies = flag + + def set_hide(self, flag=False): + self._hide = flag + + def set_show(self, flag=False): + self._show = flag + + def get_width(self): + return self._width + + def get_height(self): + return self._height + + def get_innie_width(self): + return (self._innie_x1 + self._innie_x2) * self._scale + + def get_slot_depth(self): + return self._slot_y * self._scale + + def clear_docks(self): + self.docks = [] + + def set_scale(self, scale=1): + self._scale = scale + + def set_orientation(self, orientation=0): + self._orientation = orientation + + def expand(self, w=0, h=0): + self._expand_x = w + self._expand_y = h + + def set_stroke_width(self, stroke_width=1.5): + self._stroke_width = stroke_width + self._calc_porch_params() + + def set_colors(self, colors=["#00FF00", "#00A000"]): + self._fill = colors[0] + self._stroke = colors[1] + + def set_fill_color(self, color="#00FF00"): + self._fill = color + + def set_stroke_color(self, color="#00A000"): + self._stroke = color + + def set_gradient(self, flag=False, color='#FFFFFF'): + self._gradient = flag + self._gradient_color = color + + def set_innie(self, innie_array=[False]): + self._innie = innie_array + + def set_outie(self, flag=False): + self._outie = flag + + def set_slot(self, flag=True): + self._slot = flag + if self._slot is True: + self._cap = False + + def set_cap(self, flag=False): + self._cap = flag + if self._cap is True: + self._slot = False + + def set_tab(self, flag=True): + self._tab = flag + + def set_porch(self, flag=False): + self._porch = flag + + def set_boolean(self, flag=False): + self._bool = flag + + def set_else(self, flag=False): + self._else = flag + + def set_arm(self, flag=True): + self._arm = flag + + def reset_min_max(self): + self._min_x = 10000 + self._min_y = 10000 + self._max_x = -10000 + self._max_y = -10000 + + # + # Exotic methods + # + + def set_radius(self, radius=8): + self._radius = radius + + def set_innie_params(self, x1=4, y1=3, x2=4, y2=4): + self._innie_x1 = x1 + self._innie_y1 = y1 + self._innie_x2 = x2 + self._innie_y2 = y2 + self._calc_porch_params() + + def set_innie_spacer(self, innie_spacer=0): + self._innie_spacer = innie_spacer + + def set_slot_params(self, x=12, y=4): + self._slot_x = x + self._slot_y = y + + def _calc_porch_params(self): + self._porch_x = self._innie_x1 + self._innie_x2 + \ + 4 * self._stroke_width + self._porch_y = self._innie_y1 + self._innie_y2 + \ + 4 * self._stroke_width + + # + # SVG helper methods + # + def header(self, center=False): + return "%s%s%s%s%s%s%.1f%s%s%.1f%s%s%s" % ( + "<svg\n", + " xmlns:svg=\"http://www.w3.org/2000/svg\"\n", + " xmlns=\"http://www.w3.org/2000/svg\"\n", + " xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n", + " version=\"1.1\"\n", + " width=\"", self._width, "\"\n", + " height=\"", self._height, "\">\n", + self._defs(), + self._transform(center)) + + def _defs(self): + if self._gradient is True: + return "%s%s%s%s%s%s%s%s%s%s%s%s%.1f%s%s%.1f%s%s%.1f%s%s" % ( + " <defs>\n <linearGradient\n id=\"linearGradient1234\">\n", + " <stop\n style=\"stop-color:" + \ + self._gradient_color + ";stop-opacity:1;\"\n", + " offset=\"0\" />\n", + " <stop\n style=\"stop-color:", self._fill, + ";stop-opacity:1;\"\n", + " offset=\"1\" />\n", + " </linearGradient>\n", + " <linearGradient\n xlink:href=\"#linearGradient1234\"\n", + " id=\"linearGradient5678\"\n", + " x1=\"0\"\n", + " y1=\"", self._height / 2.0, "\"\n", + " x2=\"", self._width / self._scale, "\"\n", + " y2=\"", self._height / 2.0, "\"\n", + " gradientUnits=\"userSpaceOnUse\" />\n </defs>\n") + else: + return "" + + def _transform(self, center): + if self._orientation != 0: + orientation = "<g\ntransform = \"rotate(%.1f %.1f %.1f)\">\n" % ( + self._orientation, self._width / 2.0, self._height / 2.0) + else: + orientation = "" + if center: + return "<g\ntransform=\"translate(%.1f, %.1f)\">\n" % ( + -self._min_x, -self._min_y) + else: + return "<g\ntransform=\"scale(%.1f, %.1f)\">\n%s" % ( + self._scale, self._scale, orientation) + + def footer(self): + if self._orientation != 0: + return " </g>\n</g>\n</svg>\n" + else: + return " </g>\n</svg>\n" + + def style(self): + if self._gradient is True: + fill = "url(#linearGradient5678)" + else: + fill = self._fill + return "%s%s;%s%s;%s%.1f;%s%s" % ( + " style=\"fill:", fill, + "fill-opacity:1;stroke:", self._stroke, + "stroke-width:", self._stroke_width, + "stroke-linecap:round;", + "stroke-opacity:1;\" />\n") + + def text(self, x, y, size, width, string): + self._x = x + self._y = y + self._check_min_max() + self._x = x + width + self._y = y - size + self._check_min_max() + return " %s%.1f%s%s%s%.1f%s%.1f%s%.1f%s%s%s%s%s" % ( + "<text style=\"font-size:", size, "px;fill:", self._stroke, + ";font-family:Sans\">\n <tspan x=\"", x, "\" y=\"", y, + "\" style=\"font-size:", size, "px;fill:", self._stroke, "\">", + string, "</tspan>\n </text>\n") + + def image(self, x, y, w, h, path, image_data=None): + self._x = x + self._y = y + self._check_min_max() + self._x = x + w + self._y = y + h + self._check_min_max() + if image_data == None: + return " %s%.1f%s%.1f%s%.1f%s%.1f%s%s%s" % ( + "<image x=\"", x, "\" y=\"", y, + "\" width=\"", w, "\" height=\"", h, + "\" xlink:href=\"file://", path, "\"/>\n") + else: + return " %s%.1f%s%.1f%s%.1f%s%.1f%s%s%s" % ( + "<image x=\"", x, "\" y=\"", y, + "\" width=\"", w, "\" height=\"", h, + "\" xlink:href=\"data:image/png;base64,", image_data, + "\"/>\n") + + def _circle(self, r, cx, cy): + return "%s%s%s%s%s%f%s%f%s%f%s" % ("<circle style=\"fill:", + self._fill, ";stroke:", self._stroke, ";\" r=\"", r, "\" cx=\"", + cx, "\" cy=\"", cy, "\" />\n") + + def _rect(self, w, h, x, y): + return "%s%s%s%s%s%f%s%f%s%f%s%f%s" % ("<rect style=\"fill:", + self._fill, ";stroke:", self._stroke, ";\" width=\"", w, + "\" height=\"", h, "\" x=\"", x, "\" y=\"", y, "\" />\n") + + def background(self, fill): + return "%s%s%s%s%s%f%s%f%s%f%s%f%s" % ("<rect style=\"fill:", + fill, ";stroke:", fill, ";\" width=\"", + self._max_x - self._min_x, + "\" height=\"", self._max_y - self._min_y, "\" x=\"", + self._min_x, "\" y=\"", self._min_y, "\" />\n") + + def _check_min_max(self): + if self._x < self._min_x: + self._min_x = self._x + if self._y < self._min_y: + self._min_y = self._y + if self._x > self._max_x: + self._max_x = self._x + if self._y > self._max_y: + self._max_y = self._y + + def line_to(self, x, y): + self._check_min_max() + if self._x == x and self._y == y: + return "" + else: + self._x = x + self._y = y + self._check_min_max() + return "L %.1f %.1f " % (x, y) + + def _rline_to(self, dx, dy): + if dx == 0 and dy == 0: + return "" + else: + return self.line_to(self._x + dx, self._y + dy) + + def arc_to(self, x, y, r, a=90, l=0, s=1): + self._check_min_max() + if r == 0: + return self.line_to(x, y) + else: + self._x = x + self._y = y + self._check_min_max() + return "A %.1f %.1f %.1f %d %d %.1f %.1f " % ( + r, r, a, l, s, x, y) + + def _rarc_to(self, sign_x, sign_y, a=90, l=0, s=1): + if self._radius == 0: + return "" + else: + x = self._x + sign_x * self._radius + y = self._y + sign_y * self._radius + return self.arc_to(x, y, self._radius, a, l, s) + + def _inverse_corner(self, sign_x, sign_y, a=90, l=0, s=1, start=True, + end=True): + r2 = self._stroke_width + self._radius / 2.0 + if start: + if sign_x * sign_y == -1: + svg_str = self._rline_to(sign_x * (r2 - self._stroke_width), 0) + else: + svg_str = self._rline_to(0, sign_y * (r2 - self._stroke_width)) + x = self._x + sign_x * r2 + y = self._y + sign_y * r2 + svg_str += self.arc_to(x, y, r2, a, l, s) + if end: + if sign_x * sign_y == -1: + svg_str += self._rline_to(0, + sign_y * (r2 - self._stroke_width)) + else: + svg_str += self._rline_to(sign_x * (r2 - self._stroke_width), + 0) + return svg_str + + def _corner(self, sign_x, sign_y, a=90, l=0, s=1, start=True, end=True): + svg_str = "" + if sign_x == 1 and sign_y == -1: + self._hide_x = self._x + self._radius / 2 + self._stroke_width + self._hide_y = self._y - self._radius / 2 + self._stroke_width + self._show_x = self._x + self._radius / 2 + self._stroke_width + if sign_x == -1 and sign_y == 1: + self._show_y = self._y + self._radius / 2 - self._stroke_width + if self._radius > 0: + r2 = self._radius / 2.0 + if start: + if sign_x * sign_y == 1: + svg_str += self._rline_to(sign_x * r2, 0) + else: + svg_str += self._rline_to(0, sign_y * r2) + x = self._x + sign_x * r2 + y = self._y + sign_y * r2 + svg_str += self.arc_to(x, y, r2, a, l, s) + if end: + if sign_x * sign_y == 1: + svg_str += self._rline_to(0, sign_y * r2) + else: + svg_str += self._rline_to(sign_x * r2, 0) + return svg_str + + def new_path(self, x, y): + """ + self._min_x = x + self._min_y = y + self._max_x = x + self._max_y = y + """ + self._x = x + self._y = y + return " <path d=\"m%.1f %.1f " % (x, y) + + def _close_path(self): + return "z\"\n" + + def _hide_dot(self, noscale=False): + _saved_fill, _saved_stroke = self._fill, self._stroke + self._fill, self._stroke = HIT_RED, HIT_RED + svg = "</g>/n<g>/n" + if noscale: + scale = 2.0 + else: + scale = self._scale + scale2 = scale / 2 + svg += self._circle(self._dot_radius * scale2, self._hide_x * scale, + self._hide_y * scale) + self._fill, self._stroke = HIDE_WHITE, HIDE_WHITE + svg += self._rect(10 * scale2, 2 * scale2, + self._hide_x * scale - 5 * scale2, + self._hide_y * scale - scale + scale2) + self._fill, self._stroke = _saved_fill, _saved_stroke + return svg + + def _show_dot(self, noscale=False): + _saved_fill, _saved_stroke = self._fill, self._stroke + self._fill, self._stroke = HIT_GREEN, HIT_GREEN + svg = "</g>/n<g>/n" + if noscale: + scale = 2.0 + else: + scale = self._scale + scale2 = scale / 2 + svg += self._circle(self._dot_radius * scale2, self._show_x * scale, + self._show_y * scale) + self._fill, self._stroke = SHOW_WHITE, SHOW_WHITE + svg += self._rect(10 * scale2, + 2 * scale2, self._show_x * scale - 5 * scale2, + self._show_y * scale - scale + scale2) + svg += self._rect(2 * scale2, 10 * scale2, + self._show_x * scale - scale + scale2, + self._show_y * scale - 5 * scale2) + self._fill, self._stroke = _saved_fill, _saved_stroke + return svg + + def _do_slot(self): + if self._slot is True: + self.docks.append((int(self._x * self._scale), + int(self._y * self._scale))) + return "%s%s%s" % ( + self._rline_to(0, self._slot_y), + self._rline_to(self._slot_x, 0), + self._rline_to(0, -self._slot_y)) + elif self._cap is True: + return "%s%s" % ( + self._rline_to(self._slot_x / 2.0, -self._slot_y * 2.0), + self._rline_to(self._slot_x / 2.0, self._slot_y * 2.0)) + else: + return self._rline_to(self._slot_x, 0) + + def _do_tail(self): + if self._outie is True: + return self._rline_to(-self._slot_x, 0) + elif self._tail: + return "%s%s" % ( + self._rline_to(-self._slot_x / 2.0, self._slot_y * 2.0), + self._rline_to(-self._slot_x / 2.0, -self._slot_y * 2.0)) + else: + return self._rline_to(-self._slot_x, 0) + + def _do_tab(self): + s = "%s%s%s%s%s" % ( + self._rline_to(-self._stroke_width, 0), + self._rline_to(0, self._slot_y), + self._rline_to(-self._slot_x + 2 * self._stroke_width, 0), + self._rline_to(0, -self._slot_y), + self._rline_to(-self._stroke_width, 0)) + self.docks.append((int(self._x * self._scale), + int((self._y + self._stroke_width) * self._scale))) + return s + + def _do_innie(self): + self.docks.append((int((self._x + self._stroke_width) * self._scale), + int((self._y + self._innie_y2) * self._scale))) + if self.margins[2] == 0: + self.margins[1] = int((self._y - self._innie_y1) * self._scale) + self.margins[2] = int((self._x - self._innie_x1 - \ + self._innie_x2 - self._stroke_width * 2) * self._scale) + self.margins[3] =\ + int((self._y + self._innie_y2 + self._innie_y1) * self._scale) + return "%s%s%s%s%s%s%s" % ( + self._rline_to(-self._innie_x1, 0), + self._rline_to(0, -self._innie_y1), + self._rline_to(-self._innie_x2, 0), + self._rline_to(0, self._innie_y2 + 2 * self._innie_y1), + self._rline_to(self._innie_x2, 0), + self._rline_to(0, -self._innie_y1), + self._rline_to(self._innie_x1, 0)) + + def _do_reverse_innie(self): + self.docks.append((int((self._x + self._stroke_width) * self._scale), + int((self._y) * self._scale))) + return "%s%s%s%s%s%s%s" % ( + self._rline_to(-self._innie_x1, 0), + self._rline_to(0, self._innie_y1), + self._rline_to(-self._innie_x2, 0), + self._rline_to(0, -self._innie_y2 - 2 * self._innie_y1), + self._rline_to(self._innie_x2, 0), + self._rline_to(0, self._innie_y1), + self._rline_to(self._innie_x1, 0)) + + def _do_outie(self): + if self._outie is not True: + return self._rline_to(0, -self._innie_y2) + self.docks.append((int(self._x * self._scale), + int(self._y * self._scale))) + return "%s%s%s%s%s%s%s%s%s" % ( + self._rline_to(0, -self._stroke_width), + self._rline_to(-self._innie_x1 - 2 * self._stroke_width, 0), + self._rline_to(0, self._innie_y1), + self._rline_to(-self._innie_x2 + 2 * self._stroke_width, 0), + self._rline_to(0, + -self._innie_y2 - 2 * self._innie_y1 + 2 * self._stroke_width), + self._rline_to(self._innie_x2 - 2 * self._stroke_width, 0), + self._rline_to(0, self._innie_y1), + self._rline_to(self._innie_x1 + 2 * self._stroke_width, 0), + self._rline_to(0, -self._stroke_width)) + + def _do_porch(self, flag=True): + if flag: + return "%s%s%s" % ( + self._rline_to(0, self._porch_y + self._innie_y1), + self._rline_to(self._porch_x - self._radius, 0), + self._corner(1, 1)) + else: + return "%s%s%s" % ( + self._rline_to(0, self._porch_y - self._innie_y1 + \ + self._stroke_width), + self._rline_to(self._porch_x - self._radius, 0), + self._corner(1, 1)) + + def _start_boolean(self, xoffset, yoffset): + svg = self.new_path(xoffset, yoffset) + self._radius -= self._stroke_width + self.docks.append((int(self._x * self._scale), + int(self._y * self._scale))) + svg += self._rarc_to(1, -1) + self._radius += self._stroke_width + svg += self._rline_to(self._stroke_width, 0) + svg += self._rline_to(0, -self._expand_y) + return svg + + def _do_boolean(self): + self.docks.append( + (int((self._x - self._radius + self._stroke_width) * self._scale), + int((self._y + self._radius) * self._scale))) + self.margins[2] =\ + int((self._x - self._radius - self._stroke_width) * self._scale) + svg = self._rarc_to(-1, 1, 90, 0, 0) + self._rarc_to(1, 1, 90, 0, 0) + return svg + + def _end_boolean(self): + svg = self._rline_to(-self._radius * 1.5, 0) + svg += self._rline_to(0, -self._stroke_width) + svg += self._rline_to(-self._stroke_width, 0) + self._radius -= self._stroke_width + svg += self._rarc_to(-1, -1) + self._radius += self._stroke_width + svg += self._close_path() + self.calc_w_h() + svg += self.style() + if self._show is True: + svg += self._show_dot() + if self._hide is True: + svg += self._hide_dot() + return svg + self.footer() + + def calc_w_h(self, add_stroke_width=True): + if add_stroke_width: + self._width = (self._max_x - self._min_x + self._stroke_width) * \ + self._scale + else: + self._width = (self._max_x - self._min_x) * self._scale + if self.margins[2] == 0: + self.margins[2] = int((self._stroke_width + 0.5) * self._scale) + else: + self.margins[2] = int(self._width - self.margins[2]) + if add_stroke_width: + self._height = (self._max_y - self._min_y + self._stroke_width) * \ + self._scale + else: + self._height = (self._max_y - self._min_y) * self._scale + if self.margins[3] == 0: + if self._tab: + self.margins[3] = int((self._slot_y + self._stroke_width + \ + 0.5) * self._scale) + else: + self.margins[3] = int((self._slot_y * 2 + \ + self._stroke_width + 0.5) * self._scale) + else: + self.margins[3] = int(self._height - self.margins[3]) + + def _calculate_x_y(self): + x = self._stroke_width / 2.0 + y = self._stroke_width / 2.0 + self._radius + self.margins[0] = int(x + self._stroke_width + 0.5) + self.margins[1] = int(self._stroke_width + 0.5) + if self._outie is True: + x += self._innie_x1 + self._innie_x2 + self.margins[0] += self._innie_x1 + self._innie_x2 + if self._cap is True: + y += self._slot_y * 2.0 + self.margins[1] += self._slot_y * 2.0 + elif self._slot is True: + self.margins[1] += self._slot_y + self.margins[0] *= self._scale + self.margins[1] *= self._scale + return(x, y) + +# +# Command-line tools for testing +# + + +def open_file(datapath, filename): + return file(os.path.join(datapath, filename), "w") + + +def close_file(f): + f.close() + + +def generator(datapath): + svg0 = SVG() + f = open_file(datapath, "basic.svg") + svg0.set_innie([True, True]) + svg0.set_scale(2) + svg0.set_tab(True) + svg0.set_slot(True) + svg0.set_arm(True) + svg_str = svg0.basic_block() + f.write(svg_str) + close_file(f) + + +def main(): + return 0 + + +if __name__ == "__main__": + generator(os.path.abspath('.')) + main() + + +def svg_str_to_pixbuf(svg_string): + """ Load pixbuf from SVG string """ + pl = gtk.gdk.PixbufLoader('svg') + pl.write(svg_string) + pl.close() + pixbuf = pl.get_pixbuf() + return pixbuf + + +def svg_str_to_pixmap(svg_string): + """ Load pixmap from SVG string """ + (pixmap, mask) = svg_str_to_pixbuf(svg_string).render_pixmap_and_mask() + return pixmap + + +def svg_from_file(pathname): + """ Read SVG string from a file """ + f = file(pathname, 'r') + svg = f.read() + f.close() + return(svg) diff --git a/TurtleArt/taturtle.py b/TurtleArt/taturtle.py new file mode 100644 index 0000000..c70f379 --- /dev/null +++ b/TurtleArt/taturtle.py @@ -0,0 +1,312 @@ +# -*- coding: utf-8 -*- +#Copyright (c) 2010,12 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. + +from random import uniform +from math import sin, cos, pi, sqrt +from gettext import gettext as _ +import gtk +import cairo + +from taconstants import TURTLE_LAYER, DEFAULT_TURTLE_COLORS +from tasprite_factory import SVG, svg_str_to_pixbuf +from tacanvas import wrap100, COLOR_TABLE +from sprites import Sprite +from tautils import debug_output + +SHAPES = 36 + + +def generate_turtle_pixbufs(colors): + """ Generate pixbufs for generic turtles """ + shapes = [] + svg = SVG() + svg.set_scale(1.0) + for i in range(SHAPES): + svg.set_orientation(i * 10) + shapes.append(svg_str_to_pixbuf(svg.turtle(colors))) + return shapes + + +class Turtles: + + def __init__(self, sprite_list): + """ Class to hold turtles """ + self.dict = dict() + self.sprite_list = sprite_list + self.default_pixbufs = [] + + def get_turtle(self, k, append=False, colors=None): + """ Find a turtle """ + if k in self.dict: + return self.dict[k] + elif not append: + return None + else: + if colors == None: + Turtle(self, k) + elif type(colors) in [list, tuple]: + Turtle(self, k, colors) + else: + Turtle(self, k, colors.split(',')) + return self.dict[k] + + def get_turtle_key(self, turtle): + """ Find a turtle's name """ + for k in iter(self.dict): + if self.dict[k] == turtle: + return k + return None + + def turtle_count(self): + """ How many turtles are there? """ + return(len(self.dict)) + + def add_to_dict(self, k, turtle): + """ Add a new turtle """ + self.dict[k] = turtle + + def remove_from_dict(self, k): + """ Delete a turtle """ + if k in self.dict: + del(self.dict[k]) + + def show_all(self): + """ Make all turtles visible """ + for k in iter(self.dict): + self.dict[k].show() + + def spr_to_turtle(self, spr): + """ Find the turtle that corresponds to sprite spr. """ + for k in iter(self.dict): + if spr == self.dict[k].spr: + return self.dict[k] + return None + + def get_pixbufs(self): + """ Get the pixbufs for the default turtle shapes. """ + if self.default_pixbufs == []: + self.default_pixbufs = generate_turtle_pixbufs( + ["#008000", "#00A000"]) + return(self.default_pixbufs) + + +class Turtle: + + def __init__(self, turtles, key, turtle_colors=None): + """ The turtle is not a block, just a sprite with an orientation """ + self.x = 0 + self.y = 0 + self.hidden = False + self.shapes = [] + self.custom_shapes = False + self.type = 'turtle' + self.name = key + self.heading = 0 + self.pen_shade = 50 + self.pen_color = 0 + self.pen_gray = 100 + self.pen_size = 5 + self.pen_state = True + self.label_block = None + + self._prep_shapes(key, turtles, turtle_colors) + + # Choose a random angle from which to attach the turtle label. + if turtles.sprite_list is not None: + self.spr = Sprite(turtles.sprite_list, 0, 0, self.shapes[0]) + angle = uniform(0, pi * 4 / 3.0) # 240 degrees + w = self.shapes[0].get_width() + r = w * 0.67 + # Restrict angle the the sides 30-150; 210-330 + if angle > pi * 2 / 3.0: + angle += pi / 2.0 # + 90 + self.label_xy = [int(r * sin(angle)), + int(r * cos(angle) + w / 2.0)] + else: + angle += pi / 6.0 # + 30 + self.label_xy = [int(r * sin(angle) + w / 2.0), + int(r * cos(angle) + w / 2.0)] + else: + self.spr = None + turtles.add_to_dict(key, self) + + def _prep_shapes(self, name, turtles=None, turtle_colors=None): + # If the turtle name is an int, we'll use a palette color as the + # turtle color + try: + int_key = int(name) + use_color_table = True + except ValueError: + use_color_table = False + + if turtle_colors is not None: + self.colors = turtle_colors[:] + self.shapes = generate_turtle_pixbufs(self.colors) + elif use_color_table: + fill = wrap100(int_key) + stroke = wrap100(fill + 10) + self.colors = ['#%06x' % (COLOR_TABLE[fill]), + '#%06x' % (COLOR_TABLE[stroke])] + self.shapes = generate_turtle_pixbufs(self.colors) + else: + if turtles is not None: + self.colors = DEFAULT_TURTLE_COLORS + self.shapes = turtles.get_pixbufs() + + def set_turtle_colors(self, turtle_colors): + ''' reset the colors of a preloaded turtle ''' + if turtle_colors is not None: + self.colors = turtle_colors[:] + self.shapes = generate_turtle_pixbufs(self.colors) + self.set_heading(self.heading) + + def set_shapes(self, shapes, i=0): + """ Reskin the turtle """ + n = len(shapes) + if n == 1 and i > 0: # set shape[i] + if i < len(self.shapes): + self.shapes[i] = shapes[0] + elif n == SHAPES: # all shapes have been precomputed + self.shapes = shapes[:] + else: # rotate shapes + if n != 1: + debug_output("%d images passed to set_shapes: ignoring" % (n), + self.tw.running_sugar) + if self.heading == 0: # rotate the shapes + images = [] + w, h = shapes[0].get_width(), shapes[0].get_height() + nw = nh = int(sqrt(w * w + h * h)) + for i in range(SHAPES): + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, nw, nh) + context = cairo.Context(surface) + context = gtk.gdk.CairoContext(context) + context.translate(nw / 2., nh / 2.) + context.rotate(i * 10 * pi / 180.) + context.translate(-nw / 2., -nh / 2.) + context.set_source_pixbuf(shapes[0], (nw - w) / 2., + (nh - h) / 2.) + context.rectangle(0, 0, nw, nh) + context.fill() + images.append(surface) + self.shapes = images[:] + else: # associate shape with image at current heading + j = int(self.heading + 5) % 360 / (360 / SHAPES) + self.shapes[j] = shapes[0] + self.custom_shapes = True + self.show() + + def reset_shapes(self): + """ Reset the shapes to the standard turtle """ + if self.custom_shapes: + self.shapes = generate_turtle_pixbufs(self.colors) + self.custom_shapes = False + + def set_heading(self, heading): + """ Set the turtle heading (one shape per 360/SHAPES degrees) """ + self.heading = heading + i = (int(self.heading + 5) % 360) / (360 / SHAPES) + if not self.hidden and self.spr is not None: + try: + self.spr.set_shape(self.shapes[i]) + except IndexError: + self.spr.set_shape(self.shapes[0]) + + def set_color(self, color): + """ Set the pen color for this turtle. """ + self.pen_color = color + + def set_gray(self, gray): + """ Set the pen gray level for this turtle. """ + self.pen_gray = gray + + def set_shade(self, shade): + """ Set the pen shade for this turtle. """ + self.pen_shade = shade + + def set_pen_size(self, pen_size): + """ Set the pen size for this turtle. """ + self.pen_size = pen_size + + def set_pen_state(self, pen_state): + """ Set the pen state (down==True) for this turtle. """ + self.pen_state = pen_state + + def hide(self): + """ Hide the turtle. """ + if self.spr is not None: + self.spr.hide() + if self.label_block is not None: + self.label_block.spr.hide() + self.hidden = True + + def show(self): + """ Show the turtle. """ + if self.spr is not None: + self.spr.set_layer(TURTLE_LAYER) + self.hidden = False + self.move((self.x, self.y)) + self.set_heading(self.heading) + if self.label_block is not None: + self.label_block.spr.move((self.x + self.label_xy[0], + self.y + self.label_xy[1])) + self.label_block.spr.set_layer(TURTLE_LAYER + 1) + + def move(self, pos): + """ Move the turtle. """ + self.x, self.y = int(pos[0]), int(pos[1]) + if not self.hidden and self.spr is not None: + self.spr.move(pos) + if self.label_block is not None: + self.label_block.spr.move((pos[0] + self.label_xy[0], + pos[1] + self.label_xy[1])) + return(self.x, self.y) + + def get_name(self): + ''' return turtle name (key) ''' + return self.name + + def get_xy(self): + """ Return the turtle's x, y coordinates. """ + return(self.x, self.y) + + def get_heading(self): + """ Return the turtle's heading. """ + return(self.heading) + + def get_color(self): + """ Return the turtle's color. """ + return(self.pen_color) + + def get_gray(self): + """ Return the turtle's gray level. """ + return(self.pen_gray) + + def get_shade(self): + """ Return the turtle's shade. """ + return(self.pen_shade) + + def get_pen_size(self): + """ Return the turtle's pen size. """ + return(self.pen_size) + + def get_pen_state(self): + """ Return the turtle's pen state. """ + return(self.pen_state) diff --git a/TurtleArt/tautils.py b/TurtleArt/tautils.py new file mode 100644 index 0000000..40c39e9 --- /dev/null +++ b/TurtleArt/tautils.py @@ -0,0 +1,832 @@ +#Copyright (c) 2007-8, Playful Invention Company. +#Copyright (c) 2008-12, 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 gtk +import cairo +import pickle +import subprocess +import os +from gettext import gettext as _ + +try: + OLD_SUGAR_SYSTEM = False + import json + json.dumps + from json import load as jload + from json import dump as jdump +except (ImportError, AttributeError): + try: + import simplejson as json + from simplejson import load as jload + from simplejson import dump as jdump + except: + OLD_SUGAR_SYSTEM = True +from StringIO import StringIO + +from taconstants import COLLAPSIBLE, HIT_HIDE, HIT_SHOW, XO1, XO15, XO175, \ + XO30, UNKNOWN + +SANDWICHES = ['sandwichtop', 'sandwichtop_no_label', 'sandwichtop_no_arm', + 'sandwichtop_no_arm_no_label'] + +import logging +_logger = logging.getLogger('turtleart-activity') + + +def debug_output(message_string, running_sugar=False): + ''' unified debugging output ''' + if running_sugar: + _logger.debug(message_string) + else: + print(message_string) + + +def error_output(message_string, running_sugar=False): + ''' unified debugging output ''' + if running_sugar: + _logger.error(message_string) + else: + print(message_string) + + +class pythonerror(Exception): + + def __init__(self, value): + self.value = value + + def __str__(self): + return repr(self.value) + + +def convert(x, fn, try_ord=True): + ''' + The strategy for mixing numbers and strings is to first try + converting the string to a float; then if the string is a single + character, try converting it to an ord; finally, just treat it as a + string. Numbers appended to strings are first treated as ints, then + floats. + ''' + try: + return fn(x) + except ValueError: + if try_ord: + xx, flag = chr_to_ord(x) + if flag: + return fn(xx) + return x + + +def chr_to_ord(x): + ''' Try to comvert a string to an ord ''' + if strtype(x) and len(x) == 1: + try: + return ord(x[0]), True + except ValueError: + return x, False + return x, False + + +def strtype(x): + ''' Is x a string type? ''' + if type(x) == str: + return True + if type(x) == unicode: + return True + return False + + +def magnitude(pos): + ''' Calculate the magnitude of the distance between to blocks. ''' + x, y = pos + return x * x + y * y + + +def json_load(text): + ''' Load JSON data using what ever resources are available. ''' + if OLD_SUGAR_SYSTEM is True: + listdata = json.read(text) + else: + # Strip out leading and trailing whitespace, nulls, and newlines + clean_text = text.lstrip() + clean_text = clean_text.replace('\12', '') + clean_text = clean_text.replace('\00', '') + clean_text = clean_text.rstrip() + # Look for missing ']'s + left_count = clean_text.count('[') + right_count = clean_text.count(']') + while left_count > right_count: + clean_text += ']' + right_count = clean_text.count(']') + io = StringIO(clean_text) + try: + listdata = jload(io) + except ValueError: + # Assume that text is ascii list + listdata = text.split() + for i, value in enumerate(listdata): + listdata[i] = convert(value, float) + # json converts tuples to lists, so we need to convert back, + return _tuplify(listdata) + + +def _tuplify(tup): + ''' Convert to tuples ''' + if type(tup) is not list: + return tup + return tuple(map(_tuplify, tup)) + + +def get_id(connection): + ''' Get a connection block ID. ''' + if connection is not None and hasattr(connection, 'id'): + return connection.id + return None + + +def json_dump(data): + ''' Save data using available JSON tools. ''' + if OLD_SUGAR_SYSTEM is True: + return json.write(data) + else: + io = StringIO() + jdump(data, io) + return io.getvalue() + + +def get_load_name(suffix, load_save_folder): + ''' Open a load file dialog. ''' + dialog = gtk.FileChooserDialog( + _('Load...'), None, + gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, gtk.RESPONSE_OK)) + dialog.set_default_response(gtk.RESPONSE_OK) + return do_dialog(dialog, suffix, load_save_folder) + + +def get_save_name(suffix, load_save_folder, save_file_name): + ''' Open a save file dialog. ''' + dialog = gtk.FileChooserDialog( + _('Save...'), None, + gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_SAVE, gtk.RESPONSE_OK)) + dialog.set_default_response(gtk.RESPONSE_OK) + if save_file_name is not None: + dialog.set_current_name(save_file_name + suffix) + return do_dialog(dialog, suffix, load_save_folder) + + +def chooser(parent_window, filter, action): + ''' Choose an object from the datastore and take some action ''' + from sugar.graphics.objectchooser import ObjectChooser + + chooser = None + try: + chooser = ObjectChooser(parent=parent_window, what_filter=filter) + except TypeError: + chooser = ObjectChooser(None, parent_window, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + if chooser is not None: + try: + result = chooser.run() + if result == gtk.RESPONSE_ACCEPT: + dsobject = chooser.get_selected_object() + action(dsobject) + dsobject.destroy() + finally: + chooser.destroy() + del chooser + + +def data_from_file(ta_file): + ''' Open the .ta file, ignoring any .png file that might be present. ''' + file_handle = open(ta_file, 'r') + # + # We try to maintain read-compatibility with all versions of Turtle Art. + # Try pickle first; then different versions of json. + # + try: + data = pickle.load(file_handle) + except: + # Rewind necessary because of failed pickle.load attempt + file_handle.seek(0) + text = file_handle.read() + data = data_from_string(text) + file_handle.close() + return data + + +def data_from_string(text): + ''' JSON load data from a string. ''' + return json_load(text.replace(']],\n', ']], ')) + + +def data_to_file(data, ta_file): + ''' Write data to a file. ''' + file_handle = file(ta_file, 'w') + file_handle.write(data_to_string(data)) + file_handle.close() + + +def data_to_string(data): + ''' JSON dump a string. ''' + return json_dump(data).replace(']], ', ']],\n') + + +def do_dialog(dialog, suffix, load_save_folder): + ''' Open a file dialog. ''' + result = None + file_filter = gtk.FileFilter() + file_filter.add_pattern('*' + suffix) + file_filter.set_name('Turtle Art') + dialog.add_filter(file_filter) + dialog.set_current_folder(load_save_folder) + response = dialog.run() + if response == gtk.RESPONSE_OK: + result = dialog.get_filename() + load_save_folder = dialog.get_current_folder() + dialog.destroy() + return result, load_save_folder + + +def save_picture(canvas, file_name): + ''' Save the canvas to a file ''' + x_surface = canvas.canvas.get_target() + img_surface = cairo.ImageSurface(cairo.FORMAT_RGB24, + canvas.width, canvas.height) + cr = cairo.Context(img_surface) + cr.set_source_surface(x_surface) + cr.paint() + if type(file_name) == unicode: + img_surface.write_to_png(str(file_name.encode('ascii', 'replace'))) + else: + img_surface.write_to_png(str(file_name)) + + +def get_canvas_data(canvas): + ''' Get pixel data from the turtle canvas ''' + x_surface = canvas.canvas.get_target() + img_surface = cairo.ImageSurface(cairo.FORMAT_RGB24, + canvas.width, canvas.height) + cr = cairo.Context(img_surface) + cr.set_source_surface(x_surface) + cr.paint() + return img_surface.get_data() + + +def get_pixbuf_from_journal(dsobject, w, h): + ''' Load a pixbuf from a Journal object. ''' + try: + pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(dsobject.file_path, + int(w), int(h)) + except: + try: + pixbufloader = \ + gtk.gdk.pixbuf_loader_new_with_mime_type('image/png') + pixbufloader.set_size(min(300, int(w)), min(225, int(h))) + pixbufloader.write(dsobject.metadata['preview']) + pixbufloader.close() + pixbuf = pixbufloader.get_pixbuf() + except: + pixbuf = None + return pixbuf + + +def get_path(activity, subpath): + ''' Find a Rainbow-approved place for temporary files. ''' + try: + return(os.path.join(activity.get_activity_root(), subpath)) + except: + # Early versions of Sugar didn't support get_activity_root() + return(os.path.join(os.environ['HOME'], '.sugar/default', + 'org.laptop.TurtleArtActivity', subpath)) + + +def image_to_base64(image_path, tmp_path): + ''' Convert an image to base64-encoded data ''' + base64 = os.path.join(tmp_path, 'base64tmp') + cmd = 'base64 <' + image_path + ' >' + base64 + subprocess.check_call(cmd, shell=True) + file_handle = open(base64, 'r') + data = file_handle.read() + file_handle.close() + os.remove(base64) + return data + + +def base64_to_image(data, path_name): + ''' Convert base64-encoded data to an image ''' + base64 = os.path.join(path_name, 'base64tmp') + file_handle = open(base64, 'w') + file_handle.write(data) + file_handle.close() + file_name = os.path.join(path_name, 'imagetmp.png') + cmd = 'base64 -d <' + base64 + '>' + file_name + subprocess.check_call(cmd, shell=True) + return file_name + + +def movie_media_type(name): + ''' Is it movie media? ''' + return name.lower().endswith(('.ogv', '.vob', '.mp4', '.wmv', '.mov', + '.mpeg', '.ogg', '.webm')) + + +def audio_media_type(name): + ''' Is it audio media? ''' + return name.lower().endswith(('.oga', '.m4a')) + + +def image_media_type(name): + ''' Is it image media? ''' + return name.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.tiff', + '.tif', '.svg')) + + +def text_media_type(name): + ''' Is it text media? ''' + return name.lower().endswith(('.txt', '.py', '.lg', '.rtf')) + + +def round_int(num): + ''' Remove trailing decimal places if number is an int ''' + try: + float(num) + except TypeError: + raise pythonerror('#syntaxerror') + + if int(float(num)) == num: + return int(num) + else: + if float(num) < 0: + nn = int((float(num) - 0.005) * 100) / 100. + else: + nn = int((float(num) + 0.005) * 100) / 100. + if int(float(nn)) == nn: + return int(nn) + return nn + + +def calc_image_size(spr): + ''' Calculate the maximum size for placing an image onto a sprite. ''' + return int(max(spr.label_safe_width(), 1)), \ + int(max(spr.label_safe_height(), 1)) + + +# Collapsible stacks live between 'sandwichtop' and 'sandwichbottom' blocks + + +def reset_stack_arm(top): + ''' When we undock, retract the 'arm' that extends from 'sandwichtop'. ''' + if top is not None and top.name in ['sandwichtop', 'sandwichtop_no_label']: + if top.ey > 0: + top.reset_y() + top.svg.set_hide(False) + top.refresh() + + +def grow_stack_arm(top): + ''' When we dock, grow an 'arm' from 'sandwichtop'. ''' + if top is not None and top.name in ['sandwichtop', 'sandwichtop_no_label']: + bot = find_sandwich_bottom(top) + if bot is None: + return + if top.ey > 0: + top.reset_y() + ty = top.spr.get_xy()[1] + th = top.spr.get_dimensions()[1] + by = bot.spr.get_xy()[1] + dy = by - (ty + th) + if dy > 0: + top.expand_in_y(dy / top.scale) + top.svg.set_hide(True) + top.refresh() + + +def find_sandwich_top(blk): + ''' Find the sandwich top above this block. ''' + # Always follow the main branch of a flow: the first connection. + cblk = blk.connections[0] + while cblk is not None: + if cblk.name in COLLAPSIBLE: + return None + if cblk.name in ['repeat', 'if', 'ifelse', 'forever', 'while']: + if blk != cblk.connections[len(cblk.connections) - 1]: + return None + if cblk.name in SANDWICHES: + return cblk + blk = cblk + cblk = cblk.connections[0] + return None + + +def find_sandwich_bottom(blk): + ''' Find the sandwich bottom below this block. ''' + # Always follow the main branch of a flow: the last connection. + cblk = blk.connections[len(blk.connections) - 1] + while cblk is not None: + if cblk.name in SANDWICHES: + return None + if cblk.name in COLLAPSIBLE: + return cblk + cblk = cblk.connections[len(cblk.connections) - 1] + return None + + +def find_sandwich_top_below(blk): + ''' Find the sandwich top below this block. ''' + if blk.name in SANDWICHES: + return blk + # Always follow the main branch of a flow: the last connection. + cblk = blk.connections[len(blk.connections) - 1] + while cblk is not None: + if cblk.name in SANDWICHES: + return cblk + cblk = cblk.connections[len(cblk.connections) - 1] + return None + + +def restore_stack(top): + ''' Restore the blocks between the sandwich top and sandwich bottom. ''' + group = find_group(top.connections[len(top.connections) - 1]) + hit_bottom = False + bot = find_sandwich_bottom(top) + for gblk in group: + if not hit_bottom and gblk == bot: + hit_bottom = True + if len(gblk.values) == 0: + gblk.values.append(0) + else: + gblk.values[0] = 0 + olddx = gblk.docks[1][2] + olddy = gblk.docks[1][3] + # Replace 'sandwichcollapsed' shape with 'sandwichbottom' shape + gblk.name = 'sandwichbottom' + gblk.spr.set_label(' ', 1) + gblk.svg.set_show(False) + gblk.svg.set_hide(True) + gblk.refresh() + # Redock to previous block in group + you = gblk.connections[0] + (yx, yy) = you.spr.get_xy() + yd = you.docks[len(you.docks) - 1] + (bx, by) = gblk.spr.get_xy() + dx = yx + yd[2] - gblk.docks[0][2] - bx + dy = yy + yd[3] - gblk.docks[0][3] - by + gblk.spr.move_relative((dx, dy)) + # Since the shapes have changed, the dock positions have too. + dx += gblk.docks[1][2] - olddx + dy += gblk.docks[1][3] - olddy + else: + if not hit_bottom: + gblk.spr.restore() + gblk.status = None + else: + gblk.spr.move_relative((dx, dy)) + # Add 'sandwichtop' arm + if top.name == 'sandwichtop_no_arm': + top.name = 'sandwichtop' + else: + top.name = 'sandwichtop_no_label' + top.spr.set_label(' ', 1) + top.resize() + top.refresh() + grow_stack_arm(top) + + +def uncollapse_forks(top, looping=False): + ''' From the top, find and restore any collapsible stacks on forks. ''' + if top == None: + return + if looping and top.name in ['sandwichtop_no_arm', + 'sandwichtop_no_arm_no_label']: + restore_stack(top) + return + if len(top.connections) == 0: + return + cblk = top.connections[len(top.connections) - 1] + while cblk is not None: + if cblk.name in COLLAPSIBLE: + return + if cblk.name in ['sandwichtop_no_arm', 'sandwichtop_no_arm_no_label']: + restore_stack(cblk) + return + # Follow a fork + if cblk.name in ['repeat', 'if', 'ifelse', 'forever', 'while', + 'until']: + top = find_sandwich_top_below( + cblk.connections[len(cblk.connections) - 2]) + if top is not None: + uncollapse_forks(top, True) + if cblk.name == 'ifelse': + top = find_sandwich_top_below( + cblk.connections[len(cblk.connections) - 3]) + if top is not None: + uncollapse_forks(top, True) + cblk = cblk.connections[len(cblk.connections) - 1] + return + + +def collapse_stack(top): + ''' Hide all the blocks between the sandwich top and sandwich bottom. ''' + # First uncollapse any nested stacks + if top == None or top.spr == None: + return + uncollapse_forks(top) + hit_bottom = False + bot = find_sandwich_bottom(top) + group = find_group(top.connections[len(top.connections) - 1]) + for gblk in group: + if not hit_bottom and gblk == bot: + hit_bottom = True + # Replace 'sandwichbottom' with invisible 'sandwichcollapsed' + if len(gblk.values) == 0: + gblk.values.append(1) + else: + gblk.values[0] = 1 + olddx = gblk.docks[1][2] + olddy = gblk.docks[1][3] + gblk.name = 'sandwichcollapsed' + gblk.resize() + you = find_sandwich_top(gblk) + (yx, yy) = you.spr.get_xy() + yd = you.docks[len(you.docks) - 1] + (bx, by) = gblk.spr.get_xy() + dx = yx + yd[2] - gblk.docks[0][2] - bx + dy = yy + yd[3] - gblk.docks[0][3] - by + gblk.spr.move_relative((dx, dy)) + # Since the shapes have changed, the dock positions have too. + dx += gblk.docks[1][2] - olddx + dy += gblk.docks[1][3] - olddy + else: + if not hit_bottom: + gblk.spr.hide() + gblk.status = 'collapsed' + else: + gblk.spr.move_relative((dx, dy)) + # Remove 'sandwichtop' arm + if top.name == 'sandwichtop' or top.name == 'sandwichtop_no_arm': + top.name = 'sandwichtop_no_arm' + else: + top.name = 'sandwichtop_no_arm_no_label' + top.spr.set_label(' ') + top.spr.set_label(' ', 1) + top.resize() + top.spr.set_label(_('click to open'), 1) + top.resize() + top.svg.set_hide(False) + top.refresh() + + +def collapsed(blk): + ''' Is this stack collapsed? ''' + if blk is not None and blk.name in COLLAPSIBLE and\ + len(blk.values) == 1 and blk.values[0] != 0: + return True + return False + + +def collapsible(blk): + ''' Can this stack be collapsed? ''' + if blk is None or blk.name not in COLLAPSIBLE: + return False + if find_sandwich_top(blk) is None: + return False + return True + + +def hide_button_hit(spr, x, y): + ''' Did the sprite's hide (contract) button get hit? ''' + red, green, blue, alpha = spr.get_pixel((x, y)) + if red == HIT_HIDE: + return True + else: + return False + + +def show_button_hit(spr, x, y): + ''' Did the sprite's show (expand) button get hit? ''' + red, green, blue, alpha = spr.get_pixel((x, y)) + if green == HIT_SHOW: + return True + else: + return False + + +def numeric_arg(value): + ''' Dock test: looking for a numeric value ''' + if type(convert(value, float)) is float: + return True + return False + + +def zero_arg(value): + ''' Dock test: looking for a zero argument ''' + if numeric_arg(value): + if convert(value, float) == 0: + return True + return False + + +def neg_arg(value): + ''' Dock test: looking for a negative argument ''' + if numeric_arg(value): + if convert(value, float) < 0: + return True + return False + + +def journal_check(blk1, blk2, dock1, dock2): + ''' Dock blocks only if arg is Journal block ''' + if blk1 == None or blk2 == None: + return True + if (blk1.name == 'skin' and dock1 == 1) and blk2.name != 'journal': + return False + if (blk2.name == 'skin' and dock2 == 1) and blk1.name != 'journal': + return False + return True + + +def arithmetic_check(blk1, blk2, dock1, dock2): + ''' Dock strings only if they convert to numbers. Avoid /0 and root(-1)''' + if blk1 == None or blk2 == None: + return True + if blk1.name in ['sqrt', 'number', 'string'] and\ + blk2.name in ['sqrt', 'number', 'string']: + if blk1.name == 'number' or blk1.name == 'string': + if not numeric_arg(blk1.values[0]) or neg_arg(blk1.values[0]): + return False + elif blk2.name == 'number' or blk2.name == 'string': + if not numeric_arg(blk2.values[0]) or neg_arg(blk2.values[0]): + return False + elif blk1.name in ['division2', 'number', 'string'] and\ + blk2.name in ['division2', 'number', 'string']: + if blk1.name == 'number' or blk1.name == 'string': + if not numeric_arg(blk1.values[0]): + return False + if dock2 == 2 and zero_arg(blk1.values[0]): + return False + elif blk2.name == 'number' or blk2.name == 'string': + if not numeric_arg(blk2.values[0]): + return False + if dock1 == 2 and zero_arg(blk2.values[0]): + return False + elif blk1.name in ['product2', 'minus2', 'random', 'remainder2', + 'string'] and\ + blk2.name in ['product2', 'minus2', 'random', 'remainder2', + 'string']: + if blk1.name == 'string': + if not numeric_arg(blk1.values[0]): + return False + elif blk1.name == 'string': + if not numeric_arg(blk2.values[0]): + return False + elif blk1.name in ['greater2', 'less2'] and blk2.name == 'string': + # Non-numeric stings are OK only if both args are strings; + # Lots of test conditions... + if dock1 == 1 and blk1.connections[2] is not None: + if blk1.connections[2].name == 'number': + if not numeric_arg(blk2.values[0]): + return False + elif dock1 == 2 and blk1.connections[1] is not None: + if blk1.connections[1].name == 'number': + if not numeric_arg(blk2.values[0]): + return False + elif blk2.name in ['greater2', 'less2'] and blk1.name == 'string': + if dock2 == 1 and blk2.connections[2] is not None: + if blk2.connections[2].name == 'number': + if not numeric_arg(blk1.values[0]): + return False + elif dock2 == 2 and blk2.connections[1] is not None: + if blk2.connections[1].name == 'number': + if not numeric_arg(blk1.values[0]): + return False + elif blk1.name in ['greater2', 'less2'] and blk2.name == 'number': + if dock1 == 1 and blk1.connections[2] is not None: + if blk1.connections[2].name == 'string': + if not numeric_arg(blk1.connections[2].values[0]): + return False + elif dock1 == 2 and blk1.connections[1] is not None: + if blk1.connections[1].name == 'string': + if not numeric_arg(blk1.connections[1].values[0]): + return False + elif blk2.name in ['greater2', 'less2'] and blk1.name == 'number': + if dock2 == 1 and blk2.connections[2] is not None: + if blk2.connections[2].name == 'string': + if not numeric_arg(blk2.connections[2].values[0]): + return False + elif dock2 == 2 and blk2.connections[1] is not None: + if blk2.connections[1].name == 'string': + if not numeric_arg(blk2.connections[1].values[0]): + return False + return True + + +def xy(event): + ''' Where is the mouse event? ''' + return map(int, event.get_coords()) + + +# Utilities related to finding blocks in stacks. + + +def find_block_to_run(blk): + ''' Find a stack to run (any stack without a 'def action'on the top). ''' + top = find_top_block(blk) + if blk == top and blk.name[0:3] is not 'def': + return True + else: + return False + + +def find_top_block(blk): + ''' Find the top block in a stack. ''' + if blk is None: + return None + if len(blk.connections) == 0: + return blk + while blk.connections[0] is not None: + blk = blk.connections[0] + return blk + + +def find_start_stack(blk): + ''' Find a stack with a 'start' block on top. ''' + if blk is None: + return False + if find_top_block(blk).name == 'start': + return True + else: + return False + + +def find_group(blk): + ''' Find the connected group of block in a stack. ''' + if blk is None: + return [] + group = [blk] + if blk.connections is not None: + for cblk in blk.connections[1:]: + if cblk is not None: + group.extend(find_group(cblk)) + return group + + +def find_blk_below(blk, name): + ''' Find a specific block below this block. ''' + if blk == None or len(blk.connections) == 0: + return + group = find_group(blk) + for gblk in group: + if gblk.name == name: + return gblk + return None + + +def get_hardware(): + ''' Determine whether we are using XO 1.0, 1.5, or 'unknown' hardware ''' + product = _get_dmi('product_name') + if product is None: + if os.path.exists('/sys/devices/platform/lis3lv02d/position'): + return XO175 # FIXME: temporary check for XO 1.75 and XO 3.0 + elif os.path.exists('/etc/olpc-release') or \ + os.path.exists('/sys/power/olpc-pm'): + return XO1 + else: + return UNKNOWN + if product != 'XO': + return UNKNOWN + version = _get_dmi('product_version') + if version == '1': + return XO1 + elif version == '1.5': + return XO15 + else: + return XO175 + + +def _get_dmi(node): + ''' The desktop management interface should be a reliable source + for product and version information. ''' + path = os.path.join('/sys/class/dmi/id', node) + try: + return open(path).readline().strip() + except: + return None diff --git a/TurtleArt/tawindow.py b/TurtleArt/tawindow.py new file mode 100644 index 0000000..44e95a6 --- /dev/null +++ b/TurtleArt/tawindow.py @@ -0,0 +1,3424 @@ +# -*- coding: utf-8 -*- +#Copyright (c) 2007, Playful Invention Company +#Copyright (c) 2008-12, Walter Bender +#Copyright (c) 2009-11 Raúl Gutiérrez Segalés +#Copyright (c) 2011 Collabora Ltd. <http://www.collabora.co.uk/> + +#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 +from gettext import gettext as _ + +try: + import gst + GST_AVAILABLE = True +except ImportError: + # Turtle Art should not fail if gst is not available + GST_AVAILABLE = False + +import os +import subprocess + +from math import atan2, pi +DEGTOR = 2 * pi / 360 + +import locale + +from taconstants import HORIZONTAL_PALETTE, VERTICAL_PALETTE, BLOCK_SCALE, \ + MEDIA_SHAPES, STATUS_SHAPES, OVERLAY_SHAPES, \ + TOOLBAR_SHAPES, TAB_LAYER, RETURN, OVERLAY_LAYER, CATEGORY_LAYER, \ + BLOCKS_WITH_SKIN, ICON_SIZE, PALETTE_SCALE, PALETTE_WIDTH, SKIN_PATHS, \ + MACROS, TOP_LAYER, BLOCK_LAYER, OLD_NAMES, DEFAULT_TURTLE, TURTLE_LAYER, \ + CURSOR, EXPANDABLE, COLLAPSIBLE, DEAD_DICTS, DEAD_KEYS, NO_IMPORT, \ + TEMPLATES, PYTHON_SKIN, PALETTE_HEIGHT, STATUS_LAYER, OLD_DOCK, \ + EXPANDABLE_ARGS, XO1, XO15, XO175, XO30, TITLEXY, CONTENT_ARGS, \ + CONSTANTS, EXPAND_SKIN, PROTO_LAYER +from tapalette import palette_names, palette_blocks, expandable_blocks, \ + block_names, content_blocks, default_values, special_names, block_styles, \ + help_strings, hidden_proto_blocks, string_or_number_args +from talogo import LogoCode +from tacanvas import TurtleGraphics +from tablock import Blocks, Block +from taturtle import Turtles, Turtle +from tautils import magnitude, get_load_name, get_save_name, data_from_file, \ + data_to_file, round_int, get_id, get_pixbuf_from_journal, \ + movie_media_type, audio_media_type, image_media_type, save_picture, \ + calc_image_size, get_path, reset_stack_arm, grow_stack_arm, \ + find_sandwich_top, find_sandwich_bottom, restore_stack, collapse_stack, \ + collapsed, collapsible, hide_button_hit, show_button_hit, chooser, \ + arithmetic_check, xy, find_block_to_run, find_top_block, journal_check, \ + find_group, find_blk_below, data_to_string, find_start_stack, \ + get_hardware, debug_output, error_output, data_to_string +from tasprite_factory import SVG, svg_str_to_pixbuf, svg_from_file +from sprites import Sprites, Sprite + +if GST_AVAILABLE: + from tagplay import stop_media + +MOTION_THRESHOLD = 6 +SNAP_THRESHOLD = 200 + + +class TurtleArtWindow(): + """ TurtleArt Window class abstraction """ + timeout_tag = [0] + _PLUGIN_SUBPATH = 'plugins' + + def __init__(self, canvas_window, path, parent=None, + mycolors=None, mynick=None, turtle_canvas=None): + self._loaded_project = '' + self._sharing = False + self.parent = parent + self.turtle_canvas = turtle_canvas + self.send_event = None # method to send events over the network + self.gst_available = GST_AVAILABLE + if type(canvas_window) == gtk.DrawingArea: + self.interactive_mode = True + self.window = canvas_window + self.window.set_flags(gtk.CAN_FOCUS) + self.window.show_all() + if self.parent is not None: + self.parent.show_all() + self.running_sugar = True + else: + self.running_sugar = False + self._setup_events() + else: + self.interactive_mode = False + self.window = canvas_window + self.running_sugar = False + + if self.running_sugar: + from sugar import profile + + self.activity = parent + self.nick = profile.get_nick_name() + else: + self.activity = None + self.nick = None + + self.path = path + self.load_save_folder = os.path.join(path, 'samples') + self.py_load_save_folder = os.path.join(path, 'pysamples') + self.used_block_list = [] # Which blocks has the user used? + self.save_folder = None + self.save_file_name = None + self.width = gtk.gdk.screen_width() + self.height = gtk.gdk.screen_height() + self.rect = gtk.gdk.Rectangle(0, 0, 0, 0) + + self.no_help = False + self.last_label = None + + self.keypress = '' + self.keyvalue = 0 + self.dead_key = '' + self.mouse_flag = 0 + self.mouse_x = 0 + self.mouse_y = 0 + + try: + locale.setlocale(locale.LC_NUMERIC, '') + except locale.Error: + debug_output('unsupported locale', self.running_sugar) + self.decimal_point = locale.localeconv()['decimal_point'] + if self.decimal_point == '' or self.decimal_point is None: + self.decimal_point = '.' + + self.orientation = HORIZONTAL_PALETTE + + self.hw = get_hardware() + self.lead = 1.0 + if self.hw in (XO1, XO15, XO175): + self.scale = 1.2 # slight scale-up of fonts on XO + if self.hw == XO1: + self.color_mode = '565' + else: + self.color_mode = '888' + if self.running_sugar and not self.activity.has_toolbarbox: + self.orientation = VERTICAL_PALETTE + else: + self.scale = 1.0 + self.color_mode = '888' # TODO: Read visual mode from gtk image + + self.block_scale = BLOCK_SCALE[3] + self.trash_scale = 0.5 + self.myblock = {} + self.python_code = None + self.nop = 'nop' + self.loaded = 0 + self.step_time = 0 + self.hide = False + self.palette = True + self.coord_scale = 1 + self.buddies = [] + self.saved_string = '' + self.dx = 0 + self.dy = 0 + self.media_shapes = {} + self.cartesian = False + self.polar = False + self.metric = False + self.overlay_shapes = {} + self.toolbar_shapes = {} + self.toolbar_offset = 0 + self.status_spr = None + self.status_shapes = {} + self.toolbar_spr = None + self.palette_sprs = [] + self.palettes = [] + self.palette_button = [] + self.trash_stack = [] + self.selected_palette = None + self.previous_palette = None + self.selectors = [] + self.selected_selector = None + self.previous_selector = None + self.selector_shapes = [] + self.selected_blk = None + self.selected_spr = None + self.selected_turtle = None + self.triangle_sprs = [] + self.drag_group = None + self.drag_turtle = 'move', 0, 0 + self.drag_pos = 0, 0 + self.dragging_canvas = [False, 0, 0] + self.turtle_movement_to_share = None + self.paste_offset = 20 # Don't paste on top of where you copied. + + self.block_list = Blocks(font_scale_factor=self.scale, + decimal_point=self.decimal_point) + if self.interactive_mode: + self.sprite_list = Sprites(self.window) + else: + self.sprite_list = None + + self.canvas = TurtleGraphics(self, self.width, self.height) + if self.hw == XO175 and self.canvas.width == 1024: + self.hw = XO30 # FIXME: temporary test + if self.interactive_mode: + self.sprite_list.set_cairo_context(self.canvas.canvas) + + self.turtles = Turtles(self.sprite_list) + if self.nick is None: + self.default_turtle_name = DEFAULT_TURTLE + else: + self.default_turtle_name = self.nick + if mycolors is None: + Turtle(self.turtles, self.default_turtle_name) + else: + Turtle(self.turtles, self.default_turtle_name, mycolors.split(',')) + self.active_turtle = self.turtles.get_turtle(self.default_turtle_name) + self.active_turtle.show() + + self.canvas.clearscreen(False) + + CONSTANTS['titlex'] = int(-(self.canvas.width * TITLEXY[0]) / \ + (self.coord_scale * 2)) + CONSTANTS['leftx'] = int(-(self.canvas.width * TITLEXY[0]) / \ + (self.coord_scale * 2)) + CONSTANTS['rightx'] = 0 + CONSTANTS['titley'] = int((self.canvas.height * TITLEXY[1]) / \ + (self.coord_scale * 2)) + CONSTANTS['topy'] = int((self.canvas.height * (TITLEXY[1] - 0.125)) / \ + (self.coord_scale * 2)) + CONSTANTS['bottomy'] = 0 + CONSTANTS['leftpos'] = int(-self.canvas.width / (self.coord_scale * 2)) + CONSTANTS['toppos'] = int(self.canvas.height / (self.coord_scale * 2)) + CONSTANTS['rightpos'] = int(self.canvas.width / (self.coord_scale * 2)) + CONSTANTS['bottompos'] = int(-self.canvas.height / \ + (self.coord_scale * 2)) + CONSTANTS['width'] = int(self.canvas.width / self.coord_scale) + CONSTANTS['height'] = int(self.canvas.height / self.coord_scale) + + self._icon_paths = [os.path.join(self.path, 'icons')] + self._plugins = [] + + self._init_plugins() + self.lc = LogoCode(self) + + from tabasics import Palettes + p = Palettes(self) + self._setup_plugins() + + if self.interactive_mode: + self._setup_misc() + self.show_toolbar_palette(0, False) + + self.saved_pictures = [] + self.block_operation = '' + + def _get_plugin_home(self): + """ Look in the execution directory """ + path = os.path.join(self.path, self._PLUGIN_SUBPATH) + if os.path.exists(path): + return path + else: + return None + + def _get_plugins_from_plugins_dir(self, path): + """ Look for plugin files in plugin dir. """ + plugin_files = [] + if path is not None: + candidates = os.listdir(path) + for dirname in candidates: + if os.path.exists( + os.path.join(path, dirname, dirname + '.py')): + plugin_files.append(dirname) + return plugin_files + + def _init_plugins(self): + """ Try importing plugin files from the plugin dir. """ + for plugin_dir in self._get_plugins_from_plugins_dir( + self._get_plugin_home()): + self.init_plugin(plugin_dir) + + def init_plugin(self, plugin_dir): + """ Initialize plugin in plugin_dir """ + plugin_class = plugin_dir.capitalize() + f = "def f(self): from plugins.%s.%s import %s; return %s(self)" \ + % (plugin_dir, plugin_dir, plugin_class, plugin_class) + plugins = {} + try: + exec f in globals(), plugins + self._plugins.append(plugins.values()[0](self)) + debug_output('Successfully importing %s' % (plugin_class), + self.running_sugar) + # Add the icon dir to the icon_theme search path + self._add_plugin_icon_dir(os.path.join(self._get_plugin_home(), + plugin_dir)) + except ImportError, e: + debug_output('Failed to import %s: %s' % (plugin_class, str(e)), + self.running_sugar) + + def _add_plugin_icon_dir(self, dirname): + ''' If there is an icon subdir, add it to the search path. ''' + icon_theme = gtk.icon_theme_get_default() + icon_path = os.path.join(dirname, 'icons') + if os.path.exists(icon_path): + icon_theme.append_search_path(icon_path) + self._icon_paths.append(icon_path) + + def _get_plugin_instance(self, plugin_name): + """ Returns the plugin 'plugin_name' instance """ + list_plugins = self._get_plugins_from_plugins_dir( + self._get_plugin_home()) + if plugin_name in list_plugins: + number_plugin = list_plugins.index(plugin_name) + return self._plugins[number_plugin] + else: + return None + + def _setup_plugins(self): + """ Initial setup -- called just once. """ + for plugin in self._plugins: + plugin.setup() + + def _start_plugins(self): + """ Start is called everytime we execute blocks. """ + for plugin in self._plugins: + plugin.start() + + def _stop_plugins(self): + """ Stop is called whenever we stop execution. """ + for plugin in self._plugins: + plugin.stop() + + def clear_plugins(self): + """ Clear is called from the clean block and erase button. """ + for plugin in self._plugins: + if hasattr(plugin, 'clear'): + plugin.clear() + + def background_plugins(self): + """ Background is called when we are pushed to the background. """ + for plugin in self._plugins: + plugin.goto_background() + + def foreground_plugins(self): + """ Foreground is called when we are return from the background. """ + for plugin in self._plugins: + plugin.return_to_foreground() + + def quit_plugins(self): + """ Quit is called upon program exit. """ + for plugin in self._plugins: + plugin.quit() + + def _setup_events(self): + """ Register the events we listen to. """ + self.window.add_events(gtk.gdk.BUTTON_PRESS_MASK) + self.window.add_events(gtk.gdk.BUTTON_RELEASE_MASK) + self.window.add_events(gtk.gdk.POINTER_MOTION_MASK) + self.window.add_events(gtk.gdk.KEY_PRESS_MASK) + # self.window.connect('realize', self.do_realize) + self.window.connect("expose-event", self._expose_cb) + self.window.connect("button-press-event", self._buttonpress_cb) + self.window.connect("button-release-event", self._buttonrelease_cb) + self.window.connect("motion-notify-event", self._move_cb) + self.window.connect("key-press-event", self._keypress_cb) + + def load_media_shapes(self): + """ Media shapes get positioned onto blocks """ + for name in MEDIA_SHAPES: + if name in self.media_shapes: + continue + if name[0:7] == 'journal' and not self.running_sugar: + filename = 'file' + name[7:] + else: + filename = name + # Try both images/ and plugins/*/images/ + for path in SKIN_PATHS: + if os.path.exists(os.path.join(self.path, path, + filename + '.svg')): + self.media_shapes[name] = svg_str_to_pixbuf(svg_from_file( + os.path.join(self.path, path, filename + '.svg'))) + break + + def _setup_misc(self): + """ Misc. sprites for status, overlays, etc. """ + self.load_media_shapes() + for i, name in enumerate(STATUS_SHAPES): + # Temporary hack to use wider shapes + if name in ['print', 'help', 'status'] and self.width > 1024: + self.status_shapes[name] = svg_str_to_pixbuf(svg_from_file( + os.path.join(self.path, 'images', name + '1200.svg'))) + else: + self.status_shapes[name] = svg_str_to_pixbuf(svg_from_file( + os.path.join(self.path, 'images', name + '.svg'))) + self.status_spr = Sprite(self.sprite_list, 0, self.height - 200, + self.status_shapes['status']) + self.status_spr.hide() + self.status_spr.type = 'status' + + for name in OVERLAY_SHAPES: + self.overlay_shapes[name] = Sprite(self.sprite_list, + int(self.width / 2 - 600), + int(self.height / 2 - 450), + svg_str_to_pixbuf( + svg_from_file("%s/images/%s.svg" % (self.path, name)))) + self.overlay_shapes[name].hide() + self.overlay_shapes[name].type = 'overlay' + + if not self.running_sugar: + # offset = 2 * self.width - 55 * len(TOOLBAR_SHAPES) + offset = 55 * (2 + len(palette_blocks)) + for i, name in enumerate(TOOLBAR_SHAPES): + self.toolbar_shapes[name] = Sprite( + self.sprite_list, i * 55 + offset, 0, + svg_str_to_pixbuf(svg_from_file(os.path.join( + self.path, 'icons', '%s.svg' % (name))))) + self.toolbar_shapes[name].set_layer(TAB_LAYER) + self.toolbar_shapes[name].name = name + self.toolbar_shapes[name].type = 'toolbar' + self.toolbar_shapes['stopiton'].hide() + + # Make the triangle buttons for adjusting numeric values + svg = SVG() + svg.set_scale(self.scale) + self.triangle_sprs.append(Sprite(self.sprite_list, 0, 0, + svg_str_to_pixbuf(svg.triangle_up(["#FF00FF", "#A000A0"])))) + self.triangle_sprs[-1].set_label('+') + self.triangle_sprs[-1].type = 'control' + self.triangle_sprs[-1].hide() + self.triangle_sprs.append(Sprite(self.sprite_list, 0, 0, + svg_str_to_pixbuf(svg.triangle_down(["#FF00FF", "#A000A0"])))) + self.triangle_sprs[-1].set_label('-') + self.triangle_sprs[-1].type = 'control' + self.triangle_sprs[-1].hide() + + def set_sharing(self, shared): + self._sharing = shared + + def sharing(self): + return self._sharing + + def is_project_empty(self): + """ Check to see if project has any blocks in use """ + return len(self.just_blocks()) == 1 + + def _expose_cb(self, win=None, event=None): + """ Repaint """ + self.do_expose_event(event) + return True + + # Handle the expose-event by drawing + def do_expose_event(self, event=None): + + # Create the cairo context + cr = self.window.window.cairo_create() + # TODO: set global scale + # find_sprite needs rescaled coordinates + # sw needs new bounds set + # cr.scale(self.activity.global_x_scale, self.activity.global_y_scale) + + if event is None: + cr.rectangle(self.rect.x, self.rect.y, + self.rect.width, self.rect.height) + else: + # Restrict Cairo to the exposed area; avoid extra work + cr.rectangle(event.area.x, event.area.y, + event.area.width, event.area.height) + cr.clip() + + if self.turtle_canvas is not None: + cr.set_source_surface(self.turtle_canvas) + cr.paint() + + # Refresh sprite list + self.sprite_list.redraw_sprites(cr=cr) + + def eraser_button(self): + """ Eraser_button (hide status block when clearing the screen.) """ + if self.status_spr is not None: + self.status_spr.hide() + self.lc.find_value_blocks() # Are there blocks to update? + self.lc.prim_clear() + self.display_coordinates() + self.parent.restore_challenge() + + def run_button(self, time, running_from_button_push=False): + """ Run turtle! """ + if self.running_sugar: + self.activity.recenter() + + # Look for a 'start' block + for blk in self.just_blocks(): + if find_start_stack(blk): + self.step_time = time + debug_output("running stack starting from %s" % (blk.name), + self.running_sugar) + if running_from_button_push: + self.selected_blk = None + else: + self.selected_blk = blk + self._run_stack(blk) + return + + # If there is no 'start' block, run stacks that aren't 'def action' + for blk in self.just_blocks(): + if find_block_to_run(blk): + self.step_time = time + debug_output("running stack starting from %s" % (blk.name), + self.running_sugar) + if running_from_button_push: + self.selected_blk = None + else: + self.selected_blk = blk + self._run_stack(blk) + return + + def stop_button(self): + """ Stop button """ + self.lc.stop_logo() + self._stop_plugins() + + def set_userdefined(self, blk=None): + """ Change icon for user-defined blocks after loading Python code. """ + if blk is not None: + if blk.name in PYTHON_SKIN: + x, y = self._calc_image_offset('pythonon', blk.spr) + blk.set_image(self.media_shapes['pythonon'], x, y) + self._resize_skin(blk) + + def set_fullscreen(self): + """ Enter fullscreen mode """ + if self.running_sugar: + self.activity.fullscreen() + self.activity.recenter() + + def set_cartesian(self, flag): + """ Turn on/off Cartesian coordinates """ + if self.coord_scale == 1: + self.draw_overlay('Cartesian_labeled') + else: + self.draw_overlay('Cartesian') + return + + def set_polar(self, flag): + """ Turn on/off polar coordinates """ + self.draw_overlay('polar') + return + + def set_metric(self, flag): + """ Turn on/off metric coordinates """ + self.draw_overlay('metric') + return + + def draw_overlay(self, overlay): + ''' Draw a coordinate grid onto the canvas. ''' + save_heading = self.canvas.heading + self.canvas.heading = 0 + w = self.overlay_shapes[overlay].rect[2] + h = self.overlay_shapes[overlay].rect[3] + self.canvas.draw_surface( + self.overlay_shapes[overlay].cached_surfaces[0], + (self.canvas.width - w) / 2., + (self.canvas.height - h) / 2., w, h) + self.canvas.heading = save_heading + + def update_overlay_position(self, widget, event): + """ Reposition the overlays when window size changes """ + self.width = event.width + self.height = event.height + for name in OVERLAY_SHAPES: + shape = self.overlay_shapes[name] + showing = False + if shape in shape._sprites.list: + shape.hide() + showing = True + self.overlay_shapes[name] = Sprite(self.sprite_list, + int(self.width / 2 - 600), + int(self.height / 2 - 450), + svg_str_to_pixbuf( + svg_from_file("%s/images/%s.svg" % (self.path, name)))) + if showing: + self.overlay_shapes[name].set_layer(OVERLAY_LAYER) + else: + self.overlay_shapes[name].hide() + self.overlay_shapes[name].type = 'overlay' + self.cartesian = False + self.polar = False + self.metric = False + self.canvas.width = self.width + self.canvas.height = self.height + self.canvas.move_turtle() + + def hideshow_button(self): + """ Hide/show button """ + if not self.hide: + for blk in self.just_blocks(): + blk.spr.hide() + for spr in self.triangle_sprs: + spr.hide() + self.hide_palette() + self.hide = True + else: + for blk in self.just_blocks(): + if blk.status != 'collapsed': + blk.spr.set_layer(BLOCK_LAYER) + self.show_palette() + self.hide = False + if self.running_sugar: + self.activity.recenter() + self.inval_all() + + def inval_all(self): + """ Force a refresh """ + if self.interactive_mode: + self.window.queue_draw_area(0, 0, self.width, self.height) + + def hideshow_palette(self, state): + """ Hide or show palette """ + if not state: + self.palette = False + if self.running_sugar: + self.activity.do_hidepalette() + self.hide_palette() + else: + self.palette = True + if self.running_sugar: + self.activity.do_showpalette() + self.activity.recenter() + self.show_palette() + + def show_palette(self, n=None): + """ Show palette. """ + if n is None: + if self.selected_palette is None: + n = 0 + else: + n = self.selected_palette + self.show_toolbar_palette(n) + self.palette_button[self.orientation].set_layer(TAB_LAYER) + self.palette_button[2].set_layer(TAB_LAYER) + self._display_palette_shift_button(n) + if self.activity is None or not self.activity.has_toolbarbox: + self.toolbar_spr.set_layer(CATEGORY_LAYER) + self.palette = True + + def hide_palette(self): + """ Hide the palette. """ + self._hide_toolbar_palette() + self.palette_button[self.orientation].hide() + self.palette_button[2].hide() + self.palette_button[3].hide() + self.palette_button[4].hide() + if self.activity is None or not self.activity.has_toolbarbox: + self.toolbar_spr.hide() + self.palette = False + + def move_palettes(self, x, y): + """ Move the palettes. """ + for p in self.palettes: + for blk in p: + blk.spr.move((x + blk.spr.save_xy[0], y + blk.spr.save_xy[1])) + for spr in self.palette_button: + spr.move((x + spr.save_xy[0], y + spr.save_xy[1])) + for p in self.palette_sprs: + if p[0] is not None: + p[0].move((x + p[0].save_xy[0], y + p[0].save_xy[1])) + if p[1] is not None: + p[1].move((x + p[1].save_xy[0], y + p[1].save_xy[1])) + + self.status_spr.move((x + self.status_spr.save_xy[0], + y + self.status_spr.save_xy[1])) + + # To do: set save_xy for blocks in Trash + for blk in self.trash_stack: + for gblk in find_group(blk): + gblk.spr.move((x + gblk.spr.save_xy[0], + y + gblk.spr.save_xy[1])) + + def hideblocks(self): + """ Callback from 'hide blocks' block """ + if not self.interactive_mode: + return + self.hide = False + self.hideshow_button() + if self.running_sugar: + self.activity.do_hide_blocks() + + def showblocks(self): + """ Callback from 'show blocks' block """ + if not self.interactive_mode: + return + self.hide = True + self.hideshow_button() + if self.running_sugar: + self.activity.do_show_blocks() + + def resize_blocks(self, blocks=None): + """ Resize blocks or if blocks is None, all of the blocks """ + if blocks is None: + blocks = self.just_blocks() + + # We need to restore collapsed stacks before resizing. + for blk in blocks: + if blk.status == 'collapsed': + bot = find_sandwich_bottom(blk) + if collapsed(bot): + dy = bot.values[0] + restore_stack(find_sandwich_top(blk)) + bot.values[0] = dy + + # Do the resizing. + for blk in blocks: + blk.rescale(self.block_scale) + for blk in blocks: + self._adjust_dock_positions(blk) + + # Re-collapsed stacks after resizing. + for blk in blocks: + if collapsed(blk): + collapse_stack(find_sandwich_top(blk)) + for blk in blocks: + if blk.name in ['sandwichtop', 'sandwichtop_no_label']: + grow_stack_arm(blk) + + # Resize the skins on some blocks: media content and Python + for blk in blocks: + if blk.name in BLOCKS_WITH_SKIN: + self._resize_skin(blk) + + def _shift_toolbar_palette(self, n): + ''' Shift blocks on specified palette ''' + x, y = self.palette_sprs[n][self.orientation].get_xy() + w, h = self.palette_sprs[n][self.orientation].get_dimensions() + bx, by = self.palettes[n][0].spr.get_xy() + if self.orientation == 0: + dx = w - self.width + dy = 0 + if bx - x > 0: + dx *= -1 + else: + dx = 0 + dy = h - self.height + ICON_SIZE + if by - y > 0: + dy *= -1 + for blk in self.palettes[n]: + if blk.get_visibility(): + blk.spr.move_relative((dx, dy)) + + def show_toolbar_palette(self, n, init_only=False, regenerate=False, + show=True): + """ Show the toolbar palettes, creating them on init_only """ + # If we are running the 0.86+ toolbar, the selectors are already + # created, as toolbar buttons. Otherwise, we need to create them. + if (self.activity is None or not self.activity.has_toolbarbox) and \ + self.selectors == []: + # First, create the selector buttons + self._create_the_selectors() + + # Create the empty palettes that we'll then populate with prototypes. + if self.palette_sprs == []: + self._create_the_empty_palettes() + + # At initialization of the program, we don't actually populate + # the palettes. + if init_only: + return + + if show: + # Hide the previously displayed palette + self._hide_previous_palette() + else: + save_selected = self.selected_palette + save_previous = self.previous_palette + + self.selected_palette = n + self.previous_palette = self.selected_palette + + # Make sure all of the selectors are visible. (We don't need to do + # this for 0.86+ toolbars since the selectors are toolbar buttons.) + if show and \ + (self.activity is None or not self.activity.has_toolbarbox): + self.selected_selector = self.selectors[n] + self.selectors[n].set_shape(self.selector_shapes[n][1]) + for i in range(len(palette_blocks)): + self.selectors[i].set_layer(TAB_LAYER) + + # Show the palette with the current orientation. + if self.palette_sprs[n][self.orientation] is not None: + self.palette_sprs[n][self.orientation].set_layer( + CATEGORY_LAYER) + self._display_palette_shift_button(n) + + # Create 'proto' blocks for each palette entry + self._create_proto_blocks(n) + + if show or save_selected == n: + self._layout_palette(n, regenerate=regenerate) + else: + self._layout_palette(n, regenerate=regenerate, show=False) + for blk in self.palettes[n]: + if blk.get_visibility(): + if hasattr(blk.spr, 'set_layer'): + blk.spr.set_layer(PROTO_LAYER) + else: + debug_output('WARNING: block sprite is None' % (blk.name), + self.running_sugar) + else: + blk.spr.hide() + if n == palette_names.index('trash'): + for blk in self.trash_stack: + for gblk in find_group(blk): + if gblk.status != 'collapsed': + gblk.spr.set_layer(TAB_LAYER) + + if not show: + if not save_selected == n: + self._hide_previous_palette(palette=n) + self.selected_palette = save_selected + self.previous_palette = save_previous + + def _display_palette_shift_button(self, n): + ''' Palettes too wide (or tall) for the screen get a shift button ''' + if self.palette_sprs[n][self.orientation].type == \ + 'category-shift-horizontal': + self.palette_button[3].set_layer(CATEGORY_LAYER) + self.palette_button[4].hide() + elif self.palette_sprs[n][self.orientation].type == \ + 'category-shift-vertical': + self.palette_button[3].hide() + self.palette_button[4].set_layer(CATEGORY_LAYER) + else: + self.palette_button[3].hide() + self.palette_button[4].hide() + + def _create_the_selectors(self): + ''' Create the palette selector buttons: only when running + old-style Sugar toolbars or from GNOME ''' + svg = SVG() + x, y = 50, 0 # positioned at the left, top + for i, name in enumerate(palette_names): + for path in self._icon_paths: + if os.path.exists(os.path.join(path, '%soff.svg' % (name))): + icon_pathname = os.path.join(path, '%soff.svg' % (name)) + break + if icon_pathname is not None: + off_shape = svg_str_to_pixbuf(svg_from_file(icon_pathname)) + else: + off_shape = svg_str_to_pixbuf(svg_from_file(os.path.join( + self._icon_paths[0], 'extrasoff.svg'))) + error_output('Unable to open %soff.svg' % (name), + self.running_sugar) + for path in self._icon_paths: + if os.path.exists(os.path.join(path, '%son.svg' % (name))): + icon_pathname = os.path.join(path, '%son.svg' % (name)) + break + if icon_pathname is not None: + on_shape = svg_str_to_pixbuf(svg_from_file(icon_pathname)) + else: + on_shape = svg_str_to_pixbuf(svg_from_file(os.path.join( + self._icon_paths[0], 'extrason.svg'))) + error_output('Unable to open %son.svg' % (name), + self.running_sugar) + + self.selector_shapes.append([off_shape, on_shape]) + self.selectors.append(Sprite(self.sprite_list, x, y, off_shape)) + self.selectors[i].type = 'selector' + self.selectors[i].name = name + self.selectors[i].set_layer(TAB_LAYER) + w = self.selectors[i].get_dimensions()[0] + x += int(w) # running from left to right + + # Create the toolbar background for the selectors + self.toolbar_offset = ICON_SIZE + self.toolbar_spr = Sprite(self.sprite_list, 0, 0, + svg_str_to_pixbuf(svg.toolbar(2 * self.width, ICON_SIZE))) + self.toolbar_spr.type = 'toolbar' + self.toolbar_spr.set_layer(CATEGORY_LAYER) + + def _create_the_empty_palettes(self): + ''' Create the empty palettes to be populated by prototype blocks. ''' + if len(self.palettes) == 0: + for i in range(len(palette_blocks)): + self.palettes.append([]) + + # Create empty palette backgrounds + for i in palette_names: + self.palette_sprs.append([None, None]) + + # Create the palette orientation button + self.palette_button.append(Sprite(self.sprite_list, 0, + self.toolbar_offset, svg_str_to_pixbuf(svg_from_file( + "%s/images/palettehorizontal.svg" % (self.path))))) + self.palette_button.append(Sprite(self.sprite_list, 0, + self.toolbar_offset, svg_str_to_pixbuf(svg_from_file( + "%s/images/palettevertical.svg" % (self.path))))) + self.palette_button[0].name = _('orientation') + self.palette_button[1].name = _('orientation') + self.palette_button[0].type = 'palette' + self.palette_button[1].type = 'palette' + self.palette_button[self.orientation].set_layer(TAB_LAYER) + self.palette_button[1 - self.orientation].hide() + + # Create the palette next button + self.palette_button.append(Sprite(self.sprite_list, 16, + self.toolbar_offset, svg_str_to_pixbuf(svg_from_file( + "%s/images/palettenext.svg" % (self.path))))) + self.palette_button[2].name = _('next') + self.palette_button[2].type = 'palette' + self.palette_button[2].set_layer(TAB_LAYER) + + # Create the palette shift buttons + dims = self.palette_button[0].get_dimensions() + self.palette_button.append(Sprite(self.sprite_list, 0, + self.toolbar_offset + dims[1], svg_str_to_pixbuf(svg_from_file( + "%s/images/palettehshift.svg" % (self.path))))) + self.palette_button.append(Sprite(self.sprite_list, dims[0], + self.toolbar_offset, svg_str_to_pixbuf(svg_from_file( + "%s/images/palettevshift.svg" % (self.path))))) + self.palette_button[3].name = _('shift') + self.palette_button[4].name = _('shift') + self.palette_button[3].type = 'palette' + self.palette_button[4].type = 'palette' + self.palette_button[3].hide() + self.palette_button[4].hide() + + def _create_proto_blocks(self, n): + ''' Create the protoblocks that will populate a palette. ''' + # Reload the palette, but reuse the existing blocks + # If a block doesn't exist, add it + + if not n < len(self.palettes): + debug_output( + '_create_proto_blocks: palette index %d is out of range' % (n), + self.running_sugar) + return + + for blk in self.palettes[n]: + blk.spr.hide() + old_blocks = self.palettes[n][:] + self.palettes[n] = [] + for name in palette_blocks[n]: + found_block = False + for oblk in old_blocks: + if oblk.name == name: + self.palettes[n].append(oblk) + found_block = True + break + if not found_block: + self.palettes[n].append(Block( + self.block_list, self.sprite_list, name, 0, 0, + 'proto', [], PALETTE_SCALE)) + if name in hidden_proto_blocks: + self.palettes[n][-1].set_visibility(False) + else: + if hasattr(self.palettes[n][-1].spr, 'set_layer'): + self.palettes[n][-1].spr.set_layer(PROTO_LAYER) + self.palettes[n][-1].unhighlight() + else: + debug_output('WARNING: block sprite is None' % ( + self.palettes[n][-1].name), self.running_sugar) + + # Some proto blocks get a skin. + if name in block_styles['box-style-media']: + self._proto_skin(name + 'small', n, -1) + elif name[:8] == 'template': # Deprecated + self._proto_skin(name[8:], n, -1) + elif name[:7] == 'picture': # Deprecated + self._proto_skin(name[7:], n, -1) + elif name in PYTHON_SKIN: + self._proto_skin('pythonsmall', n, -1) + return + + def _hide_toolbar_palette(self): + """ Hide the toolbar palettes """ + self._hide_previous_palette() + if self.activity is None or not self.activity.has_toolbarbox: + # Hide the selectors + for i in range(len(palette_blocks)): + self.selectors[i].hide() + elif self.selected_palette is not None and \ + not self.activity.has_toolbarbox: + self.activity.palette_buttons[self.selected_palette].set_icon( + palette_names[self.selected_palette] + 'off') + + def _hide_previous_palette(self, palette=None): + """ Hide just the previously viewed toolbar palette """ + if palette is None: + palette = self.previous_palette + # Hide previously selected palette + if palette is not None: + if not palette < len(self.palettes): + debug_output( + '_hide_previous_palette: index %d is out of range' % \ + (palette), self.running_sugar) + return + for proto in self.palettes[palette]: + proto.spr.hide() + if self.palette_sprs[palette][self.orientation] is not None: + self.palette_sprs[palette][self.orientation].hide() + if self.activity is None or not self.activity.has_toolbarbox: + self.selectors[palette].set_shape( + self.selector_shapes[palette][0]) + elif palette is not None and palette != self.selected_palette \ + and not self.activity.has_toolbarbox: + self.activity.palette_buttons[palette].set_icon( + palette_names[palette] + 'off') + if palette == palette_names.index('trash'): + for blk in self.trash_stack: + for gblk in find_group(blk): + gblk.spr.hide() + + def _horizontal_layout(self, x, y, blocks): + """ Position prototypes in a horizontal palette. """ + max_w = 0 + for blk in blocks: + if not blk.get_visibility(): + continue + w, h = self._width_and_height(blk) + if y + h > PALETTE_HEIGHT + self.toolbar_offset: + x += int(max_w + 3) + y = self.toolbar_offset + 3 + max_w = 0 + (bx, by) = blk.spr.get_xy() + dx = x - bx + dy = y - by + for g in find_group(blk): + g.spr.move_relative((int(dx), int(dy))) + g.spr.save_xy = g.spr.get_xy() + if self.running_sugar and not self.hw in [XO1]: + g.spr.move_relative((self.activity.hadj_value, + self.activity.vadj_value)) + y += int(h + 3) + if w > max_w: + max_w = w + return x, y, max_w + + def _vertical_layout(self, x, y, blocks): + """ Position prototypes in a vertical palette. """ + row = [] + row_w = 0 + max_h = 0 + for blk in blocks: + if not blk.get_visibility(): + continue + w, h = self._width_and_height(blk) + if x + w > PALETTE_WIDTH: + # Recenter row. + dx = int((PALETTE_WIDTH - row_w) / 2) + for r in row: + for g in find_group(r): + g.spr.move_relative((dx, 0)) + g.spr.save_xy = (g.spr.save_xy[0] + dx, + g.spr.save_xy[1]) + row = [] + row_w = 0 + x = 4 + y += int(max_h + 3) + max_h = 0 + row.append(blk) + row_w += (4 + w) + (bx, by) = blk.spr.get_xy() + dx = int(x - bx) + dy = int(y - by) + for g in find_group(blk): + g.spr.move_relative((dx, dy)) + g.spr.save_xy = g.spr.get_xy() + if self.running_sugar and not self.hw in [XO1]: + g.spr.move_relative((self.activity.hadj_value, + self.activity.vadj_value)) + x += int(w + 4) + if h > max_h: + max_h = h + # Recenter last row. + dx = int((PALETTE_WIDTH - row_w) / 2) + for r in row: + for g in find_group(r): + g.spr.move_relative((dx, 0)) + g.spr.save_xy = (g.spr.save_xy[0] + dx, g.spr.save_xy[1]) + return x, y, max_h + + def _layout_palette(self, n, regenerate=False, show=True): + """ Layout prototypes in a palette. """ + if n is not None: + if self.orientation == HORIZONTAL_PALETTE: + x, y = 20, self.toolbar_offset + 5 + x, y, max_w = self._horizontal_layout(x, y, self.palettes[n]) + if n == palette_names.index('trash'): + x, y, max_w = self._horizontal_layout(x + max_w, y, + self.trash_stack) + w = x + max_w + 25 + self._make_palette_spr(n, 0, self.toolbar_offset, + w, PALETTE_HEIGHT, regenerate) + if show: + self.palette_button[2].move((w - 20, self.toolbar_offset)) + else: + x, y = 5, self.toolbar_offset + 15 + x, y, max_h = self._vertical_layout(x, y, self.palettes[n]) + if n == palette_names.index('trash'): + x, y, max_h = self._vertical_layout(x, y + max_h, + self.trash_stack) + h = y + max_h + 25 - self.toolbar_offset + self._make_palette_spr(n, 0, self.toolbar_offset, + PALETTE_WIDTH, h, regenerate) + if show: + self.palette_button[2].move((PALETTE_WIDTH - 20, + self.toolbar_offset)) + if show: + self.palette_button[2].save_xy = \ + self.palette_button[2].get_xy() + if self.running_sugar and not self.hw in [XO1]: + self.palette_button[2].move_relative( + (self.activity.hadj_value, self.activity.vadj_value)) + self.palette_sprs[n][self.orientation].set_layer( + CATEGORY_LAYER) + self._display_palette_shift_button(n) + + def _make_palette_spr(self, n, x, y, w, h, regenerate=False): + ''' Make the background for the palette. ''' + if regenerate and not self.palette_sprs[n][self.orientation] is None: + self.palette_sprs[n][self.orientation].hide() + self.palette_sprs[n][self.orientation] = None + if self.palette_sprs[n][self.orientation] is None: + svg = SVG() + self.palette_sprs[n][self.orientation] = \ + Sprite(self.sprite_list, x, y, svg_str_to_pixbuf( + svg.palette(w, h))) + self.palette_sprs[n][self.orientation].save_xy = (x, y) + if self.running_sugar and not self.hw in [XO1]: + self.palette_sprs[n][self.orientation].move_relative( + (self.activity.hadj_value, self.activity.vadj_value)) + if self.orientation == 0 and w > self.width: + self.palette_sprs[n][self.orientation].type = \ + 'category-shift-horizontal' + elif self.orientation == 1 and h > self.height - ICON_SIZE: + self.palette_sprs[n][self.orientation].type = \ + 'category-shift-vertical' + else: + self.palette_sprs[n][self.orientation].type = 'category' + if n == palette_names.index('trash'): + svg = SVG() + self.palette_sprs[n][self.orientation].set_shape( + svg_str_to_pixbuf(svg.palette(w, h))) + + def _buttonpress_cb(self, win, event): + """ Button press """ + self.window.grab_focus() + x, y = xy(event) + self.mouse_flag = 1 + self.mouse_x = x + self.mouse_y = y + self.button_press(event.get_state() & gtk.gdk.CONTROL_MASK, x, y) + return True + + def button_press(self, mask, x, y): + self.block_operation = 'click' + + # Find out what was clicked + spr = self.sprite_list.find_sprite((x, y)) + + # Unselect things that may have been selected earlier + if self.selected_blk is not None: + if self.selected_blk.name == 'number' and \ + spr in self.triangle_sprs: + # increment or decrement a number block + nf = float(self.selected_blk.spr.labels[0].replace(CURSOR, '')) + ni = int(nf) + if ni == nf: + n = ni + else: + n = nf + if spr == self.triangle_sprs[0]: + n += 1 + else: + n -= 1 + self.selected_blk.spr.set_label(str(n) + CURSOR) + return True + self._unselect_block() + self.selected_turtle = None + + # Always hide the status layer on a click + if self.status_spr is not None: + self.status_spr.hide() + + self.dx = 0 + self.dy = 0 + self.dragging_canvas[1] = x + self.dragging_canvas[2] = y + if spr is None: + self.dragging_canvas[0] = True + return True + self.dragging_canvas[0] = False + self.selected_spr = spr + + # From the sprite at x, y, look for a corresponding block + blk = self.block_list.spr_to_block(spr) + if blk is not None: + if blk.type == 'block': + self.selected_blk = blk + self._block_pressed(x, y, blk) + elif blk.type == 'trash': + self._restore_from_trash(find_top_block(blk)) + elif blk.type == 'proto': + if blk.name == 'restoreall': + self._restore_all_from_trash() + elif blk.name == 'restore': + self._restore_latest_from_trash() + elif blk.name == 'empty': + self._empty_trash() + elif blk.name == 'trashall': + for b in self.just_blocks(): + if b.type != 'trash': + self._put_in_trash(find_top_block(b)) + elif blk.name in MACROS: + self._new_macro(blk.name, x + 20, y + 20) + else: + # You can only have one instance of some blocks + if blk.name in ['start', 'hat1', 'hat2']: + if len(self.block_list.get_similar_blocks( + 'block', blk.name)) > 0: + self.showlabel('dupstack') + return True + # You cannot mix and match sensor blocks + elif blk.name in ['sound', 'volume', 'pitch']: + if len(self.block_list.get_similar_blocks( + 'block', ['resistance', 'voltage', + 'resistance2', 'voltage2'])) > 0: + self.showlabel('incompatible') + return True + elif blk.name in ['resistance', 'voltage', + 'resistance2', 'voltage2']: + if len(self.block_list.get_similar_blocks( + 'block', ['sound', 'volume', 'pitch'])) > 0: + self.showlabel('incompatible') + return True + if blk.name in ['resistance', 'resistance2']: + if len(self.block_list.get_similar_blocks( + 'block', ['voltage', 'voltage2'])) > 0: + self.showlabel('incompatible') + return True + elif blk.name in ['voltage', 'voltage2']: + if len(self.block_list.get_similar_blocks( + 'block', ['resistance', + 'resistance2'])) > 0: + self.showlabel('incompatible') + return True + blk.highlight() + self._new_block(blk.name, x, y) + blk.unhighlight() + return True + + # Next, look for a turtle + t = self.turtles.spr_to_turtle(spr) + if t is not None: + # If turtle is shared, ignore click + if self.remote_turtle(t.get_name()): + return True + self.selected_turtle = t + self.canvas.set_turtle(self.turtles.get_turtle_key(t)) + self._turtle_pressed(x, y) + return True + + # Finally, check for anything else + if hasattr(spr, 'type'): + if spr.type == 'selector': + self._select_category(spr) + elif spr.type in ['category', 'category-shift-horizontal', + 'category-shift-vertical']: + if hide_button_hit(spr, x, y): + self.hideshow_palette(False) + elif spr.type == 'palette': + if spr.name == _('next'): + i = self.selected_palette + 1 + if i == len(palette_names): + i = 0 + if self.activity is None or \ + not self.activity.has_toolbarbox: + self._select_category(self.selectors[i]) + else: + if self.selected_palette is not None and \ + not self.activity.has_toolbarbox: + self.activity.palette_buttons[ + self.selected_palette].set_icon( + palette_names[self.selected_palette] + 'off') + else: + # select radio button associated with this palette + self.activity.palette_buttons[i].set_active(True) + if not self.activity.has_toolbarbox: + self.activity.palette_buttons[i].set_icon( + palette_names[i] + 'on') + self.show_palette(i) + elif spr.name == _('shift'): + self._shift_toolbar_palette(self.selected_palette) + else: + self.orientation = 1 - self.orientation + self.palette_button[self.orientation].set_layer(TAB_LAYER) + self.palette_button[1 - self.orientation].hide() + self.palette_sprs[self.selected_palette][ + 1 - self.orientation].hide() + self._layout_palette(self.selected_palette) + self.show_palette(self.selected_palette) + elif spr.type == 'toolbar': + self._select_toolbar_button(spr) + return True + + def _select_category(self, spr): + """ Select a category from the toolbar """ + i = self.selectors.index(spr) + spr.set_shape(self.selector_shapes[i][1]) + if self.selected_selector is not None: + j = self.selectors.index(self.selected_selector) + if i == j: + return + self.selected_selector.set_shape(self.selector_shapes[j][0]) + self.previous_selector = self.selected_selector + self.selected_selector = spr + self.show_palette(i) + + def _select_toolbar_button(self, spr): + """ Select a toolbar button (Used when not running Sugar). """ + if not hasattr(spr, 'name'): + return + if spr.name == 'run-fastoff': + self.lc.trace = 0 + self.hideblocks() + self.run_button(0) + elif spr.name == 'run-slowoff': + self.lc.trace = 1 + self.run_button(3) + elif spr.name == 'debugoff': + self.lc.trace = 1 + self.run_button(6) + elif spr.name == 'stopiton': + self.stop_button() + self.toolbar_shapes['stopiton'].hide() + elif spr.name == 'eraseron': + self.eraser_button() + elif spr.name == 'hideshowoff': + self.hideshow_button() + + def _put_in_trash(self, blk, x=0, y=0): + """ Put a group of blocks into the trash. """ + self.trash_stack.append(blk) + group = find_group(blk) + for gblk in group: + if gblk.status == 'collapsed': + # Collapsed stacks are restored for rescaling + # and then recollapsed after they are moved to the trash. + bot = find_sandwich_bottom(gblk) + if collapsed(bot): + dy = bot.values[0] + restore_stack(find_sandwich_top(gblk)) + bot.values[0] = dy + gblk.type = 'trash' + gblk.rescale(self.trash_scale) + blk.spr.move((x, y)) + for gblk in group: + self._adjust_dock_positions(gblk) + + # Re-collapsing any stacks we had restored for scaling + for gblk in group: + if collapsed(gblk): + collapse_stack(find_sandwich_top(gblk)) + + # And resize any skins. + for gblk in group: + if gblk.name in BLOCKS_WITH_SKIN: + self._resize_skin(gblk) + + # self.show_palette(palette_names.index('trash')) + if self.selected_palette != palette_names.index('trash'): + for gblk in group: + gblk.spr.hide() + + def _restore_all_from_trash(self): + """ Restore all the blocks in the trash can. """ + for blk in self.block_list.list: + if blk.type == 'trash': + self._restore_from_trash(blk) + + def _restore_latest_from_trash(self): + """ Restore most recent blocks from the trash can. """ + if len(self.trash_stack) == 0: + return + self._restore_from_trash(self.trash_stack[len(self.trash_stack) - 1]) + + def _restore_from_trash(self, blk): + group = find_group(blk) + for gblk in group: + gblk.rescale(self.block_scale) + gblk.spr.set_layer(BLOCK_LAYER) + x, y = gblk.spr.get_xy() + if self.orientation == 0: + gblk.spr.move((x, y + PALETTE_HEIGHT + self.toolbar_offset)) + else: + gblk.spr.move((x + PALETTE_WIDTH, y)) + gblk.type = 'block' + for gblk in group: + self._adjust_dock_positions(gblk) + # If the stack had been collapsed before going into the trash, + # collapse it again now. + for gblk in group: + if collapsed(gblk): + collapse_stack(find_sandwich_top(gblk)) + + # And resize any skins. + for gblk in group: + if gblk.name in BLOCKS_WITH_SKIN: + self._resize_skin(gblk) + + self.trash_stack.remove(blk) + + def _empty_trash(self): + """ Permanently remove all blocks presently in the trash can. """ + for blk in self.block_list.list: + if blk.type == 'trash': + blk.type = 'deleted' + blk.spr.hide() + self.trash_stack = [] + + def _in_the_trash(self, x, y): + """ Is x, y over a palette? """ + if self.selected_palette is not None and \ + self.palette_sprs[self.selected_palette][self.orientation].hit( + (x, y)): + return True + return False + + def _block_pressed(self, x, y, blk): + """ Block pressed """ + if blk is not None: + blk.highlight() + self._disconnect(blk) + self.drag_group = find_group(blk) + (sx, sy) = blk.spr.get_xy() + self.drag_pos = x - sx, y - sy + for blk in self.drag_group: + if blk.status != 'collapsed': + blk.spr.set_layer(TOP_LAYER) + if len(blk.spr.labels) > 0: + self.saved_string = blk.spr.labels[0] + else: + self.saved_string = '' + + def _unselect_block(self): + """ Unselect block """ + # After unselecting a 'number' block, we need to check its value + if self.selected_blk.name == 'number': + self._number_check() + for spr in self.triangle_sprs: + spr.hide() + elif self.selected_blk.name == 'string': + self._string_check() + self.selected_blk.unhighlight() + self.selected_blk = None + + def _new_block(self, name, x, y, defaults=None): + """ Make a new block. """ + x_pos = x - 20 + y_pos = y - 20 + if name in content_blocks: + if defaults == None: + defaults = default_values[name] + newblk = Block(self.block_list, self.sprite_list, name, x_pos, + y_pos, 'block', defaults, self.block_scale) + else: + newblk = Block(self.block_list, self.sprite_list, name, x_pos, + y_pos, 'block', [], self.block_scale) + + # Add a 'skin' to some blocks + if name in PYTHON_SKIN: + if self.nop == 'pythonloaded': + self._block_skin('pythonon', newblk) + else: + self._block_skin('pythonoff', newblk) + elif name in block_styles['box-style-media']: + if name in EXPAND_SKIN: + if newblk.ex == 0: + newblk.expand_in_x(EXPAND_SKIN[name][0]) + if newblk.ey == 0: + newblk.expand_in_y(EXPAND_SKIN[name][1]) + self._block_skin(name + 'off', newblk) + + newspr = newblk.spr + newspr.set_layer(TOP_LAYER) + self.drag_pos = 20, 20 + newblk.connections = [None] * len(newblk.docks) + if newblk.name in default_values: + if defaults == None: + defaults = default_values[newblk.name] + for i, argvalue in enumerate(defaults): + # skip the first dock position since it is always a connector + dock = newblk.docks[i + 1] + argname = dock[0] + if argname == 'unavailable': + continue + if argname == 'media': + argname = 'journal' + elif argname == 'number' and \ + (type(argvalue) is str or type(argvalue) is unicode): + argname = 'string' + elif argname == 'bool': + argname = argvalue + elif argname == 'flow': + argname = argvalue + (sx, sy) = newspr.get_xy() + if argname is not None: + if argname in content_blocks: + argblk = Block(self.block_list, self.sprite_list, + argname, 0, 0, 'block', [argvalue], + self.block_scale) + else: + argblk = Block(self.block_list, self.sprite_list, + argname, 0, 0, 'block', [], + self.block_scale) + argdock = argblk.docks[0] + nx = sx + dock[2] - argdock[2] + ny = sy + dock[3] - argdock[3] + if argname == 'journal': + self._block_skin('journaloff', argblk) + argblk.spr.move((nx, ny)) + argblk.spr.set_layer(TOP_LAYER) + argblk.connections = [newblk, None] + newblk.connections[i + 1] = argblk + self.drag_group = find_group(newblk) + self.block_operation = 'new' + if len(newblk.spr.labels) > 0 and newblk.spr.labels[0] is not None \ + and newblk.name not in ['', 'number', 'string']: + if len(self.used_block_list) > 0: + self.used_block_list.append(', ') + if newblk.name in special_names: + self.used_block_list.append(special_names[newblk.name]) + elif newblk.spr.labels[0] not in self.used_block_list: + self.used_block_list.append(newblk.spr.labels[0]) + + def _new_macro(self, name, x, y): + """ Create a "macro" (predefined stack of blocks). """ + macro = MACROS[name] + macro[0][2] = x + macro[0][3] = y + top = self.process_data(macro) + self.block_operation = 'new' + self._check_collapsibles(top) + self.drag_group = find_group(top) + + def process_data(self, block_data, offset=0): + """ Process block_data (from a macro, a file, or the clipboard). """ + + # Create the blocks (or turtle). + blocks = [] + for blk in block_data: + if not self._found_a_turtle(blk): + blocks.append(self.load_block(blk, offset)) + + # Make the connections. + for i in range(len(blocks)): + cons = [] + # Normally, it is simply a matter of copying the connections. + if blocks[i].connections is None: + if block_data[i][4] is not None: + for c in block_data[i][4]: + if c is None or c > (len(blocks) - 1): + cons.append(None) + else: + cons.append(blocks[c]) + else: + debug_output("connection error %s" % (str(block_data[i])), + self.running_sugar) + cons.append(None) + elif blocks[i].connections == 'check': + # Convert old-style boolean and arithmetic blocks + cons.append(None) # Add an extra connection. + for c in block_data[i][4]: + if c is None: + cons.append(None) + else: + cons.append(blocks[c]) + # If the boolean op was connected, readjust the plumbing. + if blocks[i].name in block_styles['boolean-style']: + if block_data[i][4][0] is not None: + c = block_data[i][4][0] + cons[0] = blocks[block_data[c][4][0]] + c0 = block_data[c][4][0] + for j, cj in enumerate(block_data[c0][4]): + if cj == c: + blocks[c0].connections[j] = blocks[i] + if c < i: + blocks[c].connections[0] = blocks[i] + blocks[c].connections[3] = None + else: + # Connection was to a block we haven't seen yet. + debug_output("Warning: dock to the future", + self.running_sugar) + else: + if block_data[i][4][0] is not None: + c = block_data[i][4][0] + cons[0] = blocks[block_data[c][4][0]] + c0 = block_data[c][4][0] + for j, cj in enumerate(block_data[c0][4]): + if cj == c: + blocks[c0].connections[j] = blocks[i] + if c < i: + blocks[c].connections[0] = blocks[i] + blocks[c].connections[1] = None + else: + # Connection was to a block we haven't seen yet. + debug_output("Warning: dock to the future", + self.running_sugar) + else: + debug_output("Warning: unknown connection state %s" % \ + (str(blocks[i].connections)), + self.running_sugar) + blocks[i].connections = cons[:] + + # Block sizes and shapes may have changed. + for blk in blocks: + self._adjust_dock_positions(blk) + + # Look for any stacks that need to be collapsed or sandwiched + for blk in blocks: + if collapsed(blk): + collapse_stack(find_sandwich_top(blk)) + elif blk.name == 'sandwichbottom' and collapsible(blk): + blk.svg.set_hide(True) + blk.svg.set_show(False) + blk.refresh() + grow_stack_arm(find_sandwich_top(blk)) + + # Resize blocks to current scale + self.resize_blocks(blocks) + + if len(blocks) > 0: + return blocks[0] + else: + return None + + def _adjust_dock_positions(self, blk): + """ Adjust the dock x, y positions """ + if not self.interactive_mode: + return + (sx, sy) = blk.spr.get_xy() + for i, c in enumerate(blk.connections): + if i > 0 and c is not None and i < len(blk.docks): + bdock = blk.docks[i] + for j in range(len(c.docks)): + if j < len(c.connections) and c.connections[j] == blk: + cdock = c.docks[j] + nx = sx + bdock[2] - cdock[2] + ny = sy + bdock[3] - cdock[3] + c.spr.move((nx, ny)) + self._adjust_dock_positions(c) + + def _turtle_pressed(self, x, y): + (tx, ty) = self.selected_turtle.get_xy() + w = self.selected_turtle.spr.rect.width / 2 + h = self.selected_turtle.spr.rect.height / 2 + dx = x - tx - w + dy = y - ty - h + # if x, y is near the edge, rotate + if not hasattr(self.lc, 'value_blocks'): + self.lc.find_value_blocks() + self.lc.update_values = True + if (dx * dx) + (dy * dy) > ((w * w) + (h * h)) / 6: + self.drag_turtle = ('turn', + self.canvas.heading - atan2(dy, dx) / DEGTOR, 0) + else: + self.drag_turtle = ('move', x - tx, y - ty) + + def _move_cb(self, win, event): + x, y = xy(event) + self.mouse_x = x + self.mouse_y = y + self._mouse_move(x, y) + return True + + def _share_mouse_move(self): + ''' Share turtle movement and rotation after button up ''' + if self.sharing(): + nick = self.turtle_movement_to_share.get_name() + self.send_event("r|%s" % ( + data_to_string([nick, round_int(self.canvas.heading)]))) + if self.canvas.pendown: + self.send_event('p|%s' % (data_to_string([nick, False]))) + put_pen_back_down = True + else: + put_pen_back_down = False + self.send_event("x|%s" % ( + data_to_string([nick, [round_int(self.canvas.xcor), + round_int(self.canvas.ycor)]]))) + if put_pen_back_down: + self.send_event('p|%s' % (data_to_string([nick, True]))) + self.turtle_movement_to_share = None + + def _mouse_move(self, x, y): + """ Process mouse movements """ + + if self.running_sugar and self.dragging_canvas[0]: + dx = self.dragging_canvas[1] - x + dy = self.dragging_canvas[2] - y + self.dragging_canvas[1] = x + self.dragging_canvas[2] = y + self.activity.adjust_sw(dx, dy) + return True + + self.block_operation = 'move' + + # First, check to see if we are dragging or rotating a turtle. + if self.selected_turtle is not None: + dtype, dragx, dragy = self.drag_turtle + (sx, sy) = self.selected_turtle.get_xy() + # self.canvas.set_turtle(self.selected_turtle.get_name()) + if dtype == 'move': + dx = x - dragx - sx + self.selected_turtle.spr.rect.width / 2 + dy = y - dragy - sy + self.selected_turtle.spr.rect.height / 2 + self.selected_turtle.spr.set_layer(TOP_LAYER) + tx, ty = self.canvas.screen_to_turtle_coordinates(sx + dx, + sy + dy) + if self.canvas.pendown: + self.canvas.setpen(False) + self.canvas.setxy(tx, ty, share=False) + self.canvas.setpen(True) + else: + self.canvas.setxy(tx, ty, share=False) + else: + dx = x - sx - self.selected_turtle.spr.rect.width / 2 + dy = y - sy - self.selected_turtle.spr.rect.height / 2 + self.canvas.seth(int(dragx + atan2(dy, dx) / DEGTOR + 5) / \ + 10 * 10, share=False) + self.lc.update_label_value('heading', self.canvas.heading) + self.turtle_movement_to_share = self.selected_turtle + + # If we are hoving, show popup help. + elif self.drag_group is None: + self._show_popup(x, y) + return + + # If we have a stack of blocks selected, move them. + elif self.drag_group[0] is not None: + blk = self.drag_group[0] + + # Don't move a bottom blk if the stack is collapsed + if collapsed(blk): + return + + self.selected_spr = blk.spr + dragx, dragy = self.drag_pos + (sx, sy) = blk.spr.get_xy() + dx = x - dragx - sx + dy = y - dragy - sy + + # Take no action if there was a move of 0, 0. + if dx == 0 and dy == 0: + return + + self.drag_group = find_group(blk) + + # Prevent blocks from ending up with a negative x or y + for blk in self.drag_group: + (bx, by) = blk.spr.get_xy() + if bx + dx < 0: + dx = -bx + if by + dy < 0: + dy = -by + + # Calculate a bounding box and only invalidate once. + minx = blk.spr.rect.x + miny = blk.spr.rect.y + maxx = blk.spr.rect.x + blk.spr.rect.width + maxy = blk.spr.rect.y + blk.spr.rect.height + + for blk in self.drag_group: + if blk.spr.rect.x < minx: + minx = blk.spr.rect.x + if blk.spr.rect.x + blk.spr.rect.width > maxx: + maxx = blk.spr.rect.x + blk.spr.rect.width + if blk.spr.rect.y < miny: + miny = blk.spr.rect.y + if blk.spr.rect.y + blk.spr.rect.height > maxy: + maxy = blk.spr.rect.y + blk.spr.rect.height + blk.spr.rect.x += dx + blk.spr.rect.y += dy + + if dx < 0: + minx += dx + else: + maxx += dx + if dy < 0: + miny += dy + else: + maxy += dy + + self.rect.x = minx + self.rect.y = miny + self.rect.width = maxx - minx + self.rect.height = maxy - miny + self.window.queue_draw_area(self.rect.x, + self.rect.y, + self.rect.width, + self.rect.height) + self.dx += dx + self.dy += dy + + def _show_popup(self, x, y): + """ Let's help our users by displaying a little help. """ + spr = self.sprite_list.find_sprite((x, y)) + blk = self.block_list.spr_to_block(spr) + if spr and blk is not None: + if self.timeout_tag[0] == 0: + self.timeout_tag[0] = self._do_show_popup(blk.name) + self.selected_spr = spr + else: + if self.timeout_tag[0] > 0: + try: + gobject.source_remove(self.timeout_tag[0]) + self.timeout_tag[0] = 0 + except: + self.timeout_tag[0] = 0 + elif spr and hasattr(spr, 'type') and (spr.type == 'selector' or \ + spr.type == 'palette' or \ + spr.type == 'toolbar'): + if self.timeout_tag[0] == 0 and hasattr(spr, 'name'): + self.timeout_tag[0] = self._do_show_popup(spr.name) + self.selected_spr = spr + else: + if self.timeout_tag[0] > 0: + try: + gobject.source_remove(self.timeout_tag[0]) + self.timeout_tag[0] = 0 + except: + self.timeout_tag[0] = 0 + else: + if self.timeout_tag[0] > 0: + try: + gobject.source_remove(self.timeout_tag[0]) + self.timeout_tag[0] = 0 + except: + self.timeout_tag[0] = 0 + + def _do_show_popup(self, block_name): + """ Fetch the help text and display it. """ + if self.no_help: + return 0 + if block_name in special_names: + special_block_name = special_names[block_name] + elif block_name in block_names: + special_block_name = block_names[block_name][0] + elif block_name in TOOLBAR_SHAPES: + special_block_name = '' + else: + special_block_name = _(block_name) + if block_name in help_strings: + label = help_strings[block_name] + else: + label = special_block_name + if self.last_label == label: + return 0 + self.showlabel('help', label=label) + self.last_label = label + return 0 + + def _buttonrelease_cb(self, win, event): + """ Button release """ + x, y = xy(event) + self.mouse_flag = 0 + self.mouse_x = x + self.mouse_y = y + self.button_release(x, y) + if self.turtle_movement_to_share is not None: + self._share_mouse_move() + return True + + def button_release(self, x, y): + if self.running_sugar and self.dragging_canvas[0]: + self.dragging_canvas[0] = False + self.dragging_canvas[1] = x + self.dragging_canvas[2] = y + self.activity.adjust_palette() + return True + + # We may have been moving the turtle + if self.selected_turtle is not None: + (tx, ty) = self.selected_turtle.get_xy() + k = self.turtles.get_turtle_key(self.selected_turtle) + + # Remove turtles by dragging them onto the trash palette. + if self._in_the_trash(tx, ty): + # If it is the default turtle, just recenter it. + if k == self.default_turtle_name: + self._move_turtle(0, 0) + self.canvas.heading = 0 + self.canvas.turn_turtle() + self.lc.update_label_value('heading', self.canvas.heading) + else: + self.selected_turtle.hide() + self.turtles.remove_from_dict(k) + self.active_turtle = None + else: + self._move_turtle(tx - self.canvas.width / 2 + \ + self.active_turtle.spr.rect.width / 2, + self.canvas.height / 2 - ty - \ + self.active_turtle.spr.rect.height / 2) + self.selected_turtle = None + if self.active_turtle is None: + self.canvas.set_turtle(self.default_turtle_name) + return + + # If we don't have a group of blocks, then there is nothing to do. + if self.drag_group is None: + return + + blk = self.drag_group[0] + # Remove blocks by dragging them onto any palette. + if self.block_operation == 'move' and self._in_the_trash(x, y): + self._put_in_trash(blk, x, y) + self.drag_group = None + return + + # Pull a stack of new blocks off of the category palette. + if self.block_operation == 'new': + for gblk in self.drag_group: + (bx, by) = gblk.spr.get_xy() + if self.orientation == 0: + gblk.spr.move((bx + 20, + by + PALETTE_HEIGHT + self.toolbar_offset)) + else: + gblk.spr.move((bx + PALETTE_WIDTH, by + 20)) + + # Look to see if we can dock the current stack. + self._snap_to_dock() + self._check_collapsibles(blk) + for gblk in self.drag_group: + if gblk.status != 'collapsed': + gblk.spr.set_layer(BLOCK_LAYER) + self.drag_group = None + + # Find the block we clicked on and process it. + # Consider a very small move a click (for touch interfaces) + if self.block_operation == 'click' or \ + (self.hw in [XO175, XO30] and self.block_operation == 'move' and ( + abs(self.dx) < MOTION_THRESHOLD and \ + abs(self.dy < MOTION_THRESHOLD))): + self._click_block(x, y) + + def remote_turtle(self, name): + ''' Is this a remote turtle? ''' + if name == self.nick: + return False + if hasattr(self, 'remote_turtle_dictionary') and \ + name in self.remote_turtle_dictionary: + return True + return False + + def label_remote_turtle(self, name, colors=['#A0A0A0', '#C0C0C0']): + ''' Add a label to remote turtles ''' + turtle = self.turtles.get_turtle(name) + if turtle is not None: + turtle.label_block = Block(self.block_list, + self.sprite_list, 'turtle-label', 0, 0, + 'label', [], 1.0 / self.scale, + colors) + turtle.label_block.spr.set_label_attributes(6.0 / self.scale) + if len(name) > 6: + turtle.label_block.spr.set_label(name[0:4] + '…') + else: + turtle.label_block.spr.set_label(name) + turtle.show() + + def _move_turtle(self, x, y): + """ Move the selected turtle to (x, y). """ + self.canvas.xcor = x + self.canvas.ycor = y + self.canvas.move_turtle() + if self.interactive_mode: + self.display_coordinates() + if self.running_sugar: + self.selected_turtle.spr.set_layer(TURTLE_LAYER) + self.lc.update_label_value('xcor', + self.canvas.xcor / self.coord_scale) + self.lc.update_label_value('ycor', + self.canvas.ycor / self.coord_scale) + + def _click_block(self, x, y): + """ Click block: lots of special cases to handle... """ + blk = self.block_list.spr_to_block(self.selected_spr) + if blk is None: + return + self.selected_blk = blk + + if blk.name == 'number' or blk.name == 'string': + self.saved_string = blk.spr.labels[0] + blk.spr.labels[0] += CURSOR + if blk.name == 'number': + bx, by = blk.spr.get_xy() + bw, bh = blk.spr.get_dimensions() + tw, th = self.triangle_sprs[0].get_dimensions() + for spr in self.triangle_sprs: + spr.set_layer(TOP_LAYER) + self.triangle_sprs[0].move((int(bx + (bw - tw) / 2), by - th)) + self.triangle_sprs[1].move((int(bx + (bw - tw) / 2), by + bh)) + + elif blk.name in block_styles['box-style-media'] and \ + blk.name not in NO_IMPORT: + self._import_from_journal(self.selected_blk) + if blk.name == 'journal' and self.running_sugar: + self._load_description_block(blk) + + elif blk.name == 'identity2' or blk.name == 'hspace': + group = find_group(blk) + if hide_button_hit(blk.spr, x, y): + dx = blk.reset_x() + elif show_button_hit(blk.spr, x, y): + dx = 20 + blk.expand_in_x(dx) + else: + self._run_stack(blk) + return + for gblk in group: + if gblk != blk: + gblk.spr.move_relative((dx * blk.scale, 0)) + + elif blk.name == 'vspace': + group = find_group(blk) + if hide_button_hit(blk.spr, x, y): + dy = blk.reset_y() + elif show_button_hit(blk.spr, x, y): + dy = 20 + blk.expand_in_y(dy) + else: + self._run_stack(blk) + return + for gblk in group: + if gblk != blk: + gblk.spr.move_relative((0, dy * blk.scale)) + grow_stack_arm(find_sandwich_top(blk)) + + elif blk.name in expandable_blocks: + # Connection may be lost during expansion, so store it... + blk0 = blk.connections[0] + if blk0 is not None: + dock0 = blk0.connections.index(blk) + + if hide_button_hit(blk.spr, x, y): + dy = blk.reset_y() + elif show_button_hit(blk.spr, x, y): + dy = 20 + blk.expand_in_y(dy) + else: + self._run_stack(blk) + return + + if blk.name in block_styles['boolean-style']: + self._expand_boolean(blk, blk.connections[2], dy) + else: + self._expand_expandable(blk, blk.connections[1], dy) + + # and restore it... + if blk0 is not None: + blk.connections[0] = blk0 + blk0.connections[dock0] = blk + self._cascade_expandable(blk) + + grow_stack_arm(find_sandwich_top(blk)) + + elif blk.name in EXPANDABLE_ARGS or blk.name == 'nop': + if show_button_hit(blk.spr, x, y): + n = len(blk.connections) + group = find_group(blk.connections[n - 1]) + if blk.name == 'myfunc1arg': + blk.spr.labels[1] = 'f(x, y)' + blk.spr.labels[2] = ' ' + dy = blk.add_arg() + blk.primitive = 'myfunction2' + blk.name = 'myfunc2arg' + elif blk.name == 'myfunc2arg': + blk.spr.labels[1] = 'f(x, y, z)' + dy = blk.add_arg(False) + blk.primitive = 'myfunction3' + blk.name = 'myfunc3arg' + elif blk.name == 'userdefined': + dy = blk.add_arg() + blk.primitive = 'userdefined2' + blk.name = 'userdefined2args' + self._resize_skin(blk) + elif blk.name == 'userdefined2args': + dy = blk.add_arg(False) + blk.primitive = 'userdefined3' + blk.name = 'userdefined3args' + self._resize_skin(blk) + else: + dy = blk.add_arg() + for gblk in group: + gblk.spr.move_relative((0, dy)) + blk.connections.append(blk.connections[n - 1]) + argname = blk.docks[n - 1][0] + argvalue = default_values[blk.name][len( + default_values[blk.name]) - 1] + argblk = Block(self.block_list, self.sprite_list, argname, + 0, 0, 'block', [argvalue], self.block_scale) + argdock = argblk.docks[0] + (bx, by) = blk.spr.get_xy() + nx = bx + blk.docks[n - 1][2] - argdock[2] + ny = by + blk.docks[n - 1][3] - argdock[3] + argblk.spr.move((nx, ny)) + argblk.spr.set_layer(TOP_LAYER) + argblk.connections = [blk, None] + blk.connections[n - 1] = argblk + if blk.name in block_styles['number-style-var-arg']: + self._cascade_expandable(blk) + grow_stack_arm(find_sandwich_top(blk)) + elif blk.name in PYTHON_SKIN: + self._import_py() + else: + self._run_stack(blk) + + elif blk.name in ['sandwichtop_no_arm_no_label', + 'sandwichtop_no_arm']: + restore_stack(blk) + + elif blk.name in COLLAPSIBLE or blk.name == 'sandwichtop_no_label': + if blk.name == 'sandwichtop_no_label': + if hide_button_hit(blk.spr, x, y): + collapse_stack(blk) + else: + self._run_stack(blk) + top = find_sandwich_top(blk) + if collapsed(blk): + restore_stack(top) # deprecated (bottom block is invisible) + elif top is not None: + collapse_stack(top) + else: + self._run_stack(blk) + + def _expand_boolean(self, blk, blk2, dy): + """ Expand a boolean blk if blk2 is too big to fit. """ + group = find_group(blk2) + for gblk in find_group(blk): + if gblk not in group: + gblk.spr.move_relative((0, -dy * blk.scale)) + + def _expand_expandable(self, blk, blk2, dy): + """ Expand an expandable blk if blk2 is too big to fit. """ + if blk2 is None: + group = [blk] + else: + group = find_group(blk2) + group.append(blk) + for gblk in find_group(blk): + if gblk not in group: + gblk.spr.move_relative((0, dy * blk.scale)) + if blk.name in block_styles['compare-style'] or \ + blk.name in block_styles['compare-porch-style']: + for gblk in find_group(blk): + gblk.spr.move_relative((0, -dy * blk.scale)) + + def _number_style(self, name): + if name in block_styles['number-style']: + return True + if name in block_styles['number-style-porch']: + return True + if name in block_styles['number-style-block']: + return True + if name in block_styles['number-style-var-arg']: + return True + return False + + def _cascade_expandable(self, blk): + """ If expanding/shrinking a block, cascade. """ + while self._number_style(blk.name): + if blk.connections[0] is None: + break + if blk.connections[0].name in expandable_blocks: + if blk.connections[0].connections.index(blk) != 1: + break + blk = blk.connections[0] + if blk.connections[1].name == 'myfunc2arg': + dy = 40 + blk.connections[1].ey - blk.ey + elif blk.connections[1].name == 'myfunc3arg': + dy = 60 + blk.connections[1].ey - blk.ey + else: + dy = 20 + blk.connections[1].ey - blk.ey + blk.expand_in_y(dy) + if dy != 0: + group = find_group(blk.connections[1]) + group.append(blk) + for gblk in find_group(blk): + if gblk not in group: + gblk.spr.move_relative((0, dy * blk.scale)) + if blk.name in block_styles['compare-style'] or \ + blk.name in block_styles['compare-porch-style']: + for gblk in find_group(blk): + gblk.spr.move_relative((0, -dy * blk.scale)) + else: + break + + def _check_collapsibles(self, blk): + """ Check state of collapsible blocks upon change in dock state. """ + group = find_group(blk) + for gblk in group: + if gblk.name in COLLAPSIBLE: + if collapsed(gblk): + gblk.svg.set_show(True) + gblk.svg.set_hide(False) + reset_stack_arm(find_sandwich_top(gblk)) + elif collapsible(gblk): + gblk.svg.set_hide(True) + gblk.svg.set_show(False) + grow_stack_arm(find_sandwich_top(gblk)) + else: + gblk.svg.set_hide(False) + gblk.svg.set_show(False) + # Ouch: When you tear off the sandwich bottom, you + # no longer have access to the group with the sandwich top + # so check them all. + for b in self.just_blocks(): + if b.name in ['sandwichtop', 'sandwichtop_no_label']: + if find_sandwich_bottom(b) is None: + reset_stack_arm(b) + gblk.refresh() + + def _run_stack(self, blk): + """ Run a stack of blocks. """ + if blk is None: + return + self.lc.find_value_blocks() # Are there blocks to update? + # Is there a savesvg block? + if len(self.block_list.get_similar_blocks('block', 'savesvg')) > 0: + if self.canvas.cr_svg is None: + self.canvas.setup_svg_surface() + self._start_plugins() # Let the plugins know we are running. + top = find_top_block(blk) + self.lc.run_blocks(top, self.just_blocks(), True) + if self.interactive_mode: + gobject.idle_add(self.lc.doevalstep) + else: + while self.lc.doevalstep(): + pass + + def _snap_to_dock(self): + """ Snap a block (selected_block) to the dock of another block + (destination_block). + """ + selected_block = self.drag_group[0] + best_destination = None + d = SNAP_THRESHOLD + for selected_block_dockn in range(len(selected_block.docks)): + for destination_block in self.just_blocks(): + # Don't link to a block that is hidden + if destination_block.status == 'collapsed': + continue + # Don't link to a block to which you're already connected + if destination_block in self.drag_group: + continue + # Check each dock of destination for a possible connection + for destination_dockn in range(len(destination_block.docks)): + this_xy = dock_dx_dy(destination_block, destination_dockn, + selected_block, selected_block_dockn) + if magnitude(this_xy) > d: + continue + d = magnitude(this_xy) + best_xy = this_xy + best_destination = destination_block + best_destination_dockn = destination_dockn + best_selected_block_dockn = selected_block_dockn + if d < SNAP_THRESHOLD: + # Some combinations of blocks are not valid + if not arithmetic_check(selected_block, best_destination, + best_selected_block_dockn, + best_destination_dockn): + return + if not journal_check(selected_block, best_destination, + best_selected_block_dockn, + best_destination_dockn): + return + + # Move the selected blocks into the docked position + for blk in self.drag_group: + (sx, sy) = blk.spr.get_xy() + blk.spr.move((sx + best_xy[0], sy + best_xy[1])) + + # If there was already a block docked there, move it to the trash. + blk_in_dock = best_destination.connections[best_destination_dockn] + if blk_in_dock is not None and blk_in_dock != selected_block: + blk_in_dock.connections[0] = None + self._put_in_trash(blk_in_dock) + + # Note the connection in destination dock + best_destination.connections[best_destination_dockn] = \ + selected_block + + # And in the selected block dock + if selected_block.connections is not None: + if best_selected_block_dockn < len(selected_block.connections): + selected_block.connections[best_selected_block_dockn] = \ + best_destination + + # Some destination blocks expand to accomodate large blocks + if best_destination.name in block_styles['boolean-style']: + if best_destination_dockn == 2 and \ + (selected_block.name in block_styles['boolean-style'] or \ + selected_block.name in block_styles['compare-style'] or \ + selected_block.name in block_styles['compare-porch-style'] + ): + dy = selected_block.ey - best_destination.ey + if selected_block.name in block_styles['boolean-style']: + # Even without expanding, boolean blocks are + # too large to fit in the lower dock position + dy += 45 + best_destination.expand_in_y(dy) + self._expand_boolean(best_destination, selected_block, dy) + elif best_destination.name in expandable_blocks and \ + best_destination_dockn == 1: + dy = 0 + if (selected_block.name in expandable_blocks or + selected_block.name in block_styles[ + 'number-style-var-arg']): + if selected_block.name == 'myfunc2arg': + dy = 40 + selected_block.ey - best_destination.ey + elif selected_block.name == 'myfunc3arg': + dy = 60 + selected_block.ey - best_destination.ey + else: + dy = 20 + selected_block.ey - best_destination.ey + best_destination.expand_in_y(dy) + else: + if best_destination.ey > 0: + dy = best_destination.reset_y() + if dy != 0: + self._expand_expandable( + best_destination, selected_block, dy) + self._cascade_expandable(best_destination) + grow_stack_arm(find_sandwich_top(best_destination)) + + def _disconnect(self, blk): + """ Disconnect block from stack above it. """ + if blk is None: + return + if blk.connections[0] is None: + return + if collapsed(blk): + return + blk2 = blk.connections[0] + if blk in blk2.connections: + c = blk2.connections.index(blk) + blk2.connections[c] = None + + if blk2.name in block_styles['boolean-style']: + if c == 2 and blk2.ey > 0: + dy = -blk2.ey + blk2.expand_in_y(dy) + self._expand_boolean(blk2, blk, dy) + elif blk2.name in expandable_blocks and c == 1: + if blk2.ey > 0: + dy = blk2.reset_y() + if dy != 0: + self._expand_expandable(blk2, blk, dy) + self._cascade_expandable(blk2) + grow_stack_arm(find_sandwich_top(blk2)) + + blk.connections[0] = None + + def _import_from_journal(self, blk): + """ Import a file from the Sugar Journal """ + # TODO: check blk name to set filter + if self.running_sugar: + chooser(self.parent, '', self._update_media_blk) + else: + fname, self.load_save_folder = get_load_name('.*', + self.load_save_folder) + if fname is None: + return + self._update_media_icon(blk, fname) + + def _load_description_block(self, blk): + """ Look for a corresponding description block """ + if blk is None or blk.name != 'journal' or len(blk.values) == 0 or \ + blk.connections[0] is None: + return + _blk = blk.connections[0] + dblk = find_blk_below(_blk, 'description') + # Autoupdate the block if it is empty + if dblk != None and (len(dblk.values) == 0 or dblk.values[0] is None): + self._update_media_icon(dblk, None, blk.values[0]) + + def _update_media_blk(self, dsobject): + """ Called from the chooser to load a media block """ + self._update_media_icon(self.selected_blk, dsobject, + dsobject.object_id) + + def _update_media_icon(self, blk, name, value=''): + """ Update the icon on a 'loaded' media block. """ + if blk.name == 'journal': + self._load_image_thumb(name, blk) + elif blk.name == 'audio': + self._block_skin('audioon', blk) + elif blk.name == 'video': + self._block_skin('videoon', blk) + else: + self._block_skin('descriptionon', blk) + if value == '': + value = name + if len(blk.values) > 0: + blk.values[0] = value + else: + blk.values.append(value) + blk.spr.set_label(' ') + + def _load_image_thumb(self, picture, blk): + """ Replace icon with a preview image. """ + pixbuf = None + self._block_skin('descriptionon', blk) + + if self.running_sugar: + w, h = calc_image_size(blk.spr) + pixbuf = get_pixbuf_from_journal(picture, w, h) + else: + if movie_media_type(picture): + self._block_skin('videoon', blk) + blk.name = 'video' + elif audio_media_type(picture): + self._block_skin('audioon', blk) + blk.name = 'audio' + elif image_media_type(picture): + w, h = calc_image_size(blk.spr) + pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(picture, w, h) + else: + blk.name = 'description' + if pixbuf is not None: + x, y = self._calc_image_offset('', blk.spr) + blk.set_image(pixbuf, x, y) + self._resize_skin(blk) + + def _keypress_cb(self, area, event): + """ Keyboard """ + keyname = gtk.gdk.keyval_name(event.keyval) + keyunicode = gtk.gdk.keyval_to_unicode(event.keyval) + if event.get_state() & gtk.gdk.MOD1_MASK: + alt_mask = True + alt_flag = 'T' + else: + alt_mask = False + alt_flag = 'F' + self._key_press(alt_mask, keyname, keyunicode) + return keyname + + def _key_press(self, alt_mask, keyname, keyunicode): + if keyname is None: + return False + + self.keypress = keyname + + if alt_mask: + if keyname == "p": + self.hideshow_button() + elif keyname == 'q': + self.quit_plugins() + if self.gst_available: + stop_media(self.lc) + exit() + elif keyname == 'g': + self._align_to_grid() + + elif self.selected_blk is not None: + if self.selected_blk.name == 'number': + self._process_numeric_input(keyname) + elif self.selected_blk.name == 'string': + self.process_alphanumeric_input(keyname, keyunicode) + if self.selected_blk is not None: + self.selected_blk.resize() + elif self.selected_blk.name != 'proto': + self._process_keyboard_commands(keyname, block_flag=True) + + elif self.turtles.spr_to_turtle(self.selected_spr) is not None: + self._process_keyboard_commands(keyname, block_flag=False) + + return True + + def _process_numeric_input(self, keyname): + ''' Make sure numeric input is valid. ''' + oldnum = self.selected_blk.spr.labels[0].replace(CURSOR, '') + if len(oldnum) == 0: + oldnum = '0' + if keyname == 'minus': + if oldnum == '0': + newnum = '-' + elif oldnum[0] != '-': + newnum = '-' + oldnum + else: + newnum = oldnum + elif keyname == 'comma' and self.decimal_point == ',' and \ + ',' not in oldnum: + newnum = oldnum + ',' + elif keyname == 'period' and self.decimal_point == '.' and \ + '.' not in oldnum: + newnum = oldnum + '.' + elif keyname == 'BackSpace': + if len(oldnum) > 0: + newnum = oldnum[:len(oldnum) - 1] + else: + newnum = '' + elif keyname in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']: + if oldnum == '0': + newnum = keyname + else: + newnum = oldnum + keyname + elif keyname == 'Return': + self._unselect_block() + return + else: + newnum = oldnum + if newnum == '.': + newnum = '0.' + if newnum == ',': + newnum = '0,' + if len(newnum) > 0 and newnum != '-': + try: + float(newnum.replace(self.decimal_point, '.')) + except ValueError, e: + newnum = oldnum + self.selected_blk.spr.set_label(newnum + CURSOR) + + def process_alphanumeric_input(self, keyname, keyunicode): + """ Make sure alphanumeric input is properly parsed. """ + if len(self.selected_blk.spr.labels[0]) > 0: + c = self.selected_blk.spr.labels[0].count(CURSOR) + if c == 0: + oldleft = self.selected_blk.spr.labels[0] + oldright = '' + elif len(self.selected_blk.spr.labels[0]) == 1: + oldleft = '' + oldright = '' + else: + try: # Why are getting a ValueError on occasion? + oldleft, oldright = \ + self.selected_blk.spr.labels[0].split(CURSOR) + except ValueError: + debug_output("[%s]" % self.selected_blk.spr.labels[0], + self.running_sugar) + oldleft = self.selected_blk.spr.labels[0] + oldright = '' + else: + oldleft = '' + oldright = '' + newleft = oldleft + if keyname in ['Shift_L', 'Shift_R', 'Control_L', 'Caps_Lock', \ + 'Alt_L', 'Alt_R', 'KP_Enter', 'ISO_Level3_Shift']: + keyname = '' + keyunicode = 0 + # Hack until I sort out input and unicode and dead keys, + if keyname[0:5] == 'dead_': + self.dead_key = keyname + keyname = '' + keyunicode = 0 + if keyname == 'space': + keyunicode = 32 + elif keyname == 'Tab': + keyunicode = 9 + if keyname == 'BackSpace': + if len(oldleft) > 1: + newleft = oldleft[:len(oldleft) - 1] + else: + newleft = '' + if keyname == 'Delete': + if len(oldright) > 0: + oldright = oldright[1:] + elif keyname == 'Home': + oldright = oldleft + oldright + newleft = '' + elif keyname == 'Left': + if len(oldleft) > 0: + oldright = oldleft[len(oldleft) - 1:] + oldright + newleft = oldleft[:len(oldleft) - 1] + elif keyname == 'Right': + if len(oldright) > 0: + newleft = oldleft + oldright[0] + oldright = oldright[1:] + elif keyname == 'End': + newleft = oldleft + oldright + oldright = '' + elif keyname == 'Return': + newleft = oldleft + RETURN + elif keyname == 'Down': + self._unselect_block() + return + elif keyname == 'Up' or keyname == 'Escape': # Restore previous state + self.selected_blk.spr.set_label(self.saved_string) + self._unselect_block() + return + else: + if self.dead_key is not '': + keyunicode = \ + DEAD_DICTS[DEAD_KEYS.index(self.dead_key[5:])][keyname] + self.dead_key = '' + if keyunicode > 0: + if unichr(keyunicode) != '\x00': + newleft = oldleft + unichr(keyunicode) + else: + newleft = oldleft + elif keyunicode == -1: # clipboard text + if keyname == '\n': + newleft = oldleft + RETURN + else: + newleft = oldleft + keyname + self.selected_blk.spr.set_label("%s%s%s" % (newleft, CURSOR, oldright)) + + def _process_keyboard_commands(self, keyname, block_flag=True): + """ Use the keyboard to move blocks and turtle """ + mov_dict = {'KP_Up': [0, 20], 'j': [0, 20], 'Up': [0, 20], + 'KP_Down': [0, -20], 'k': [0, -20], 'Down': [0, -20], + 'KP_Left': [-20, 0], 'h': [-20, 0], 'Left': [-20, 0], + 'KP_Right': [20, 0], 'l': [20, 0], 'Right': [20, 0], + 'KP_Page_Down': [-1, -1], 'Page_Down': [-1, -1], + 'KP_Page_Up': [-1, -1], 'Page_Up': [-1, -1], + 'KP_End': [0, 0], 'End': [0, 0], + 'KP_Home': [0, 0], 'Home': [0, 0], 'space': [0, 0], + 'Return': [-1, -1], 'Esc': [-1, -1]} + + if keyname not in mov_dict: + return True + + if keyname in ['KP_End', 'End']: + self.run_button(0) + elif self.selected_spr is not None: + if not self.lc.running and block_flag: + blk = self.block_list.spr_to_block(self.selected_spr) + if keyname in ['Return', 'KP_Page_Up', 'Page_Up', 'Esc']: + (x, y) = blk.spr.get_xy() + self._click_block(x, y) + elif keyname in ['KP_Page_Down', 'Page_Down']: + if self.drag_group is None: + self.drag_group = find_group(blk) + self._put_in_trash(blk) + self.drag_group = None + elif keyname in ['KP_Home', 'Home', 'space']: + block = self.block_list.spr_to_block(self.selected_spr) + if block is None: + return True + block.unhighlight() + block = self.block_list.get_next_block_of_same_type( + block) + if block is not None: + self.selected_spr = block.spr + block.highlight() + else: + self._jog_block(blk, mov_dict[keyname][0], + mov_dict[keyname][1]) + elif not block_flag: + self._jog_turtle(mov_dict[keyname][0], mov_dict[keyname][1]) + return True + + def _jog_turtle(self, dx, dy): + """ Jog turtle """ + if dx == -1 and dy == -1: + self.canvas.xcor = 0 + self.canvas.ycor = 0 + else: + self.canvas.xcor += dx + self.canvas.ycor += dy + self.active_turtle = self.turtles.spr_to_turtle(self.selected_spr) + self.canvas.move_turtle() + self.display_coordinates() + self.selected_turtle = None + + def _align_to_grid(self, grid=20): + """ Align blocks at the top of stacks to a grid """ + for blk in self.block_list.list: + if blk.type == 'block': + top = find_top_block(blk) + if top == blk: + x = top.spr.get_xy()[0] + y = top.spr.get_xy()[1] + if x < 0: + dx = -x % grid + else: + dx = -(x % grid) + if y < 0: + dy = -y % grid + else: + dy = -(y % grid) + self._jog_block(top, dx, -dy) + + def _jog_block(self, blk, dx, dy): + """ Jog block """ + if blk.type == 'proto': + return + if collapsed(blk): + return + if dx == 0 and dy == 0: + return + self._disconnect(blk) + self.drag_group = find_group(blk) + + for blk in self.drag_group: + (sx, sy) = blk.spr.get_xy() + if sx + dx < 0: + dx += -(sx + dx) + if sy + dy < 0: + dy += -(sy + dy) + + for blk in self.drag_group: + (sx, sy) = blk.spr.get_xy() + blk.spr.move((sx + dx, sy - dy)) + + self._snap_to_dock() + self.drag_group = None + + def _number_check(self): + """ Make sure a 'number' block contains a number. """ + n = self.selected_blk.spr.labels[0].replace(CURSOR, '') + if n in ['-', '.', '-.', ',', '-,']: + n = 0 + elif n is not None: + try: + f = float(n.replace(self.decimal_point, '.')) + if f > 1000000: + n = 1 + self.showlabel("#overflowerror") + elif f < -1000000: + n = -1 + self.showlabel("#overflowerror") + except ValueError: + n = 0 + self.showlabel("#notanumber") + else: + n = 0 + self.selected_blk.spr.set_label(str(n)) + try: + self.selected_blk.values[0] = \ + float(str(n).replace(self.decimal_point, '.')) + except ValueError: + self.selected_blk.values[0] = float(str(n)) + except IndexError: + self.selected_blk.values[0] = float(str(n)) + + def _string_check(self): + s = self.selected_blk.spr.labels[0].replace(CURSOR, '') + self.selected_blk.spr.set_label(s) + self.selected_blk.values[0] = s.replace(RETURN, "\12") + + def load_python_code_from_file(self, fname=None, add_new_block=True): + """ Load Python code from a file """ + id = None + self.python_code = None + if fname is None: + fname, self.py_load_save_folder = get_load_name('.py', + self.py_load_save_folder) + if fname is None: + return id + try: + f = open(fname, 'r') + self.python_code = f.read() + f.close() + id = fname + except IOError: + error_output("Unable to read Python code from %s" % (fname), + self.running_sugar) + return id + + # if we are running Sugar, copy the file into the Journal + if self.running_sugar: + from sugar.datastore import datastore + from sugar import profile + + dsobject = datastore.create() + dsobject.metadata['title'] = os.path.basename(fname) + dsobject.metadata['icon-color'] = \ + profile.get_color().to_string() + dsobject.metadata['mime_type'] = 'text/x-python' + dsobject.metadata['activity'] = 'org.laptop.Pippy' + dsobject.set_file_path(fname) + try: + datastore.write(dsobject) + id = dsobject.object_id + debug_output("Copying %s to the datastore" % (fname), + self.running_sugar) + except IOError: + error_output("Error copying %s to the datastore" % (fname), + self.running_sugar) + id = None + dsobject.destroy() + + if add_new_block: + # add a new block for this code at turtle position + (tx, ty) = self.active_turtle.get_xy() + self._new_block('userdefined', tx, ty) + self.myblock[self.block_list.list.index(self.drag_group[0])] =\ + self.python_code + self.set_userdefined(self.drag_group[0]) + self.drag_group[0].values.append(dsobject.object_id) + self.drag_group = None + # Save object ID in block value + if self.selected_blk is not None: + if len(self.selected_blk.values) == 0: + self.selected_blk.values.append(dsobject.object_id) + else: + self.selected_blk.values[0] = dsobject.object_id + else: + if len(self.selected_blk.values) == 0: + self.selected_blk.values.append(fname) + else: + self.selected_blk.values[0] = fname + + return id + + def load_python_code_from_journal(self, dsobject, blk=None): + """ Read the Python code from the Journal object """ + self.python_code = None + try: + debug_output("opening %s " % dsobject.file_path, + self.running_sugar) + file_handle = open(dsobject.file_path, "r") + self.python_code = file_handle.read() + file_handle.close() + except IOError: + debug_output("couldn't open %s" % dsobject.file_path, + self.running_sugar) + # Save the object id as the block value + if blk is None: + blk = self.selected_blk + if blk is not None: + if len(blk.values) == 0: + blk.values.append(dsobject.object_id) + else: + blk.values[0] = dsobject.object_id + + def _import_py(self): + """ Import Python code into a block """ + if self.running_sugar: + chooser(self.parent, 'org.laptop.Pippy', + self.load_python_code_from_journal) + else: + self.load_python_code_from_file(fname=None, add_new_block=False) + + if self.selected_blk is not None: + self.myblock[self.block_list.list.index(self.selected_blk)] = \ + self.python_code + self.set_userdefined(self.selected_blk) + + def new_project(self): + """ Start a new project """ + self.lc.stop_logo() + self._loaded_project = "" + # Put current project in the trash. + while len(self.just_blocks()) > 0: + blk = self.just_blocks()[0] + top = find_top_block(blk) + self._put_in_trash(top) + self.canvas.clearscreen() + self.save_file_name = None + + def is_new_project(self): + """ Is this a new project or was a old project loaded from a file? """ + return self._loaded_project == "" + + def project_has_changed(self): + """ WARNING: order of JSON serialized data may have changed. """ + try: + f = open(self._loaded_project, 'r') + saved_project_data = f.read() + f.close() + except: + debug_output("problem loading saved project data from %s" % \ + (self._loaded_project), + self.running_sugar) + saved_project_data = "" + current_project_data = data_to_string(self.assemble_data_to_save()) + + return saved_project_data != current_project_data + + def load_files(self, ta_file, create_new_project=True): + """ Load a project from a file """ + if create_new_project: + self.new_project() + self._check_collapsibles(self.process_data(data_from_file(ta_file))) + self._loaded_project = ta_file + + def load_file(self, create_new_project=True): + _file_name, self.load_save_folder = get_load_name('.ta', + self.load_save_folder) + if _file_name is None: + return + if _file_name[-3:] == '.ta': + _file_name = _file_name[0: -3] + self.load_files(_file_name + '.ta', create_new_project) + if create_new_project: + self.save_file_name = os.path.basename(_file_name) + if self.running_sugar: + self.activity.metadata['title'] = os.path.split(_file_name)[1] + + def _found_a_turtle(self, blk): + """ Either [-1, 'turtle', ...] or [-1, ['turtle', key], ...] """ + if blk[1] == 'turtle': + self.load_turtle(blk) + return True + elif type(blk[1]) in [list, tuple] and blk[1][0] == 'turtle': + if blk[1][1] == DEFAULT_TURTLE: + if self.nick is not None and self.nick is not '': + self.load_turtle(blk, self.nick) + else: + self.load_turtle(blk, blk[1][1]) + return True + return False + + def load_turtle(self, blk, key=1): + """ Restore a turtle from its saved state """ + tid, name, xcor, ycor, heading, color, shade, pensize = blk + self.canvas.set_turtle(key) + self.canvas.setxy(xcor, ycor, pendown=False) + self.canvas.seth(heading) + self.canvas.setcolor(color) + self.canvas.setshade(shade) + self.canvas.setpensize(pensize) + + def load_block(self, b, offset=0): + """ Restore individual blocks from saved state """ + if self.running_sugar: + from sugar.datastore import datastore + + # A block is saved as: (i, (btype, value), x, y, (c0,... cn)) + # The x, y position is saved/loaded for backward compatibility + btype, value = b[1], None + if type(btype) == tuple: + btype, value = btype + elif type(btype) == list: + btype, value = btype[0], btype[1] + if btype in content_blocks or btype in COLLAPSIBLE: + if btype == 'number': + try: + values = [round_int(value)] + except ValueError: + values = [0] + elif btype in COLLAPSIBLE: + if value is not None: + values = [int(value)] + else: + values = [] + else: + values = [value] + else: + values = [] + + if btype in OLD_DOCK: + check_dock = True + else: + check_dock = False + if btype in OLD_NAMES: + btype = OLD_NAMES[btype] + + blk = Block(self.block_list, self.sprite_list, btype, + b[2] + self.canvas.cx + offset, + b[3] + self.canvas.cy + offset, + 'block', values, self.block_scale) + + # Some blocks get transformed. + if btype in block_styles['basic-style-var-arg'] and value is not None: + # Is there code stored in this userdefined block? + if value > 0: # catch deprecated format (#2501) + self.python_code = None + if self.running_sugar: + debug_output(value, self.running_sugar) + # For security reasons, only open files found in + # Python samples directory + if os.path.exists(os.path.join(self.path, value)) and \ + value[0:9] == 'pysamples': + self.selected_blk = blk + self.load_python_code_from_file( + fname=os.path.join(self.path, value), + add_new_block=False) + self.selected_blk = None + else: # or files from the Journal + try: + dsobject = datastore.get(value) + except: # Should be IOError, but dbus error is raised + dsobject = None + debug_output("couldn't get dsobject %s" % value, + self.running_sugar) + if dsobject is not None: + self.load_python_code_from_journal(dsobject, blk) + else: + self.selected_blk = blk + self.load_python_code_from_file(fname=value, + add_new_block=False) + self.selected_blk = None + if self.python_code is not None: + self.myblock[self.block_list.list.index(blk)] = \ + self.python_code + self.set_userdefined(blk) + if btype == 'string' and blk.spr is not None: + blk.spr.set_label(blk.values[0].replace('\n', RETURN)) + elif btype == 'start': # block size is saved in start block + if value is not None: + self.block_scale = value + elif btype in block_styles['box-style-media'] and blk.spr is not None: + if btype in EXPAND_SKIN: + if blk.ex == 0: + blk.expand_in_x(EXPAND_SKIN[btype][0]) + if blk.ey == 0: + blk.expand_in_y(EXPAND_SKIN[btype][1]) + if len(blk.values) == 0 or blk.values[0] == 'None' or \ + blk.values[0] is None or btype in NO_IMPORT: + self._block_skin(btype + 'off', blk) + elif btype in ['video', 'audio', 'description']: + self._block_skin(btype + 'on', blk) + elif self.running_sugar: + try: + dsobject = datastore.get(blk.values[0]) + if not movie_media_type(dsobject.file_path[-4:]): + w, h, = calc_image_size(blk.spr) + pixbuf = get_pixbuf_from_journal(dsobject, w, h) + if pixbuf is not None: + x, y = self._calc_image_offset('', blk.spr) + blk.set_image(pixbuf, x, y) + else: + self._block_skin('journalon', blk) + dsobject.destroy() + except: + try: + w, h, = calc_image_size(blk.spr) + pixbuf = gtk.gdk.pixbuf_new_from_file_at_size( + blk.values[0], w, h) + x, y = self._calc_image_offset('', blk.spr) + blk.set_image(pixbuf, x, y) + except: + debug_output("Couldn't open dsobject (%s)" % \ + (blk.values[0]), self.running_sugar) + self._block_skin('journaloff', blk) + else: + if not movie_media_type(blk.values[0][-4:]): + try: + w, h, = calc_image_size(blk.spr) + pixbuf = gtk.gdk.pixbuf_new_from_file_at_size( + blk.values[0], w, h) + x, y = self._calc_image_offset('', blk.spr) + blk.set_image(pixbuf, x, y) + except: + self._block_skin('journaloff', blk) + else: + self._block_skin('journalon', blk) + blk.spr.set_label(' ') + blk.resize() + elif btype in EXPANDABLE or btype in expandable_blocks or \ + btype in EXPANDABLE_ARGS or btype == 'nop': + if btype == 'vspace' or btype in expandable_blocks: + if value is not None: + blk.expand_in_y(value) + elif btype == 'hspace' or btype == 'identity2': + if value is not None: + blk.expand_in_x(value) + elif btype == 'templatelist' or btype == 'list': + for i in range(len(b[4]) - 4): + blk.add_arg() + elif btype == 'myfunc2arg' or btype == 'myfunc3arg' or\ + btype == 'userdefined2args' or btype == 'userdefined3args': + blk.add_arg() + if btype == 'myfunc3arg' or btype == 'userdefined3args': + blk.add_arg(False) + if btype in PYTHON_SKIN: + if self.nop == 'pythonloaded': + self._block_skin('pythonon', blk) + else: + self._block_skin('pythonoff', blk) + + if self.interactive_mode: + blk.spr.set_layer(BLOCK_LAYER) + if check_dock: + blk.connections = 'check' + if self.running_sugar and len(blk.spr.labels) > 0 and \ + blk.name not in ['', ' ', 'number', 'string']: + if len(self.used_block_list) > 0: + self.used_block_list.append(', ') + if blk.name in special_names: + self.used_block_list.append(special_names[blk.name]) + elif blk.spr.labels[0] not in self.used_block_list: + self.used_block_list.append(blk.spr.labels[0]) + return blk + + def load_start(self, ta_file=None): + """ Start a new project with a 'start' brick """ + if ta_file is None: + self.process_data([[0, "start", PALETTE_WIDTH + 20, + self.toolbar_offset + PALETTE_HEIGHT + 20, + [None, None]]]) + else: + self.process_data(data_from_file(ta_file)) + + def save_file(self, _file_name=None): + """ Start a project to a file """ + if self.save_folder is not None: + self.load_save_folder = self.save_folder + if _file_name is None: + _file_name, self.load_save_folder = get_save_name('.ta', + self.load_save_folder, self.save_file_name) + if _file_name is None: + return + if _file_name[-3:] == '.ta': + _file_name = _file_name[0: -3] + data_to_file(self.assemble_data_to_save(), _file_name + '.ta') + self.save_file_name = os.path.basename(_file_name) + if not self.running_sugar: + self.save_folder = self.load_save_folder + + def assemble_data_to_save(self, save_turtle=True, save_project=True): + """ Pack the project (or stack) into a datastream to be serialized """ + _data = [] + _blks = [] + + if save_project: + _blks = self.just_blocks() + else: + if self.selected_blk is None: + return [] + _blks = find_group(find_top_block(self.selected_blk)) + + for _i, _blk in enumerate(_blks): + _blk.id = _i + for _blk in _blks: + if _blk.name in content_blocks or _blk.name in COLLAPSIBLE: + if len(_blk.values) > 0: + _name = (_blk.name, _blk.values[0]) + else: + _name = (_blk.name) + elif _blk.name in block_styles['basic-style-var-arg'] and \ + len(_blk.values) > 0: + _name = (_blk.name, _blk.values[0]) + elif _blk.name in EXPANDABLE or _blk.name in expandable_blocks or\ + _blk.name in EXPANDABLE_ARGS: + _ex, _ey = _blk.get_expand_x_y() + if _ex > 0: + _name = (_blk.name, _ex) + elif _ey > 0: + _name = (_blk.name, _ey) + else: + _name = (_blk.name, 0) + elif _blk.name == 'start': # save block_size in start block + _name = (_blk.name, self.block_scale) + else: + _name = (_blk.name) + if hasattr(_blk, 'connections') and _blk.connections is not None: + connections = [get_id(_cblk) for _cblk in _blk.connections] + else: + connections = None + (_sx, _sy) = _blk.spr.get_xy() + # Add a slight offset for copy/paste + if not save_project: + _sx += 20 + _sy += 20 + _data.append((_blk.id, _name, _sx - self.canvas.cx, + _sy - self.canvas.cy, connections)) + if save_turtle: + for turtle in iter(self.turtles.dict): + # Don't save remote turtles + if not self.remote_turtle(turtle): + # Save default turtle as 'Yertle' + if turtle == self.nick: + turtle = DEFAULT_TURTLE + _data.append((-1, ['turtle', turtle], + self.canvas.xcor, self.canvas.ycor, + self.canvas.heading, self.canvas.color, + self.canvas.shade, self.canvas.pensize)) + return _data + + def display_coordinates(self): + """ Display the coordinates of the current turtle on the toolbar """ + x = round_int(float(self.canvas.xcor) / self.coord_scale) + y = round_int(float(self.canvas.ycor) / self.coord_scale) + h = round_int(self.canvas.heading) + if self.running_sugar: + self.activity.coordinates_label.set_text("%s: %d %s: %d %s: %d" %\ + (_("xcor"), x, _("ycor"), y, _("heading"), h)) + self.activity.coordinates_label.show() + elif self.interactive_mode: + self.parent.set_title("%s — %s: %d %s: %d %s: %d" % \ + (_("Turtle Art"), _("xcor"), x, _("ycor"), y, _("heading"), h)) + + def showlabel(self, shp, label=''): + """ Display a message on a status block """ + if not self.interactive_mode: + debug_output(label, self.running_sugar) + return + if shp == 'syntaxerror' and str(label) != '': + if str(label)[1:] in self.status_shapes: + shp = str(label)[1:] + label = '' + else: + shp = 'status' + elif shp[0] == '#': + shp = shp[1:] + label = '' + self.status_spr.set_shape(self.status_shapes[shp]) + self.status_spr.set_label_attributes(12.0, rescale=False) + if shp == 'status': + self.status_spr.set_label('"%s"' % (str(label))) + else: + self.status_spr.set_label(str(label)) + self.status_spr.set_layer(STATUS_LAYER) + if shp == 'info': + self.status_spr.move((PALETTE_WIDTH, self.height - 400)) + else: + # Adjust vertical position based on scrolled window adjustment + if self.running_sugar: + self.status_spr.move((0, self.height - 200 + \ + self.activity.sw.get_vadjustment().get_value())) + elif self.interactive_mode: + self.status_spr.move((0, self.height - 100)) + + def calc_position(self, template): + """ Relative placement of portfolio objects (deprecated) """ + w, h, x, y, dx, dy = TEMPLATES[template] + x *= self.canvas.width + y *= self.canvas.height + w *= (self.canvas.width - x) + h *= (self.canvas.height - y) + dx *= w + dy *= h + return(w, h, x, y, dx, dy) + + def save_for_upload(self, _file_name): + """ Grab the current canvas and save it for upload """ + if _file_name[-3:] == '.ta': + _file_name = _file_name[0: -3] + data_to_file(self.assemble_data_to_save(), _file_name + '.ta') + save_picture(self.canvas, _file_name + '.png') + ta_file = _file_name + '.ta' + image_file = _file_name + '.png' + return ta_file, image_file + + def save_as_image(self, name="", svg=False, pixbuf=None): + """ Grab the current canvas and save it. """ + if svg: + suffix = '.svg' + else: + suffix = '.png' + + if not self.interactive_mode: + save_picture(self.canvas, name[:-3] + suffix) + return + if self.running_sugar: + if len(name) == 0: + filename = 'ta' + suffix + else: + filename = name + suffix + datapath = get_path(self.activity, 'instance') + elif len(name) == 0: + name = 'ta' + if self.save_folder is not None: + self.load_save_folder = self.save_folder + filename, self.load_save_folder = get_save_name( + suffix, self.load_save_folder, name) + datapath = self.load_save_folder + else: + datapath = os.getcwd() + filename = name + suffix + if filename is None: + return + + file_path = os.path.join(datapath, filename) + if svg: + if self.canvas.cr_svg is None: + return + self.canvas.svg_reset() + else: + save_picture(self.canvas, file_path) + + if self.running_sugar: + from sugar.datastore import datastore + from sugar import profile + + dsobject = datastore.create() + if len(name) == 0: + dsobject.metadata['title'] = "%s %s" % \ + (self.activity.metadata['title'], _("image")) + else: + dsobject.metadata['title'] = name + dsobject.metadata['icon-color'] = profile.get_color().to_string() + if svg: + dsobject.metadata['mime_type'] = 'image/svg+xml' + dsobject.set_file_path(os.path.join(datapath, 'output.svg')) + else: + dsobject.metadata['mime_type'] = 'image/png' + dsobject.set_file_path(file_path) + datastore.write(dsobject) + dsobject.destroy() + self.saved_pictures.append((dsobject.object_id, svg)) + if svg: + os.remove(os.path.join(datapath, 'output.svg')) + else: + os.remove(file_path) + else: + if svg: + output = subprocess.check_output( + ['mv', os.path.join(datapath, 'output.svg'), + os.path.join(datapath, filename)]) + self.saved_pictures.append((file_path, svg)) + + def just_blocks(self): + """ Filter out 'proto', 'trash', and 'deleted' blocks """ + just_blocks_list = [] + for _blk in self.block_list.list: + if _blk.type == 'block': + just_blocks_list.append(_blk) + return just_blocks_list + + def _width_and_height(self, blk): + """ What are the width and height of a stack? """ + minx = 10000 + miny = 10000 + maxx = -10000 + maxy = -10000 + for gblk in find_group(blk): + (x, y) = gblk.spr.get_xy() + w, h = gblk.spr.get_dimensions() + if x < minx: + minx = x + if y < miny: + miny = y + if x + w > maxx: + maxx = x + w + if y + h > maxy: + maxy = y + h + return(maxx - minx, maxy - miny) + + # Utilities related to putting a image 'skin' on a block + + def _calc_image_offset(self, name, spr, iw=0, ih=0): + """ Calculate the postion for placing an image onto a sprite. """ + _l, _t = spr.label_left_top() + if name == '': + return _l, _t + _w = spr.label_safe_width() + _h = spr.label_safe_height() + if iw == 0: + iw = self.media_shapes[name].get_width() + ih = self.media_shapes[name].get_height() + return int(_l + (_w - iw) / 2), int(_t + (_h - ih) / 2) + + def _calc_w_h(self, name, spr): + """ Calculate new image size """ + target_w = spr.label_safe_width() + target_h = spr.label_safe_height() + if name == '': + return target_w, target_h + image_w = self.media_shapes[name].get_width() + image_h = self.media_shapes[name].get_height() + scale_factor = float(target_w) / image_w + new_w = target_w + new_h = image_h * scale_factor + if new_h > target_h: + scale_factor = float(target_h) / new_h + new_h = target_h + new_w = target_w * scale_factor + return int(new_w), int(new_h) + + def _proto_skin(self, name, n, i): + """ Utility for calculating proto skin images """ + x, y = self._calc_image_offset(name, self.palettes[n][i].spr) + self.palettes[n][i].spr.set_image(self.media_shapes[name], 1, x, y) + + def _block_skin(self, name, blk): + """ Some blocks get a skin """ + x, y = self._calc_image_offset(name, blk.spr) + blk.set_image(self.media_shapes[name], x, y) + self._resize_skin(blk) + + def _resize_skin(self, blk): + """ Resize the 'skin' when block scale changes. """ + if blk.name in PYTHON_SKIN: + w, h = self._calc_w_h('pythonoff', blk.spr) + x, y = self._calc_image_offset('pythonoff', blk.spr, w, h) + elif blk.name == 'journal': + if len(blk.values) == 1 and blk.values[0] is not None: + w, h = self._calc_w_h('', blk.spr) + x, y = self._calc_image_offset('journaloff', blk.spr, w, h) + else: + w, h = self._calc_w_h('journaloff', blk.spr) + x, y = self._calc_image_offset('journaloff', blk.spr, w, h) + else: + # w, h = self._calc_w_h('descriptionoff', blk.spr) + w, h = self._calc_w_h('', blk.spr) + # x, y = self._calc_image_offset('descriptionoff', blk.spr, w, h) + x, y = self._calc_image_offset('', blk.spr, w, h) + blk.scale_image(x, y, w, h) + + +def dock_dx_dy(block1, dock1n, block2, dock2n): + """ Find the distance between the dock points of two blocks. """ + _dock1 = block1.docks[dock1n] + _dock2 = block2.docks[dock2n] + _d1type, _d1dir, _d1x, _d1y = _dock1[0:4] + _d2type, _d2dir, _d2x, _d2y = _dock2[0:4] + if block1 == block2: + return (100, 100) + if _d1dir == _d2dir: + return (100, 100) + if (_d2type is not 'number') or (dock2n is not 0): + if block1.connections is not None and \ + dock1n < len(block1.connections) and \ + block1.connections[dock1n] is not None: + return (100, 100) + if block2.connections is not None and \ + dock2n < len(block2.connections) and \ + block2.connections[dock2n] is not None: + return (100, 100) + if _d1type != _d2type: + if block1.name in string_or_number_args: + if _d2type == 'number' or _d2type == 'string': + pass + elif block1.name in CONTENT_ARGS: + if _d2type in content_blocks: + pass + else: + return (100, 100) + (_b1x, _b1y) = block1.spr.get_xy() + (_b2x, _b2y) = block2.spr.get_xy() + return ((_b1x + _d1x) - (_b2x + _d2x), (_b1y + _d1y) - (_b2y + _d2y)) diff --git a/activity/activity-turtleart.svg b/activity/activity-turtleart.svg new file mode 100644 index 0000000..8fb0dd4 --- /dev/null +++ b/activity/activity-turtleart.svg @@ -0,0 +1,74 @@ +<?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.32702086,0,0,0.32702086,-28.281255,4.0632089)" + id="g3861"> + <path + d="m 229.4265,82.10708 a 34.448574,31.598513 0 1 1 -68.8971,0 34.448574,31.598513 0 1 1 68.8971,0 z" + id="path3825" + style="fill:#000000;fill-opacity:1;stroke:none" /> + <path + d="m 146.8466,108.06462 c 0,0 16.2359,10.15496 24.2773,15.19797 3.6656,2.29879 3.4995,-9.01041 6.1186,-11.44782 1.9482,-0.15766 15.138,8.36289 23.0931,7.10554 8.2572,-1.3051 15.3714,-6.28257 20.4032,-13.78888 -0.5953,-2.28828 -5.5925,-0.008 -7.6013,-0.91343 -2.8453,4.78261 -5.6956,6.90448 -10.0387,7.00464 -13.9586,0.32192 -33.532,-19.36329 -35.3303,-23.68516 4.3069,0.8831 11.4973,1.51301 14.2111,-2.56589 1.5823,-2.3782 -0.543,-5.35067 -2.1712,-7.69767 -3.0708,-4.42645 -11.4011,-4.77895 -13.2242,-8.48717 -2.0107,-4.08982 4.488,-8.63853 8.2898,-11.15177 4.5762,-3.02521 11.481,-8.36867 16.1849,-4.04621 2.4052,2.2102 -7.5659,0.16838 -8.882,3.15802 -1.7425,3.95823 5.8602,4.97597 6.3161,9.27668 0.4237,3.99739 -3.7475,7.27492 -4.3423,11.25045 -0.4099,2.73981 1.6536,5.73092 0.5921,8.2898 -1.2332,2.97281 -7.8906,3.15173 -7.3029,6.31604 10.1484,6.52995 20.5559,10.53313 31.7776,11.44783 9.0031,0.73386 19.1464,0.10081 26.6458,-4.93441 5.4546,-3.6623 10.6274,-10.00969 10.6583,-16.57961 0.03,-6.29744 -5.6333,-11.51446 -10.0662,-15.98748 -6.7701,-6.83137 -18.11,-8.21253 -24.2773,-15.59272 -2.6481,-3.16893 -1.2426,-9.24702 -4.737,-11.44783 -7.9984,-1.60894 -19.6673,-0.96019 -29.0143,1.57901 -11.3585,3.08564 -23.6697,8.68727 -31.3828,16.18486 -4.051,9.65189 9.514,19.53633 9.2766,30.00119 -0.1808,7.96857 -9.6714,21.31664 -9.6714,21.31664" + id="path3821" + style="fill:&stroke_color;;fill-opacity:1;stroke:&fill_color;;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 178.3733,63.02406 -1.8587,2.72615 c 0,0 -2.6364,-0.66145 -2.7262,-1.73482 -0.2829,-3.38076 4.202,-7.30607 7.5589,-6.81537 1.5666,4.57181 5.2044,8.55019 5.2044,8.55019 l -7.4349,-4.08922 -1.7348,0.74349" + id="path3823" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="m 221.1936,90.19267 -0.819,4.70927" + id="path3834" + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 238.3927,87.32616 2.0475,2.66176" + id="path3836" + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 141.89,121.50238 c 0,0 -29.3042,3.77758 -44,-21.33334 -3.9435,-6.73831 -2.7258,-15.11656 -2,-22.66666 2.1847,-22.72591 12.5505,-46.54858 22,-61.33334 20.3839,-1.77411 47.6318,-0.0892 70.6667,2.66667 4.623,0.5531 28.2288,7.16728 32.6667,14.66667 2.2322,3.77212 -0.7807,20.81554 -2.6651,20.39909 -10.8427,-2.39622 -7.4629,-16.14428 -10.3501,-15.81288 -10.3315,1.20112 -23.4198,0.59834 -31.741,3.3315 -8.8873,3.54201 -27.3925,11.3578 -30.4555,17.88252 -2.6561,5.65803 11.5495,23.95055 10.2746,28.17891 -2.3379,7.75325 -13.9551,33.45122 -14.3241,33.9338" + id="path2997" + style="fill:&fill_color;;fill-opacity:1;stroke:&stroke_color;;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 175.0714,119.31507 2.7633,-6.51342 c 0,0 15.3169,6.68998 23.2904,5.92129 5.2145,-0.5027 14.2111,-6.7108 14.2111,-6.7108 l 5.9212,13.81634 c 0,0 -16.5168,2.99189 -24.672,1.77639 -7.6013,-1.13294 -21.514,-8.2898 -21.514,-8.2898 z" + id="path3806" + style="fill:&fill_color;;fill-opacity:1;stroke:&stroke_color;;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 112.7004,115.17017 c 0,0 5.8137,1.1256 8.0925,-0.19738 4.9111,-2.8512 2.925,-12.1206 7.6976,-15.19797 5.0919,-3.28324 12.7474,1.93531 18.1587,-0.78951 2.7991,-1.40946 5.9212,-7.30292 5.9212,-7.30292" + id="path3767" + style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 99.7723,102.48516 c 0,0 11.7349,0.53347 15.198,-2.17114 4.4756,-3.49537 5.0962,-12.1206 9.8688,-15.19797 5.0919,-3.28324 11.5631,1.93531 16.9744,-0.78951 2.7991,-1.40946 7.6976,-10.06619 7.6976,-10.06619" + id="path3767-4" + style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + transform="translate(-1185.4433,-637.16429)" + id="g3797" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-opacity:1"> + <path + d="m 1280.3799,717.7936 12.04,-11.05307 -6.1187,0.39476 1.9738,-12.43471 8.0924,-3.3554 -2.3685,13.42159 c 0,0 27.6772,-26.02525 44.2123,-34.9356 9.3957,-5.06314 29.6064,-9.86881 30.3959,-10.06619 0.7895,-0.19738 16.777,0.59213 16.777,0.59213 -7.5003,-3.3554 -16.5796,-5.32916 -26.0537,-5.32916 l -2.3685,5.13178 -20.1324,0.19738 4.1449,-5.72391 -6.7108,-0.59213 -15.1979,8.88193 15.0006,-1.38163 -4.1449,11.84257 -15.7901,0.98688 4.9344,-11.25044 -16.777,13.61896 8.2898,-0.19738 -0.7895,10.8557 -12.04,2.76327 3.7502,-12.03996 -15.3954,11.84258 -2.7632,9.86882" + id="path3787" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 1287.8802,703.38514 1.7764,0.39475 1.7764,-5.92129 -2.1711,-0.39475 z" + id="path3789" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 1303.2756,685.62127 0.9869,-5.13178 2.3685,3.75015 z" + id="path3791" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 1320.8421,671.2128 1.1842,-5.13178 7.5003,-0.19738 -2.7633,5.13179 -5.1317,-0.19738" + id="path3793" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 1345.1193,658.18597 0,-4.1449 10.461,0.7895 -1.1843,3.15802 z" + id="path3795" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> + <path + d="m 97.5025,100.16957 18.7508,-21.11926 17.9612,-13.42159 c 0,0 8.0484,-5.69596 12.2373,-8.28981 8.5409,-5.28872 16.7256,-11.61232 26.2511,-14.80322 8.9376,-2.99395 18.73,-2.20005 28.0274,-3.75015 1.6545,-0.27585 4.9344,-0.98688 4.9344,-0.98688 l -0.9869,-8.48718 9.0793,3.94753 -0.5921,1.97376 -5.3291,-2.17114 1.1842,5.72391 0.9869,-2.17113 5.9213,2.17113 0.9869,-5.52653 -12.6321,-5.72391 -5.9213,7.30292 -21.9088,2.76327 -3.9475,-7.30293 13.2242,-3.55277 0.5921,3.94753 -7.6976,1.18425 -0.1974,2.36852 11.2504,-2.17114 -1.7764,-7.30292 -17.7638,3.55277 -7.6977,15.19798 -15.3953,9.0793 -6.5135,-4.53965 14.0138,-9.67144 0,2.56589 -9.4741,5.72392 c 0,0 0.3947,1.77638 1.3816,1.57901 0.9869,-0.19738 10.2636,-5.52654 10.2636,-5.52654 l -1.1843,-6.71079 -17.9612,11.6452 -8.4872,17.56649 -8.4872,7.30292 -2.9606,-3.94753 6.7108,-7.30292 0.5921,1.57901 -5.3291,4.93441 7.6976,-5.13179 -2.9606,-4.9344 -10.461,9.67143 -2.9606,13.81634 -7.8951,8.68456 -4.3422,-1.77639 5.3291,-6.51341 0.7895,1.38163 -2.7632,4.53966 3.3554,-9.27669 -7.8951,6.90817 -2.1712,9.67143 z" + id="path3804" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> +</svg> diff --git a/activity/activity.info b/activity/activity.info new file mode 100644 index 0000000..dde81c2 --- /dev/null +++ b/activity/activity.info @@ -0,0 +1,10 @@ +[Activity] +name = Amazonas Tortuga +activity_version = 1 +license = MIT +bundle_id = org.sugarlabs.AmazonasTortuga +exec = sugar-activity AmazonasTortugaActivity.AmazonasTortugaActivity +icon = activity-turtleart +show_launcher = yes +update_url = http://wiki.laptop.org/go/Activities/G1G1 +mime_types = application/x-turtle-art diff --git a/activity/application-x-turtle-art.svg b/activity/application-x-turtle-art.svg new file mode 100644 index 0000000..a885712 --- /dev/null +++ b/activity/application-x-turtle-art.svg @@ -0,0 +1,120 @@ +<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://w +ww.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ + <!ENTITY stroke_color "#010101"> + <!ENTITY fill_color "#FFFFFF"> +]> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2" + xml:space="preserve"> +<g + transform="translate(-0.5507515,-1.7569535)"> + <line + style="fill:none;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + y2="4.9" + y1="16.2" + x2="52.4" + x1="41.2" /> + <polyline + style="fill:none;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + points="51.6,15.3 41.2,16.2 42.1,5.8" /> +</g> +<polygon + points="11.0,6.1 31.9,6.1 43.9,18.0 43.9,48.9 10.9,48.9 10.9,6.1 " + transform="translate(-6,2)" + stroke="&stroke_color;" + style="fill:none;stroke-width:3.5" /> +<polyline + points="43.818,18.027 31.874,18.027 31.874,6.088" + stroke="&stroke_color;" + style="fill:none;stroke-width:3.5" + transform="translate(-6,2)" /> +<path + d="M 21.379465,44.19975 C 21.102965,44.19975 20.829965,44.18225 20.560965,44.14975 L 21.254965,45.32425 L 21.938965,44.16775 C 21.753465,44.18275 21.568465,44.19975 21.379465,44.19975 z" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> +<g + transform="matrix(0.5,0,0,0.5,7.6,20.0)" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"> + <path + d="M 40.16,11.726 C 37.996,11.726 36.202,13.281 35.817,15.333 C 37.676,16.678 39.274,18.448 40.492,20.541 C 42.777,20.369 44.586,18.48 44.586,16.151 C 44.586,13.707 42.604,11.726 40.16,11.726 z" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 40.713,39.887 C 39.489,42.119 37.853,44.018 35.916,45.443 C 36.437,47.307 38.129,48.682 40.16,48.682 C 42.603,48.682 44.586,46.702 44.586,44.258 C 44.586,42.003 42.893,40.162 40.713,39.887 z" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 14.273,39.871 C 12.02,40.077 10.249,41.95 10.249,44.258 C 10.249,46.701 12.229,48.682 14.673,48.682 C 16.737,48.682 18.457,47.262 18.945,45.35 C 17.062,43.934 15.47,42.061 14.273,39.871 z" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 19.026,15.437 C 18.683,13.334 16.872,11.726 14.673,11.726 C 12.229,11.726 10.249,13.707 10.249,16.15 C 10.249,18.532 12.135,20.46 14.494,20.556 C 15.68,18.513 17.226,16.772 19.026,15.437 z" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> +<path + d="M 21.379465,26.34175 C 22.333465,26.34175 23.243465,26.54725 24.088465,26.90575 C 24.458965,26.36775 24.677465,25.71725 24.677465,25.01425 C 24.677465,23.17075 23.182965,21.67575 21.338965,21.67575 C 19.495465,21.67575 18.000965,23.17075 18.000965,25.01425 C 18.000965,25.72825 18.226965,26.38875 18.608965,26.93125 C 19.470965,26.55675 20.402465,26.34175 21.379465,26.34175 z" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> +<g + transform="matrix(0.5,0,0,0.5,7.630965,20.06025)" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"> + <path + d="M 43.102,30.421 C 43.102,35.1554 41.4568,39.7008 38.5314,43.0485 C 35.606,46.3963 31.6341,48.279 27.497,48.279 C 23.3599,48.279 19.388,46.3963 16.4626,43.0485 C 13.5372,39.7008 11.892,35.1554 11.892,30.421 C 11.892,20.6244 18.9364,12.563 27.497,12.563 C 36.0576,12.563 43.102,20.6244 43.102,30.421 z" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:3;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> +<g + transform="matrix(0.5,0,0,0.5,7.630965,20.06025)" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"> + <path + d="M 25.875,33.75 L 24.333,29.125 L 27.497,26.538 L 31.112,29.164 L 29.625,33.833 L 25.875,33.75 z" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 27.501,41.551 C 23.533,41.391 21.958,39.542 21.958,39.542 L 25.528,35.379 L 29.993,35.547 L 33.125,39.667 C 33.125,39.667 30.235,41.661 27.501,41.551 z" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 18.453,33.843 C 17.604,30.875 18.625,26.959 18.625,26.959 L 22.625,29.126 L 24.118,33.755 L 20.536,37.988 C 20.536,37.987 19.071,35.998 18.453,33.843 z" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 19.458,25.125 C 19.458,25.125 19.958,23.167 22.497,21.303 C 24.734,19.66 26.962,19.583 26.962,19.583 L 26.925,24.564 L 23.404,27.314 L 19.458,25.125 z" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 32.084,27.834 L 28.625,24.959 L 29,19.75 C 29,19.75 30.834,19.708 32.959,21.417 C 35.187,23.208 36.321,26.4 36.321,26.4 L 32.084,27.834 z" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 31.292,34.042 L 32.605,29.578 L 36.792,28.042 C 36.792,28.042 37.469,30.705 36.75,33.709 C 36.21,35.965 34.666,38.07 34.666,38.07 L 31.292,34.042 z" + stroke="&stroke_color;" + fill="&fill_color;" + style="fill-opacity:1;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> +</svg> diff --git a/activity/menu-icon.svg b/activity/menu-icon.svg new file mode 100644 index 0000000..433c130 --- /dev/null +++ b/activity/menu-icon.svg @@ -0,0 +1,83 @@ +<?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.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2"> + <defs + id="defs40" /> + <g + transform="matrix(0.96592583,-0.25881905,0.25881905,0.96592583,-6.8005861,7.9133051)" + id="g3661" + style="fill:#00a000;fill-opacity:1"> + <path + d="m 27.497,48.279 c -0.553,0 -1.099,-0.035 -1.637,-0.1 l 1.388,2.349 1.368,-2.313 c -0.371,0.03 -0.741,0.064 -1.119,0.064 z" + id="path6" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-opacity:1" /> + <g + id="g8" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"> + <path + d="m 40.16,11.726 c -2.164,0 -3.958,1.555 -4.343,3.607 1.859,1.345 3.457,3.115 4.675,5.208 2.285,-0.172 4.094,-2.061 4.094,-4.39 0,-2.444 -1.982,-4.425 -4.426,-4.425 z" + id="path10" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 40.713,39.887 c -1.224,2.232 -2.86,4.131 -4.797,5.556 0.521,1.864 2.213,3.239 4.244,3.239 2.443,0 4.426,-1.98 4.426,-4.424 0,-2.255 -1.693,-4.096 -3.873,-4.371 z" + id="path12" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 14.273,39.871 c -2.253,0.206 -4.024,2.079 -4.024,4.387 0,2.443 1.98,4.424 4.424,4.424 2.064,0 3.784,-1.42 4.272,-3.332 -1.883,-1.416 -3.475,-3.289 -4.672,-5.479 z" + id="path14" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 19.026,15.437 c -0.343,-2.103 -2.154,-3.711 -4.353,-3.711 -2.444,0 -4.424,1.981 -4.424,4.424 0,2.382 1.886,4.31 4.245,4.406 1.186,-2.043 2.732,-3.784 4.532,-5.119 z" + id="path16" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <path + d="m 27.497,12.563 c 1.908,0 3.728,0.411 5.418,1.128 0.741,-1.076 1.178,-2.377 1.178,-3.783 0,-3.687 -2.989,-6.677 -6.677,-6.677 -3.687,0 -6.676,2.99 -6.676,6.677 0,1.428 0.452,2.749 1.216,3.834 1.724,-0.749 3.587,-1.179 5.541,-1.179 z" + id="path18" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + id="g20" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"> + <path + d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z" + id="path22" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + id="g24" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"> + <path + d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z" + id="path26" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z" + id="path28" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z" + id="path30" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z" + id="path32" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z" + id="path34" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z" + id="path36" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + </g> +</svg> diff --git a/activity/mimetypes.xml b/activity/mimetypes.xml new file mode 100644 index 0000000..aa24955 --- /dev/null +++ b/activity/mimetypes.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info"> +<mime-type type="application/x-turtle-art"> +<comment xml:lang="en">Turtle Art</comment> +<glob pattern="*.ta"/> +</mime-type> +</mime-info> diff --git a/activity/turtleart.svg b/activity/turtleart.svg new file mode 100644 index 0000000..433c130 --- /dev/null +++ b/activity/turtleart.svg @@ -0,0 +1,83 @@ +<?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.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2"> + <defs + id="defs40" /> + <g + transform="matrix(0.96592583,-0.25881905,0.25881905,0.96592583,-6.8005861,7.9133051)" + id="g3661" + style="fill:#00a000;fill-opacity:1"> + <path + d="m 27.497,48.279 c -0.553,0 -1.099,-0.035 -1.637,-0.1 l 1.388,2.349 1.368,-2.313 c -0.371,0.03 -0.741,0.064 -1.119,0.064 z" + id="path6" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-opacity:1" /> + <g + id="g8" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"> + <path + d="m 40.16,11.726 c -2.164,0 -3.958,1.555 -4.343,3.607 1.859,1.345 3.457,3.115 4.675,5.208 2.285,-0.172 4.094,-2.061 4.094,-4.39 0,-2.444 -1.982,-4.425 -4.426,-4.425 z" + id="path10" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 40.713,39.887 c -1.224,2.232 -2.86,4.131 -4.797,5.556 0.521,1.864 2.213,3.239 4.244,3.239 2.443,0 4.426,-1.98 4.426,-4.424 0,-2.255 -1.693,-4.096 -3.873,-4.371 z" + id="path12" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 14.273,39.871 c -2.253,0.206 -4.024,2.079 -4.024,4.387 0,2.443 1.98,4.424 4.424,4.424 2.064,0 3.784,-1.42 4.272,-3.332 -1.883,-1.416 -3.475,-3.289 -4.672,-5.479 z" + id="path14" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 19.026,15.437 c -0.343,-2.103 -2.154,-3.711 -4.353,-3.711 -2.444,0 -4.424,1.981 -4.424,4.424 0,2.382 1.886,4.31 4.245,4.406 1.186,-2.043 2.732,-3.784 4.532,-5.119 z" + id="path16" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <path + d="m 27.497,12.563 c 1.908,0 3.728,0.411 5.418,1.128 0.741,-1.076 1.178,-2.377 1.178,-3.783 0,-3.687 -2.989,-6.677 -6.677,-6.677 -3.687,0 -6.676,2.99 -6.676,6.677 0,1.428 0.452,2.749 1.216,3.834 1.724,-0.749 3.587,-1.179 5.541,-1.179 z" + id="path18" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + id="g20" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"> + <path + d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z" + id="path22" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:2.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + id="g24" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"> + <path + d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z" + id="path26" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z" + id="path28" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z" + id="path30" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z" + id="path32" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z" + id="path34" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z" + id="path36" + style="fill:#00a000;fill-opacity:1;stroke:#004000;stroke-width:1.5;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + </g> +</svg> diff --git a/amazonas-tortuga.py b/amazonas-tortuga.py new file mode 100755 index 0000000..e639e38 --- /dev/null +++ b/amazonas-tortuga.py @@ -0,0 +1,712 @@ +#!/usr/bin/env python +#Copyright (c) 2007-8, Playful Invention Company +#Copyright (c) 2008-12, Walter Bender +#Copyright (c) 2011 Collabora Ltd. <http://www.collabora.co.uk/> + +#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 cairo + +import getopt +import sys +import os +import os.path +import cStringIO +import errno +import ConfigParser + +try: + # Try to use XDG Base Directory standard for config files. + import xdg.BaseDirectory + CONFIG_HOME = os.path.join(xdg.BaseDirectory.xdg_config_home, 'turtleart') +except ImportError, e: + # Default to `.config` per the spec. + CONFIG_HOME = os.path.expanduser(os.path.join('~', '.config', 'turtleart')) + +argv = sys.argv[:] # Workaround for import behavior of gst in tagplay +sys.argv[1:] = [] # Execution of import gst cannot see '--help' or '-h' + +import gettext + +# Commenting out bindtextdomain so that GNOME can find the installed .mo files, +# but it will not find the .mo files in the local locale directory when running +# from a git repository or the unzipped .xo file. +# gettext.bindtextdomain('org.laptop.TurtleArtActivity', 'locale') + +import gettext + +from TurtleArt.taconstants import OVERLAY_LAYER, DEFAULT_TURTLE_COLORS +from TurtleArt.tautils import data_to_string, data_from_string, get_save_name +from TurtleArt.tawindow import TurtleArtWindow +from TurtleArt.taexporthtml import save_html +from TurtleArt.taexportlogo import save_logo + +from util.menubuilder import MenuBuilder + + +class TurtleMain(): + ''' Launch Turtle Confusion from outside of Sugar. ''' + _INSTALL_PATH = '/usr/share/sugar/activities/TurtleArt.activity' + _ALTERNATIVE_INSTALL_PATH = \ + '/usr/local/share/sugar/activities/TurtleArt.activity' + _ICON_SUBPATH = 'images/turtle.png' + _GNOME_PLUGIN_SUBPATH = 'gnome_plugins' + + def __init__(self): + self._abspath = os.path.abspath('.') + self._execdirname = self._get_execution_dir() + if self._execdirname is not None: + os.chdir(self._execdirname) + file_activity_info = ConfigParser.ConfigParser() + activity_info_path = os.path.abspath('./activity/activity.info') + file_activity_info.read(activity_info_path) + bundle_id = file_activity_info.get('Activity', 'bundle_id') + gettext.textdomain(bundle_id) + global _ + _ = gettext.gettext + self._HELP_MSG = 'turtleart.py: ' + _('usage is') + ''' + \tturtleconfusion.py + \tturtleconfusion.py project.ta + \tturtleconfusion.py --output_png project.ta + \tturtleconfusion.py -o project + \tturtleconfusion.py --run project.ta + \tturtleconfusion.py -r project''' + self._init_vars() + self._parse_command_line() + self._ensure_sugar_paths() + self._plugins = [] + + if self._output_png: + # Fix me: We need to create a cairo surface to work with + pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, + gtk.gdk.screen_width(), + gtk.gdk.screen_height()) + # self.canvas, mask = pixbuf.render_pixmap_and_mask() + self.canvas = pixbuf + self._build_window(interactive=False) + self._draw_and_quit() + else: + self._read_initial_pos() + self._init_plugins() + self._setup_gtk() + self._build_window() + self._run_plugins() + self._start_gtk() + + def get_config_home(self): + return CONFIG_HOME + + def _get_gnome_plugin_home(self): + ''' Use plugin directory associated with execution path. ''' + if os.path.exists(os.path.join(self._execdirname, + self._GNOME_PLUGIN_SUBPATH)): + return os.path.join(self._execdirname, self._GNOME_PLUGIN_SUBPATH) + else: + return None + + def _get_plugin_candidates(self, path): + ''' Look for plugin files in plugin directory. ''' + plugin_files = [] + if path is not None: + candidates = os.listdir(path) + for c in candidates: + if c[-10:] == '_plugin.py' and c[0] != '#' and c[0] != '.': + plugin_files.append(c.split('.')[0]) + return plugin_files + + def _init_plugins(self): + ''' Try launching any plugins we may have found. ''' + for p in self._get_plugin_candidates(self._get_gnome_plugin_home()): + P = p.capitalize() + f = \ + "def f(self): from gnome_plugins.%s import %s; return %s(self)" % (p, P, P) + plugin = {} + try: + exec f in globals(), plugin + self._plugins.append(plugin.values()[0](self)) + except ImportError, e: + print 'failed to import %s: %s' % (P, str(e)) + + def _run_plugins(self): + ''' Tell the plugin about the TurtleWindow instance. ''' + for p in self._plugins: + p.set_tw(self.tw) + + def _mkdir_p(self, path): + '''Create a directory in a fashion similar to `mkdir -p`.''' + try: + os.makedirs(path) + except OSError, exc: + if exc.errno == errno.EEXIST: + pass + else: + raise + + def _makepath(self, path): + ''' Make a path if it doesn't previously exist ''' + from os import makedirs + from os.path import normpath, dirname, exists + + dpath = normpath(dirname(path)) + if not exists(dpath): + makedirs(dpath) + + def _start_gtk(self): + ''' Get a main window set up. ''' + self.win.connect('configure_event', self.tw.update_overlay_position) + self.tw.parent = self.win + if self._ta_file is None: + self.tw.load_start() + else: + print self._ta_file + self.tw.load_start(self._ta_file) + self.tw.lc.trace = 0 + if self._run_on_launch: + self._do_run_cb() + gtk.main() + + def _draw_and_quit(self): + ''' Non-interactive mode: run the project, save it to a file + and quit. ''' + self.tw.load_start(self._ta_file) + self.tw.lc.trace = 0 + self.tw.run_button(0) + self.tw.save_as_image(self._ta_file) + + def _build_window(self, interactive=True): + ''' Initialize the TurtleWindow instance. ''' + if interactive: + win = self.canvas.get_window() + cr = win.cairo_create() + surface = cr.get_target() + else: + img_surface = cairo.ImageSurface(cairo.FORMAT_RGB24, + 1024, 768) + cr = cairo.Context(img_surface) + surface = cr.get_target() + self.turtle_canvas = surface.create_similar( + cairo.CONTENT_COLOR, gtk.gdk.screen_width() * 2, + gtk.gdk.screen_height() * 2) + self.tw = TurtleArtWindow(self.canvas, self._execdirname, + turtle_canvas=self.turtle_canvas) + self.tw.save_folder = os.path.expanduser('~') + + def _init_vars(self): + ''' If we are invoked to start a project from Gnome, we should make + sure our current directory is TA's source dir. ''' + self._ta_file = None + self._output_png = False + self.i = 0 # FIXME: use a better name for this variable + self.scale = 2.0 + self.tw = None + + def _parse_command_line(self): + ''' Try to make sense of the command-line arguments. ''' + try: + opts, args = getopt.getopt(argv[1:], 'hor', + ['help', '_output_png', 'run']) + except getopt.GetoptError, err: + print str(err) + print self._HELP_MSG + sys.exit(2) + self._run_on_launch = False + for o, a in opts: + if o in ('-h', '--help'): + print self._HELP_MSG + sys.exit() + if o in ('-o', '--output_png'): + self._output_png = True + elif o in ('-r', '--run'): + self._run_on_launch = True + else: + assert False, _('No option action:') + ' ' + o + if args: + self._ta_file = args[0] + + if len(args) > 1 or self._output_png and self._ta_file is None: + print self._HELP_MSG + sys.exit() + + if self._ta_file is not None: + if not self._ta_file.endswith(('.ta')): + self._ta_file += '.ta' + if not os.path.exists(self._ta_file): + assert False, ('%s: %s' % (self._ta_file, _('File not found'))) + + def _ensure_sugar_paths(self): + ''' Make sure Sugar paths are present. ''' + tapath = os.path.join(os.environ['HOME'], '.sugar', 'default', + 'org.laptop.TurtleArtActivity') + map(self._makepath, (os.path.join(tapath, 'data/'), + os.path.join(tapath, 'instance/'))) + + def _read_initial_pos(self): + ''' Read saved configuration. ''' + try: + data_file = open(os.path.join(CONFIG_HOME, 'turtleartrc'), 'r') + except IOError: + # Opening the config file failed + # We'll assume it needs to be created + try: + self._mkdir_p(CONFIG_HOME) + data_file = open(os.path.join(CONFIG_HOME, 'turtleartrc'), + 'a+') + except IOError, e: + # We can't write to the configuration file, use + # a faux file that will persist for the length of + # the session. + print _('Configuration directory not writable: %s') % (e) + data_file = cStringIO.StringIO() + data_file.write(str(50) + '\n') + data_file.write(str(50) + '\n') + data_file.write(str(800) + '\n') + data_file.write(str(550) + '\n') + data_file.seek(0) + try: + self.x = int(data_file.readline()) + self.y = int(data_file.readline()) + self.width = int(data_file.readline()) + self.height = int(data_file.readline()) + except ValueError: + self.x = 50 + self.y = 50 + self.width = 800 + self.height = 550 + + def _setup_gtk(self): + ''' Set up a scrolled window in which to run Turtle Blocks. ''' + win = gtk.Window(gtk.WINDOW_TOPLEVEL) + win.set_default_size(self.width, self.height) + win.move(self.x, self.y) + win.maximize() + win.set_title(_('Turtle Art')) + if os.path.exists(os.path.join(self._execdirname, self._ICON_SUBPATH)): + win.set_icon_from_file(os.path.join(self._execdirname, + self._ICON_SUBPATH)) + win.connect('delete_event', self._quit_ta) + + vbox = gtk.VBox(False, 0) + win.add(vbox) + vbox.show() + + menu_bar = self._get_menu_bar() + vbox.pack_start(menu_bar, False, False, 2) + menu_bar.show() + + sw = gtk.ScrolledWindow() + sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + sw.show() + canvas = gtk.DrawingArea() + width = gtk.gdk.screen_width() * 2 + height = gtk.gdk.screen_height() * 2 + canvas.set_size_request(width, height) + sw.add_with_viewport(canvas) + canvas.show() + vbox.pack_end(sw, True, True) + + win.show_all() + self.win = win + self.canvas = canvas + + def _get_menu_bar(self): + ''' Instead of Sugar toolbars, use GNOME menus. ''' + menu = gtk.Menu() + MenuBuilder.make_menu_item(menu, _('New'), self._do_new_cb) + MenuBuilder.make_menu_item(menu, _('Open'), self._do_open_cb) + MenuBuilder.make_menu_item(menu, _('Save'), self._do_save_cb) + MenuBuilder.make_menu_item(menu, _('Save as'), self._do_save_as_cb) + MenuBuilder.make_menu_item(menu, _('Save as image'), + self._do_save_picture_cb) + MenuBuilder.make_menu_item(menu, _('Save as HTML'), + self._do_save_html_cb) + MenuBuilder.make_menu_item(menu, _('Save as Logo'), + self._do_save_logo_cb) + MenuBuilder.make_menu_item(menu, _('Quit'), self.destroy) + activity_menu = MenuBuilder.make_sub_menu(menu, _('File')) + + menu = gtk.Menu() + MenuBuilder.make_menu_item(menu, _('Cartesian coordinates'), + self._do_cartesian_cb) + MenuBuilder.make_menu_item(menu, _('Polar coordinates'), + self._do_polar_cb) + MenuBuilder.make_menu_item(menu, _('Rescale coordinates'), + self._do_rescale_cb) + MenuBuilder.make_menu_item(menu, _('Grow blocks'), + self._do_resize_cb, 1.5) + MenuBuilder.make_menu_item(menu, _('Shrink blocks'), + self._do_resize_cb, 0.667) + MenuBuilder.make_menu_item(menu, _('Reset block size'), + self._do_resize_cb, -1) + MenuBuilder.make_menu_item(menu, _('Turn off hover help'), + self._do_hover_help_off_cb) + MenuBuilder.make_menu_item(menu, _('Turn on hover help'), + self._do_hover_help_on_cb) + view_menu = MenuBuilder.make_sub_menu(menu, _('View')) + + menu = gtk.Menu() + MenuBuilder.make_menu_item(menu, _('Copy'), self._do_copy_cb) + MenuBuilder.make_menu_item(menu, _('Paste'), self._do_paste_cb) + edit_menu = MenuBuilder.make_sub_menu(menu, _('Edit')) + + menu = gtk.Menu() + MenuBuilder.make_menu_item(menu, _('Show palette'), + self._do_palette_cb) + MenuBuilder.make_menu_item(menu, _('Hide palette'), + self._do_hide_palette_cb) + MenuBuilder.make_menu_item(menu, _('Show/hide blocks'), + self._do_hideshow_cb) + tool_menu = MenuBuilder.make_sub_menu(menu, _('Tools')) + + menu = gtk.Menu() + MenuBuilder.make_menu_item(menu, _('Clean'), self._do_eraser_cb) + MenuBuilder.make_menu_item(menu, _('Run'), self._do_run_cb) + MenuBuilder.make_menu_item(menu, _('Step'), self._do_step_cb) + MenuBuilder.make_menu_item(menu, _('Stop'), self._do_stop_cb) + turtle_menu = MenuBuilder.make_sub_menu(menu, _('Turtle')) + + + menu = gtk.Menu() + self._level = 0 + self._levels = self._get_levels() + self._custom_filepath = None + for i in range(40): + MenuBuilder.make_menu_item(menu, _('Challenge') + ' ' + str(i + 1), + self._do_level_cb, i) + turtle_menu = MenuBuilder.make_sub_menu(menu, _('Challenges')) + + menu_bar = gtk.MenuBar() + menu_bar.append(activity_menu) + menu_bar.append(edit_menu) + menu_bar.append(view_menu) + menu_bar.append(tool_menu) + menu_bar.append(turtle_menu) + + # Add menus for plugins + for p in self._plugins: + menu_bar.append(p.get_menu()) + return menu_bar + + def _quit_ta(self, widget=None, e=None): + ''' Save changes on exit ''' + project_empty = self.tw.is_project_empty() + if not project_empty: + if self.tw.is_new_project(): + self._show_save_dialog(True) + else: + if self.tw.project_has_changed(): + self._show_save_dialog(False) + gtk.main_quit() + + def _show_save_dialog(self, new_project=True): + ''' Dialog for save project ''' + dlg = gtk.MessageDialog(parent=None, type=gtk.MESSAGE_INFO, + buttons=gtk.BUTTONS_OK_CANCEL, + message_format=_( + 'You have unsaved work. Would you like to save before quitting?')) + dlg.set_title(_('Save project?')) + dlg.set_property('skip-taskbar-hint', False) + + resp = dlg.run() + dlg.destroy() + if resp == gtk.RESPONSE_OK: + if new_project: + self._save_as() + else: + self._save_changes() + + def _do_new_cb(self, widget): + ''' Callback for new project. ''' + self.tw.new_project() + self.tw.load_start() + + def _do_open_cb(self, widget): + ''' Callback for open project. ''' + self.tw.load_file(True) + + def _do_save_cb(self, widget): + ''' Callback for save project. ''' + self.tw.save_file() + + def _do_save_as_cb(self, widget): + ''' Callback for save-as project. ''' + self._save_as() + + def _save_as(self): + ''' Save as is called from callback and quit ''' + self.tw.save_file_name = None + self.tw.save_file() + + def _save_changes(self): + ''' Save changes to current project ''' + self.tw.save_file_name = None + self.tw.save_file(self.tw._loaded_project) + + def _do_save_picture_cb(self, widget): + ''' Callback for save canvas. ''' + self.tw.save_as_image() + + def _do_save_html_cb(self, widget): + ''' Callback for save project to HTML. ''' + html = save_html(self, self.tw, False) + if len(html) == 0: + return + save_type = '.html' + if len(self.tw.saved_pictures) > 0: + if self.tw.saved_pictures[0].endswith(('.svg')): + save_type = '.xml' + filename, self.tw.load_save_folder = get_save_name(save_type, + self.tw.load_save_folder, 'portfolio') + f = file(filename, 'w') + f.write(html) + f.close() + self.tw.saved_pictures = [] + + def _do_save_logo_cb(self, widget): + ''' Callback for save project to Logo. ''' + logocode = save_logo(self.tw) + if len(logocode) == 0: + return + save_type = '.lg' + filename, self.tw.load_save_folder = get_save_name(save_type, + self.tw.load_save_folder, 'logosession') + f = file(filename, 'w') + f.write(logocode) + f.close() + + def _do_resize_cb(self, widget, factor): + ''' Callback to resize blocks. ''' + if factor == -1: + self.tw.block_scale = 2.0 + else: + self.tw.block_scale *= factor + self.tw.resize_blocks() + + def _do_cartesian_cb(self, button): + ''' Callback to display/hide Cartesian coordinate overlay. ''' + self.tw.set_cartesian(True) + + def _do_polar_cb(self, button): + ''' Callback to display/hide Polar coordinate overlay. ''' + self.tw.set_polar(True) + + def _do_rescale_cb(self, button): + ''' Callback to rescale coordinate space. ''' + if self.tw.coord_scale == 1: + self.tw.coord_scale = self.tw.height / 200 + self.tw.eraser_button() + if self.tw.cartesian is True: + self.tw.overlay_shapes['Cartesian_labeled'].hide() + self.tw.overlay_shapes['Cartesian'].set_layer(OVERLAY_LAYER) + else: + self.tw.coord_scale = 1 + self.tw.eraser_button() + if self.tw.cartesian is True: + self.tw.overlay_shapes['Cartesian'].hide() + self.tw.overlay_shapes['Cartesian_labeled'].set_layer( + OVERLAY_LAYER) + + def _do_hover_help_on_cb(self, button): + ''' Turn hover help on ''' + self.tw.no_help = False + + def _do_hover_help_off_cb(self, button): + ''' Turn hover help off ''' + self.tw.no_help = True + self.tw.last_label = None + self.tw.status_spr.hide() + + def _do_palette_cb(self, widget): + ''' Callback to show/hide palette of blocks. ''' + self.tw.show_palette(self.i) + self.i += 1 + if self.i == len(self.tw.palettes): + self.i = 0 + + def _do_hide_palette_cb(self, widget): + ''' Hide the palette of blocks. ''' + self.tw.hide_palette() + + def _do_hideshow_cb(self, widget): + ''' Hide/show the blocks. ''' + self.tw.hideshow_button() + + def _do_eraser_cb(self, widget): + ''' Callback for eraser button. ''' + self.tw.eraser_button() + return + + def _do_run_cb(self, widget): + ''' Callback for run button (rabbit). ''' + self.tw.lc.trace = 0 + self.tw.hideblocks() + self.tw.run_button(0, running_from_button_push=True) + return + + def _do_step_cb(self, widget): + ''' Callback for step button (turtle). ''' + self.tw.lc.trace = 0 + self.tw.run_button(3, running_from_button_push=True) + return + + def _do_trace_cb(self, widget): + ''' Callback for debug button (bug). ''' + self.tw.lc.trace = 1 + self.tw.run_button(9, running_from_button_push=True) + return + + def _do_stop_cb(self, widget): + ''' Callback for stop button. ''' + self.tw.lc.trace = 0 + self.tw.showblocks() + self.tw.stop_button() + return + + def restore_challenge(self): + ''' Restore the current challange after a clear screen ''' + if self._custom_filepath is None: + self._load_level() + else: + self._load_level(custom=True) + + def _load_level(self, custom=False): + self.tw.canvas.clearscreen() + if custom: + self.tw.canvas.setxy(0, 0, pendown=False) + self.tw.lc.insert_image(center=True, + filepath=self._custom_filepath, + resize=True, offset=False) + else: + self.tw.canvas.setxy(int(-gtk.gdk.screen_width() / 2), 0, + pendown=False) + self.tw.lc.insert_image(center=False, resize=False, + filepath=os.path.join( + self._get_execution_dir(), 'images', + 'turtle-a.png')) + # Slight offset to account for stroke width + if self._level + 1 in self.offsets: + xoffset = self.offsets[self._level + 1][0] + yoffset = self.offsets[self._level + 1][1] + else: + xoffset = 0 + yoffset = 0 + self.tw.canvas.setxy(-2.5 + xoffset, -2.5 + yoffset, pendown=False) + self.tw.lc.insert_image(center=False, + filepath=os.path.join( + self._get_execution_dir(), 'challenges', + self._levels[self._level] + '.svg'), resize=False, + offset=True) + self.tw.canvas.setxy(0, 0, pendown=False) + + def _do_level_cb(self, widget, level): + ''' Callback to resize blocks. ''' + self._level = level + self._load_level() + + def _get_levels(self): + ''' Look for level files in lessons directory. ''' + level_files = [] + + for i in range(40): + level_files.append('confusion-%d' % (i+1)) + + self.offsets = {} + offset_fd = open(os.path.join(self._get_execution_dir(), 'challenges', + 'offsets')) + for line in offset_fd: + try: + idx, offsets = line.strip('\n').split(':') + xoffset, yoffset = offsets.split(',') + self.offsets[int(idx)] = (int(xoffset), int(yoffset)) + except ValueError: + pass + offset_fd.close() + return level_files + + def _do_copy_cb(self, button): + ''' Callback for copy button. ''' + clipBoard = gtk.Clipboard() + data = self.tw.assemble_data_to_save(False, False) + if data is not []: + text = data_to_string(data) + clipBoard.set_text(text) + + def _do_paste_cb(self, button): + ''' Callback for paste button. ''' + clipBoard = gtk.Clipboard() + text = clipBoard.wait_for_text() + if text is not None: + if self.tw.selected_blk is not None and\ + self.tw.selected_blk.name == 'string': + for i in text: + self.tw.process_alphanumeric_input(i, -1) + self.tw.selected_blk.resize() + else: + self.tw.process_data(data_from_string(text), + self.tw.paste_offset) + self.tw.paste_offset += 20 + + def _window_event(self, event, data): + ''' Callback for resize event. ''' + data_file = open('.turtleartrc', 'w') + data_file.write(str(data.x) + '\n') + data_file.write(str(data.y) + '\n') + data_file.write(str(data.width) + '\n') + data_file.write(str(data.height) + '\n') + + def destroy(self, event, data=None): + ''' Callback for destroy event. ''' + gtk.main_quit() + + def nick_changed(self, nick): + ''' TODO: Rename default turtle in dictionary ''' + pass + + def color_changed(self, colors): + ''' Reskin turtle with collaboration colors ''' + turtle = self.tw.turtles.get_turtle(self.tw.default_turtle_name) + try: + turtle.colors = colors.split(',') + except: + turtle.colors = DEFAULT_TURTLE_COLORS + turtle.custom_shapes = True # Force regeneration of shapes + turtle.reset_shapes() + turtle.show() + + def _get_execution_dir(self): + ''' From whence is the program being executed? ''' + dirname = os.path.dirname(__file__) + if dirname == '': + if os.path.exists(os.path.join('~', 'Activities', + 'TurtleArt.activity')): + return os.path.join('~', 'Activities', 'TurtleArt.activity') + elif os.path.exists(self._INSTALL_PATH): + return self._INSTALL_PATH + elif os.path.exists(self._ALTERNATIVE_INSTALL_PATH): + return self._ALTERNATIVE_INSTALL_PATH + else: + return os.path.abspath('.') + else: + return os.path.abspath(dirname) + + +if __name__ == '__main__': + TurtleMain() diff --git a/challenges/amazonas-1.svg b/challenges/amazonas-1.svg new file mode 100644 index 0000000..85f443e --- /dev/null +++ b/challenges/amazonas-1.svg @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,133.17736,19.304487)" + id="g3994"> + <path + d="m 16.965852,144.30017 0,-43.75725" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 16.987605,45.050682 0,14.58563" + id="path2995-3-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-85.85524" + y="20.616865" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-85.85524" + y="20.616865" + id="tspan4235-7" + style="font-size:10px">110</tspan></text> + </g> +</svg> diff --git a/challenges/amazonas-10.svg b/challenges/amazonas-10.svg new file mode 100644 index 0000000..1739638 --- /dev/null +++ b/challenges/amazonas-10.svg @@ -0,0 +1,411 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4131" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4133" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-69" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-96" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-87" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-40" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4285" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4287" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="M 3.1842866,103.10283 98.288312,47.696243 193.39234,102.89054 97.439169,158.29713 z" + id="path5489" + style="fill:#7f7f7f;fill-opacity:1;stroke:#7f7f7f;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + id="g4083"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,226.35918,76.594049)" + id="g3994"> + <path + d="m 16.965852,144.30017 0,-43.75725" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 16.987605,45.050682 0,14.58563" + id="path2995-3-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-85.85524" + y="20.616865" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-85.85524" + y="20.616865" + id="tspan4235-7" + style="font-size:10px">110</tspan></text> + </g> + <path + d="M 28.021722,103.5274 98.500598,62.131676 168.97947,103.5274 98.076026,144.28627 z" + id="path6119" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <g + transform="matrix(0.5,0,0,0.5,48.975654,51.68773)" + id="g4083-1" + style="stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <path + d="M 52.2223,103.5274 98.288312,76.354822 145.62804,103.31512 97.651455,130.48769 z" + id="path6121" + style="fill:#7f7f7f;fill-opacity:1;stroke:none" /> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,-28.552651,25.23772)" + id="g3994-8"> + <path + d="m 146.16597,-108.12177 0,14.585629" + id="path2995-3-1-8" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="74.397118" + y="150.22018" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3-5" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="74.397118" + y="150.22018" + id="tspan4235-7-8" + style="font-size:10px">55</tspan></text> + <path + d="m 146.32105,-52.352642 0,-14.585631" + id="path2995-3-1-8-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + <g + transform="matrix(0.74289795,0,0,0.74289795,25.183482,26.578043)" + id="g4083-1-1" + style="stroke-width:6.73039961;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0-9" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2-3" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7-0" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4-9" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(30.255316,19.03157)" + id="g4321"> + <path + d="M 92.428426,57.769579 79.796901,65.062393" + id="path2995-3-1-8-3" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="4.121335" + y="99.936424" + transform="matrix(0.8660254,-0.5,0.5,0.8660254,0,0)" + id="text4233-3-5-7" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="4.121335" + y="99.936424" + id="tspan4235-7-8-7" + style="font-size:10px">77.5</tspan></text> + <path + d="M 22.004987,98.720153 34.636514,91.427337" + id="path2995-3-1-8-1-7" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> +</svg> diff --git a/challenges/amazonas-11.svg b/challenges/amazonas-11.svg new file mode 100644 index 0000000..a36058c --- /dev/null +++ b/challenges/amazonas-11.svg @@ -0,0 +1,184 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="600" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <g + transform="translate(0.54624033,-0.8754605)" + id="g3003"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,141.92967,23.204117)" + id="g3994"> + <path + d="m 16.965852,144.30017 0,-43.75725" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 16.987605,45.050682 0,14.58563" + id="path2995-3-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-85.85524" + y="20.616865" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-85.85524" + y="20.616865" + id="tspan4235-7" + style="font-size:10px">110</tspan></text> + </g> + <g + transform="translate(192.45868,-0.8754605)" + id="g3003-9"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-45" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-3" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-0" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(384.37068,-0.8754605)" + id="g3003-4"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-2" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> +</svg> diff --git a/challenges/amazonas-12.svg b/challenges/amazonas-12.svg new file mode 100644 index 0000000..bd79359 --- /dev/null +++ b/challenges/amazonas-12.svg @@ -0,0 +1,483 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="600" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-87" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-69" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-96" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4131" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4133" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-0" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-16" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <g + transform="translate(0.54624033,-0.8754605)" + id="g3003"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,135.92967,21.204117)" + id="g3994"> + <path + d="m 16.965852,144.30017 0,-43.75725" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 16.987605,45.050682 0,14.58563" + id="path2995-3-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-85.85524" + y="20.616865" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-85.85524" + y="20.616865" + id="tspan4235-7" + style="font-size:10px">110</tspan></text> + </g> + <g + transform="translate(192.45868,-0.8754605)" + id="g3003-9"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-45" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-3" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-0" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(384.37068,-0.8754605)" + id="g3003-4"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-2" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(217.00814,135.42497)" + id="g3547-0"> + <path + d="m -166.48859,-33.26589 47.72799,-27.33268" + id="path2993-0-8" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -70.5326,-33.26589 -47.728,-27.33268" + id="path2993-9-2-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -166.48859,-32.58405 47.72799,27.33268" + id="path2993-5-7-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -70.5326,-32.58405 -47.728,27.33268" + id="path2993-9-4-4-6" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(408.92058,135.42497)" + id="g3547-0-0"> + <path + d="m -166.48859,-33.26589 47.72799,-27.33268" + id="path2993-0-8-0" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -70.5326,-33.26589 -47.728,-27.33268" + id="path2993-9-2-5-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -166.48859,-32.58405 47.72799,27.33268" + id="path2993-5-7-9-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -70.5326,-32.58405 -47.728,27.33268" + id="path2993-9-4-4-6-6" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(600.83258,135.42497)" + id="g3547-0-3"> + <path + d="m -166.48859,-33.26589 47.72799,-27.33268" + id="path2993-0-8-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -70.5326,-33.26589 -47.728,-27.33268" + id="path2993-9-2-5-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -166.48859,-32.58405 47.72799,27.33268" + id="path2993-5-7-9-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -70.5326,-32.58405 -47.728,27.33268" + id="path2993-9-4-4-6-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(173.8,109.4)" + id="g3628"> + <path + d="m -63.899696,-27.804392 -12.631525,7.292814" + id="path2995-3-1-8" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-75.161217" + y="-51.974945" + transform="matrix(0.8660254,-0.5,0.5,0.8660254,0,0)" + id="text4233-3-5" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-75.161217" + y="-51.974945" + id="tspan4235-7-8" + style="font-size:10px">55</tspan></text> + <path + d="M -112.11964,0.21447485 -99.48811,-7.0783406" + id="path2995-3-1-8-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> +</svg> diff --git a/challenges/amazonas-13.svg b/challenges/amazonas-13.svg new file mode 100644 index 0000000..562c399 --- /dev/null +++ b/challenges/amazonas-13.svg @@ -0,0 +1,256 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="600" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <g + transform="translate(0.54624033,-0.8754605)" + id="g3003"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,136.79609,19.995628)" + id="g3994"> + <path + d="m 16.965852,144.30017 0,-43.75725" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 16.987605,45.050682 0,14.58563" + id="path2995-3-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-85.85524" + y="20.616865" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-85.85524" + y="20.616865" + id="tspan4235-7" + style="font-size:10px">110</tspan></text> + </g> + <g + transform="translate(192.45868,-0.8754605)" + id="g3003-9"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-45" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-3" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-0" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(384.37068,-0.8754605)" + id="g3003-4"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-2" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <path + d="m 52.619212,101.68667 45.560537,-27.593002 46.843931,28.234702 -46.843931,27.593 z" + id="path3728" + style="fill:#7f7f7f;fill-opacity:1;stroke:none" /> + <g + transform="translate(217.00814,135.42497)" + id="g3547-0"> + <path + d="m -166.48859,-33.26589 47.72799,-27.33268" + id="path2993-0-8" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -70.5326,-33.26589 -47.728,-27.33268" + id="path2993-9-2-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -166.48859,-32.58405 47.72799,27.33268" + id="path2993-5-7-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -70.5326,-32.58405 -47.728,27.33268" + id="path2993-9-4-4-6" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <path + d="m 244.20775,102.17915 45.56054,-27.592998 46.84393,28.234698 -46.84393,27.593 z" + id="path3728-2" + style="fill:#7f7f7f;fill-opacity:1;stroke:none" /> + <g + transform="translate(408.92058,135.42497)" + id="g3547-0-5"> + <path + d="m -166.48859,-33.26589 47.72799,-27.33268" + id="path2993-0-8-0" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -70.5326,-33.26589 -47.728,-27.33268" + id="path2993-9-2-5-0" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -166.48859,-32.58405 47.72799,27.33268" + id="path2993-5-7-9-7" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -70.5326,-32.58405 -47.728,27.33268" + id="path2993-9-4-4-6-7" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <path + d="m 436.11975,102.17915 45.56053,-27.592999 46.84394,28.234699 -46.84394,27.593 z" + id="path3728-29" + style="fill:#7f7f7f;fill-opacity:1;stroke:none" /> + <g + transform="translate(600.83258,135.42497)" + id="g3547-0-0"> + <path + d="m -166.48859,-33.26589 47.72799,-27.33268" + id="path2993-0-8-7" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -70.5326,-33.26589 -47.728,-27.33268" + id="path2993-9-2-5-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -166.48859,-32.58405 47.72799,27.33268" + id="path2993-5-7-9-2" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -70.5326,-32.58405 -47.728,27.33268" + id="path2993-9-4-4-6-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> +</svg> diff --git a/challenges/amazonas-14.svg b/challenges/amazonas-14.svg new file mode 100644 index 0000000..b50d5ad --- /dev/null +++ b/challenges/amazonas-14.svg @@ -0,0 +1,656 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="600" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4285" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4287" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-40" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-87" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-69" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-96" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4131" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4133" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-31" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-07" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-0" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4909" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4911" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4913" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4915" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4917" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4919" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <g + transform="translate(0.54624033,-0.8754605)" + id="g3003"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,225.58043,75.710049)" + id="g3994"> + <path + d="m 16.965852,144.30017 0,-43.75725" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 16.987605,45.050682 0,14.58563" + id="path2995-3-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-85.85524" + y="20.616865" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-85.85524" + y="20.616865" + id="tspan4235-7" + style="font-size:10px">110</tspan></text> + </g> + <g + transform="translate(192.45868,-0.8754605)" + id="g3003-9"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-45" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-3" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-0" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(384.37068,-0.8754605)" + id="g3003-4"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-2" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(656.91244,194.08649)" + id="g5025"> + <g + transform="matrix(0.5,0,0,0.5,-223.56611,-143.27422)" + id="g4083-1" + style="stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.74289795,0,0,0.74289795,-247.35828,-168.38391)" + id="g4083-1-1" + style="stroke-width:6.73039961;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0-9" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2-3" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7-0" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4-9" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + </g> + <g + transform="translate(465.00044,194.08649)" + id="g4875-2"> + <g + transform="matrix(0.5,0,0,0.5,-223.56611,-143.27422)" + id="g4083-1-0" + style="stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0-7" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2-4" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7-1" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4-3" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,-301.09441,-169.72423)" + id="g3994-8-8"> + <path + d="m 146.16597,-108.12177 0,14.585629" + id="path2995-3-1-8-37" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="74.397118" + y="150.22018" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3-5-0" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="74.397118" + y="150.22018" + id="tspan4235-7-8-9" + style="font-size:10px">55</tspan></text> + <path + d="m 146.32105,-52.352642 0,-14.585631" + id="path2995-3-1-8-1-73" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + <g + transform="matrix(0.74289795,0,0,0.74289795,-247.35828,-168.38391)" + id="g4083-1-1-9" + style="stroke-width:6.73039961;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0-9-8" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2-3-5" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7-0-4" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4-9-6" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(-242.28644,-175.93038)" + id="g4321-7"> + <path + d="M 92.428426,57.769579 79.796901,65.062393" + id="path2995-3-1-8-3-2" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="4.121335" + y="99.936424" + transform="matrix(0.8660254,-0.5,0.5,0.8660254,0,0)" + id="text4233-3-5-7-9" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="4.121335" + y="99.936424" + id="tspan4235-7-8-7-4" + style="font-size:10px">77.5</tspan></text> + <path + d="M 22.004987,98.720153 34.636514,91.427337" + id="path2995-3-1-8-1-7-4" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + </g> + <g + transform="translate(273.088,194.08649)" + id="g5025-9"> + <g + transform="matrix(0.5,0,0,0.5,-223.56611,-143.27422)" + id="g4083-1-9" + style="stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0-4" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2-5" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7-10" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4-2" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.74289795,0,0,0.74289795,-247.35828,-168.38391)" + id="g4083-1-1-7" + style="stroke-width:6.73039961;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0-9-80" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2-3-9" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7-0-2" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4-9-5" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + </g> +</svg> diff --git a/challenges/amazonas-15.svg b/challenges/amazonas-15.svg new file mode 100644 index 0000000..838c9a8 --- /dev/null +++ b/challenges/amazonas-15.svg @@ -0,0 +1,864 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="600" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4285" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4287" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-40" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-87" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-69" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-96" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4131" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4133" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-66" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4285-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4287-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-8-0" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-40-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-87-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-69-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-96-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4131-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4133-6" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5-0" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-44" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-53" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-0" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-6" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-62" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-6" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <g + transform="translate(0.54624033,-0.8754605)" + id="g3003"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,226.3516,75.641452)" + id="g3994"> + <path + d="m 16.965852,144.30017 0,-43.75725" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 16.987605,45.050682 0,14.58563" + id="path2995-3-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-85.85524" + y="20.616865" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-85.85524" + y="20.616865" + id="tspan4235-7" + style="font-size:10px">110</tspan></text> + </g> + <g + transform="translate(192.45868,-0.8754605)" + id="g3003-9"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-45" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-3" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-0" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(384.37068,-0.8754605)" + id="g3003-4"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-2" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <path + d="m 244.46869,102.43966 46.70287,-27.59716 46.70287,27.80944 -47.33972,27.59715 z" + id="path4173" + style="fill:#7f7f7f;fill-opacity:1;stroke:none" /> + <g + transform="matrix(0.5,0,0,0.5,241.43433,50.81227)" + id="g4083-1" + style="stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.74289795,0,0,0.74289795,217.64216,25.70258)" + id="g4083-1-1" + style="stroke-width:6.73039961;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0-9" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2-3" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7-0" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4-9" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(-294.81171,5.7017363)" + id="g5733"> + <path + d="m 707.23048,96.407193 69.74789,-40.458739 71.98182,41.203379 -71.98182,40.706957 z" + id="path4840" + style="fill:#7f7f7f;fill-opacity:1;stroke:none" /> + <path + d="M 730.43083,96.692123 777.1337,69.094971 823.83657,96.904403 776.49684,124.50155 z" + id="path4173-2" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <g + transform="matrix(0.5,0,0,0.5,728.15804,45.110533)" + id="g4083-1-7" + style="stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0-8" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2-6" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7-2" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4-5" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.74289795,0,0,0.74289795,704.36587,20.000846)" + id="g4083-1-1-3" + style="stroke-width:6.73039961;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0-9-5" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2-3-7" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7-0-9" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4-9-7" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + </g> + <g + transform="translate(-678.63615,5.7017363)" + id="g5733-0"> + <path + d="m 707.23048,96.407193 69.74789,-40.458739 71.98182,41.203379 -71.98182,40.706957 z" + id="path4840-8" + style="fill:#7f7f7f;fill-opacity:1;stroke:none" /> + <path + d="M 730.43083,96.692123 777.1337,69.094971 823.83657,96.904403 776.49684,124.50155 z" + id="path4173-2-2" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <g + transform="matrix(0.5,0,0,0.5,728.15804,45.110533)" + id="g4083-1-7-5" + style="stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0-8-6" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2-6-2" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7-2-1" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4-5-4" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.74289795,0,0,0.74289795,704.36587,20.000846)" + id="g4083-1-1-3-0" + style="stroke-width:6.73039961;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0-9-5-1" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2-3-7-8" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7-0-9-7" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4-9-7-2" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,-29.742219,24.144679)" + id="g3994-8"> + <path + d="m 146.16597,-108.12177 0,14.585629" + id="path2995-3-1-8" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="74.397118" + y="150.22018" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3-5" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="74.397118" + y="150.22018" + id="tspan4235-7-8" + style="font-size:10px">55</tspan></text> + <path + d="m 146.32105,-52.352642 0,-14.585631" + id="path2995-3-1-8-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + <g + transform="translate(421.36663,23.378085)" + id="g4321"> + <path + d="M 92.428426,57.769579 79.796901,65.062393" + id="path2995-3-1-8-3" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="4.121335" + y="99.936424" + transform="matrix(0.8660254,-0.5,0.5,0.8660254,0,0)" + id="text4233-3-5-7" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="4.121335" + y="99.936424" + id="tspan4235-7-8-7" + style="font-size:10px">77.5</tspan></text> + <path + d="M 22.004987,98.720153 34.636514,91.427337" + id="path2995-3-1-8-1-7" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> +</svg> diff --git a/challenges/amazonas-16.svg b/challenges/amazonas-16.svg new file mode 100644 index 0000000..0dc222a --- /dev/null +++ b/challenges/amazonas-16.svg @@ -0,0 +1,307 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-55" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-84" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="m 2.5,122.5 0,-40 40,0 0,-40 40,0 0,-40 40,0 0,40 40,0 0,40 40,0 0,40 -40,0 0,40 -40,0 0,40 -40,0 0,-40 -40,0 0,-40 z" + id="path3005" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + id="g4049"> + <path + d="m 85.498883,47.573331 7.74004,0" + id="path2995" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="98.102356" + y="50.509941" + transform="scale(0.98607787,1.0141187)" + id="text4233" + xml:space="preserve" + style="font-size:39.44311523px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="98.102356" + y="50.509941" + id="tspan4235" + style="font-size:9.86077881px">40</tspan></text> + <path + d="m 120.18084,47.592547 -7.74004,0" + id="path2995-9" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> +</svg> diff --git a/challenges/amazonas-17.svg b/challenges/amazonas-17.svg new file mode 100644 index 0000000..00b1228 --- /dev/null +++ b/challenges/amazonas-17.svg @@ -0,0 +1,316 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-55" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-84" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="m 2.5,122.5 0,-40 40,0 0,-40 40,0 0,-40 40,0 0,40 40,0 0,40 40,0 0,40 -40,0 0,40 -40,0 0,40 -40,0 0,-40 -40,0 0,-40 z" + id="path3005" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + id="g4049"> + <path + d="m 85.498883,47.573331 7.74004,0" + id="path2995" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="98.102356" + y="50.509941" + transform="scale(0.98607787,1.0141187)" + id="text4233" + xml:space="preserve" + style="font-size:39.44311523px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="98.102356" + y="50.509941" + id="tspan4235" + style="font-size:9.86077881px">40</tspan></text> + <path + d="m 120.18084,47.592547 -7.74004,0" + id="path2995-9" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + <rect + width="42.5" + height="42.5" + rx="24" + ry="0" + x="81.25" + y="81.25" + id="rect4074" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/challenges/amazonas-18.svg b/challenges/amazonas-18.svg new file mode 100644 index 0000000..84ddacd --- /dev/null +++ b/challenges/amazonas-18.svg @@ -0,0 +1,316 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-55" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-84" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="m 2.5,122.5 0,-40 40,0 0,-40 40,0 0,-40 40,0 0,40 40,0 0,40 40,0 0,40 -40,0 0,40 -40,0 0,40 -40,0 0,-40 -40,0 0,-40 z" + id="path3005" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + id="g4049"> + <path + d="m 85.498883,47.573331 7.74004,0" + id="path2995" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="98.102356" + y="50.509941" + transform="scale(0.98607787,1.0141187)" + id="text4233" + xml:space="preserve" + style="font-size:39.44311523px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="98.102356" + y="50.509941" + id="tspan4235" + style="font-size:9.86077881px">40</tspan></text> + <path + d="m 120.18084,47.592547 -7.74004,0" + id="path2995-9" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + <rect + width="42.5" + height="42.5" + rx="24" + ry="0" + x="81.25" + y="81.25" + id="rect4074" + style="fill:#7f7f7f;fill-opacity:1;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/challenges/amazonas-19.svg b/challenges/amazonas-19.svg new file mode 100644 index 0000000..d77ab2e --- /dev/null +++ b/challenges/amazonas-19.svg @@ -0,0 +1,316 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-55" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-84" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="m 2.5,122.5 0,-40 40,0 0,-40 40,0 0,-40 40,0 0,40 40,0 0,40 40,0 0,40 -40,0 0,40 -40,0 0,40 -40,0 0,-40 -40,0 0,-40 z" + id="path3005" + style="fill:#7f7f7f;fill-opacity:1;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + id="g4049"> + <path + d="m 85.498883,47.573331 7.74004,0" + id="path2995" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="98.102356" + y="50.509941" + transform="scale(0.98607787,1.0141187)" + id="text4233" + xml:space="preserve" + style="font-size:39.44311523px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="98.102356" + y="50.509941" + id="tspan4235" + style="font-size:9.86077881px">40</tspan></text> + <path + d="m 120.18084,47.592547 -7.74004,0" + id="path2995-9" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + <rect + width="42.5" + height="42.5" + rx="24" + ry="0" + x="81.25" + y="81.25" + id="rect4074" + style="fill:#ffffff;fill-opacity:1;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/challenges/amazonas-2.svg b/challenges/amazonas-2.svg new file mode 100644 index 0000000..5def30e --- /dev/null +++ b/challenges/amazonas-2.svg @@ -0,0 +1,266 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 2.5,102.5 c 135.97643,-0.69024 191.5,0 191.5,0" + id="path3003" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,226.35918,76.594049)" + id="g3994"> + <path + d="m 16.965852,144.30017 0,-43.75725" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 16.987605,45.050682 0,14.58563" + id="path2995-3-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-85.85524" + y="20.616865" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-85.85524" + y="20.616865" + id="tspan4235-7" + style="font-size:10px">110</tspan></text> + </g> + <g + transform="translate(-8.3170911,74.685141)" + id="g5715"> + <g + transform="matrix(0.97234963,0,0,1,0.27715027,0)" + id="g4037"> + <path + d="m 11.522128,100.84054 72.69378,0" + id="path2995" + style="fill:none;stroke:#000000;stroke-width:1.13166273px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 208.04135,100.85782 -72.69379,0" + id="path2995-3" + style="fill:none;stroke:#000000;stroke-width:1.13166285px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Mstart)" /> + <text + x="100.58539" + y="104.48931" + id="text4233" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="100.58539" + y="104.48931" + id="tspan4235" + style="font-size:10px">194</tspan></text> + </g> + </g> +</svg> diff --git a/challenges/amazonas-20.svg b/challenges/amazonas-20.svg new file mode 100644 index 0000000..93b383b --- /dev/null +++ b/challenges/amazonas-20.svg @@ -0,0 +1,329 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="405" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-55" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-84" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="m 2.5,122.5 0,-40 40,0 0,-40 40,0 0,-40 40,0 0,40 40,0 0,40 40,0 0,40 -40,0 0,40 -40,0 0,40 -40,0 0,-40 -40,0 0,-40 z" + id="path3005" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + id="g4049"> + <path + d="m 85.498883,47.573331 7.74004,0" + id="path2995" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="98.102356" + y="50.509941" + transform="scale(0.98607787,1.0141187)" + id="text4233" + xml:space="preserve" + style="font-size:39.44311523px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="98.102356" + y="50.509941" + id="tspan4235" + style="font-size:9.86077881px">40</tspan></text> + <path + d="m 120.18084,47.592547 -7.74004,0" + id="path2995-9" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + <rect + width="42.5" + height="42.5" + rx="24" + ry="0" + x="81.25" + y="81.25" + id="rect4074" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 202.5,122.5 0,-40 40,0 0,-40 40,0 0,-40 40,0 0,40 40,0 0,40 40,0 0,40 -40,0 0,40 -40,0 0,40 -40,0 0,-40 -40,0 0,-40 z" + id="path3005-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <rect + width="42.5" + height="42.5" + rx="24" + ry="0" + x="281.25" + y="81.25" + id="rect4074-0" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/challenges/amazonas-21.svg b/challenges/amazonas-21.svg new file mode 100644 index 0000000..fbb1d64 --- /dev/null +++ b/challenges/amazonas-21.svg @@ -0,0 +1,329 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="405" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-55" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-84" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="m 202.5,122.5 -40,0 0,40 -40,0 0,40 -40,0 0,-40 -40,0 0,-40 -40,0 0,-40 40,0 0,-40 40,0 0,-40 40,0 0,40 40,0 0,40 40,0" + id="path3005" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + id="g4049"> + <path + d="m 85.498883,47.573331 7.74004,0" + id="path2995" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="98.102356" + y="50.509941" + transform="scale(0.98607787,1.0141187)" + id="text4233" + xml:space="preserve" + style="font-size:39.44311523px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="98.102356" + y="50.509941" + id="tspan4235" + style="font-size:9.86077881px">40</tspan></text> + <path + d="m 120.18084,47.592547 -7.74004,0" + id="path2995-9" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + <rect + width="42.5" + height="42.5" + rx="24" + ry="0" + x="81.25" + y="81.25" + id="rect4074" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 162.5,82.5 40,0 0,-40 40,0 0,-40 40,0 0,40 40,0 0,40 40,0 0,40 -40,0 0,40 -40,0 0,40 -40,0 0,-40 -40,0 0,-40 -40,0" + id="path3005-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <rect + width="42.5" + height="42.5" + rx="24" + ry="0" + x="241.25" + y="81.25" + id="rect4074-0" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/challenges/amazonas-22.svg b/challenges/amazonas-22.svg new file mode 100644 index 0000000..6f1aa36 --- /dev/null +++ b/challenges/amazonas-22.svg @@ -0,0 +1,316 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-55" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-84" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="m 2.5,202.5 0,-200 40,0 0,40 40,0 0,40 40,0 0,40 40,0 0,40 40,0 0,40 z" + id="path3005" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + id="g4049"> + <path + d="m 85.498883,47.573331 7.74004,0" + id="path2995" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="98.102356" + y="50.509941" + transform="scale(0.98607787,1.0141187)" + id="text4233" + xml:space="preserve" + style="font-size:39.44311523px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="98.102356" + y="50.509941" + id="tspan4235" + style="font-size:9.86077881px">40</tspan></text> + <path + d="m 120.18084,47.592547 -7.74004,0" + id="path2995-9" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + <rect + width="200.06024" + height="200.06024" + rx="0" + ry="0" + x="2.4698792" + y="2.4698792" + id="rect3030" + style="fill:none;stroke:#7f7f7f;stroke-width:4.93975925;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/challenges/amazonas-23.svg b/challenges/amazonas-23.svg new file mode 100644 index 0000000..159372d --- /dev/null +++ b/challenges/amazonas-23.svg @@ -0,0 +1,453 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-55" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-84" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-54" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4046" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4048" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-48" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4090" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4092" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-31" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4138" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4140" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="m 3.1060653,201.89394 0,-198.7878769 198.7878647,0 0,198.7878769 z" + id="path4000" + style="fill:none;stroke:#7f7f7f;stroke-width:6.21212149;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 29.42,175.58 0,-146.16 146.16,0 0,146.16 z" + id="path4000-3" + style="fill:none;stroke:#7f7f7f;stroke-width:6.09000015;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 54.382351,150.61765 0,-96.235299 96.235299,0 0,96.235299 z" + id="path4000-2" + style="fill:none;stroke:#7f7f7f;stroke-width:6.01470566;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 79.277779,125.72222 0,-46.444441 46.444441,0 0,46.444441 z" + id="path4000-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5.80555534;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + transform="matrix(1.1846986,0,0,1.2024474,-227.84119,-42.479606)" + id="g4049-9"> + <path + d="m 241.2406,89.573331 7.74004,0" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="273.16318" + y="91.925209" + transform="scale(0.98607787,1.0141187)" + id="text4233-4" + xml:space="preserve" + style="font-size:39.44311523px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="273.16318" + y="91.925209" + id="tspan4235-6" + style="font-size:9.86077881px">100</tspan></text> + <path + d="m 316.43912,89.592547 -7.74004,0" + id="path2995-9-5" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + <path + d="m 31.872581,40.372618 9.169615,0" + id="path2995-0-8" + style="fill:none;stroke:#000000;stroke-width:1.19353998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="93.353088" + y="43.811108" + transform="scale(0.97877325,1.0216871)" + id="text4233-4-0" + xml:space="preserve" + style="font-size:47.07693863px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="93.353088" + y="43.811108" + id="tspan4235-6-6" + style="font-size:11.76923466px">150</tspan></text> + <path + d="m 172.96016,40.395724 -9.16961,0" + id="path2995-9-5-1" + style="fill:none;stroke:#000000;stroke-width:1.19353998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 7.65881,14.465983 9.16961,0" + id="path2995-0-8-0" + style="fill:none;stroke:#000000;stroke-width:1.19353998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="93.445038" + y="18.454386" + transform="scale(0.97877325,1.0216871)" + id="text4233-4-0-3" + xml:space="preserve" + style="font-size:47.07693863px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="93.445038" + y="18.454386" + id="tspan4235-6-6-0" + style="font-size:11.76923466px">200</tspan></text> + <path + d="m 196.74638,14.489089 -9.16961,0" + id="path2995-9-5-1-4" + style="fill:none;stroke:#000000;stroke-width:1.19353998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <g + transform="matrix(1.1846986,0,0,1.2024474,-227.84119,-18.872772)" + id="g4049"> + <path + d="m 261.49888,89.573331 7.74004,0" + id="path2995" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="276.58725" + y="91.925209" + transform="scale(0.98607787,1.0141187)" + id="text4233" + xml:space="preserve" + style="font-size:39.44311523px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="276.58725" + y="91.925209" + id="tspan4235" + style="font-size:9.86077881px">50</tspan></text> + <path + d="m 296.18084,89.592547 -7.74004,0" + id="path2995-9" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> +</svg> diff --git a/challenges/amazonas-24.svg b/challenges/amazonas-24.svg new file mode 100644 index 0000000..8cc533b --- /dev/null +++ b/challenges/amazonas-24.svg @@ -0,0 +1,453 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-55" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-84" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-54" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4046" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4048" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-48" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4090" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4092" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-31" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4138" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4140" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="m 3.1060653,201.89394 0,-198.7878769 198.7878647,0 0,198.7878769 z" + id="path4000" + style="fill:none;stroke:#7f7f7f;stroke-width:6.21212149;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 29.42,175.58 0,-146.16 146.16,0 0,146.16 z" + id="path4000-3" + style="fill:#7f7f7f;fill-opacity:1;stroke:#7f7f7f;stroke-width:6.09000015;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 54.382351,150.61765 0,-96.235299 96.235299,0 0,96.235299 z" + id="path4000-2" + style="fill:#ffffff;fill-opacity:1;stroke:#7f7f7f;stroke-width:6.01470566;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 79.277779,125.72222 0,-46.444441 46.444441,0 0,46.444441 z" + id="path4000-4" + style="fill:#7f7f7f;fill-opacity:1;stroke:#7f7f7f;stroke-width:5.80555534;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + transform="matrix(1.1846986,0,0,1.2024474,-227.84119,-42.479606)" + id="g4049-9"> + <path + d="m 241.2406,89.573331 7.74004,0" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="273.16318" + y="91.925209" + transform="scale(0.98607787,1.0141187)" + id="text4233-4" + xml:space="preserve" + style="font-size:39.44311523px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="273.16318" + y="91.925209" + id="tspan4235-6" + style="font-size:9.86077881px">100</tspan></text> + <path + d="m 316.43912,89.592547 -7.74004,0" + id="path2995-9-5" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + <path + d="m 31.872581,40.372618 9.169615,0" + id="path2995-0-8" + style="fill:none;stroke:#000000;stroke-width:1.19353998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="93.353088" + y="43.811108" + transform="scale(0.97877325,1.0216871)" + id="text4233-4-0" + xml:space="preserve" + style="font-size:47.07693863px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="93.353088" + y="43.811108" + id="tspan4235-6-6" + style="font-size:11.76923466px">150</tspan></text> + <path + d="m 172.96016,40.395724 -9.16961,0" + id="path2995-9-5-1" + style="fill:none;stroke:#000000;stroke-width:1.19353998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 7.65881,14.465983 9.16961,0" + id="path2995-0-8-0" + style="fill:none;stroke:#000000;stroke-width:1.19353998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="93.445038" + y="18.454386" + transform="scale(0.97877325,1.0216871)" + id="text4233-4-0-3" + xml:space="preserve" + style="font-size:47.07693863px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="93.445038" + y="18.454386" + id="tspan4235-6-6-0" + style="font-size:11.76923466px">200</tspan></text> + <path + d="m 196.74638,14.489089 -9.16961,0" + id="path2995-9-5-1-4" + style="fill:none;stroke:#000000;stroke-width:1.19353998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <g + transform="matrix(1.1846986,0,0,1.2024474,-227.84119,-18.872772)" + id="g4049"> + <path + d="m 261.49888,89.573331 7.74004,0" + id="path2995" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="276.58725" + y="91.925209" + transform="scale(0.98607787,1.0141187)" + id="text4233" + xml:space="preserve" + style="font-size:39.44311523px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="276.58725" + y="91.925209" + id="tspan4235" + style="font-size:9.86077881px">50</tspan></text> + <path + d="m 296.18084,89.592547 -7.74004,0" + id="path2995-9" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> +</svg> diff --git a/challenges/amazonas-25.svg b/challenges/amazonas-25.svg new file mode 100644 index 0000000..1b0ce8b --- /dev/null +++ b/challenges/amazonas-25.svg @@ -0,0 +1,453 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-55" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-84" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-54" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4046" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4048" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-48" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4090" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4092" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-31" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4138" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4140" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="m 3.1060653,201.89394 0,-198.7878769 198.7878647,0 0,198.7878769 z" + id="path4000" + style="fill:#7f7f7f;fill-opacity:1;stroke:#7f7f7f;stroke-width:6.21212149;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 29.42,175.58 0,-146.16 146.16,0 0,146.16 z" + id="path4000-3" + style="fill:#ffffff;fill-opacity:1;stroke:#7f7f7f;stroke-width:6.09000015;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 54.382351,150.61765 0,-96.235299 96.235299,0 0,96.235299 z" + id="path4000-2" + style="fill:#7f7f7f;fill-opacity:1;stroke:#7f7f7f;stroke-width:6.01470566;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 79.277779,125.72222 0,-46.444441 46.444441,0 0,46.444441 z" + id="path4000-4" + style="fill:#ffffff;fill-opacity:1;stroke:#7f7f7f;stroke-width:5.80555534;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + transform="matrix(1.1846986,0,0,1.2024474,-227.84119,-42.479606)" + id="g4049-9"> + <path + d="m 241.2406,89.573331 7.74004,0" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="273.16318" + y="91.925209" + transform="scale(0.98607787,1.0141187)" + id="text4233-4" + xml:space="preserve" + style="font-size:39.44311523px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="273.16318" + y="91.925209" + id="tspan4235-6" + style="font-size:9.86077881px">100</tspan></text> + <path + d="m 316.43912,89.592547 -7.74004,0" + id="path2995-9-5" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + <path + d="m 31.872581,40.372618 9.169615,0" + id="path2995-0-8" + style="fill:none;stroke:#000000;stroke-width:1.19353998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="93.353088" + y="43.811108" + transform="scale(0.97877325,1.0216871)" + id="text4233-4-0" + xml:space="preserve" + style="font-size:47.07693863px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="93.353088" + y="43.811108" + id="tspan4235-6-6" + style="font-size:11.76923466px">150</tspan></text> + <path + d="m 172.96016,40.395724 -9.16961,0" + id="path2995-9-5-1" + style="fill:none;stroke:#000000;stroke-width:1.19353998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 7.65881,14.465983 9.16961,0" + id="path2995-0-8-0" + style="fill:none;stroke:#000000;stroke-width:1.19353998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="93.445038" + y="18.454386" + transform="scale(0.97877325,1.0216871)" + id="text4233-4-0-3" + xml:space="preserve" + style="font-size:47.07693863px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="93.445038" + y="18.454386" + id="tspan4235-6-6-0" + style="font-size:11.76923466px">200</tspan></text> + <path + d="m 196.74638,14.489089 -9.16961,0" + id="path2995-9-5-1-4" + style="fill:none;stroke:#000000;stroke-width:1.19353998;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <g + transform="matrix(1.1846986,0,0,1.2024474,-227.84119,-18.872772)" + id="g4049"> + <path + d="m 261.49888,89.573331 7.74004,0" + id="path2995" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="276.58725" + y="91.925209" + transform="scale(0.98607787,1.0141187)" + id="text4233" + xml:space="preserve" + style="font-size:39.44311523px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="276.58725" + y="91.925209" + id="tspan4235" + style="font-size:9.86077881px">50</tspan></text> + <path + d="m 296.18084,89.592547 -7.74004,0" + id="path2995-9" + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> +</svg> diff --git a/challenges/amazonas-26.svg b/challenges/amazonas-26.svg new file mode 100644 index 0000000..cb6dc24 --- /dev/null +++ b/challenges/amazonas-26.svg @@ -0,0 +1,361 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-55" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-84" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-54" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4046" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4048" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-48" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4090" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4092" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-31" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4138" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4140" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="m 2.5,202.5 0,-200 173,0 0,173 0,0 -120.5,0 0,-123 70.5,0 0,73 -23,0 0,-43 -23,0 0,67 73,0 0,-120 -123,0 0,173 -27,0" + id="path3990" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 202.5,2.5 0,200 -173,0 0,-173 0,0 123,0 0,120 -73.000002,0 0,-67.500001 23.000002,0 0,43.000001 23,0 0,-72.5 -70.5,0 0,123 120.5,0 0,-173 27,0" + id="path3990-7" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/challenges/amazonas-27.svg b/challenges/amazonas-27.svg new file mode 100644 index 0000000..6b13c09 --- /dev/null +++ b/challenges/amazonas-27.svg @@ -0,0 +1,361 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-55" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-84" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-54" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4046" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4048" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-48" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4090" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4092" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-31" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4138" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4140" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="m 2.5,202.5 0,-200 173,0 0,173 0,0 -120.5,0 0,-123 70.5,0 0,73 -23,0 0,-43 -23,0 0,67 73,0 0,-120 -123,0 0,173 -27,0" + id="path3990" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 202.5,2.5 0,200 -173,0 0,-173 0,0 123,0 0,120 -73.000002,0 0,-67.500001 23.000002,0 0,43.000001 23,0 0,-72.5 -70.5,0 0,123 120.5,0 0,-173 27,0" + id="path3990-7" + style="fill:#7f7f7f;fill-opacity:1;stroke:#7f7f7f;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/challenges/amazonas-28.svg b/challenges/amazonas-28.svg new file mode 100644 index 0000000..15916ab --- /dev/null +++ b/challenges/amazonas-28.svg @@ -0,0 +1,369 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="405" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7-2" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-55" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-5" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-84" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-54" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4046" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4048" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-48" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-3" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4090" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4092" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-31" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4138" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4140" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="m 2.5,202.5 0,-200 173,0 0,173 0,0 -120.5,0 0,-123 70.5,0 0,73 -23,0 0,-43 -23,0 0,67 73,0 0,-120 -123,0 0,173 -27,0" + id="path3990" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 202.5,102.5 0,100 -173,0 0,-173 0,0 123,0 0,120 -73.000002,0 0,-67.500001 23.000002,0 0,43.000001 23,0 0,-72.5 -70.5,0 0,123 120.5,0 0,-173 27,0" + id="path3990-7" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 402.49999,202.5 -199.99999,0 0,-173 173,0 0,0 0,120.5 -123,0 0,-70.500001 73,0 0,23.000001 -43,0 0,23 67,0 0,-73.000001 -120,0 0,123.000001 172.99999,0 0,27" + id="path3990-1" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 202.5,2.5404056 200,0 0,173.0000044 -173,0 0,0 0,-123.000005 120,0 0,73.000015 -67.5,0 0,-23.00001 43,0 0,-23.000001 -72.5,0 0,70.500001 123,0 0,-120.500004 -173,0" + id="path3990-7-8" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/challenges/amazonas-3.svg b/challenges/amazonas-3.svg new file mode 100644 index 0000000..1559e1b --- /dev/null +++ b/challenges/amazonas-3.svg @@ -0,0 +1,270 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 2.5,102.5 c 135.97643,-0.69024 191.5,0 191.5,0" + id="path3003" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,226.35918,76.594049)" + id="g3994"> + <path + d="m 16.965852,144.30017 0,-43.75725" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 16.987605,45.050682 0,14.58563" + id="path2995-3-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-85.85524" + y="20.616865" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-85.85524" + y="20.616865" + id="tspan4235-7" + style="font-size:10px">110</tspan></text> + </g> + <g + transform="translate(-8.3170911,74.685141)" + id="g5715"> + <g + transform="matrix(0.97234963,0,0,1,0.27715027,0)" + id="g4037"> + <path + d="m 11.522128,100.84054 72.69378,0" + id="path2995" + style="fill:none;stroke:#000000;stroke-width:1.13166273px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 208.04135,100.85782 -72.69379,0" + id="path2995-3" + style="fill:none;stroke:#000000;stroke-width:1.13166285px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#Arrow2Mstart)" /> + <text + x="100.58539" + y="104.48931" + id="text4233" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="100.58539" + y="104.48931" + id="tspan4235" + style="font-size:10px">194</tspan></text> + </g> + </g> + <path + d="m 98.5,49.69697 c 0,93.18182 0,109.05303 0,109.05303" + id="path4062" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/challenges/amazonas-4.svg b/challenges/amazonas-4.svg new file mode 100644 index 0000000..ac65335 --- /dev/null +++ b/challenges/amazonas-4.svg @@ -0,0 +1,331 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4131" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4133" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-69" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-96" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-87" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <g + id="g4083"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,226.35918,76.594049)" + id="g3994"> + <path + d="m 16.965852,144.30017 0,-43.75725" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 16.987605,45.050682 0,14.58563" + id="path2995-3-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-85.85524" + y="20.616865" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-85.85524" + y="20.616865" + id="tspan4235-7" + style="font-size:10px">110</tspan></text> + </g> + <g + transform="matrix(0.5,0,0,0.5,48.975654,51.68773)" + id="g4083-1" + style="stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,-14.156977,35.973477)" + id="g3994-8"> + <path + d="m 146.16597,-108.12177 0,14.585629" + id="path2995-3-1-8" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="74.397118" + y="150.22018" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3-5" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="74.397118" + y="150.22018" + id="tspan4235-7-8" + style="font-size:10px">55</tspan></text> + <path + d="m 146.32105,-52.352642 0,-14.585631" + id="path2995-3-1-8-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> +</svg> diff --git a/challenges/amazonas-5.svg b/challenges/amazonas-5.svg new file mode 100644 index 0000000..68c9d86 --- /dev/null +++ b/challenges/amazonas-5.svg @@ -0,0 +1,342 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4131" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4133" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-69" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-96" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-87" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-40" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4285" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4287" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <g + id="g4083"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,226.35918,76.594049)" + id="g3994"> + <path + d="m 16.965852,144.30017 0,-43.75725" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 16.987605,45.050682 0,14.58563" + id="path2995-3-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-85.85524" + y="20.616865" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-85.85524" + y="20.616865" + id="tspan4235-7" + style="font-size:10px">110</tspan></text> + </g> + <path + d="M 145.9293,103.71638 98.201307,131.04906 M 49.973312,103.71638 97.701307,131.04906 M 145.9293,103.03454 98.201307,75.701861 M 49.973312,103.03454 97.701307,75.701861" + id="path2993-9-4-4" + style="fill:#7f7f7f;fill-opacity:1;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 51.842818,103.50491 97.357404,76.73162 145.54932,103.99169 98.817765,131.00837 53.059785,104.23509" + id="path3974" + style="fill:#7f7f7f;fill-opacity:1;stroke:none" /> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,-13.462253,37.164002)" + id="g3994-8"> + <path + d="m 146.16597,-108.12177 0,14.585629" + id="path2995-3-1-8" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="74.397118" + y="150.22018" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3-5" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="74.397118" + y="150.22018" + id="tspan4235-7-8" + style="font-size:10px">55</tspan></text> + <path + d="m 146.32105,-52.352642 0,-14.585631" + id="path2995-3-1-8-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> +</svg> diff --git a/challenges/amazonas-6.svg b/challenges/amazonas-6.svg new file mode 100644 index 0000000..ffb2437 --- /dev/null +++ b/challenges/amazonas-6.svg @@ -0,0 +1,346 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4131" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4133" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-69" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-96" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-87" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-40" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4285" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4287" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <g + id="g4083"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <path + d="M 2.9720008,103.31512 98.076026,48.969958 193.18005,103.73969 97.651455,158.08484 z" + id="path3264" + style="fill:#7f7f7f;fill-opacity:1;stroke:none" /> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,226.35918,76.594049)" + id="g3994"> + <path + d="m 16.965852,144.30017 0,-43.75725" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 16.987605,45.050682 0,14.58563" + id="path2995-3-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-85.85524" + y="20.616865" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-85.85524" + y="20.616865" + id="tspan4235-7" + style="font-size:10px">110</tspan></text> + </g> + <path + d="M 145.9293,103.71638 98.201307,131.04906 M 49.973312,103.71638 97.701307,131.04906 M 145.9293,103.03454 98.201307,75.701861 M 49.973312,103.03454 97.701307,75.701861" + id="path2993-9-4-4" + style="fill:#7f7f7f;fill-opacity:1;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 51.842818,103.50491 97.357404,76.73162 145.54932,103.99169 98.817765,131.00837 53.059785,104.23509" + id="path3974" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,-13.462253,37.164002)" + id="g3994-8"> + <path + d="m 146.16597,-108.12177 0,14.585629" + id="path2995-3-1-8" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="74.397118" + y="150.22018" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3-5" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="74.397118" + y="150.22018" + id="tspan4235-7-8" + style="font-size:10px">55</tspan></text> + <path + d="m 146.32105,-52.352642 0,-14.585631" + id="path2995-3-1-8-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> +</svg> diff --git a/challenges/amazonas-7.svg b/challenges/amazonas-7.svg new file mode 100644 index 0000000..74dda19 --- /dev/null +++ b/challenges/amazonas-7.svg @@ -0,0 +1,399 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4131" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4133" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-69" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-96" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-87" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-40" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4285" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4287" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <g + id="g4083"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,226.35918,76.594049)" + id="g3994"> + <path + d="m 16.965852,144.30017 0,-43.75725" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 16.987605,45.050682 0,14.58563" + id="path2995-3-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-85.85524" + y="20.616865" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-85.85524" + y="20.616865" + id="tspan4235-7" + style="font-size:10px">110</tspan></text> + </g> + <g + transform="matrix(0.5,0,0,0.5,48.975654,51.68773)" + id="g4083-1" + style="stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,-28.552651,25.23772)" + id="g3994-8"> + <path + d="m 146.16597,-108.12177 0,14.585629" + id="path2995-3-1-8" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="74.397118" + y="150.22018" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3-5" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="74.397118" + y="150.22018" + id="tspan4235-7-8" + style="font-size:10px">55</tspan></text> + <path + d="m 146.32105,-52.352642 0,-14.585631" + id="path2995-3-1-8-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + <g + transform="matrix(0.74289795,0,0,0.74289795,25.183482,26.578043)" + id="g4083-1-1" + style="stroke-width:6.73039961;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0-9" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2-3" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7-0" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4-9" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(30.255316,19.03157)" + id="g4321"> + <path + d="M 92.428426,57.769579 79.796901,65.062393" + id="path2995-3-1-8-3" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="4.121335" + y="99.936424" + transform="matrix(0.8660254,-0.5,0.5,0.8660254,0,0)" + id="text4233-3-5-7" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="4.121335" + y="99.936424" + id="tspan4235-7-8-7" + style="font-size:10px">77.5</tspan></text> + <path + d="M 22.004987,98.720153 34.636514,91.427337" + id="path2995-3-1-8-1-7" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> +</svg> diff --git a/challenges/amazonas-8.svg b/challenges/amazonas-8.svg new file mode 100644 index 0000000..e484d1b --- /dev/null +++ b/challenges/amazonas-8.svg @@ -0,0 +1,403 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4131" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4133" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-69" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-96" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-87" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-40" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4285" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4287" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="M 52.010014,103.31512 98.712884,75.717965 145.41575,103.5274 98.076026,131.12455 z" + id="path4173" + style="fill:#7f7f7f;fill-opacity:1;stroke:none" /> + <g + id="g4083"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,226.35918,76.594049)" + id="g3994"> + <path + d="m 16.965852,144.30017 0,-43.75725" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 16.987605,45.050682 0,14.58563" + id="path2995-3-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-85.85524" + y="20.616865" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-85.85524" + y="20.616865" + id="tspan4235-7" + style="font-size:10px">110</tspan></text> + </g> + <g + transform="matrix(0.5,0,0,0.5,48.975654,51.68773)" + id="g4083-1" + style="stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,-28.552651,25.23772)" + id="g3994-8"> + <path + d="m 146.16597,-108.12177 0,14.585629" + id="path2995-3-1-8" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="74.397118" + y="150.22018" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3-5" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="74.397118" + y="150.22018" + id="tspan4235-7-8" + style="font-size:10px">55</tspan></text> + <path + d="m 146.32105,-52.352642 0,-14.585631" + id="path2995-3-1-8-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + <g + transform="matrix(0.74289795,0,0,0.74289795,25.183482,26.578043)" + id="g4083-1-1" + style="stroke-width:6.73039961;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0-9" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2-3" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7-0" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4-9" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(30.255316,19.03157)" + id="g4321"> + <path + d="M 92.428426,57.769579 79.796901,65.062393" + id="path2995-3-1-8-3" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="4.121335" + y="99.936424" + transform="matrix(0.8660254,-0.5,0.5,0.8660254,0,0)" + id="text4233-3-5-7" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="4.121335" + y="99.936424" + id="tspan4235-7-8-7" + style="font-size:10px">77.5</tspan></text> + <path + d="M 22.004987,98.720153 34.636514,91.427337" + id="path2995-3-1-8-1-7" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> +</svg> diff --git a/challenges/amazonas-9.svg b/challenges/amazonas-9.svg new file mode 100644 index 0000000..d3f90dc --- /dev/null +++ b/challenges/amazonas-9.svg @@ -0,0 +1,407 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="205" + height="205" + id="svg2"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs16"> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-9" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-9" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-6" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-7" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4268" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4270" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-2" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735-4" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-4" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-8" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5733" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5735" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-5" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-1" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5099" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5101" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5095" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5097" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker5091" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path5093" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-3" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-97" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-7" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-0" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4131" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4133" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-69" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-96" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-1" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-87" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="Arrow2Mstart-8" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path3792-40" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + <marker + refX="0" + refY="0" + orient="auto" + id="marker4285" + style="overflow:visible"> + <path + d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z" + transform="scale(0.6,0.6)" + id="path4287" + style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round" /> + </marker> + </defs> + <path + d="M 28.048086,102.98439 97.795981,62.525651 169.7778,103.72903 97.795981,144.43599 z" + id="path4840" + style="fill:#7f7f7f;fill-opacity:1;stroke:none" /> + <g + id="g4083"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4" + style="fill:none;stroke:#7f7f7f;stroke-width:5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,226.35918,76.594049)" + id="g3994"> + <path + d="m 16.965852,144.30017 0,-43.75725" + id="path2995-0" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <path + d="m 16.987605,45.050682 0,14.58563" + id="path2995-3-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="-85.85524" + y="20.616865" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="-85.85524" + y="20.616865" + id="tspan4235-7" + style="font-size:10px">110</tspan></text> + </g> + <path + d="M 51.248436,103.26932 97.95131,75.672168 144.65418,103.4816 97.31445,131.07875 z" + id="path4173" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <g + transform="matrix(0.5,0,0,0.5,48.975654,51.68773)" + id="g4083-1" + style="stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4" + style="fill:none;stroke:#7f7f7f;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.5,0.8660254,-0.8660254,0.5,-28.552651,25.23772)" + id="g3994-8"> + <path + d="m 146.16597,-108.12177 0,14.585629" + id="path2995-3-1-8" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="74.397118" + y="150.22018" + transform="matrix(0,-1,1,0,0,0)" + id="text4233-3-5" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="74.397118" + y="150.22018" + id="tspan4235-7-8" + style="font-size:10px">55</tspan></text> + <path + d="m 146.32105,-52.352642 0,-14.585631" + id="path2995-3-1-8-1" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> + <g + transform="matrix(0.74289795,0,0,0.74289795,25.183482,26.578043)" + id="g4083-1-1" + style="stroke-width:6.73039961;stroke-miterlimit:4;stroke-dasharray:none"> + <path + d="M 1.995316,102.69362 97.451307,48.028261" + id="path2993-0-9" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,102.69362 98.451307,48.028261" + id="path2993-9-2-3" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 1.995316,104.0573 95.455991,54.66536" + id="path2993-5-7-0" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 193.9073,104.0573 98.451307,158.72266" + id="path2993-9-4-4-9" + style="fill:none;stroke:#7f7f7f;stroke-width:6.73039961;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="translate(30.255316,19.03157)" + id="g4321"> + <path + d="M 92.428426,57.769579 79.796901,65.062393" + id="path2995-3-1-8-3" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + <text + x="4.121335" + y="99.936424" + transform="matrix(0.8660254,-0.5,0.5,0.8660254,0,0)" + id="text4233-3-5-7" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="4.121335" + y="99.936424" + id="tspan4235-7-8-7" + style="font-size:10px">77.5</tspan></text> + <path + d="M 22.004987,98.720153 34.636514,91.427337" + id="path2995-3-1-8-1-7" + style="fill:none;stroke:#000000;stroke-width:1.13199997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:url(#Arrow2Mstart)" /> + </g> +</svg> diff --git a/challenges/offsets b/challenges/offsets new file mode 100644 index 0000000..b991582 --- /dev/null +++ b/challenges/offsets @@ -0,0 +1,23 @@ +1:0, -100 +2:0, -100 +3:0, -100 +4:0, -100 +5:0, -100 +6:0, -100 +7:0, -100 +8:0, -100 +9:0, -100 +10:0, -100 +11:0, -100 +12:0, -100 +13:0, -100 +14:0, -100 +15:0, -100 +16:0, -80 +17:0, -80 +18:0, -80 +19:0, -80 +20:0, -80 +21:0, -80 + + diff --git a/collaboration/__init__.py b/collaboration/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/collaboration/__init__.py diff --git a/collaboration/activity.py b/collaboration/activity.py new file mode 100644 index 0000000..bd58e92 --- /dev/null +++ b/collaboration/activity.py @@ -0,0 +1,720 @@ +# Copyright (C) 2007, Red Hat, Inc. +# Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +"""UI interface to an activity in the presence service + +STABLE. +""" + +import logging +from functools import partial + +import dbus +from dbus import PROPERTIES_IFACE +import gobject +from telepathy.client import Channel +from telepathy.interfaces import CHANNEL, \ + CHANNEL_INTERFACE_GROUP, \ + CHANNEL_TYPE_TUBES, \ + CHANNEL_TYPE_TEXT, \ + CONNECTION, \ + PROPERTIES_INTERFACE +from telepathy.constants import CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES, \ + HANDLE_TYPE_ROOM, \ + HANDLE_TYPE_CONTACT, \ + PROPERTY_FLAG_WRITE + + +CONN_INTERFACE_ACTIVITY_PROPERTIES = 'org.laptop.Telepathy.ActivityProperties' +CONN_INTERFACE_BUDDY_INFO = 'org.laptop.Telepathy.BuddyInfo' + +_logger = logging.getLogger('sugar.presence.activity') + + +class Activity(gobject.GObject): + """UI interface for an Activity in the presence service + + Activities in the presence service represent your and other user's + shared activities. + + Properties: + id + color + name + type + joined + """ + __gsignals__ = { + 'buddy-joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'buddy-left': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'new-channel': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])), + } + + __gproperties__ = { + 'id': (str, None, None, None, gobject.PARAM_READABLE), + 'name': (str, None, None, None, gobject.PARAM_READWRITE), + 'tags': (str, None, None, None, gobject.PARAM_READWRITE), + 'color': (str, None, None, None, gobject.PARAM_READWRITE), + 'type': (str, None, None, None, gobject.PARAM_READABLE), + 'private': (bool, None, None, True, gobject.PARAM_READWRITE), + 'joined': (bool, None, None, False, gobject.PARAM_READABLE), + } + + def __init__(self, account_path, connection, room_handle=None, + properties=None): + if room_handle is None and properties is None: + raise ValueError('Need to pass one of room_handle or properties') + + if properties is None: + properties = {} + + gobject.GObject.__init__(self) + + self._account_path = account_path + self.telepathy_conn = connection + self.telepathy_text_chan = None + self.telepathy_tubes_chan = None + + self.room_handle = room_handle + self._join_command = None + self._share_command = None + self._id = properties.get('id', None) + self._color = properties.get('color', None) + self._name = properties.get('name', None) + self._type = properties.get('type', None) + self._tags = properties.get('tags', None) + self._private = properties.get('private', True) + self._joined = properties.get('joined', False) + self._channel_self_handle = None + self._text_channel_group_flags = 0 + self._buddies = {} + + self._get_properties_call = None + if not self.room_handle is None: + self._start_tracking_properties() + + def _start_tracking_properties(self): + bus = dbus.SessionBus() + self._get_properties_call = bus.call_async( + self.telepathy_conn.requested_bus_name, + self.telepathy_conn.object_path, + CONN_INTERFACE_ACTIVITY_PROPERTIES, + 'GetProperties', + 'u', + (self.room_handle,), + reply_handler=self.__got_properties_cb, + error_handler=self.__error_handler_cb, + utf8_strings=True) + + # As only one Activity instance is needed per activity process, + # we can afford listening to ActivityPropertiesChanged like this. + self.telepathy_conn.connect_to_signal( + 'ActivityPropertiesChanged', + self.__activity_properties_changed_cb, + dbus_interface=CONN_INTERFACE_ACTIVITY_PROPERTIES) + + def __activity_properties_changed_cb(self, room_handle, properties): + print('%r: Activity properties changed to %r', self, + properties) + self._update_properties(properties) + + def __got_properties_cb(self, properties): + print('__got_properties_cb %r', properties) + self._get_properties_call = None + self._update_properties(properties) + + def __error_handler_cb(self, error): + print('__error_handler_cb %r', error) + + def _update_properties(self, new_props): + val = new_props.get('name', self._name) + if isinstance(val, str) and val != self._name: + self._name = val + self.notify('name') + val = new_props.get('tags', self._tags) + if isinstance(val, str) and val != self._tags: + self._tags = val + self.notify('tags') + val = new_props.get('color', self._color) + if isinstance(val, str) and val != self._color: + self._color = val + self.notify('color') + val = bool(new_props.get('private', self._private)) + if val != self._private: + self._private = val + self.notify('private') + val = new_props.get('id', self._id) + if isinstance(val, str) and self._id is None: + self._id = val + self.notify('id') + val = new_props.get('type', self._type) + if isinstance(val, str) and self._type is None: + self._type = val + self.notify('type') + + def object_path(self): + """Get our dbus object path""" + return self._object_path + + def do_get_property(self, pspec): + """Retrieve a particular property from our property dictionary""" + + if pspec.name == 'joined': + return self._joined + + if self._get_properties_call is not None: + print('%r: Blocking on GetProperties() because someone ' + 'wants property %s', self, pspec.name) + self._get_properties_call.block() + + if pspec.name == 'id': + return self._id + elif pspec.name == 'name': + return self._name + elif pspec.name == 'color': + return self._color + elif pspec.name == 'type': + return self._type + elif pspec.name == 'tags': + return self._tags + elif pspec.name == 'private': + return self._private + + def do_set_property(self, pspec, val): + """Set a particular property in our property dictionary""" + # FIXME: need an asynchronous API to set these properties, + # particularly 'private' + + if pspec.name == 'name': + self._name = val + elif pspec.name == 'color': + self._color = val + elif pspec.name == 'tags': + self._tags = val + elif pspec.name == 'private': + self._private = val + else: + raise ValueError('Unknown property %r', pspec.name) + + self._publish_properties() + + def set_private(self, val, reply_handler, error_handler): + print('set_private %r', val) + self._activity.SetProperties({'private': bool(val)}, + reply_handler=reply_handler, + error_handler=error_handler) + + def get_joined_buddies(self): + """Retrieve the set of Buddy objects attached to this activity + + returns list of presence Buddy objects that we can successfully + create from the buddy object paths that PS has for this activity. + """ + return self._buddies.values() + + def get_buddy_by_handle(self, handle): + """Retrieve the Buddy object given a telepathy handle. + + buddy object paths are cached in self._handle_to_buddy_path, + so we can get the buddy without calling PS. + """ + object_path = self._handle_to_buddy_path.get(handle, None) + if object_path: + buddy = self._ps_new_object(object_path) + return buddy + return None + + def invite(self, buddy, message, response_cb): + """Invite the given buddy to join this activity. + + The callback will be called with one parameter: None on success, + or an exception on failure. + """ + if not self._joined: + raise RuntimeError('Cannot invite a buddy to an activity that is' + 'not shared.') + self.telepathy_text_chan.AddMembers([buddy.contact_handle], message, + dbus_interface=CHANNEL_INTERFACE_GROUP, + reply_handler=partial(self.__invite_cb, response_cb), + error_handler=partial(self.__invite_cb, response_cb)) + + def __invite_cb(self, response_cb, error=None): + response_cb(error) + + def set_up_tubes(self, reply_handler, error_handler): + raise NotImplementedError() + + def __joined_cb(self, join_command, error): + print('%r: Join finished %r', self, error) + if error is not None: + self.emit('joined', error is None, str(error)) + self.telepathy_text_chan = join_command.text_channel + self.telepathy_tubes_chan = join_command.tubes_channel + self._channel_self_handle = join_command.channel_self_handle + self._text_channel_group_flags = join_command.text_channel_group_flags + self._start_tracking_buddies() + self._start_tracking_channel() + + def _start_tracking_buddies(self): + group = self.telepathy_text_chan[CHANNEL_INTERFACE_GROUP] + + group.GetAllMembers(reply_handler=self.__get_all_members_cb, + error_handler=self.__error_handler_cb) + + group.connect_to_signal('MembersChanged', + self.__text_channel_members_changed_cb) + + def _start_tracking_channel(self): + channel = self.telepathy_text_chan[CHANNEL] + channel.connect_to_signal('Closed', self.__text_channel_closed_cb) + + def __get_all_members_cb(self, members, local_pending, remote_pending): + print('__get_all_members_cb %r %r', members, + self._text_channel_group_flags) + if self._channel_self_handle in members: + members.remove(self._channel_self_handle) + + if not members: + return + + self._resolve_handles(members, reply_cb=self._add_initial_buddies) + + def _resolve_handles(self, input_handles, reply_cb): + def get_handle_owners_cb(handles): + self.telepathy_conn.InspectHandles(HANDLE_TYPE_CONTACT, handles, + reply_handler=reply_cb, + error_handler=self.__error_handler_cb, + dbus_interface=CONNECTION) + + if self._text_channel_group_flags & \ + CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES: + + group = self.telepathy_text_chan[CHANNEL_INTERFACE_GROUP] + group.GetHandleOwners(input_handles, + reply_handler=get_handle_owners_cb, + error_handler=self.__error_handler_cb) + else: + get_handle_owners_cb(input_handles) + + def _add_initial_buddies(self, contact_ids): + print('__add_initial_buddies %r', contact_ids) + #for contact_id in contact_ids: + # self._buddies[contact_id] = self._get_buddy(contact_id) + # Once we have the initial members, we can finish the join process + self._joined = True + self.emit('joined', True, None) + + def __text_channel_members_changed_cb(self, message, added, removed, + local_pending, remote_pending, + actor, reason): + print('__text_channel_members_changed_cb %r', + [added, message, added, removed, local_pending, + remote_pending, actor, reason]) + if self._channel_self_handle in added: + added.remove(self._channel_self_handle) + if added: + self._resolve_handles(added, reply_cb=self._add_buddies) + + if self._channel_self_handle in removed: + removed.remove(self._channel_self_handle) + if removed: + self._resolve_handles(added, reply_cb=self._remove_buddies) + + def _add_buddies(self, contact_ids): + for contact_id in contact_ids: + if contact_id not in self._buddies: + buddy = self._get_buddy(contact_id) + self.emit('buddy-joined', buddy) + self._buddies[contact_id] = buddy + + def _remove_buddies(self, contact_ids): + for contact_id in contact_ids: + if contact_id in self._buddies: + buddy = self._get_buddy(contact_id) + self.emit('buddy-left', buddy) + del self._buddies[contact_id] + + def _get_buddy(self, contact_id): + return None + #if contact_id in self._buddies: + # return self._buddies[contact_id] + #else: + # return Buddy(self._account_path, contact_id) + + def join(self): + """Join this activity. + + Emits 'joined' and otherwise does nothing if we're already joined. + """ + if self._join_command is not None: + return + + if self._joined: + self.emit('joined', True, None) + return + + print('%r: joining', self) + + self._join_command = _JoinCommand(self.telepathy_conn, + self.room_handle) + self._join_command.connect('finished', self.__joined_cb) + self._join_command.run() + + def share(self, share_activity_cb, share_activity_error_cb): + if not self.room_handle is None: + raise ValueError('Already have a room handle') + + self._share_command = _ShareCommand(self.telepathy_conn, self._id) + self._share_command.connect('finished', + partial(self.__shared_cb, + share_activity_cb, + share_activity_error_cb)) + self._share_command.run() + + def __shared_cb(self, share_activity_cb, share_activity_error_cb, + share_command, error): + print('%r: Share finished %r', self, error) + if error is None: + print "There was no error!" + self._joined = True + self.room_handle = share_command.room_handle + self.telepathy_text_chan = share_command.text_channel + self.telepathy_tubes_chan = share_command.tubes_channel + self._channel_self_handle = share_command.channel_self_handle + self._text_channel_group_flags = \ + share_command.text_channel_group_flags + self._publish_properties() + self._start_tracking_properties() + self._start_tracking_buddies() + self._start_tracking_channel() + share_activity_cb(self) + else: + print("error = %s" % error) + share_activity_error_cb(self, error) + + def _publish_properties(self): + properties = {} + + if self._color is not None: + properties['color'] = str(self._color) + if self._name is not None: + properties['name'] = str(self._name) + if self._type is not None: + properties['type'] = self._type + if self._tags is not None: + properties['tags'] = self._tags + properties['private'] = self._private + + self.telepathy_conn.SetProperties( + self.room_handle, + properties, + dbus_interface=CONN_INTERFACE_ACTIVITY_PROPERTIES) + + def __share_error_cb(self, share_activity_error_cb, error): + logging.debug('%r: Share failed because: %s', self, error) + share_activity_error_cb(self, error) + + # GetChannels() wrapper + + def get_channels(self): + """Retrieve communications channel descriptions for the activity + + Returns a tuple containing: + - the D-Bus well-known service name of the connection + (FIXME: this is redundant; in Telepathy it can be derived + from that of the connection) + - the D-Bus object path of the connection + - a list of D-Bus object paths representing the channels + associated with this activity + """ + bus_name = self.telepathy_conn.requested_bus_name + connection_path = self.telepathy_conn.object_path + channels = [self.telepathy_text_chan.object_path, + self.telepathy_tubes_chan.object_path] + + print('%r: bus name is %s, connection is %s, channels are %r', + self, bus_name, connection_path, channels) + return bus_name, connection_path, channels + + # Leaving + def __text_channel_closed_cb(self): + self._joined = False + self.emit('joined', False, 'left activity') + + def leave(self): + """Leave this shared activity""" + print('%r: leaving', self) + self.telepathy_text_chan.Close() + + +class _BaseCommand(gobject.GObject): + __gsignals__ = { + 'finished': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + } + + def __init__(self): + gobject.GObject.__init__(self) + + self.text_channel = None + self.text_channel_group_flags = None + self.tubes_channel = None + self.room_handle = None + self.channel_self_handle = None + + def run(self): + raise NotImplementedError() + + +class _ShareCommand(_BaseCommand): + def __init__(self, connection, activity_id): + _BaseCommand.__init__(self) + + self._connection = connection + self._activity_id = activity_id + self._finished = False + self._join_command = None + + def run(self): + self._connection.RequestHandles( + HANDLE_TYPE_ROOM, + [self._activity_id], + reply_handler=self.__got_handles_cb, + error_handler=self.__error_handler_cb, + dbus_interface=CONNECTION) + + def __got_handles_cb(self, handles): + logging.debug('__got_handles_cb %r', handles) + self.room_handle = handles[0] + + self._join_command = _JoinCommand(self._connection, self.room_handle) + self._join_command.connect('finished', self.__joined_cb) + self._join_command.run() + + def __joined_cb(self, join_command, error): + print('%r: Join finished %r', self, error) + if error is not None: + self._finished = True + self.emit('finished', error) + return + + self.text_channel = join_command.text_channel + self.text_channel_group_flags = join_command.text_channel_group_flags + self.tubes_channel = join_command.tubes_channel + + self._connection.AddActivity( + self._activity_id, + self.room_handle, + reply_handler=self.__added_activity_cb, + error_handler=self.__error_handler_cb, + dbus_interface=CONN_INTERFACE_BUDDY_INFO) + + def __added_activity_cb(self): + self._finished = True + self.emit('finished', None) + + def __error_handler_cb(self, error): + self._finished = True + self.emit('finished', error) + + +class _JoinCommand(_BaseCommand): + def __init__(self, connection, room_handle): + _BaseCommand.__init__(self) + + self._connection = connection + self._finished = False + self.room_handle = room_handle + self._global_self_handle = None + + def run(self): + if self._finished: + raise RuntimeError('This command has already finished') + self._connection.Get(CONNECTION, 'SelfHandle', + reply_handler=self.__get_self_handle_cb, + error_handler=self.__error_handler_cb, + dbus_interface=PROPERTIES_IFACE) + + def __get_self_handle_cb(self, handle): + self._global_self_handle = handle + + self._connection.RequestChannel(CHANNEL_TYPE_TEXT, + HANDLE_TYPE_ROOM, self.room_handle, True, + reply_handler=self.__create_text_channel_cb, + error_handler=self.__error_handler_cb, + dbus_interface=CONNECTION) + + self._connection.RequestChannel(CHANNEL_TYPE_TUBES, + HANDLE_TYPE_ROOM, self.room_handle, True, + reply_handler=self.__create_tubes_channel_cb, + error_handler=self.__error_handler_cb, + dbus_interface=CONNECTION) + + def __create_text_channel_cb(self, channel_path): + Channel(self._connection.requested_bus_name, channel_path, + ready_handler=self.__text_channel_ready_cb) + + def __create_tubes_channel_cb(self, channel_path): + print "Creating tubes channel with bus name %s" % self._connection.requested_bus_name + print "Creating tubes channel with channel path %s" % channel_path + Channel(self._connection.requested_bus_name, channel_path, + ready_handler=self.__tubes_channel_ready_cb) + + def __error_handler_cb(self, error): + self._finished = True + self.emit('finished', error) + + def __tubes_channel_ready_cb(self, channel): + print('%r: Tubes channel %r is ready', self, channel) + self.tubes_channel = channel + self._tubes_ready() + + def __text_channel_ready_cb(self, channel): + print('%r: Text channel %r is ready', self, channel) + self.text_channel = channel + self._tubes_ready() + + def _tubes_ready(self): + if self.text_channel is None or \ + self.tubes_channel is None: + return + + print('%r: finished setting up tubes', self) + + self._add_self_to_channel() + + def __text_channel_group_flags_changed_cb(self, added, removed): + print('__text_channel_group_flags_changed_cb %r %r', added, + removed) + self.text_channel_group_flags |= added + self.text_channel_group_flags &= ~removed + + def _add_self_to_channel(self): + # FIXME: cope with non-Group channels here if we want to support + # non-OLPC-compatible IMs + + group = self.text_channel[CHANNEL_INTERFACE_GROUP] + + def got_all_members(members, local_pending, remote_pending): + print('got_all_members members %r local_pending %r ' + 'remote_pending %r', members, local_pending, + remote_pending) + + if self.text_channel_group_flags & \ + CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES: + self_handle = self.channel_self_handle + else: + self_handle = self._global_self_handle + + if self_handle in local_pending: + print('%r: We are in local pending - entering', self) + group.AddMembers([self_handle], '', + reply_handler=lambda: None, + error_handler=lambda e: self._join_failed_cb(e, + 'got_all_members AddMembers')) + + if members: + self.__text_channel_members_changed_cb('', members, (), + (), (), 0, 0) + + def got_group_flags(flags): + self.text_channel_group_flags = flags + # by the time we hook this, we need to know the group flags + group.connect_to_signal('MembersChanged', + self.__text_channel_members_changed_cb) + + # bootstrap by getting the current state. This is where we find + # out whether anyone was lying to us in their PEP info + group.GetAllMembers(reply_handler=got_all_members, + error_handler=self.__error_handler_cb) + + def got_self_handle(channel_self_handle): + self.channel_self_handle = channel_self_handle + group.connect_to_signal('GroupFlagsChanged', + self.__text_channel_group_flags_changed_cb) + group.GetGroupFlags(reply_handler=got_group_flags, + error_handler=self.__error_handler_cb) + + group.GetSelfHandle(reply_handler=got_self_handle, + error_handler=self.__error_handler_cb) + + def __text_channel_members_changed_cb(self, message, added, removed, + local_pending, remote_pending, + actor, reason): + print('__text_channel_members_changed_cb added %r removed %r ' + 'local_pending %r remote_pending %r channel_self_handle ' + '%r', added, removed, local_pending, remote_pending, + self.channel_self_handle) + + if self.text_channel_group_flags & \ + CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES: + self_handle = self.channel_self_handle + else: + self_handle = self._global_self_handle + + if self_handle in added: + if PROPERTIES_INTERFACE not in self.text_channel: + self._finished = True + self.emit('finished', None) + else: + self.text_channel[PROPERTIES_INTERFACE].ListProperties( + reply_handler=self.__list_properties_cb, + error_handler=self.__error_handler_cb) + + def __list_properties_cb(self, prop_specs): + # FIXME: invite-only ought to be set on private activities; but + # since only the owner can change invite-only, that would break + # activity scope changes. + props = { + # otherwise buddy resolution breaks + 'anonymous': False, + # anyone who knows about the channel can join + 'invite-only': False, + # so non-owners can invite others + 'invite-restricted': False, + # vanish when there are no members + 'persistent': False, + # don't appear in server room lists + 'private': True, + } + props_to_set = [] + for ident, name, sig_, flags in prop_specs: + value = props.pop(name, None) + if value is not None: + if flags & PROPERTY_FLAG_WRITE: + props_to_set.append((ident, value)) + # FIXME: else error, but only if we're creating the room? + # FIXME: if props is nonempty, then we want to set props that aren't + # supported here - raise an error? + + if props_to_set: + self.text_channel[PROPERTIES_INTERFACE].SetProperties( + props_to_set, reply_handler=self.__set_properties_cb, + error_handler=self.__error_handler_cb) + else: + self._finished = True + self.emit('finished', None) + + def __set_properties_cb(self): + self._finished = True + self.emit('finished', None) diff --git a/collaboration/buddy.py b/collaboration/buddy.py new file mode 100644 index 0000000..b117940 --- /dev/null +++ b/collaboration/buddy.py @@ -0,0 +1,234 @@ +# Copyright (C) 2006-2007 Red Hat, Inc. +# Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import logging + +import gobject +import gconf +import dbus +from telepathy.client import Connection +from telepathy.interfaces import CONNECTION + +from xocolor import XoColor +import connection_watcher + + +CONNECTION_INTERFACE_BUDDY_INFO = 'org.laptop.Telepathy.BuddyInfo' + +_owner_instance = None + + +class BaseBuddyModel(gobject.GObject): + __gtype_name__ = 'SugarBaseBuddyModel' + + def __init__(self, **kwargs): + self._key = None + self._nick = None + self._color = None + self._tags = None + self._current_activity = None + + gobject.GObject.__init__(self, **kwargs) + + def get_nick(self): + return self._nick + + def set_nick(self, nick): + self._nick = nick + + nick = gobject.property(type=object, getter=get_nick, setter=set_nick) + + def get_key(self): + return self._key + + def set_key(self, key): + self._key = key + + key = gobject.property(type=object, getter=get_key, setter=set_key) + + def get_color(self): + return self._color + + def set_color(self, color): + self._color = color + + color = gobject.property(type=object, getter=get_color, setter=set_color) + + def get_tags(self): + return self._tags + + tags = gobject.property(type=object, getter=get_tags) + + def get_current_activity(self): + return self._current_activity + + def set_current_activity(self, current_activity): + if self._current_activity != current_activity: + self._current_activity = current_activity + self.notify('current-activity') + + current_activity = gobject.property(type=object, + getter=get_current_activity, + setter=set_current_activity) + + def is_owner(self): + raise NotImplementedError + + +class OwnerBuddyModel(BaseBuddyModel): + __gtype_name__ = 'SugarOwnerBuddyModel' + + def __init__(self): + BaseBuddyModel.__init__(self) + + #client = gconf.client_get_default() + #self.props.nick = client.get_string('/desktop/sugar/user/nick') + self.props.nick = "rgs" + #color = client.get_string('/desktop/sugar/user/color') + self.props.color = XoColor(None) + + #self.props.key = get_profile().pubkey + self.props.key = "foobar" + + self.connect('notify::nick', self.__property_changed_cb) + self.connect('notify::color', self.__property_changed_cb) + self.connect('notify::current-activity', + self.__current_activity_changed_cb) + + bus = dbus.SessionBus() + bus.add_signal_receiver( + self.__name_owner_changed_cb, + signal_name='NameOwnerChanged', + dbus_interface='org.freedesktop.DBus') + + bus_object = bus.get_object(dbus.BUS_DAEMON_NAME, dbus.BUS_DAEMON_PATH) + for service in bus_object.ListNames( + dbus_interface=dbus.BUS_DAEMON_IFACE): + if service.startswith(CONNECTION + '.'): + path = '/%s' % service.replace('.', '/') + Connection(service, path, bus, + ready_handler=self.__connection_ready_cb) + + def __connection_ready_cb(self, connection): + self._sync_properties_on_connection(connection) + + def __name_owner_changed_cb(self, name, old, new): + if name.startswith(CONNECTION + '.') and not old and new: + path = '/' + name.replace('.', '/') + Connection(name, path, ready_handler=self.__connection_ready_cb) + + def __property_changed_cb(self, buddy, pspec): + self._sync_properties() + + def __current_activity_changed_cb(self, buddy, pspec): + conn_watcher = connection_watcher.get_instance() + for connection in conn_watcher.get_connections(): + if self.props.current_activity is not None: + activity_id = self.props.current_activity.activity_id + room_handle = self.props.current_activity.room_handle + else: + activity_id = '' + room_handle = 0 + + connection[CONNECTION_INTERFACE_BUDDY_INFO].SetCurrentActivity( + activity_id, + room_handle, + reply_handler=self.__set_current_activity_cb, + error_handler=self.__error_handler_cb) + + def __set_current_activity_cb(self): + logging.debug('__set_current_activity_cb') + + def _sync_properties(self): + conn_watcher = connection_watcher.get_instance() + for connection in conn_watcher.get_connections(): + self._sync_properties_on_connection(connection) + + def _sync_properties_on_connection(self, connection): + if CONNECTION_INTERFACE_BUDDY_INFO in connection: + properties = {} + if self.props.key is not None: + properties['key'] = dbus.ByteArray(self.props.key) + if self.props.color is not None: + properties['color'] = self.props.color.to_string() + + logging.debug('calling SetProperties with %r', properties) + connection[CONNECTION_INTERFACE_BUDDY_INFO].SetProperties( + properties, + reply_handler=self.__set_properties_cb, + error_handler=self.__error_handler_cb) + + def __set_properties_cb(self): + logging.debug('__set_properties_cb') + + def __error_handler_cb(self, error): + raise RuntimeError(error) + + def __connection_added_cb(self, conn_watcher, connection): + self._sync_properties_on_connection(connection) + + def is_owner(self): + return True + + +def get_owner_instance(): + global _owner_instance + if _owner_instance is None: + _owner_instance = OwnerBuddyModel() + return _owner_instance + + +class BuddyModel(BaseBuddyModel): + __gtype_name__ = 'SugarBuddyModel' + + def __init__(self, **kwargs): + + self._account = None + self._contact_id = None + self._handle = None + + BaseBuddyModel.__init__(self, **kwargs) + + def is_owner(self): + return False + + def get_account(self): + return self._account + + def set_account(self, account): + self._account = account + + account = gobject.property(type=object, getter=get_account, + setter=set_account) + + def get_contact_id(self): + return self._contact_id + + def set_contact_id(self, contact_id): + self._contact_id = contact_id + + contact_id = gobject.property(type=object, getter=get_contact_id, + setter=set_contact_id) + + def get_handle(self): + return self._handle + + def set_handle(self, handle): + self._handle = handle + + handle = gobject.property(type=object, getter=get_handle, + setter=set_handle) diff --git a/collaboration/connection_watcher.py b/collaboration/connection_watcher.py new file mode 100644 index 0000000..96af1cf --- /dev/null +++ b/collaboration/connection_watcher.py @@ -0,0 +1,122 @@ +# This should eventually land in telepathy-python, so has the same license: +# Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# FIXME: this sould go upstream, in telepathy-python + +import logging + +import dbus +import dbus.mainloop.glib +import gobject + +from telepathy.client import Connection +from telepathy.interfaces import CONN_INTERFACE +from telepathy.constants import CONNECTION_STATUS_CONNECTED, \ + CONNECTION_STATUS_DISCONNECTED + + +_instance = None + + +class ConnectionWatcher(gobject.GObject): + __gsignals__ = { + 'connection-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'connection-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + } + + def __init__(self, bus=None): + gobject.GObject.__init__(self) + + if bus is None: + self.bus = dbus.Bus() + else: + self.bus = bus + + # D-Bus path -> Connection + self._connections = {} + + self.bus.add_signal_receiver(self._status_changed_cb, + dbus_interface=CONN_INTERFACE, signal_name='StatusChanged', + path_keyword='path') + + for conn in Connection.get_connections(bus): + conn.call_when_ready(self._conn_ready_cb) + + def _status_changed_cb(self, *args, **kwargs): + path = kwargs['path'] + if not path.startswith('/org/freedesktop/Telepathy/Connection/'): + return + + status, reason_ = args + service_name = path.replace('/', '.')[1:] + + if status == CONNECTION_STATUS_CONNECTED: + self._add_connection(service_name, path) + elif status == CONNECTION_STATUS_DISCONNECTED: + self._remove_connection(service_name, path) + + def _conn_ready_cb(self, conn): + if conn.object_path in self._connections: + return + + self._connections[conn.object_path] = conn + self.emit('connection-added', conn) + + def _add_connection(self, service_name, path): + if path in self._connections: + return + + try: + Connection(service_name, path, ready_handler=self._conn_ready_cb) + except dbus.exceptions.DBusException: + logging.debug('%s is propably already gone.', service_name) + + def _remove_connection(self, service_name, path): + conn = self._connections.pop(path, None) + if conn is None: + return + + self.emit('connection-removed', conn) + + def get_connections(self): + return self._connections.values() + + +def get_instance(): + global _instance + if _instance is None: + _instance = ConnectionWatcher() + return _instance + + +if __name__ == '__main__': + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + def connection_added_cb(conn_watcher, conn): + print 'new connection', conn.service_name + + def connection_removed_cb(conn_watcher, conn): + print 'removed connection', conn.service_name + + watcher = ConnectionWatcher() + watcher.connect('connection-added', connection_added_cb) + watcher.connect('connection-removed', connection_removed_cb) + + loop = gobject.MainLoop() + loop.run() diff --git a/collaboration/connectionmanager.py b/collaboration/connectionmanager.py new file mode 100644 index 0000000..5ae59dd --- /dev/null +++ b/collaboration/connectionmanager.py @@ -0,0 +1,122 @@ +# Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +""" +UNSTABLE. It should really be internal to the sugar.presence package. +""" + +from functools import partial + +import dbus +from dbus import PROPERTIES_IFACE +from telepathy.interfaces import ACCOUNT, \ + ACCOUNT_MANAGER +from telepathy.constants import CONNECTION_STATUS_CONNECTED + +ACCOUNT_MANAGER_SERVICE = 'org.freedesktop.Telepathy.AccountManager' +ACCOUNT_MANAGER_PATH = '/org/freedesktop/Telepathy/AccountManager' + + +class Connection(object): + def __init__(self, account_path, connection): + self.account_path = account_path + self.connection = connection + self.connected = False + + +class ConnectionManager(object): + """Track available telepathy connections""" + + def __init__(self): + self._connections_per_account = {} + + bus = dbus.SessionBus() + obj = bus.get_object(ACCOUNT_MANAGER_SERVICE, ACCOUNT_MANAGER_PATH) + account_manager = dbus.Interface(obj, ACCOUNT_MANAGER) + account_paths = account_manager.Get(ACCOUNT_MANAGER, 'ValidAccounts', + dbus_interface=PROPERTIES_IFACE) + for account_path in account_paths: + obj = bus.get_object(ACCOUNT_MANAGER_SERVICE, account_path) + obj.connect_to_signal('AccountPropertyChanged', + partial(self.__account_property_changed_cb, account_path)) + connection_path = obj.Get(ACCOUNT, 'Connection') + if connection_path != '/': + try: + self._track_connection(account_path, connection_path) + except: + pass + + def __account_property_changed_cb(self, account_path, properties): + if 'Connection' not in properties: + return + if properties['Connection'] == '/': + if account_path in self._connections_per_account: + del self._connections_per_account[account_path] + else: + self._track_connection(account_path, properties['Connection']) + + def _track_connection(self, account_path, connection_path): + connection_name = connection_path.replace('/', '.')[1:] + bus = dbus.SessionBus() + connection = bus.get_object(connection_name, connection_path) + connection.connect_to_signal('StatusChanged', + partial(self.__status_changed_cb, account_path)) + self._connections_per_account[account_path] = \ + Connection(account_path, connection) + + account = bus.get_object(ACCOUNT_MANAGER_SERVICE, account_path) + status = account.Get(ACCOUNT, 'ConnectionStatus') + if status == CONNECTION_STATUS_CONNECTED: + self._connections_per_account[account_path].connected = True + else: + self._connections_per_account[account_path].connected = False + + def __status_changed_cb(self, account_path, status, reason): + if status == CONNECTION_STATUS_CONNECTED: + self._connections_per_account[account_path].connected = True + else: + self._connections_per_account[account_path].connected = False + + def get_preferred_connection(self): + best_connection = None, None + for account_path, connection in self._connections_per_account.items(): + if 'salut' in account_path and connection.connected: + best_connection = account_path, connection.connection + elif 'gabble' in account_path and connection.connected: + best_connection = account_path, connection.connection + break + return best_connection + + def get_connection(self, account_path): + return self._connections_per_account[account_path].connection + + def get_connections_per_account(self): + return self._connections_per_account + + def get_account_for_connection(self, connection_path): + for account_path, connection in self._connections_per_account.items(): + if connection.connection.object_path == connection_path: + return account_path + return None + + +_connection_manager = None +def get_connection_manager(): + global _connection_manager + if not _connection_manager: + _connection_manager = ConnectionManager() + return _connection_manager diff --git a/collaboration/dispatch/Makefile.am b/collaboration/dispatch/Makefile.am new file mode 100644 index 0000000..eb44a32 --- /dev/null +++ b/collaboration/dispatch/Makefile.am @@ -0,0 +1,9 @@ +sugardir = $(pythondir)/sugar/dispatch +sugar_PYTHON = \ + __init__.py \ + dispatcher.py \ + saferef.py + +EXTRA_DIST = \ + license.txt + diff --git a/collaboration/dispatch/__init__.py b/collaboration/dispatch/__init__.py new file mode 100644 index 0000000..9f0a092 --- /dev/null +++ b/collaboration/dispatch/__init__.py @@ -0,0 +1,10 @@ +"""Multi-consumer multi-producer dispatching mechanism + +Originally based on pydispatch (BSD) +http://pypi.python.org/pypi/PyDispatcher/2.0.1 +See license.txt for original license. + +Heavily modified for Django's purposes. +""" + +from dispatcher import Signal diff --git a/collaboration/dispatch/dispatcher.py b/collaboration/dispatch/dispatcher.py new file mode 100644 index 0000000..45c32fe --- /dev/null +++ b/collaboration/dispatch/dispatcher.py @@ -0,0 +1,191 @@ +import weakref +import saferef + +WEAKREF_TYPES = (weakref.ReferenceType, saferef.BoundMethodWeakref) + + +def _make_id(target): + if hasattr(target, 'im_func'): + return (id(target.im_self), id(target.im_func)) + return id(target) + + +class Signal(object): + """Base class for all signals + + Internal attributes: + receivers -- { receriverkey (id) : weakref(receiver) } + """ + + def __init__(self, providing_args=None): + """providing_args -- A list of the arguments this signal can pass along + in a send() call. + """ + self.receivers = [] + if providing_args is None: + providing_args = [] + self.providing_args = set(providing_args) + + def connect(self, receiver, sender=None, weak=True, dispatch_uid=None): + """Connect receiver to sender for signal + + receiver -- a function or an instance method which is to + receive signals. Receivers must be + hashable objects. + + if weak is True, then receiver must be weak-referencable + (more precisely saferef.safeRef() must be able to create + a reference to the receiver). + + Receivers must be able to accept keyword arguments. + + If receivers have a dispatch_uid attribute, the receiver will + not be added if another receiver already exists with that + dispatch_uid. + + sender -- the sender to which the receiver should respond + Must either be of type Signal, or None to receive events + from any sender. + + weak -- whether to use weak references to the receiver + By default, the module will attempt to use weak + references to the receiver objects. If this parameter + is false, then strong references will be used. + + dispatch_uid -- an identifier used to uniquely identify a particular + instance of a receiver. This will usually be a string, though it + may be anything hashable. + + returns None + """ + if dispatch_uid: + lookup_key = (dispatch_uid, _make_id(sender)) + else: + lookup_key = (_make_id(receiver), _make_id(sender)) + + if weak: + receiver = saferef.safeRef(receiver, + onDelete=self._remove_receiver) + + for r_key, _ in self.receivers: + if r_key == lookup_key: + break + else: + self.receivers.append((lookup_key, receiver)) + + def disconnect(self, receiver=None, sender=None, weak=True, + dispatch_uid=None): + """Disconnect receiver from sender for signal + + receiver -- the registered receiver to disconnect. May be none if + dispatch_uid is specified. + sender -- the registered sender to disconnect + weak -- the weakref state to disconnect + dispatch_uid -- the unique identifier of the receiver to disconnect + + disconnect reverses the process of connect. + + If weak references are used, disconnect need not be called. + The receiver will be remove from dispatch automatically. + + returns None + """ + + if dispatch_uid: + lookup_key = (dispatch_uid, _make_id(sender)) + else: + lookup_key = (_make_id(receiver), _make_id(sender)) + + for idx, (r_key, _) in enumerate(self.receivers): + if r_key == lookup_key: + del self.receivers[idx] + + def send(self, sender, **named): + """Send signal from sender to all connected receivers. + + sender -- the sender of the signal + Either a specific object or None. + + named -- named arguments which will be passed to receivers. + + Returns a list of tuple pairs [(receiver, response), ... ]. + + If any receiver raises an error, the error propagates back + through send, terminating the dispatch loop, so it is quite + possible to not have all receivers called if a raises an + error. + """ + + responses = [] + if not self.receivers: + return responses + + for receiver in self._live_receivers(_make_id(sender)): + response = receiver(signal=self, sender=sender, **named) + responses.append((receiver, response)) + return responses + + def send_robust(self, sender, **named): + """Send signal from sender to all connected receivers catching errors + + sender -- the sender of the signal + Can be any python object (normally one registered with + a connect if you actually want something to occur). + + named -- named arguments which will be passed to receivers. + These arguments must be a subset of the argument names + defined in providing_args. + + Return a list of tuple pairs [(receiver, response), ... ], + may raise DispatcherKeyError + + if any receiver raises an error (specifically any subclass of + Exception), the error instance is returned as the result for that + receiver. + """ + + responses = [] + if not self.receivers: + return responses + + # Call each receiver with whatever arguments it can accept. + # Return a list of tuple pairs [(receiver, response), ... ]. + for receiver in self._live_receivers(_make_id(sender)): + try: + response = receiver(signal=self, sender=sender, **named) + except Exception, err: + responses.append((receiver, err)) + else: + responses.append((receiver, response)) + return responses + + def _live_receivers(self, senderkey): + """Filter sequence of receivers to get resolved, live receivers + + This checks for weak references + and resolves them, then returning only live + receivers. + """ + none_senderkey = _make_id(None) + + for (receiverkey_, r_senderkey), receiver in self.receivers: + if r_senderkey == none_senderkey or r_senderkey == senderkey: + if isinstance(receiver, WEAKREF_TYPES): + # Dereference the weak reference. + receiver = receiver() + if receiver is not None: + yield receiver + else: + yield receiver + + def _remove_receiver(self, receiver): + """Remove dead receivers from connections.""" + + to_remove = [] + for key, connected_receiver in self.receivers: + if connected_receiver == receiver: + to_remove.append(key) + for key in to_remove: + for idx, (r_key, _) in enumerate(self.receivers): + if r_key == key: + del self.receivers[idx] diff --git a/collaboration/dispatch/license.txt b/collaboration/dispatch/license.txt new file mode 100644 index 0000000..0272c28 --- /dev/null +++ b/collaboration/dispatch/license.txt @@ -0,0 +1,66 @@ +sugar.dispatch was originally forked from django.dispatch + +Copyright (c) Django Software Foundation and individual contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of Django nor the names of its contributors may be used + to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +django.dispatch was originally forked from PyDispatcher. + +PyDispatcher License: + + Copyright (c) 2001-2003, Patrick K. O'Brien and Contributors + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + The name of Patrick K. O'Brien, or the name of any Contributor, + may not be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/collaboration/dispatch/saferef.py b/collaboration/dispatch/saferef.py new file mode 100644 index 0000000..bb73b5d --- /dev/null +++ b/collaboration/dispatch/saferef.py @@ -0,0 +1,254 @@ +""" +"Safe weakrefs", originally from pyDispatcher. + +Provides a way to safely weakref any function, including bound methods (which +aren't handled by the core weakref module). +""" + +import weakref +import traceback + + +def safeRef(target, onDelete=None): + """Return a *safe* weak reference to a callable target + + target -- the object to be weakly referenced, if it's a + bound method reference, will create a BoundMethodWeakref, + otherwise creates a simple weakref. + onDelete -- if provided, will have a hard reference stored + to the callable to be called after the safe reference + goes out of scope with the reference object, (either a + weakref or a BoundMethodWeakref) as argument. + """ + if hasattr(target, 'im_self'): + if target.im_self is not None: + # Turn a bound method into a BoundMethodWeakref instance. + # Keep track of these instances for lookup by disconnect(). + if not hasattr(target, 'im_func'): + raise TypeError("safeRef target %r has im_self, but no" + " im_func, don't know how to create reference" % + (target, )) + reference = get_bound_method_weakref(target=target, + onDelete=onDelete) + return reference + if callable(onDelete): + return weakref.ref(target, onDelete) + else: + return weakref.ref(target) + + +class BoundMethodWeakref(object): + """'Safe' and reusable weak references to instance methods + + BoundMethodWeakref objects provide a mechanism for + referencing a bound method without requiring that the + method object itself (which is normally a transient + object) is kept alive. Instead, the BoundMethodWeakref + object keeps weak references to both the object and the + function which together define the instance method. + + Attributes: + key -- the identity key for the reference, calculated + by the class's calculateKey method applied to the + target instance method + deletionMethods -- sequence of callable objects taking + single argument, a reference to this object which + will be called when *either* the target object or + target function is garbage collected (i.e. when + this object becomes invalid). These are specified + as the onDelete parameters of safeRef calls. + weakSelf -- weak reference to the target object + weakFunc -- weak reference to the target function + + Class Attributes: + _allInstances -- class attribute pointing to all live + BoundMethodWeakref objects indexed by the class's + calculateKey(target) method applied to the target + objects. This weak value dictionary is used to + short-circuit creation so that multiple references + to the same (object, function) pair produce the + same BoundMethodWeakref instance. + + """ + + _allInstances = weakref.WeakValueDictionary() + + def __new__(cls, target, onDelete=None, *arguments, **named): + """Create new instance or return current instance + + Basically this method of construction allows us to + short-circuit creation of references to already- + referenced instance methods. The key corresponding + to the target is calculated, and if there is already + an existing reference, that is returned, with its + deletionMethods attribute updated. Otherwise the + new instance is created and registered in the table + of already-referenced methods. + """ + key = cls.calculateKey(target) + current = cls._allInstances.get(key) + if current is not None: + current.deletionMethods.append(onDelete) + return current + else: + base = super(BoundMethodWeakref, cls).__new__(cls) + cls._allInstances[key] = base + base.__init__(target, onDelete, *arguments, **named) + return base + + def __init__(self, target, onDelete=None): + """Return a weak-reference-like instance for a bound method + + target -- the instance-method target for the weak + reference, must have im_self and im_func attributes + and be reconstructable via: + target.im_func.__get__( target.im_self ) + which is true of built-in instance methods. + onDelete -- optional callback which will be called + when this weak reference ceases to be valid + (i.e. either the object or the function is garbage + collected). Should take a single argument, + which will be passed a pointer to this object. + """ + def remove(weak, self=self): + """Set self.isDead to true when method or instance is destroyed""" + methods = self.deletionMethods[:] + del self.deletionMethods[:] + try: + # pylint: disable=W0212 + del self.__class__._allInstances[self.key] + except KeyError: + pass + for function in methods: + try: + if callable(function): + function(self) + except Exception, e: + try: + traceback.print_exc() + except AttributeError: + print ('Exception during saferef %s cleanup function' + ' %s: %s' % (self, function, e)) + self.deletionMethods = [onDelete] + self.key = self.calculateKey(target) + self.weakSelf = weakref.ref(target.im_self, remove) + self.weakFunc = weakref.ref(target.im_func, remove) + self.selfName = str(target.im_self) + self.funcName = str(target.im_func.__name__) + + def calculateKey(cls, target): + """Calculate the reference key for this reference + + Currently this is a two-tuple of the id()'s of the + target object and the target function respectively. + """ + return (id(target.im_self), id(target.im_func)) + calculateKey = classmethod(calculateKey) + + def __str__(self): + """Give a friendly representation of the object""" + return '%s( %s.%s )' % (self.__class__.__name__, self.selfName, + self.funcName) + + __repr__ = __str__ + + def __nonzero__(self): + """Whether we are still a valid reference""" + return self() is not None + + def __cmp__(self, other): + """Compare with another reference""" + if not isinstance(other, self.__class__): + return cmp(self.__class__, type(other)) + return cmp(self.key, other.key) + + def __call__(self): + """Return a strong reference to the bound method + + If the target cannot be retrieved, then will + return None, otherwise returns a bound instance + method for our object and function. + + Note: + You may call this method any number of times, + as it does not invalidate the reference. + """ + target = self.weakSelf() + if target is not None: + function = self.weakFunc() + if function is not None: + return function.__get__(target) + return None + + +class BoundNonDescriptorMethodWeakref(BoundMethodWeakref): + """A specialized BoundMethodWeakref, for platforms where instance methods + are not descriptors. + + It assumes that the function name and the target attribute name are the + same, instead of assuming that the function is a descriptor. This approach + is equally fast, but not 100% reliable because functions can be stored on + an attribute named differenty than the function's name such as in: + + class A: pass + def foo(self): return 'foo' + A.bar = foo + + But this shouldn't be a common use case. So, on platforms where methods + aren't descriptors (such as Jython) this implementation has the advantage + of working in the most cases. + """ + def __init__(self, target, onDelete=None): + """Return a weak-reference-like instance for a bound method + + target -- the instance-method target for the weak + reference, must have im_self and im_func attributes + and be reconstructable via: + target.im_func.__get__( target.im_self ) + which is true of built-in instance methods. + onDelete -- optional callback which will be called + when this weak reference ceases to be valid + (i.e. either the object or the function is garbage + collected). Should take a single argument, + which will be passed a pointer to this object. + """ + assert getattr(target.im_self, target.__name__) == target, \ + ("method %s isn't available as the attribute %s of %s" % + (target, target.__name__, target.im_self)) + super(BoundNonDescriptorMethodWeakref, self).__init__(target, onDelete) + + def __call__(self): + """Return a strong reference to the bound method + + If the target cannot be retrieved, then will + return None, otherwise returns a bound instance + method for our object and function. + + Note: + You may call this method any number of times, + as it does not invalidate the reference. + """ + target = self.weakSelf() + if target is not None: + function = self.weakFunc() + if function is not None: + # Using curry() would be another option, but it erases the + # "signature" of the function. That is, after a function is + # curried, the inspect module can't be used to determine how + # many arguments the function expects, nor what keyword + # arguments it supports, and pydispatcher needs this + # information. + return getattr(target, function.__name__) + return None + + +def get_bound_method_weakref(target, onDelete): + """Instantiates the appropiate BoundMethodWeakRef, depending on the details + of the underlying class method implementation""" + if hasattr(target, '__get__'): + # target method is a descriptor, so the default implementation works: + return BoundMethodWeakref(target=target, onDelete=onDelete) + else: + # no luck, use the alternative implementation: + return BoundNonDescriptorMethodWeakref(target=target, + onDelete=onDelete) diff --git a/collaboration/neighborhood.py b/collaboration/neighborhood.py new file mode 100755 index 0000000..192b66f --- /dev/null +++ b/collaboration/neighborhood.py @@ -0,0 +1,1048 @@ +#!/usr/bin/python +# Copyright (C) 2007, Red Hat, Inc. +# Copyright (C) 2010-11 Collabora Ltd. <http://www.collabora.co.uk/> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +from functools import partial +from hashlib import sha1 + +import traceback +import gobject +import gconf +import dbus +from dbus import PROPERTIES_IFACE +from telepathy.interfaces import ACCOUNT, \ + ACCOUNT_MANAGER, \ + CHANNEL, \ + CHANNEL_INTERFACE_GROUP, \ + CHANNEL_TYPE_CONTACT_LIST, \ + CHANNEL_TYPE_FILE_TRANSFER, \ + CLIENT, \ + CONNECTION, \ + CONNECTION_INTERFACE_ALIASING, \ + CONNECTION_INTERFACE_CONTACTS, \ + CONNECTION_INTERFACE_CONTACT_CAPABILITIES, \ + CONNECTION_INTERFACE_REQUESTS, \ + CONNECTION_INTERFACE_SIMPLE_PRESENCE +from telepathy.constants import HANDLE_TYPE_CONTACT, \ + HANDLE_TYPE_LIST, \ + CONNECTION_PRESENCE_TYPE_OFFLINE, \ + CONNECTION_STATUS_CONNECTED, \ + CONNECTION_STATUS_DISCONNECTED +from telepathy.client import Connection, Channel + +from buddy import get_owner_instance +from buddy import BuddyModel + +from xocolor import XoColor + +import activity + +from connectionmanager import get_connection_manager + +import signal, os, sys +from activity import Activity + +ACCOUNT_MANAGER_SERVICE = 'org.freedesktop.Telepathy.AccountManager' +ACCOUNT_MANAGER_PATH = '/org/freedesktop/Telepathy/AccountManager' +CHANNEL_DISPATCHER_SERVICE = 'org.freedesktop.Telepathy.ChannelDispatcher' +CHANNEL_DISPATCHER_PATH = '/org/freedesktop/Telepathy/ChannelDispatcher' +SUGAR_CLIENT_SERVICE = 'org.freedesktop.Telepathy.Client.Sugar' +SUGAR_CLIENT_PATH = '/org/freedesktop/Telepathy/Client/Sugar' + +CONNECTION_INTERFACE_BUDDY_INFO = 'org.laptop.Telepathy.BuddyInfo' +CONNECTION_INTERFACE_ACTIVITY_PROPERTIES = \ + 'org.laptop.Telepathy.ActivityProperties' + +_QUERY_DBUS_TIMEOUT = 200 +""" +Time in seconds to wait when querying contact properties. Some jabber servers +will be very slow in returning these queries, so just be patient. +""" + + +class ActivityModel(gobject.GObject): + __gsignals__ = { + 'current-buddy-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'current-buddy-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'buddy-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'buddy-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + } + + def __init__(self, activity_id, room_handle): + gobject.GObject.__init__(self) + + self.activity_id = activity_id + self.room_handle = room_handle + self._bundle = None + self._color = None + self._private = True + self._name = None + self._current_buddies = [] + self._buddies = [] + + def get_color(self): + return self._color + + def set_color(self, color): + self._color = color + + color = gobject.property(type=object, getter=get_color, setter=set_color) + + def get_bundle(self): + return self._bundle + + def set_bundle(self, bundle): + self._bundle = bundle + + bundle = gobject.property(type=object, getter=get_bundle, + setter=set_bundle) + + def get_name(self): + return self._name + + def set_name(self, name): + self._name = name + + name = gobject.property(type=object, getter=get_name, setter=set_name) + + def is_private(self): + return self._private + + def set_private(self, private): + self._private = private + + private = gobject.property(type=object, getter=is_private, + setter=set_private) + + def get_buddies(self): + return self._buddies + + def add_buddy(self, buddy): + self._buddies.append(buddy) + self.notify('buddies') + self.emit('buddy-added', buddy) + + def remove_buddy(self, buddy): + self._buddies.remove(buddy) + self.notify('buddies') + self.emit('buddy-removed', buddy) + + buddies = gobject.property(type=object, getter=get_buddies) + + def get_current_buddies(self): + return self._current_buddies + + def add_current_buddy(self, buddy): + self._current_buddies.append(buddy) + self.notify('current-buddies') + self.emit('current-buddy-added', buddy) + + def remove_current_buddy(self, buddy): + self._current_buddies.remove(buddy) + self.notify('current-buddies') + self.emit('current-buddy-removed', buddy) + + current_buddies = gobject.property(type=object, getter=get_current_buddies) + + +class _Account(gobject.GObject): + __gsignals__ = { + 'activity-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object, object])), + 'activity-updated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object, object])), + 'activity-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'buddy-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object, object, object])), + 'buddy-updated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object, object])), + 'buddy-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'buddy-joined-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object, object])), + 'buddy-left-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object, object])), + 'current-activity-updated': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([object, object])), + 'connected': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), + 'disconnected': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), + } + + def __init__(self, account_path): + gobject.GObject.__init__(self) + + self.object_path = account_path + + self._connection = None + self._buddy_handles = {} + self._activity_handles = {} + self._self_handle = None + + self._buddies_per_activity = {} + self._activities_per_buddy = {} + + self._start_listening() + + def _start_listening(self): + bus = dbus.Bus() + obj = bus.get_object(ACCOUNT_MANAGER_SERVICE, self.object_path) + obj.Get(ACCOUNT, 'Connection', + reply_handler=self.__got_connection_cb, + error_handler=partial(self.__error_handler_cb, + 'Account.GetConnection')) + obj.connect_to_signal( + 'AccountPropertyChanged', self.__account_property_changed_cb) + + def __error_handler_cb(self, function_name, error): + raise RuntimeError('Error when calling %s: %s' % (function_name, + error)) + + def __got_connection_cb(self, connection_path): + #print('_Account.__got_connection_cb %r', connection_path) + + if connection_path == '/': + self._check_registration_error() + return + + self._prepare_connection(connection_path) + + def _check_registration_error(self): + """ + See if a previous connection attempt failed and we need to unset + the register flag. + """ + bus = dbus.Bus() + obj = bus.get_object(ACCOUNT_MANAGER_SERVICE, self.object_path) + obj.Get(ACCOUNT, 'ConnectionError', + reply_handler=self.__got_connection_error_cb, + error_handler=partial(self.__error_handler_cb, + 'Account.GetConnectionError')) + + def __got_connection_error_cb(self, error): + #print('_Account.__got_connection_error_cb %r', error) + if error == 'org.freedesktop.Telepathy.Error.RegistrationExists': + bus = dbus.Bus() + obj = bus.get_object(ACCOUNT_MANAGER_SERVICE, self.object_path) + obj.UpdateParameters({'register': False}, [], + dbus_interface=ACCOUNT) + + def __account_property_changed_cb(self, properties): + #print('_Account.__account_property_changed_cb %r %r %r', + #self.object_path, properties.get('Connection', None), + # self._connection) + if 'Connection' not in properties: + return + if properties['Connection'] == '/': + self._check_registration_error() + self._connection = None + elif self._connection is None: + self._prepare_connection(properties['Connection']) + + def _prepare_connection(self, connection_path): + connection_name = connection_path.replace('/', '.')[1:] + print("Preparing %s" % connection_name) + self._connection = Connection(connection_name, connection_path, + ready_handler=self.__connection_ready_cb) + + def __connection_ready_cb(self, connection): + print('_Account.__connection_ready_cb %r', connection.object_path) + connection.connect_to_signal('StatusChanged', + self.__status_changed_cb) + + connection[PROPERTIES_IFACE].Get(CONNECTION, + 'Status', + reply_handler=self.__get_status_cb, + error_handler=partial(self.__error_handler_cb, + 'Connection.GetStatus')) + + def __get_status_cb(self, status): + #print('_Account.__get_status_cb %r %r', + #self._connection.object_path, status) + self._update_status(status) + + def __status_changed_cb(self, status, reason): + #print('_Account.__status_changed_cb %r %r', status, reason) + self._update_status(status) + + def _update_status(self, status): + if status == CONNECTION_STATUS_CONNECTED: + self._connection[PROPERTIES_IFACE].Get(CONNECTION, + 'SelfHandle', + reply_handler=self.__get_self_handle_cb, + error_handler=partial(self.__error_handler_cb, + 'Connection.GetSelfHandle')) + self.emit('connected') + else: + for contact_handle, contact_id in self._buddy_handles.items(): + if contact_id is not None: + self.emit('buddy-removed', contact_id) + + for room_handle, activity_id in self._activity_handles.items(): + self.emit('activity-removed', activity_id) + + self._buddy_handles = {} + self._activity_handles = {} + self._buddies_per_activity = {} + self._activities_per_buddy = {} + + self.emit('disconnected') + + if status == CONNECTION_STATUS_DISCONNECTED: + self._connection = None + + def __get_self_handle_cb(self, self_handle): + self._self_handle = self_handle + + if CONNECTION_INTERFACE_CONTACT_CAPABILITIES in self._connection: + interface = CONNECTION_INTERFACE_CONTACT_CAPABILITIES + connection = self._connection[interface] + client_name = CLIENT + '.Sugar.FileTransfer' + file_transfer_channel_class = { + CHANNEL + '.ChannelType': CHANNEL_TYPE_FILE_TRANSFER, + CHANNEL + '.TargetHandleType': HANDLE_TYPE_CONTACT} + capabilities = [] + connection.UpdateCapabilities( + [(client_name, [file_transfer_channel_class], capabilities)], + reply_handler=self.__update_capabilities_cb, + error_handler=partial(self.__error_handler_cb, + 'Connection.UpdateCapabilities')) + + connection = self._connection[CONNECTION_INTERFACE_ALIASING] + connection.connect_to_signal('AliasesChanged', + self.__aliases_changed_cb) + + connection = self._connection[CONNECTION_INTERFACE_SIMPLE_PRESENCE] + connection.connect_to_signal('PresencesChanged', + self.__presences_changed_cb) + + if CONNECTION_INTERFACE_BUDDY_INFO in self._connection: + connection = self._connection[CONNECTION_INTERFACE_BUDDY_INFO] + connection.connect_to_signal('PropertiesChanged', + self.__buddy_info_updated_cb, + byte_arrays=True) + + connection.connect_to_signal('ActivitiesChanged', + self.__buddy_activities_changed_cb) + + connection.connect_to_signal('CurrentActivityChanged', + self.__current_activity_changed_cb) + else: + print('Connection %s does not support OLPC buddy ' + 'properties', self._connection.object_path) + pass + + if CONNECTION_INTERFACE_ACTIVITY_PROPERTIES in self._connection: + connection = self._connection[ + CONNECTION_INTERFACE_ACTIVITY_PROPERTIES] + connection.connect_to_signal( + 'ActivityPropertiesChanged', + self.__activity_properties_changed_cb) + else: + print('Connection %s does not support OLPC activity ' + 'properties', self._connection.object_path) + pass + + properties = { + CHANNEL + '.ChannelType': CHANNEL_TYPE_CONTACT_LIST, + CHANNEL + '.TargetHandleType': HANDLE_TYPE_LIST, + CHANNEL + '.TargetID': 'subscribe', + } + properties = dbus.Dictionary(properties, signature='sv') + connection = self._connection[CONNECTION_INTERFACE_REQUESTS] + is_ours, channel_path, properties = \ + connection.EnsureChannel(properties) + + channel = Channel(self._connection.service_name, channel_path) + channel[CHANNEL_INTERFACE_GROUP].connect_to_signal( + 'MembersChanged', self.__members_changed_cb) + + channel[PROPERTIES_IFACE].Get(CHANNEL_INTERFACE_GROUP, + 'Members', + reply_handler=self.__get_members_ready_cb, + error_handler=partial(self.__error_handler_cb, + 'Connection.GetMembers')) + + def __update_capabilities_cb(self): + pass + + def __aliases_changed_cb(self, aliases): + #print('_Account.__aliases_changed_cb') + for handle, alias in aliases: + if handle in self._buddy_handles: + #print('Got handle %r with nick %r, going to update', + # handle, alias) + properties = {CONNECTION_INTERFACE_ALIASING + '/alias': alias} + self.emit('buddy-updated', self._buddy_handles[handle], + properties) + + def __presences_changed_cb(self, presences): + #print('_Account.__presences_changed_cb %r', presences) + for handle, presence in presences.iteritems(): + if handle in self._buddy_handles: + presence_type, status_, message_ = presence + if presence_type == CONNECTION_PRESENCE_TYPE_OFFLINE: + contact_id = self._buddy_handles[handle] + del self._buddy_handles[handle] + self.emit('buddy-removed', contact_id) + + def __buddy_info_updated_cb(self, handle, properties): + #print('_Account.__buddy_info_updated_cb %r', handle) + self.emit('buddy-updated', self._buddy_handles[handle], properties) + + def __current_activity_changed_cb(self, contact_handle, activity_id, + room_handle): + #print('_Account.__current_activity_changed_cb %r %r %r', + # contact_handle, activity_id, room_handle) + if contact_handle in self._buddy_handles: + contact_id = self._buddy_handles[contact_handle] + if not activity_id and room_handle: + activity_id = self._activity_handles.get(room_handle, '') + self.emit('current-activity-updated', contact_id, activity_id) + + def __get_current_activity_cb(self, contact_handle, activity_id, + room_handle): + #print('_Account.__get_current_activity_cb %r %r %r', + # contact_handle, activity_id, room_handle) + contact_id = self._buddy_handles[contact_handle] + self.emit('current-activity-updated', contact_id, activity_id) + + def __buddy_activities_changed_cb(self, buddy_handle, activities): + self._update_buddy_activities(buddy_handle, activities) + + def _update_buddy_activities(self, buddy_handle, activities): + #print('_Account._update_buddy_activities') + if not buddy_handle in self._buddy_handles: + self._buddy_handles[buddy_handle] = None + + if not buddy_handle in self._activities_per_buddy: + self._activities_per_buddy[buddy_handle] = set() + + for activity_id, room_handle in activities: + if room_handle not in self._activity_handles: + self._activity_handles[room_handle] = activity_id + self.emit('activity-added', room_handle, activity_id) + + connection = self._connection[ + CONNECTION_INTERFACE_ACTIVITY_PROPERTIES] + connection.GetProperties(room_handle, + reply_handler=partial(self.__get_properties_cb, + room_handle), + error_handler=partial(self.__error_handler_cb, + 'ActivityProperties.GetProperties')) + + # Sometimes we'll get CurrentActivityChanged before we get to + # know about the activity so we miss the event. In that case, + # request again the current activity for this buddy. + connection = self._connection[CONNECTION_INTERFACE_BUDDY_INFO] + connection.GetCurrentActivity( + buddy_handle, + reply_handler=partial(self.__get_current_activity_cb, + buddy_handle), + error_handler=partial(self.__error_handler_cb, + 'BuddyInfo.GetCurrentActivity')) + + if not activity_id in self._buddies_per_activity: + self._buddies_per_activity[activity_id] = set() + self._buddies_per_activity[activity_id].add(buddy_handle) + if activity_id not in self._activities_per_buddy[buddy_handle]: + self._activities_per_buddy[buddy_handle].add(activity_id) + if self._buddy_handles[buddy_handle] is not None: + self.emit('buddy-joined-activity', + self._buddy_handles[buddy_handle], + activity_id) + + current_activity_ids = \ + [activity_id for activity_id, room_handle in activities] + for activity_id in self._activities_per_buddy[buddy_handle].copy(): + if not activity_id in current_activity_ids: + self._remove_buddy_from_activity(buddy_handle, activity_id) + + def __get_properties_cb(self, room_handle, properties): + #print('_Account.__get_properties_cb %r %r', room_handle, + # properties) + if properties: + self._update_activity(room_handle, properties) + + def _remove_buddy_from_activity(self, buddy_handle, activity_id): + if buddy_handle in self._buddies_per_activity[activity_id]: + self._buddies_per_activity[activity_id].remove(buddy_handle) + + if activity_id in self._activities_per_buddy[buddy_handle]: + self._activities_per_buddy[buddy_handle].remove(activity_id) + + if self._buddy_handles[buddy_handle] is not None: + self.emit('buddy-left-activity', + self._buddy_handles[buddy_handle], + activity_id) + + if not self._buddies_per_activity[activity_id]: + del self._buddies_per_activity[activity_id] + + for room_handle in self._activity_handles.copy(): + if self._activity_handles[room_handle] == activity_id: + del self._activity_handles[room_handle] + break + + self.emit('activity-removed', activity_id) + + def __activity_properties_changed_cb(self, room_handle, properties): + #print('_Account.__activity_properties_changed_cb %r %r', + # room_handle, properties) + self._update_activity(room_handle, properties) + + def _update_activity(self, room_handle, properties): + if room_handle in self._activity_handles: + self.emit('activity-updated', self._activity_handles[room_handle], + properties) + else: + #print('_Account.__activity_properties_changed_cb unknown ' + # 'activity') + # We don't get ActivitiesChanged for the owner of the connection, + # so we query for its activities in order to find out. + if CONNECTION_INTERFACE_BUDDY_INFO in self._connection: + handle = self._self_handle + connection = self._connection[CONNECTION_INTERFACE_BUDDY_INFO] + connection.GetActivities( + handle, + reply_handler=partial(self.__got_activities_cb, handle), + error_handler=partial(self.__error_handler_cb, + 'BuddyInfo.Getactivities')) + + def __members_changed_cb(self, message, added, removed, local_pending, + remote_pending, actor, reason): + self._add_buddy_handles(added) + + def __get_members_ready_cb(self, handles): + #print('_Account.__get_members_ready_cb %r', handles) + if not handles: + return + + self._add_buddy_handles(handles) + + def _add_buddy_handles(self, handles): + #print('_Account._add_buddy_handles %r', handles) + interfaces = [CONNECTION, CONNECTION_INTERFACE_ALIASING] + self._connection[CONNECTION_INTERFACE_CONTACTS].GetContactAttributes( + handles, interfaces, False, + reply_handler=self.__get_contact_attributes_cb, + error_handler=partial(self.__error_handler_cb, + 'Contacts.GetContactAttributes')) + + def __got_buddy_info_cb(self, handle, nick, properties): + #print('_Account.__got_buddy_info_cb %r', handle) + self.emit('buddy-updated', self._buddy_handles[handle], properties) + + def __get_contact_attributes_cb(self, attributes): + #print('_Account.__get_contact_attributes_cb %r', + # attributes.keys()) + + for handle in attributes.keys(): + nick = attributes[handle][CONNECTION_INTERFACE_ALIASING + '/alias'] + + if handle in self._buddy_handles and \ + not self._buddy_handles[handle] is None: + #print('Got handle %r with nick %r, going to update', + # handle, nick) + self.emit('buddy-updated', self._buddy_handles[handle], + attributes[handle]) + else: + #print('Got handle %r with nick %r, going to add', + # handle, nick) + + contact_id = attributes[handle][CONNECTION + '/contact-id'] + self._buddy_handles[handle] = contact_id + + if CONNECTION_INTERFACE_BUDDY_INFO in self._connection: + connection = \ + self._connection[CONNECTION_INTERFACE_BUDDY_INFO] + + connection.GetProperties( + handle, + reply_handler=partial(self.__got_buddy_info_cb, handle, + nick), + error_handler=partial(self.__error_handler_cb, + 'BuddyInfo.GetProperties'), + byte_arrays=True, + timeout=_QUERY_DBUS_TIMEOUT) + + connection.GetActivities( + handle, + reply_handler=partial(self.__got_activities_cb, + handle), + error_handler=partial(self.__error_handler_cb, + 'BuddyInfo.GetActivities'), + timeout=_QUERY_DBUS_TIMEOUT) + + connection.GetCurrentActivity( + handle, + reply_handler=partial(self.__get_current_activity_cb, + handle), + error_handler=partial(self.__error_handler_cb, + 'BuddyInfo.GetCurrentActivity'), + timeout=_QUERY_DBUS_TIMEOUT) + + self.emit('buddy-added', contact_id, nick, handle) + + def __got_activities_cb(self, buddy_handle, activities): + #print('_Account.__got_activities_cb %r %r', buddy_handle, + # activities) + self._update_buddy_activities(buddy_handle, activities) + + def enable(self): + #print('_Account.enable %s', self.object_path) + self._set_enabled(True) + + def disable(self): + #print('_Account.disable %s', self.object_path) + self._set_enabled(False) + self._connection = None + + def _set_enabled(self, value): + bus = dbus.Bus() + obj = bus.get_object(ACCOUNT_MANAGER_SERVICE, self.object_path) + obj.Set(ACCOUNT, 'Enabled', value, + reply_handler=self.__set_enabled_cb, + error_handler=partial(self.__error_handler_cb, + 'Account.SetEnabled'), + dbus_interface='org.freedesktop.DBus.Properties') + + def __set_enabled_cb(self): + #print('_Account.__set_enabled_cb success') + pass + + + +class Neighborhood(gobject.GObject): + __gsignals__ = { + 'activity-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'activity-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'buddy-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'buddy-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + } + + def __init__(self, params = {}): + gobject.GObject.__init__(self) + + self._buddies = {None: get_owner_instance()} + self._activities = {} + self._server_account = None + self._nicks = {} + + # + # Jabber params + # + self._nickname = params["nickname"] + self._account_id = params["account_id"] + self._server = params["server"] + self._port = params["port"] + self._password = params["password"] + self._register = params["register"] + + bus = dbus.Bus() + obj = bus.get_object(ACCOUNT_MANAGER_SERVICE, ACCOUNT_MANAGER_PATH) + account_manager = dbus.Interface(obj, ACCOUNT_MANAGER) + account_manager.Get(ACCOUNT_MANAGER, 'ValidAccounts', + dbus_interface=PROPERTIES_IFACE, + reply_handler=self.__got_accounts_cb, + error_handler=self.__error_handler_cb) + + def show_buddies(self): + print "\n\nBuddy list\n\n" + for k in self._nicks.keys(): + try: + print "%s = %s" % (k, self._nicks[k]) + except: + pass + + print "\n\nActivities list\n\n" + for k in self._activities.keys(): + try: + print "%s" % k + except: + pass + + def __got_accounts_cb(self, account_paths): + self._server_account = self._ensure_server_account(account_paths) + self._connect_to_account(self._server_account) + + def __error_handler_cb(self, error): + raise RuntimeError(error) + + + def _connect_to_account(self, account): + account.connect('buddy-added', self.__buddy_added_cb) + account.connect('buddy-updated', self.__buddy_updated_cb) + account.connect('buddy-removed', self.__buddy_removed_cb) + account.connect('buddy-joined-activity', + self.__buddy_joined_activity_cb) + account.connect('buddy-left-activity', self.__buddy_left_activity_cb) + account.connect('activity-added', self.__activity_added_cb) + account.connect('activity-updated', self.__activity_updated_cb) + account.connect('activity-removed', self.__activity_removed_cb) + account.connect('current-activity-updated', + self.__current_activity_updated_cb) + account.connect('connected', self.__account_connected_cb) + account.connect('disconnected', self.__account_disconnected_cb) + + def __account_connected_cb(self, account): + #print('__account_connected_cb %s', account.object_path) + if account == self._server_account: + #self._link_local_account.disable() + pass + + def __account_disconnected_cb(self, account): + #print('__account_disconnected_cb %s', account.object_path) + if account == self._server_account: + self._link_local_account.enable() + + def _ensure_link_local_account(self, account_paths): + for account_path in account_paths: + if 'salut' in account_path: + #print('Already have a Salut account') + account = _Account(account_path) + account.enable() + return account + + #print('Still dont have a Salut account, creating one') + + client = gconf.client_get_default() + nick = client.get_string('/desktop/sugar/user/nick') + + params = { + 'nickname': nick, + 'first-name': '', + 'last-name': '', + 'jid': self._get_jabber_account_id(), + 'published-name': nick, + } + + properties = { + ACCOUNT + '.Enabled': True, + ACCOUNT + '.Nickname': nick, + ACCOUNT + '.ConnectAutomatically': True, + } + + bus = dbus.Bus() + obj = bus.get_object(ACCOUNT_MANAGER_SERVICE, ACCOUNT_MANAGER_PATH) + account_manager = dbus.Interface(obj, ACCOUNT_MANAGER) + account_path = account_manager.CreateAccount('salut', 'local-xmpp', + 'salut', params, + properties) + return _Account(account_path) + + def _ensure_server_account(self, account_paths): + bus = dbus.Bus() + + for account_path in account_paths: + if 'gabble' in account_path: + obj_acct_mgr = bus.get_object(ACCOUNT_MANAGER_SERVICE, account_path) + properties = obj_acct_mgr.Get(ACCOUNT, 'Parameters') + if properties.has_key("server") and properties["server"] == self._server: + print("Enabiling account_path = %s, server = %s", account_path, self._server) + account = _Account(account_path) + account.enable() + return account + + params = { + 'account': self._get_jabber_account_id(), + 'password': self._password, + 'server': self._server, + 'resource': 'sugar', + 'require-encryption': True, + 'ignore-ssl-errors': True, + 'register': self._register, + 'old-ssl': True, + 'port': dbus.UInt32(self._port), + } + + properties = { + ACCOUNT + '.Enabled': True, + ACCOUNT + '.Nickname': self._nickname, + ACCOUNT + '.ConnectAutomatically': True, + } + + obj = bus.get_object(ACCOUNT_MANAGER_SERVICE, ACCOUNT_MANAGER_PATH) + account_manager = dbus.Interface(obj, ACCOUNT_MANAGER) + account_path = account_manager.CreateAccount('gabble', 'jabber', + 'jabber', params, + properties) + return _Account(account_path) + + def _get_jabber_account_id(self): + return self._account_id + + def __jabber_server_changed_cb(self, client, timestamp, entry, *extra): + #print('__jabber_server_changed_cb') + + bus = dbus.Bus() + account = bus.get_object(ACCOUNT_MANAGER_SERVICE, + self._server_account.object_path) + + server = client.get_string( + '/desktop/sugar/collaboration/jabber_server') + account_id = self._get_jabber_account_id() + needs_reconnect = account.UpdateParameters({'server': server, + 'account': account_id, + 'register': True}, + dbus.Array([], 's'), + dbus_interface=ACCOUNT) + if needs_reconnect: + account.Reconnect() + + self._update_jid() + + def __nick_changed_cb(self, client, timestamp, entry, *extra): + nick = client.get_string('/desktop/sugar/user/nick') + for account in self._server_account, self._link_local_account: + bus = dbus.Bus() + obj = bus.get_object(ACCOUNT_MANAGER_SERVICE, account.object_path) + obj.Set(ACCOUNT, 'Nickname', nick, dbus_interface=PROPERTIES_IFACE) + + self._update_jid() + + def _update_jid(self): + bus = dbus.Bus() + account = bus.get_object(ACCOUNT_MANAGER_SERVICE, + self._link_local_account.object_path) + + account_id = self._get_jabber_account_id() + needs_reconnect = account.UpdateParameters({'jid': account_id}, + dbus.Array([], 's'), + dbus_interface=ACCOUNT) + if needs_reconnect: + account.Reconnect() + + def __buddy_added_cb(self, account, contact_id, nick, handle): + + self._nicks[contact_id] = nick + if contact_id in self._buddies: + #print('__buddy_added_cb buddy already tracked') + return + + buddy = BuddyModel( + nick=nick, + account=account.object_path, + contact_id=contact_id, + handle=handle) + self._buddies[contact_id] = buddy + + def __buddy_updated_cb(self, account, contact_id, properties): + #print('__buddy_updated_cb %r', contact_id) + if contact_id is None: + # Don't know the contact-id yet, will get the full state later + return + + if contact_id not in self._buddies: + #print('__buddy_updated_cb Unknown buddy with contact_id' + # ' %r', contact_id) + return + + buddy = self._buddies[contact_id] + + is_new = buddy.props.key is None and 'key' in properties + + if 'color' in properties: + buddy.props.color = XoColor(properties['color']) + + if 'key' in properties: + buddy.props.key = properties['key'] + + if 'nick' in properties: + buddy.props.nick = properties['nick'] + + if is_new: + self.emit('buddy-added', buddy) + + def __buddy_removed_cb(self, account, contact_id): + #print('Neighborhood.__buddy_removed_cb %r', contact_id) + try: + self._nicks.pop(contact_id) + except: + pass + if contact_id not in self._buddies: + #print('Neighborhood.__buddy_removed_cb Unknown buddy with ' + # 'contact_id %r', contact_id) + return + + buddy = self._buddies[contact_id] + del self._buddies[contact_id] + + if buddy.props.key is not None: + self.emit('buddy-removed', buddy) + + def __activity_added_cb(self, account, room_handle, activity_id): + #print('__activity_added_cb %r %r', room_handle, activity_id) + if activity_id in self._activities: + #print('__activity_added_cb activity already tracked') + return + + activity = ActivityModel(activity_id, room_handle) + self._activities[activity_id] = activity + + def __activity_updated_cb(self, account, activity_id, properties): + print('__activity_updated_cb %r %r', activity_id, properties) + if activity_id not in self._activities: + print('__activity_updated_cb Unknown activity with activity_id %r', activity_id) + return + + # we should somehow emulate this and say we only have TurtleArtActivity + #registry = bundleregistry.get_registry() + #bundle = registry.get_bundle(properties['type']) + #bundle = None + #if not bundle: + # print('Ignoring shared activity we don''t have') + # return + + activity = self._activities[activity_id] + + is_new = activity.props.bundle is None + + if 'color' in properties: + activity.props.color = XoColor(properties['color']) + activity.props.bundle = None # FIXME: we have no access to the bundleregistry + if 'name' in properties: + activity.props.name = properties['name'] + if 'private' in properties: + activity.props.private = properties['private'] + # FIXME: this should be configurable, we only care about the activity thats using this lib + # i.e.: Turtle Art + if properties['type']: + activity.props.bundle = properties['type'] + + if is_new: + print "The activity is new" + self.emit('activity-added', activity) + else: + print "The activity is *NOT* new" + + def __activity_removed_cb(self, account, activity_id): + if activity_id not in self._activities: + print('Unknown activity with id %s. Already removed?', activity_id) + return + activity = self._activities[activity_id] + del self._activities[activity_id] + + self.emit('activity-removed', activity) + + def __current_activity_updated_cb(self, account, contact_id, activity_id): + #print('__current_activity_updated_cb %r %r', contact_id, + # activity_id) + if contact_id not in self._buddies: + #print('__current_activity_updated_cb Unknown buddy with ' + # 'contact_id %r', contact_id) + return + if activity_id and activity_id not in self._activities: + #print('__current_activity_updated_cb Unknown activity with' + # ' id %s', activity_id) + activity_id = '' + + buddy = self._buddies[contact_id] + if buddy.props.current_activity is not None: + if buddy.props.current_activity.activity_id == activity_id: + return + buddy.props.current_activity.remove_current_buddy(buddy) + + if activity_id: + activity = self._activities[activity_id] + buddy.props.current_activity = activity + activity.add_current_buddy(buddy) + else: + buddy.props.current_activity = None + + def __buddy_joined_activity_cb(self, account, contact_id, activity_id): + if contact_id not in self._buddies: + #print('__buddy_joined_activity_cb Unknown buddy with ' + # 'contact_id %r', contact_id) + return + + if activity_id not in self._activities: + #print('__buddy_joined_activity_cb Unknown activity with ' + # 'activity_id %r', activity_id) + return + + self._activities[activity_id].add_buddy(self._buddies[contact_id]) + + def __buddy_left_activity_cb(self, account, contact_id, activity_id): + if contact_id not in self._buddies: + #print('__buddy_left_activity_cb Unknown buddy with ' + # 'contact_id %r', contact_id) + return + + if activity_id not in self._activities: + #print('__buddy_left_activity_cb Unknown activity with ' + # 'activity_id %r', activity_id) + return + + self._activities[activity_id].remove_buddy(self._buddies[contact_id]) + + def get_buddies(self): + return self._buddies.values() + + def get_buddy_by_key(self, key): + for buddy in self._buddies.values(): + if buddy.key == key: + return buddy + return None + + def get_buddy_by_handle(self, contact_handle): + for buddy in self._buddies.values(): + if not buddy.is_owner() and buddy.handle == contact_handle: + return buddy + return None + + def get_activity(self, activity_id): + return self._activities.get(activity_id, None) + + def get_activity_by_room(self, room_handle): + for activity in self._activities.values(): + if activity.room_handle == room_handle: + return activity + return None + + def get_activities(self): + return self._activities.values() + +_neighborhood = None +def get_neighborhood(params = {}): + global _neighborhood + if _neighborhood is None: + _neighborhood = Neighborhood(params) + return _neighborhood + +if __name__ == "__main__": + params = {} + params["nickname"] = "test" + params["account_id"] = "test" + params["server"] = "localhost" + params["port"] = 5223 + params["password"] = "test" + params["register"] = True + + loop = gobject.MainLoop() + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + n = get_neighborhood(params) + loop.run() diff --git a/collaboration/presenceservice.py b/collaboration/presenceservice.py new file mode 100644 index 0000000..33caadd --- /dev/null +++ b/collaboration/presenceservice.py @@ -0,0 +1,271 @@ +# Copyright (C) 2007, Red Hat, Inc. +# Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +""" +STABLE. +""" + +import logging + +import gobject +import dbus +import dbus.exceptions +import dbus.glib +from dbus import PROPERTIES_IFACE + +""" FIXME ... """ +try: + from sugar.presence.buddy import Buddy, Owner + from sugar.presence.activity import Activity + from sugar.presence.connectionmanager import get_connection_manager +except: + pass + +from telepathy.interfaces import ACCOUNT, \ + ACCOUNT_MANAGER, \ + CONNECTION +from telepathy.constants import HANDLE_TYPE_CONTACT + + +_logger = logging.getLogger('sugar.presence.presenceservice') + +ACCOUNT_MANAGER_SERVICE = 'org.freedesktop.Telepathy.AccountManager' +ACCOUNT_MANAGER_PATH = '/org/freedesktop/Telepathy/AccountManager' + +CONN_INTERFACE_ACTIVITY_PROPERTIES = 'org.laptop.Telepathy.ActivityProperties' + + +class PresenceService(gobject.GObject): + """Provides simplified access to the Telepathy framework to activities""" + __gsignals__ = { + 'activity-shared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, + gobject.TYPE_PYOBJECT])), + } + + def __init__(self): + """Initialise the service and attempt to connect to events + """ + gobject.GObject.__init__(self) + + self._activity_cache = None + self._buddy_cache = {} + + def get_activity(self, activity_id, warn_if_none=True): + """Retrieve single Activity object for the given unique id + + activity_id -- unique ID for the activity + + returns single Activity object or None if the activity + is not found using GetActivityById on the service + """ + if self._activity_cache is not None: + if self._activity_cache.props.id != activity_id: + raise RuntimeError('Activities can only access their own' + ' shared instance') + return self._activity_cache + else: + connection_manager = get_connection_manager() + connections_per_account = \ + connection_manager.get_connections_per_account() + for account_path, connection in connections_per_account.items(): + if not connection.connected: + continue + logging.debug('Calling GetActivity on %s', account_path) + try: + room_handle = connection.connection.GetActivity( + activity_id, + dbus_interface=CONN_INTERFACE_ACTIVITY_PROPERTIES) + except dbus.exceptions.DBusException, e: + name = 'org.freedesktop.Telepathy.Error.NotAvailable' + if e.get_dbus_name() == name: + logging.debug("There's no shared activity with the id " + "%s" % (activity_id)) + else: + raise + else: + activity = Activity(account_path, connection.connection, + room_handle=room_handle) + self._activity_cache = activity + return activity + + return None + + def get_activity_by_handle(self, connection_path, room_handle): + if self._activity_cache is not None: + if self._activity_cache.room_handle != room_handle: + raise RuntimeError('Activities can only access their own' + ' shared instance') + return self._activity_cache + else: + connection_manager = get_connection_manager() + account_path = \ + connection_manager.get_account_for_connection(connection_path) + + connection_name = connection_path.replace('/', '.')[1:] + bus = dbus.SessionBus() + connection = bus.get_object(connection_name, connection_path) + activity = Activity(account_path, connection, + room_handle=room_handle) + self._activity_cache = activity + return activity + + def get_buddy(self, account_path, contact_id): + if (account_path, contact_id) in self._buddy_cache: + return self._buddy_cache[(account_path, contact_id)] + + buddy = Buddy(account_path, contact_id) + self._buddy_cache[(account_path, contact_id)] = buddy + return buddy + + # DEPRECATED + def get_buddy_by_telepathy_handle(self, tp_conn_name, tp_conn_path, + handle): + """Retrieve single Buddy object for the given public key + + :Parameters: + `tp_conn_name` : str + The well-known bus name of a Telepathy connection + `tp_conn_path` : dbus.ObjectPath + The object path of the Telepathy connection + `handle` : int or long + The handle of a Telepathy contact on that connection, + of type HANDLE_TYPE_CONTACT. This may not be a + channel-specific handle. + :Returns: the Buddy object, or None if the buddy is not found + """ + + bus = dbus.Bus() + obj = bus.get_object(ACCOUNT_MANAGER_SERVICE, ACCOUNT_MANAGER_PATH) + account_manager = dbus.Interface(obj, ACCOUNT_MANAGER) + account_paths = account_manager.Get(ACCOUNT_MANAGER, 'ValidAccounts', + dbus_interface=PROPERTIES_IFACE) + for account_path in account_paths: + obj = bus.get_object(ACCOUNT_MANAGER_SERVICE, account_path) + connection_path = obj.Get(ACCOUNT, 'Connection') + if connection_path == tp_conn_path: + connection_name = connection_path.replace('/', '.')[1:] + connection = bus.get_object(connection_name, connection_path) + contact_ids = connection.InspectHandles(HANDLE_TYPE_CONTACT, + [handle], + dbus_interface=CONNECTION) + return self.get_buddy(account_path, contact_ids[0]) + + raise ValueError('Unknown buddy in connection %s with handle %d' % \ + (tp_conn_path, handle)) + + def get_owner(self): + """Retrieves the laptop Buddy object.""" + #return Owner() + return None + + def __share_activity_cb(self, activity): + """Finish sharing the activity + """ + self.emit('activity-shared', True, activity, None) + + def __share_activity_error_cb(self, activity, error): + """Notify with GObject event of unsuccessful sharing of activity + """ + self.emit('activity-shared', False, activity, error) + + def share_activity(self, activity, properties=None, private=True): + if properties is None: + properties = {} + + if 'id' not in properties: + properties['id'] = activity.get_id() + + if 'type' not in properties: + properties['type'] = activity.get_bundle_id() + + if 'name' not in properties: + properties['name'] = activity.metadata.get('title', None) + + if 'color' not in properties: + properties['color'] = activity.metadata.get('icon-color', None) + + properties['private'] = private + + if self._activity_cache is not None: + raise ValueError('Activity %s is already tracked' % \ + (activity.get_id())) + + connection_manager = get_connection_manager() + account_path, connection = \ + connection_manager.get_preferred_connection() + + if connection is None: + self.emit('activity-shared', False, None, + 'No active connection available') + return + + shared_activity = Activity(account_path, connection, + properties=properties) + self._activity_cache = shared_activity + + if shared_activity.props.joined: + raise RuntimeError('Activity %s is already shared.' % \ + (activity.props.id)) + + shared_activity.share(self.__share_activity_cb, + self.__share_activity_error_cb) + + def get_preferred_connection(self): + """Gets the preferred telepathy connection object that an activity + should use when talking directly to telepathy + + returns the bus name and the object path of the Telepathy connection + """ + manager = get_connection_manager() + account_path, connection = manager.get_preferred_connection() + if connection is None: + return None + else: + return connection.requested_bus_name, connection.object_path + + # DEPRECATED + def get(self, object_path): + raise NotImplementedError() + + # DEPRECATED + def get_activities(self): + raise NotImplementedError() + + # DEPRECATED + def get_activities_async(self, reply_handler=None, error_handler=None): + raise NotImplementedError() + + # DEPRECATED + def get_buddies(self): + raise NotImplementedError() + + # DEPRECATED + def get_buddies_async(self, reply_handler=None, error_handler=None): + raise NotImplementedError() + + +_ps = None + + +def get_instance(allow_offline_iface=False): + """Retrieve this process' view of the PresenceService""" + global _ps + if not _ps: + _ps = PresenceService() + return _ps diff --git a/collaboration/telepathyclient.py b/collaboration/telepathyclient.py new file mode 100644 index 0000000..e00f053 --- /dev/null +++ b/collaboration/telepathyclient.py @@ -0,0 +1,105 @@ +# Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import logging + +import dbus +from dbus import PROPERTIES_IFACE + +from telepathy.interfaces import CLIENT, \ + CLIENT_APPROVER, \ + CLIENT_HANDLER, \ + CLIENT_INTERFACE_REQUESTS +from telepathy.server import DBusProperties + +import dispatch + + +SUGAR_CLIENT_SERVICE = 'org.freedesktop.Telepathy.Client.Sugar' +SUGAR_CLIENT_PATH = '/org/freedesktop/Telepathy/Client/Sugar' + +_instance = None + + +class TelepathyClient(dbus.service.Object, DBusProperties): + + def __init__(self): + self._interfaces = set([CLIENT, CLIENT_HANDLER, + CLIENT_INTERFACE_REQUESTS, PROPERTIES_IFACE, + CLIENT_APPROVER]) + + bus = dbus.Bus() + bus_name = dbus.service.BusName(SUGAR_CLIENT_SERVICE, bus=bus) + + dbus.service.Object.__init__(self, bus_name, SUGAR_CLIENT_PATH) + DBusProperties.__init__(self) + + self._implement_property_get(CLIENT, { + 'Interfaces': lambda: list(self._interfaces), + }) + self._implement_property_get(CLIENT_HANDLER, { + 'HandlerChannelFilter': self.__get_filters_cb, + }) + self._implement_property_get(CLIENT_APPROVER, { + 'ApproverChannelFilter': self.__get_filters_cb, + }) + + self.got_channel = dispatch.Signal() + self.got_dispatch_operation = dispatch.Signal() + + def __get_filters_cb(self): + logging.debug('__get_filters_cb') + filter_dict = dbus.Dictionary({}, signature='sv') + return dbus.Array([filter_dict], signature='a{sv}') + + @dbus.service.method(dbus_interface=CLIENT_HANDLER, + in_signature='ooa(oa{sv})aota{sv}', out_signature='') + def HandleChannels(self, account, connection, channels, requests_satisfied, + user_action_time, handler_info): + logging.debug('HandleChannels\n%r\n%r\n%r\n%r\n%r\n%r\n', account, + connection, channels, requests_satisfied, + user_action_time, handler_info) + for channel in channels: + self.got_channel.send(self, account=account, + connection=connection, channel=channel) + + @dbus.service.method(dbus_interface=CLIENT_INTERFACE_REQUESTS, + in_signature='oa{sv}', out_signature='') + def AddRequest(self, request, properties): + logging.debug('AddRequest\n%r\n%r', request, properties) + + @dbus.service.method(dbus_interface=CLIENT_APPROVER, + in_signature='a(oa{sv})oa{sv}', out_signature='', + async_callbacks=('success_cb', 'error_cb_')) + def AddDispatchOperation(self, channels, dispatch_operation_path, + properties, success_cb, error_cb_): + success_cb() + try: + logging.debug('AddDispatchOperation\n%r\n%r\n%r', channels, + dispatch_operation_path, properties) + + self.got_dispatch_operation.send(self, channels=channels, + dispatch_operation_path=dispatch_operation_path, + properties=properties) + except Exception, e: + logging.exception(e) + + +def get_instance(): + global _instance + if not _instance: + _instance = TelepathyClient() + return _instance diff --git a/collaboration/test.py b/collaboration/test.py new file mode 100755 index 0000000..db7be0d --- /dev/null +++ b/collaboration/test.py @@ -0,0 +1,14 @@ +#!/usr/bin/python + +import gobject +import dbus +import dbus.mainloop +import dbus.mainloop.glib +from connectionmanager import get_connection_manager + +dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + +conn_manager = get_connection_manager() +account_path, connection = conn_manager.get_preferred_connection() +print account_path diff --git a/collaboration/tubeconn.py b/collaboration/tubeconn.py new file mode 100644 index 0000000..1014a46 --- /dev/null +++ b/collaboration/tubeconn.py @@ -0,0 +1,114 @@ +# This should eventually land in telepathy-python, so has the same license: + +# Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +""" +STABLE. +""" + +__all__ = ('TubeConnection', ) +__docformat__ = 'reStructuredText' + + +import logging + +from dbus.connection import Connection + + +logger = logging.getLogger('telepathy.tubeconn') + + +class TubeConnection(Connection): + + def __new__(cls, conn, tubes_iface, tube_id, address=None, + group_iface=None, mainloop=None): + # pylint: disable=W0212 + # Confused by __new__ + if address is None: + address = tubes_iface.GetDBusTubeAddress(tube_id) + self = super(TubeConnection, cls).__new__(cls, address, + mainloop=mainloop) + + self._tubes_iface = tubes_iface + self.tube_id = tube_id + self.participants = {} + self.bus_name_to_handle = {} + self._mapping_watches = [] + + if group_iface is None: + method = conn.GetSelfHandle + else: + method = group_iface.GetSelfHandle + method(reply_handler=self._on_get_self_handle_reply, + error_handler=self._on_get_self_handle_error) + + return self + + def _on_get_self_handle_reply(self, handle): + # pylint: disable=W0201 + # Confused by __new__ + self.self_handle = handle + match = self._tubes_iface.connect_to_signal('DBusNamesChanged', + self._on_dbus_names_changed) + self._tubes_iface.GetDBusNames(self.tube_id, + reply_handler=self._on_get_dbus_names_reply, + error_handler=self._on_get_dbus_names_error) + self._dbus_names_changed_match = match + + def _on_get_self_handle_error(self, e): + logging.basicConfig() + logger.error('GetSelfHandle failed: %s', e) + + def close(self): + self._dbus_names_changed_match.remove() + self._on_dbus_names_changed(self.tube_id, (), self.participants.keys()) + super(TubeConnection, self).close() + + def _on_get_dbus_names_reply(self, names): + self._on_dbus_names_changed(self.tube_id, names, ()) + + def _on_get_dbus_names_error(self, e): + logging.basicConfig() + logger.error('GetDBusNames failed: %s', e) + + def _on_dbus_names_changed(self, tube_id, added, removed): + if tube_id == self.tube_id: + for handle, bus_name in added: + if handle == self.self_handle: + # I've just joined - set my unique name + self.set_unique_name(bus_name) + self.participants[handle] = bus_name + self.bus_name_to_handle[bus_name] = handle + + # call the callback while the removed people are still in + # participants, so their bus names are available + for callback in self._mapping_watches: + callback(added, removed) + + for handle in removed: + bus_name = self.participants.pop(handle, None) + self.bus_name_to_handle.pop(bus_name, None) + + def watch_participants(self, callback): + self._mapping_watches.append(callback) + if self.participants: + # GetDBusNames already returned: fake a participant add event + # immediately + added = [] + for k, v in self.participants.iteritems(): + added.append((k, v)) + callback(added, []) diff --git a/collaboration/xocolor.py b/collaboration/xocolor.py new file mode 100644 index 0000000..395e345 --- /dev/null +++ b/collaboration/xocolor.py @@ -0,0 +1,282 @@ +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +""" +STABLE. +""" + +import random +import logging + +import gconf + +colors = [ +['#B20008', '#FF2B34'], \ +['#FF2B34', '#B20008'], \ +['#E6000A', '#FF2B34'], \ +['#FF2B34', '#E6000A'], \ +['#FFADCE', '#FF2B34'], \ +['#9A5200', '#FF2B34'], \ +['#FF2B34', '#9A5200'], \ +['#FF8F00', '#FF2B34'], \ +['#FF2B34', '#FF8F00'], \ +['#FFC169', '#FF2B34'], \ +['#807500', '#FF2B34'], \ +['#FF2B34', '#807500'], \ +['#BE9E00', '#FF2B34'], \ +['#FF2B34', '#BE9E00'], \ +['#F8E800', '#FF2B34'], \ +['#008009', '#FF2B34'], \ +['#FF2B34', '#008009'], \ +['#00B20D', '#FF2B34'], \ +['#FF2B34', '#00B20D'], \ +['#8BFF7A', '#FF2B34'], \ +['#00588C', '#FF2B34'], \ +['#FF2B34', '#00588C'], \ +['#005FE4', '#FF2B34'], \ +['#FF2B34', '#005FE4'], \ +['#BCCDFF', '#FF2B34'], \ +['#5E008C', '#FF2B34'], \ +['#FF2B34', '#5E008C'], \ +['#7F00BF', '#FF2B34'], \ +['#FF2B34', '#7F00BF'], \ +['#D1A3FF', '#FF2B34'], \ +['#9A5200', '#FF8F00'], \ +['#FF8F00', '#9A5200'], \ +['#C97E00', '#FF8F00'], \ +['#FF8F00', '#C97E00'], \ +['#FFC169', '#FF8F00'], \ +['#807500', '#FF8F00'], \ +['#FF8F00', '#807500'], \ +['#BE9E00', '#FF8F00'], \ +['#FF8F00', '#BE9E00'], \ +['#F8E800', '#FF8F00'], \ +['#008009', '#FF8F00'], \ +['#FF8F00', '#008009'], \ +['#00B20D', '#FF8F00'], \ +['#FF8F00', '#00B20D'], \ +['#8BFF7A', '#FF8F00'], \ +['#00588C', '#FF8F00'], \ +['#FF8F00', '#00588C'], \ +['#005FE4', '#FF8F00'], \ +['#FF8F00', '#005FE4'], \ +['#BCCDFF', '#FF8F00'], \ +['#5E008C', '#FF8F00'], \ +['#FF8F00', '#5E008C'], \ +['#A700FF', '#FF8F00'], \ +['#FF8F00', '#A700FF'], \ +['#D1A3FF', '#FF8F00'], \ +['#B20008', '#FF8F00'], \ +['#FF8F00', '#B20008'], \ +['#FF2B34', '#FF8F00'], \ +['#FF8F00', '#FF2B34'], \ +['#FFADCE', '#FF8F00'], \ +['#807500', '#F8E800'], \ +['#F8E800', '#807500'], \ +['#BE9E00', '#F8E800'], \ +['#F8E800', '#BE9E00'], \ +['#FFFA00', '#EDDE00'], \ +['#008009', '#F8E800'], \ +['#F8E800', '#008009'], \ +['#00EA11', '#F8E800'], \ +['#F8E800', '#00EA11'], \ +['#8BFF7A', '#F8E800'], \ +['#00588C', '#F8E800'], \ +['#F8E800', '#00588C'], \ +['#00A0FF', '#F8E800'], \ +['#F8E800', '#00A0FF'], \ +['#BCCEFF', '#F8E800'], \ +['#5E008C', '#F8E800'], \ +['#F8E800', '#5E008C'], \ +['#AC32FF', '#F8E800'], \ +['#F8E800', '#AC32FF'], \ +['#D1A3FF', '#F8E800'], \ +['#B20008', '#F8E800'], \ +['#F8E800', '#B20008'], \ +['#FF2B34', '#F8E800'], \ +['#F8E800', '#FF2B34'], \ +['#FFADCE', '#F8E800'], \ +['#9A5200', '#F8E800'], \ +['#F8E800', '#9A5200'], \ +['#FF8F00', '#F8E800'], \ +['#F8E800', '#FF8F00'], \ +['#FFC169', '#F8E800'], \ +['#008009', '#00EA11'], \ +['#00EA11', '#008009'], \ +['#00B20D', '#00EA11'], \ +['#00EA11', '#00B20D'], \ +['#8BFF7A', '#00EA11'], \ +['#00588C', '#00EA11'], \ +['#00EA11', '#00588C'], \ +['#005FE4', '#00EA11'], \ +['#00EA11', '#005FE4'], \ +['#BCCDFF', '#00EA11'], \ +['#5E008C', '#00EA11'], \ +['#00EA11', '#5E008C'], \ +['#7F00BF', '#00EA11'], \ +['#00EA11', '#7F00BF'], \ +['#D1A3FF', '#00EA11'], \ +['#B20008', '#00EA11'], \ +['#00EA11', '#B20008'], \ +['#FF2B34', '#00EA11'], \ +['#00EA11', '#FF2B34'], \ +['#FFADCE', '#00EA11'], \ +['#9A5200', '#00EA11'], \ +['#00EA11', '#9A5200'], \ +['#FF8F00', '#00EA11'], \ +['#00EA11', '#FF8F00'], \ +['#FFC169', '#00EA11'], \ +['#807500', '#00EA11'], \ +['#00EA11', '#807500'], \ +['#BE9E00', '#00EA11'], \ +['#00EA11', '#BE9E00'], \ +['#F8E800', '#00EA11'], \ +['#00588C', '#00A0FF'], \ +['#00A0FF', '#00588C'], \ +['#005FE4', '#00A0FF'], \ +['#00A0FF', '#005FE4'], \ +['#BCCDFF', '#00A0FF'], \ +['#5E008C', '#00A0FF'], \ +['#00A0FF', '#5E008C'], \ +['#9900E6', '#00A0FF'], \ +['#00A0FF', '#9900E6'], \ +['#D1A3FF', '#00A0FF'], \ +['#B20008', '#00A0FF'], \ +['#00A0FF', '#B20008'], \ +['#FF2B34', '#00A0FF'], \ +['#00A0FF', '#FF2B34'], \ +['#FFADCE', '#00A0FF'], \ +['#9A5200', '#00A0FF'], \ +['#00A0FF', '#9A5200'], \ +['#FF8F00', '#00A0FF'], \ +['#00A0FF', '#FF8F00'], \ +['#FFC169', '#00A0FF'], \ +['#807500', '#00A0FF'], \ +['#00A0FF', '#807500'], \ +['#BE9E00', '#00A0FF'], \ +['#00A0FF', '#BE9E00'], \ +['#F8E800', '#00A0FF'], \ +['#008009', '#00A0FF'], \ +['#00A0FF', '#008009'], \ +['#00B20D', '#00A0FF'], \ +['#00A0FF', '#00B20D'], \ +['#8BFF7A', '#00A0FF'], \ +['#5E008C', '#AC32FF'], \ +['#AC32FF', '#5E008C'], \ +['#7F00BF', '#AC32FF'], \ +['#AC32FF', '#7F00BF'], \ +['#D1A3FF', '#AC32FF'], \ +['#B20008', '#AC32FF'], \ +['#AC32FF', '#B20008'], \ +['#FF2B34', '#AC32FF'], \ +['#AC32FF', '#FF2B34'], \ +['#FFADCE', '#AC32FF'], \ +['#9A5200', '#AC32FF'], \ +['#AC32FF', '#9A5200'], \ +['#FF8F00', '#AC32FF'], \ +['#AC32FF', '#FF8F00'], \ +['#FFC169', '#AC32FF'], \ +['#807500', '#AC32FF'], \ +['#AC32FF', '#807500'], \ +['#BE9E00', '#AC32FF'], \ +['#AC32FF', '#BE9E00'], \ +['#F8E800', '#AC32FF'], \ +['#008009', '#AC32FF'], \ +['#AC32FF', '#008009'], \ +['#00B20D', '#AC32FF'], \ +['#AC32FF', '#00B20D'], \ +['#8BFF7A', '#AC32FF'], \ +['#00588C', '#AC32FF'], \ +['#AC32FF', '#00588C'], \ +['#005FE4', '#AC32FF'], \ +['#AC32FF', '#005FE4'], \ +['#BCCDFF', '#AC32FF'], \ +] + + +def _parse_string(color_string): + if not isinstance(color_string, (str, unicode)): + logging.error('Invalid color string: %r', color_string) + return None + + if color_string == 'white': + return ['#ffffff', '#414141'] + elif color_string == 'insensitive': + return ['#ffffff', '#e2e2e2'] + + splitted = color_string.split(',') + if len(splitted) == 2: + return [splitted[0], splitted[1]] + else: + return None + + +def is_valid(color_string): + return (_parse_string(color_string) != None) + + +class XoColor: + + def __init__(self, color_string=None): + if color_string == None: + randomize = True + elif not is_valid(color_string): + logging.debug('Color string is not valid: %s, ' + 'fallback to default', color_string) + client = gconf.client_get_default() + color_string = client.get_string('/desktop/sugar/user/color') + randomize = False + else: + randomize = False + + if randomize: + n = int(random.random() * (len(colors) - 1)) + [self.stroke, self.fill] = colors[n] + else: + [self.stroke, self.fill] = _parse_string(color_string) + + def __cmp__(self, other): + if isinstance(other, XoColor): + if self.stroke == other.stroke and self.fill == other.fill: + return 0 + return -1 + + def get_stroke_color(self): + return self.stroke + + def get_fill_color(self): + return self.fill + + def to_string(self): + return '%s,%s' % (self.stroke, self.fill) + + +if __name__ == '__main__': + import sys + import re + + f = open(sys.argv[1], 'r') + + print 'colors = [' + + for line in f.readlines(): + match = re.match(r'fill: ([A-Z0-9]*) stroke: ([A-Z0-9]*)', line) + print "['#%s', '#%s'], \\" % (match.group(2), match.group(1)) + + print ']' + + f.close() diff --git a/gnome_plugins/__init__.py b/gnome_plugins/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/gnome_plugins/__init__.py diff --git a/gnome_plugins/collaboration_plugin.py b/gnome_plugins/collaboration_plugin.py new file mode 100644 index 0000000..19c084b --- /dev/null +++ b/gnome_plugins/collaboration_plugin.py @@ -0,0 +1,350 @@ +#!/usr/bin/env python +#Copyright (c) 2011 Walter Bender +#Copyright (c) 2011 Collabora Ltd. <http://www.collabora.co.uk/> + +#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 sys +sys.path.append("..") +import os.path + +import dbus +from gettext import gettext as _ +import gobject +import gtk + +from plugin import Plugin + +from util.menubuilder import MenuBuilder +from util.configfile import ConfigFile +from util.configwizard import ConfigWizard + +import telepathy +from collaboration.neighborhood import get_neighborhood +from collaboration.connectionmanager import get_connection_manager +from collaboration.activity import Activity +from collaboration import telepathyclient +from collaboration.tubeconn import TubeConnection + +from TurtleArt.tacollaboration import Collaboration + +import traceback + +CONNECTION_INTERFACE_ACTIVITY_PROPERTIES = \ + 'org.laptop.Telepathy.ActivityProperties' + + +class Collaboration_plugin(Plugin): + + __gsignals__ = { + 'joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ()), + 'shared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ()), + } + + def __init__(self, parent): + Plugin.__init__(self) + + self._parent = parent + self._neighborhood = None + self._title = _('My Turtle Art session') + self._bundle_id = "org.laptop.TurtleArt" + # This could be hashed from the file path (if resuming) + self._activity_id = "1234567" + self._nick = "" + self._setup_has_been_called = False + + def _setup_config_file(self, config_file_path): + self._config_file_path = os.path.join(config_file_path, + 'turtleartrc.collab') + self._collaboration_config_values = ConfigFile(self._config_file_path) + self._valid_config_values = { + 'nick': {'type': 'text'}, + 'account_id': {'type': 'text'}, + 'password': {'type': 'text'}, + 'server': {'type': 'text'}, + 'port': {'type': 'integer'}, + 'register': {'type': 'boolean'}, + 'colors': {'type': 'text'} + } + + def _connect_cb(self, button): + """ Enable connection """ + self._collaboration_config_values.set_valid_keys( + self._valid_config_values) + self._collaboration_config_values.connect( + 'configuration-loaded', self._connect_to_neighborhood) + self._collaboration_config_values.connect( + 'configuration-saved', self._connect_to_neighborhood) + self._collaboration_config_values.load() + self.setup() + + def setup(self): + self._collaboration = Collaboration(self.tw, self) + self._collaboration.setup() + # Do we know if we were successful? + self._setup_has_been_called = True + # TODO: + # use set_sensitive to enable Share and Configuration menuitems + + def set_tw(self, turtleart_window): + self.tw = turtleart_window + self.tw.nick = self._get_nick() + self._setup_config_file(self._parent.get_config_home()) + + def get_menu(self): + menu = gtk.Menu() + + MenuBuilder.make_menu_item(menu, _('Enable collaboration'), + self._connect_cb) + + self._activities_submenu = gtk.Menu() + activities_menu = MenuBuilder.make_sub_menu(self._activities_submenu, + _('Activities')) + menu.append(activities_menu) + + self._buddies_submenu = gtk.Menu() + buddies_menu = MenuBuilder.make_sub_menu(self._buddies_submenu, + _('Buddies')) + menu.append(buddies_menu) + + MenuBuilder.make_menu_item(menu, _('Share'), self._share_cb) + MenuBuilder.make_menu_item(menu, _('Configuration'), + self._config_neighborhood_cb) + + neighborhood_menu = MenuBuilder.make_sub_menu(menu, _('Neighborhood')) + + return neighborhood_menu + + def get_colors(self): + return self._colors + + def _get_nick(self): + return self._nick + + def _get_activity_id(self): + return self._activity_id + + def _get_bundle_id(self): + return self._bundle_id + + def _get_title(self): + return self._title + + def _connect_to_neighborhood(self, config_file_obj): + if self._neighborhood is not None: + return + + params = {} + params['nickname'] = self._collaboration_config_values.get('nick') + params['account_id'] = self._collaboration_config_values.get( + 'account_id') + params['server'] = self._collaboration_config_values.get('server') + params['port'] = self._collaboration_config_values.get('port') + params['password'] = self._collaboration_config_values.get('password') + params['register'] = self._collaboration_config_values.get('register') + if params['server'] == '': + raise RuntimeError('Invalid server address') + + self._nick = self._collaboration_config_values.get('nick') + # Tell the parent activity that the nick may have changed + self._parent.nick_changed(self._nick) + + self._colors = self._collaboration_config_values.get('colors') + # Tell the parent activity that the colors may have changed + self._parent.color_changed(self._colors) + + self._activities = {} + self._buddies = {} + + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + self._client_handler = telepathyclient.get_instance() + if self._client_handler == None: + raise RuntimeError('Telepathy client unavailable') + self._neighborhood = get_neighborhood(params) + self._neighborhood.connect('activity-added', self._activity_added_cb) + self._neighborhood.connect('activity-removed', + self._activity_removed_cb) + self._neighborhood.connect('buddy-added', self._buddy_added_cb) + self._neighborhood.connect('buddy-removed', self._buddy_removed_cb) + + # TODO: + # - show nick of sharer + # - show icon with color of sharer + def _activity_added_cb(self, model, activity_model): + self._activities[activity_model.props.name] = activity_model + self._recreate_available_activities_menu() + + def _activity_removed_cb(self, model, activity_model): + try: + self._activities.pop(activity_model.props.name) + except: + print 'Failed to remove activity %s' % activity_model.props.name + + self._recreate_available_activities_menu() + + def _buddy_added_cb(self, activity, buddy): + self._buddies[buddy.get_key()] = buddy + self._recreate_available_buddies_menu() + + def _buddy_removed_cb(self, activity, buddy): + try: + self._buddies.pop(buddy.get_key()) + except: + print "Couldn't remove buddy %s" % buddy.get_key() + self._recreate_available_buddies_menu() + + # TODO: we should have a list of available actions over + # a given buddy. I.e.: a) chat with him b) make friend + # c) invite to current activity + # + def _recreate_available_buddies_menu(self): + for child in self._buddies_submenu.get_children(): + self._buddies_submenu.remove(child) + + for buddy in self._buddies.values(): + key = buddy.get_key() + if key is None: + key = '' + n = buddy.get_nick() + '|' + key[0:15] + MenuBuilder.make_menu_item(self._buddies_submenu, n, + self._buddy_actions_cb, buddy) + + def _buddy_actions_cb(self, widget, buddy): + print 'do something with %s' % buddy.get_nick() + + # TODO: + # we need an extra menu branch with a) 'Join' button b) List of buddies + def _recreate_available_activities_menu(self): + for child in self._activities_submenu.get_children(): + self._activities_submenu.remove(child) + + for activity in self._activities.values(): + n = activity.props.name + MenuBuilder.make_menu_item(self._activities_submenu, n, + self._join_activity_cb, activity) + + def _join_activity_cb(self, widget, activity): + print 'Lets try to join...' + + connection_manager = get_connection_manager() + account_path, connection = \ + connection_manager.get_preferred_connection() + if connection is None: + print('No active connection available') + return + + properties = {} + properties['id'] = activity.activity_id + properties['color'] = activity.get_color() + print 'room handle according to activity %s' % activity.room_handle + properties['private'] = True + + try: + room_handle = connection.GetActivity(activity.activity_id, + dbus_interface=CONNECTION_INTERFACE_ACTIVITY_PROPERTIES) + print('room_handle = %s' % str(room_handle)) + self._joined_activity = Activity( + account_path, connection, room_handle, properties=properties) + # FIXME: this should be unified, no need to keep 2 references + self._shared_activity = self._joined_activity + except: + traceback.print_exc(file=sys.stdout) + + if self._joined_activity.props.joined: + raise RuntimeError('Activity %s is already shared.' % + activity.activity_id) + + _join_id = self._joined_activity.connect('joined', self.__joined_cb) + self._joined_activity.join() + + def __joined_cb(self, activity, success, err): + print "We've joined an activity" + self.emit('joined') + + def _config_neighborhood_cb(self, widget): + if not self._setup_has_been_called: + return + config_w = ConfigWizard(self._config_file_path) + config_items = [ + {'item_label': _('Nickname'), 'item_type': 'text', + 'item_name': 'nick'}, + {'item_label': _('Account ID'), 'item_type': 'text', + 'item_name': 'account_id'}, + {'item_label': _('Server'), 'item_type': 'text', + 'item_name': 'server'}, + {'item_label': _('Port'), 'item_type': 'text', + 'item_name': 'port'}, + {'item_label': _('Password'), 'item_type': 'text', + 'item_name': 'password'}, + {'item_label': _('Register'), 'item_type': 'boolean', + 'item_name': 'register'}, + {'item_label': _('Colors'), 'item_type': 'text', + 'item_name': 'colors'} + ] + config_w.set_config_items(config_items) + config_w.set_config_file_obj(self._collaboration_config_values) + config_w.show() + + def _share_cb(self, button): + if not self._setup_has_been_called: + return + properties = {} + properties['id'] = self._get_activity_id() + properties['type'] = self._get_bundle_id() + properties['name'] = self._get_title() + properties['color'] = self.get_colors() + properties['private'] = False + + connection_manager = get_connection_manager() + account_path, connection = \ + connection_manager.get_preferred_connection() + + if connection is None: + print('No active connection available') + return + + try: + self._parent._shared_activity = Activity(account_path, + connection, + properties=properties) + # FIXME: this should be unified, no need to keep 2 references + self._shared_activity = self._parent._shared_activity + except: + traceback.print_exc(file=sys.stdout) + + if self._parent._shared_parent.props.joined: + raise RuntimeError('Activity %s is already shared.' % + self._parent._get_activity_id()) + + self._parent._shared_parent.share(self.__share_activity_cb, + self.__share_activity_error_cb) + + def __share_activity_cb(self, activity): + """Finish sharing the activity""" + self.emit('shared') + + def __share_activity_error_cb(self, activity, error): + """Notify with GObject event of unsuccessful sharing of activity""" + print '%s got error: %s' % (activity, error) + +if __name__ == '__main__': + print 'testing collaboration' diff --git a/gnome_plugins/plugin.py b/gnome_plugins/plugin.py new file mode 100644 index 0000000..590c9bc --- /dev/null +++ b/gnome_plugins/plugin.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +#Copyright (c) 2011 Walter Bender +#Copyright (c) 2011 Collabora Ltd. <http://www.collabora.co.uk/> + +#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 gobject + + +class Plugin(gobject.GObject): + def __init__(self): + gobject.GObject.__init__(self) + + def get_menu(self): + raise RuntimeError("You need to define get__menu for your plugin.") + + def set_tw(self, turtle_window=None): + raise RuntimeError("You need to define set_tw for your plugin.") diff --git a/gnome_plugins/uploader_plugin.py b/gnome_plugins/uploader_plugin.py new file mode 100644 index 0000000..06224fa --- /dev/null +++ b/gnome_plugins/uploader_plugin.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python +#Copyright (c) 2011 Walter Bender +#Copyright (c) 2010 Jamie Boisture +#Copyright (c) 2011 Collabora Ltd. <http://www.collabora.co.uk/> + +#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. + +#!/usr/bin/python + +try: + import pycurl + import xmlrpclib + _UPLOAD_AVAILABLE = True +except ImportError, e: + print "Import Error: %s. Project upload is disabled." % (e) + _UPLOAD_AVAILABLE = False + +import os +import gtk + +from plugin import Plugin +from util.menubuilder import MenuBuilder + +from gettext import gettext as _ + + +class Uploader_plugin(Plugin): + MAX_FILE_SIZE = 950000 + UPLOAD_SERVER = 'http://turtleartsite.appspot.com' + + def __init__(self, parent, upload_server=None, max_file_size=None): + self._parent = parent + self.uploading = False + + if upload_server is None: + self._upload_server = self.UPLOAD_SERVER + + if max_file_size is None: + self._max_file_size = self.MAX_FILE_SIZE + else: + self._max_file_size = max_file_size + + def set_tw(self, turtleart_window): + self.tw = turtleart_window + + def get_menu(self): + menu = gtk.Menu() + MenuBuilder.make_menu_item(menu, _('Upload to Web'), + self.do_upload_to_web) + upload_menu = MenuBuilder.make_sub_menu(menu, _('Upload')) + return upload_menu + + def enabled(self): + return _UPLOAD_AVAILABLE + + def do_upload_to_web(self, widget=None): + if self.uploading: + return + + self.uploading = False + self.pop_up = gtk.Window() + self.pop_up.set_default_size(600, 400) + self.pop_up.connect('delete_event', self._stop_uploading) + table = gtk.Table(8, 1, False) + self.pop_up.add(table) + + login_label = gtk.Label(_('You must have an account at \ +http://turtleartsite.sugarlabs.org to upload your project.')) + table.attach(login_label, 0, 1, 0, 1) + self.login_message = gtk.Label('') + table.attach(self.login_message, 0, 1, 1, 2) + + self.Hbox1 = gtk.HBox() + table.attach(self.Hbox1, 0, 1, 2, 3, xpadding=5, ypadding=3) + self.username_entry = gtk.Entry() + username_label = gtk.Label(_('Username:') + ' ') + username_label.set_size_request(150, 25) + username_label.set_alignment(1.0, 0.5) + self.username_entry.set_size_request(450, 25) + self.Hbox1.add(username_label) + self.Hbox1.add(self.username_entry) + + self.Hbox2 = gtk.HBox() + table.attach(self.Hbox2, 0, 1, 3, 4, xpadding=5, ypadding=3) + self.password_entry = gtk.Entry() + password_label = gtk.Label(_('Password:') + ' ') + self.password_entry.set_visibility(False) + password_label.set_size_request(150, 25) + password_label.set_alignment(1.0, 0.5) + self.password_entry.set_size_request(450, 25) + self.Hbox2.add(password_label) + self.Hbox2.add(self.password_entry) + + self.Hbox3 = gtk.HBox() + table.attach(self.Hbox3, 0, 1, 4, 5, xpadding=5, ypadding=3) + self.title_entry = gtk.Entry() + title_label = gtk.Label(_('Title:') + ' ') + title_label.set_size_request(150, 25) + title_label.set_alignment(1.0, 0.5) + self.title_entry.set_size_request(450, 25) + self.Hbox3.add(title_label) + self.Hbox3.add(self.title_entry) + + self.Hbox4 = gtk.HBox() + table.attach(self.Hbox4, 0, 1, 5, 6, xpadding=5, ypadding=3) + self.description_entry = gtk.TextView() + description_label = gtk.Label(_('Description:') + ' ') + description_label.set_size_request(150, 25) + description_label.set_alignment(1.0, 0.5) + self.description_entry.set_wrap_mode(gtk.WRAP_WORD) + self.description_entry.set_size_request(450, 50) + self.Hbox4.add(description_label) + self.Hbox4.add(self.description_entry) + + self.Hbox5 = gtk.HBox() + table.attach(self.Hbox5, 0, 1, 6, 7, xpadding=5, ypadding=3) + self.submit_button = gtk.Button(_('Submit to Web')) + self.submit_button.set_size_request(300, 25) + self.submit_button.connect('pressed', self._do_remote_logon) + self.Hbox5.add(self.submit_button) + self.cancel_button = gtk.Button(_('Cancel')) + self.cancel_button.set_size_request(300, 25) + self.cancel_button.connect('pressed', self._stop_uploading) + self.Hbox5.add(self.cancel_button) + + self.pop_up.show_all() + + def _stop_uploading(self, widget, event=None): + """ Hide the popup when the upload is complte """ + self.uploading = False + self.pop_up.hide() + + def _do_remote_logon(self, widget): + """ Log into the upload server """ + username = self.username_entry.get_text() + password = self.password_entry.get_text() + server = xmlrpclib.ServerProxy(self._upload_server + '/call/xmlrpc') + logged_in = server.login_remote(username, password) + if logged_in: + upload_key = logged_in + self._do_submit_to_web(upload_key) + else: + self.login_message.set_text(_('Login failed')) + + def _do_submit_to_web(self, key): + """ Submit project to the server """ + title = self.title_entry.get_text() + description = self.description_entry.get_buffer().get_text( + *self.description_entry.get_buffer().get_bounds()) + tafile, imagefile = self.tw.save_for_upload(title) + + # Set a maximum file size for image to be uploaded. + if int(os.path.getsize(imagefile)) > self._max_file_size: + import Image + while int(os.path.getsize(imagefile)) > self._max_file_size: + big_file = Image.open(imagefile) + smaller_file = big_file.resize(int(0.9 * big_file.size[0]), + int(0.9 * big_file.size[1]), + Image.ANTIALIAS) + smaller_file.save(imagefile, quality=100) + + c = pycurl.Curl() + c.setopt(c.POST, 1) + c.setopt(c.FOLLOWLOCATION, 1) + c.setopt(c.URL, self._upload_server + '/upload') + c.setopt(c.HTTPHEADER, ["Expect:"]) + c.setopt(c.HTTPPOST, [('file', (c.FORM_FILE, tafile)), + ('newimage', (c.FORM_FILE, imagefile)), + ('small_image', (c.FORM_FILE, imagefile)), + ('title', title), + ('description', description), + ('upload_key', key), ('_formname', + 'image_create')]) + c.perform() + error_code = c.getinfo(c.HTTP_CODE) + c.close + os.remove(imagefile) + os.remove(tafile) + if error_code == 400: + self.login_message.set_text(_('Failed to upload!')) + else: + self.pop_up.hide() + self.uploading = False + +if __name__ == "__main__": + # TODO: create test data... + u = Uploader(None) + if u.enabled(): + print "Uploader is enabled... trying to upload" + u.do_upload_to_web() + gtk.main() + else: + print "Uploader is not enabled... exiting" diff --git a/icons/blocksoff.svg b/icons/blocksoff.svg new file mode 100644 index 0000000..63efb3c --- /dev/null +++ b/icons/blocksoff.svg @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="55" + height="55" + id="svg2"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <g + id="g3789"> + <path + d="m 15.719636,31.331478 0.114372,5.261133 11.437247,6.290486 L 27.5,29.387146" + id="path2463" + style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 27.728744,29.501519 0.05719,13.381578 11.723178,-7.548583 0,-4.689272 -5.947368,3.545548" + id="path2465" + style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10.001012,27.328441 5.604251,-5.146761 -5.832996,-2.973684 12.123482,-7.091093 5.718623,3.316801 5.489879,-3.088056 12.123482,7.319838 -5.832996,2.401822 5.489878,5.032388 -11.322874,7.205466 -5.947369,-5.261134 -6.290485,5.261134 -11.322875,-6.976721 z" + id="path2459" + style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 16.40587,21.952935 27.156883,15.204959 38.937247,22.067308 27.614372,28.815283 16.40587,21.952935 z" + id="path2461" + style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> +</svg> diff --git a/icons/blockson.svg b/icons/blockson.svg new file mode 100644 index 0000000..4435cc2 --- /dev/null +++ b/icons/blockson.svg @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="55" + height="55" + id="svg2"> + <metadata + id="metadata12"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs4" /> + <rect + width="55" + height="55" + rx="0" + x="0" + y="0" + id="rect2839" + style="fill:#ffd200;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <g + id="g3788"> + <path + d="m 15.719636,31.331478 0.114372,5.261133 11.437247,6.290486 L 27.5,29.387146" + id="path2463" + style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#804000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 27.728744,29.501519 0.05719,13.381578 11.723178,-7.548583 0,-4.689272 -5.947368,3.545548" + id="path2465" + style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#804000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10.001012,27.328441 5.604251,-5.146761 -5.832996,-2.973684 12.123482,-7.091093 5.718623,3.316801 5.489879,-3.088056 12.123482,7.319838 -5.832996,2.401822 5.489878,5.032388 -11.322874,7.205466 -5.947369,-5.261134 -6.290485,5.261134 -11.322875,-6.976721 z" + id="path2459" + style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#804000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 16.40587,21.952935 27.156883,15.204959 38.937247,22.067308 27.614372,28.815283 16.40587,21.952935 z" + id="path2461" + style="fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:#804000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> +</svg> diff --git a/icons/colorsoff.svg b/icons/colorsoff.svg new file mode 100644 index 0000000..3991df4 --- /dev/null +++ b/icons/colorsoff.svg @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="55" + height="55" + id="svg2"> + <metadata + id="metadata14"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs5" /> + <g + transform="translate(-4.9972534e-4,0)" + id="toolbar_x5F_colors" + style="display:block"> + <g + id="g3067"> + <circle + cx="15.63" + cy="39.5" + r="10" + id="circle3069" + style="fill:#d20000;stroke:#ffffff;stroke-width:2.25" /> + <circle + cx="39.834" + cy="39.5" + r="10" + id="circle3071" + style="fill:#0010d1;stroke:#ffffff;stroke-width:2.25" /> + <circle + cx="15.167" + cy="15.5" + r="10" + id="circle3073" + style="fill:#f7e100;stroke:#ffffff;stroke-width:2.25" /> + <circle + cx="39.666" + cy="15.5" + r="10" + id="circle3075" + style="stroke:#ffffff;stroke-width:2.25" /> + </g> + </g> +</svg> diff --git a/icons/colorson.svg b/icons/colorson.svg new file mode 100644 index 0000000..42ce7c7 --- /dev/null +++ b/icons/colorson.svg @@ -0,0 +1,68 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="55" + height="55" + id="svg2"> + <metadata + id="metadata3212"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs5" /> + <rect + width="55" + height="55" + rx="0" + x="0" + y="0" + id="rect2839" + style="fill:#ffd200;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <g + transform="translate(-4.9972534e-4,0)" + id="toolbar_x5F_colors" + style="display:block"> + <g + id="g3067"> + <circle + cx="15.63" + cy="39.5" + r="10" + id="circle3069" + style="fill:#d20000;stroke:#ffffff;stroke-width:2.25" /> + <circle + cx="39.834" + cy="39.5" + r="10" + id="circle3071" + style="fill:#0010d1;stroke:#ffffff;stroke-width:2.25" /> + <circle + cx="15.167" + cy="15.5" + r="10" + id="circle3073" + style="fill:#f7e100;stroke:#ffffff;stroke-width:2.25" /> + <circle + cx="39.666" + cy="15.5" + r="10" + id="circle3075" + style="stroke:#ffffff;stroke-width:2.25" /> + </g> + </g> +</svg> diff --git a/icons/contract-coordinates.svg b/icons/contract-coordinates.svg new file mode 100644 index 0000000..1f704f3 --- /dev/null +++ b/icons/contract-coordinates.svg @@ -0,0 +1,79 @@ +<?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="svg2384"> + <defs + id="defs2386" /> + <rect + width="50" + height="50" + x="2.5" + y="2.5" + id="rect2394" + style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 27.333333,1 C 28.083333,50.75 27.333333,54 27.333333,54" + id="path3168" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 54,27.333333 C 4.2499997,28.083333 1,27.333333 1,27.333333" + id="path3170" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <g + transform="matrix(-1,0,0,-1,72.75,37.25)" + id="g3161" + style="stroke:#ffffff;stroke-opacity:1"> + <path + d="M 28,27 L 37,18" + id="path2387" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 30,17 L 38,17 L 38,25" + id="path3159" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <g + transform="matrix(-1,0,0,1,72.75,18.25)" + id="g3167" + style="stroke:#ffffff;stroke-opacity:1"> + <path + d="M 28,27 L 37,18" + id="path3169" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 30,17 L 38,17 L 38,25" + id="path3171" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <g + transform="matrix(1,0,0,-1,-18.25,37.25)" + id="g3173" + style="stroke:#ffffff;stroke-opacity:1"> + <path + d="M 28,27 L 37,18" + id="path3175" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 30,17 L 38,17 L 38,25" + id="path3177" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <g + transform="translate(-18.25,18.25)" + id="g3179" + style="stroke:#ffffff;stroke-opacity:1"> + <path + d="M 28,27 L 37,18" + id="path3181" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 30,17 L 38,17 L 38,25" + id="path3183" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> +</svg> diff --git a/icons/debugoff.svg b/icons/debugoff.svg new file mode 100644 index 0000000..32ff193 --- /dev/null +++ b/icons/debugoff.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="45" + height="45" + id="svg2"> + <defs + id="defs4" /> + ` <g + transform="matrix(0.81818179,0,0,0.81818179,2.9325954e-7,1.8913349e-6)" + id="g2941"> + <g + transform="matrix(1.5,0,0,1.5,-13.078338,-13.158384)" + id="g2418"> + <path + d="m 27.377856,20.343519 c 0.943144,-1.32305 2.909066,-2.23143 3.443893,-2.052418 0.816335,0.273235 2.634387,1.285134 2.828305,1.870614 0.363444,1.097313 -0.440961,2.212871 -0.661443,3.319307" + id="path3252" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 31.312226,33.70644 c -3.075459,5.326852 -8.151812,8.153707 -11.338352,6.313958 -3.18654,-1.83975 -3.276587,-7.649428 -0.201128,-12.97628 3.07546,-5.326852 8.151812,-8.153707 11.338352,-6.313958 3.18654,1.83975 3.276588,7.649428 0.201128,12.97628 l 0,0 z" + id="path3197" + style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:1.51091182;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 30.640788,20.96543 c -3.356038,6.044559 -3.301174,5.949533 -3.301174,5.949533" + id="path3199" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 23.640267,22.485322 c 0.955579,1.892858 2.334494,3.24269 3.831245,4.497123 0.02734,0.02291 3.988592,1.409612 5.914011,1.031489" + id="path3201" + style="fill:none;stroke:#ffffff;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 22.8141,25.484531 c 2.380046,2.460708 2.406938,2.476234 2.406938,2.476234" + id="path3203" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 21.785315,26.831706 c 2.380046,2.460709 2.551072,2.661318 2.551072,2.661318" + id="path3207" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 20.834693,28.29192 c 2.380046,2.460708 2.617044,2.733363 2.617044,2.733363" + id="path3209" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 20.016015,29.896225 c 2.380045,2.460709 2.551071,2.661318 2.551071,2.661318" + id="path3211" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 19.370877,31.63468 c 2.380046,2.460709 2.311559,2.455123 2.311559,2.455123" + id="path3213" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 19.111902,33.697954 c 2.252745,2.556991 1.685883,1.92411 1.685883,1.92411" + id="path3215" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 19.133652,36.330772 c 0.569377,0.566421 0.779483,0.823549 0.779483,0.823549" + id="path3217" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 30.786085,30.087159 C 27.465026,29.256333 27.438134,29.240807 27.438134,29.240807" + id="path3230" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 30.133789,31.6517 C 26.81273,30.820874 26.553484,30.773066 26.553484,30.773066" + id="path3232" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 29.344518,33.20507 C 26.023459,32.374244 25.668834,32.305325 25.668834,32.305325" + id="path3234" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 28.364488,34.716219 C 25.043429,33.885393 24.784183,33.837585 24.784183,33.837585" + id="path3236" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 27.18151,36.144152 C 23.860451,35.313326 23.899532,35.369845 23.899532,35.369845" + id="path3238" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 25.524151,37.400068 c -3.340792,-0.672439 -2.50927,-0.497963 -2.50927,-0.497963" + id="path3240" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 23.233189,38.697641 C 22.457965,38.487756 22.130232,38.434363 22.130232,38.434363" + id="path3242" + style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 38.499043,20.363658 c -0.698249,1.209401 -2.299567,1.592097 -3.576644,0.854776 -1.277077,-0.73732 -1.746312,-2.315451 -1.048064,-3.524852 0.698249,-1.209402 2.299567,-1.592098 3.576644,-0.854777 1.277077,0.73732 1.746312,2.315451 1.048064,3.524853 z" + id="path3244" + style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:0.84691685;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 36.397626,17.843099 c -0.197275,0.341691 -0.649694,0.449815 -1.010506,0.2415 -0.360812,-0.208315 -0.493384,-0.654183 -0.296109,-0.995875 0.197276,-0.341691 0.649695,-0.449814 1.010507,-0.241499 0.360812,0.208315 0.493384,0.654183 0.296108,0.995874 z" + id="path3246" + style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:0.79813904;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 32.748117,16.754734 c -0.698248,1.209401 -2.299567,1.592097 -3.576644,0.854776 -1.277077,-0.73732 -1.746311,-2.315451 -1.048063,-3.524852 0.698249,-1.209402 2.299567,-1.592098 3.576644,-0.854777 1.277077,0.73732 1.746312,2.315451 1.048063,3.524853 z" + id="path3248" + style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:0.84691685;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 30.781161,14.311805 c -0.197275,0.341691 -0.649694,0.449815 -1.010506,0.2415 -0.360813,-0.208315 -0.493385,-0.654183 -0.296109,-0.995875 0.197275,-0.341691 0.649695,-0.449814 1.010507,-0.241499 0.360812,0.208315 0.493384,0.654183 0.296108,0.995874 z" + id="path3250" + style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:0.79813904;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 32.6771,18.762402 c 1.915624,-3.421466 5.072352,-4.541771 5.072352,-4.541771 l 0,0" + id="path3254" + style="fill:none;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 32.234792,18.337256 c 2.005265,-3.369712 1.397113,-6.663671 1.397113,-6.663671 l 0,0" + id="path3258" + style="fill:none;stroke:#ffffff;stroke-width:0.75545591;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 26.988213,20.231746 L 25.8722,15.229742 22.062204,17.274526" + id="path3260" + style="fill:none;stroke:#ffffff;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 33.361036,23.684723 l 3.584614,-0.929858 2.882681,3.70167" + id="path3262" + style="fill:none;stroke:#ffffff;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 23.851158,22.042526 l -1.097622,-3.067217 -8.164934,2.756268" + id="path3264" + style="fill:none;stroke:#ffffff;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 33.777334,27.207476 l 3.47402,-0.42778 0.497902,7.4182" + id="path3266" + style="fill:none;stroke:#ffffff;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 12.485021,29.515384" + id="path3268" + style="fill:none;stroke:#ffffff;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 32.410841,31.851473 l 2.920057,-0.91739 -2.027798,9.412169" + id="path3270" + style="fill:none;stroke:#ffffff;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> + </g> +</svg> diff --git a/icons/debugon.svg b/icons/debugon.svg new file mode 100644 index 0000000..6232a99 --- /dev/null +++ b/icons/debugon.svg @@ -0,0 +1,146 @@ +<?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="45" + height="45" + id="svg2"> + <defs + id="defs4" /> + <g + transform="matrix(0.81818179,0,0,0.81818179,2.9325954e-7,1.8913349e-6)" + id="g2886"> + <path + d="m 12.3583,20.48583 c 0,6.948279 -1.644946,12.580972 -3.6740891,12.580972 -2.0291434,0 -3.6740891,-5.632693 -3.6740891,-12.580972 0,-6.948279 1.6449457,-12.5809723 3.6740891,-12.5809723 2.0291431,0 3.6740891,5.6326933 3.6740891,12.5809723 l 0,0 z" + transform="matrix(7.4848487,0,0,2.1858407,-37.500004,-17.278762)" + id="path3188" + style="fill:#00ff00;fill-opacity:1;stroke:none" /> + <g + transform="matrix(1.5,0,0,1.5,-13.078338,-13.158384)" + id="g3188"> + <path + d="m 27.377856,20.343519 c 0.943144,-1.32305 2.909066,-2.23143 3.443893,-2.052418 0.816335,0.273235 2.634387,1.285134 2.828305,1.870614 0.363444,1.097313 -0.440961,2.212871 -0.661443,3.319307" + 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 -3.075459,5.326852 -8.151812,8.153707 -11.338352,6.313958 -3.18654,-1.83975 -3.276587,-7.649428 -0.201128,-12.97628 3.07546,-5.326852 8.151812,-8.153707 11.338352,-6.313958 3.18654,1.83975 3.276588,7.649428 0.201128,12.97628 l 0,0 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-opacity:1;stroke-dasharray:none" /> + <path + d="m 30.640788,20.96543 c -3.356038,6.044559 -3.301174,5.949533 -3.301174,5.949533" + 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 0.955579,1.892858 2.334494,3.24269 3.831245,4.497123 0.02734,0.02291 3.988592,1.409612 5.914011,1.031489" + id="path3201" + style="fill:none;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 22.8141,25.484531 c 2.380046,2.460708 2.406938,2.476234 2.406938,2.476234" + 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-opacity:1;stroke-dasharray:none" /> + <path + d="m 21.785315,26.831706 c 2.380046,2.460709 2.551072,2.661318 2.551072,2.661318" + 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-opacity:1;stroke-dasharray:none" /> + <path + d="m 20.834693,28.29192 c 2.380046,2.460708 2.617044,2.733363 2.617044,2.733363" + 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-opacity:1;stroke-dasharray:none" /> + <path + d="m 20.016015,29.896225 c 2.380045,2.460709 2.551071,2.661318 2.551071,2.661318" + 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-opacity:1;stroke-dasharray:none" /> + <path + d="m 19.370877,31.63468 c 2.380046,2.460709 2.311559,2.455123 2.311559,2.455123" + 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-opacity:1;stroke-dasharray:none" /> + <path + d="m 19.111902,33.697954 c 2.252745,2.556991 1.685883,1.92411 1.685883,1.92411" + 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-opacity:1;stroke-dasharray:none" /> + <path + d="m 19.133652,36.330772 c 0.569377,0.566421 0.779483,0.823549 0.779483,0.823549" + 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-opacity:1;stroke-dasharray:none" /> + <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-opacity:1;stroke-dasharray:none" /> + <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-opacity:1;stroke-dasharray:none" /> + <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-opacity:1;stroke-dasharray:none" /> + <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-opacity:1;stroke-dasharray:none" /> + <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-opacity:1;stroke-dasharray:none" /> + <path + d="m 25.524151,37.400068 c -3.340792,-0.672439 -2.50927,-0.497963 -2.50927,-0.497963" + 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-opacity:1;stroke-dasharray:none" /> + <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-opacity:1;stroke-dasharray:none" /> + <path + d="m 38.499043,20.363658 c -0.698249,1.209401 -2.299567,1.592097 -3.576644,0.854776 -1.277077,-0.73732 -1.746312,-2.315451 -1.048064,-3.524852 0.698249,-1.209402 2.299567,-1.592098 3.576644,-0.854777 1.277077,0.73732 1.746312,2.315451 1.048064,3.524853 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-opacity:1;stroke-dasharray:none" /> + <path + d="m 36.397626,17.843099 c -0.197275,0.341691 -0.649694,0.449815 -1.010506,0.2415 -0.360812,-0.208315 -0.493384,-0.654183 -0.296109,-0.995875 0.197276,-0.341691 0.649695,-0.449814 1.010507,-0.241499 0.360812,0.208315 0.493384,0.654183 0.296108,0.995874 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-opacity:1;stroke-dasharray:none" /> + <path + d="m 32.748117,16.754734 c -0.698248,1.209401 -2.299567,1.592097 -3.576644,0.854776 -1.277077,-0.73732 -1.746311,-2.315451 -1.048063,-3.524852 0.698249,-1.209402 2.299567,-1.592098 3.576644,-0.854777 1.277077,0.73732 1.746312,2.315451 1.048063,3.524853 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-opacity:1;stroke-dasharray:none" /> + <path + d="m 30.781161,14.311805 c -0.197275,0.341691 -0.649694,0.449815 -1.010506,0.2415 -0.360813,-0.208315 -0.493385,-0.654183 -0.296109,-0.995875 0.197275,-0.341691 0.649695,-0.449814 1.010507,-0.241499 0.360812,0.208315 0.493384,0.654183 0.296108,0.995874 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-opacity:1;stroke-dasharray:none" /> + <path + d="m 32.6771,18.762402 c 1.915624,-3.421466 5.072352,-4.541771 5.072352,-4.541771 l 0,0" + id="path3254" + style="fill:none;stroke:#000000;stroke-width:0.75545591;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 32.234792,18.337256 c 2.005265,-3.369712 1.397113,-6.663671 1.397113,-6.663671 l 0,0" + id="path3258" + style="fill:none;stroke:#000000;stroke-width:0.75545591;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 26.988213,20.231746 L 25.8722,15.229742 22.062204,17.274526" + id="path3260" + style="fill:none;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 33.361036,23.684723 l 3.584614,-0.929858 2.882681,3.70167" + id="path3262" + style="fill:none;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 23.851158,22.042526 l -1.097622,-3.067217 -8.164934,2.756268" + id="path3264" + style="fill:none;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 33.777334,27.207476 l 3.47402,-0.42778 0.497902,7.4182" + id="path3266" + style="fill:none;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 12.485021,29.515384" + id="path3268" + style="fill:none;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 32.410841,31.851473 l 2.920057,-0.91739 -2.027798,9.412169" + id="path3270" + style="fill:none;stroke:#000000;stroke-width:1.51091182px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> + </g> +</svg> diff --git a/icons/eraseroff.svg b/icons/eraseroff.svg new file mode 100644 index 0000000..c0d739d --- /dev/null +++ b/icons/eraseroff.svg @@ -0,0 +1,33 @@ +<?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="50" + height="43" + id="svg2"> + <defs + id="defs5" /> +` <path + d="m 36.61535,26.125 l 0,-8.375 12.5,-13.5 -1.5,10.5 -11,11.375 z" + id="path2394" + style="fill:#c44000;fill-opacity:1;stroke:#a00000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 15.61535,17.75 l 13.5,-13.5 20,0 -12.5,13.5 -21,0 z" + id="path2390" + style="fill:#c44000;fill-opacity:1;stroke:#a00000;stroke-width:1.5;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 23.416068,38.75 l 2.692998,-10 10.506284,-11 0,8.375 -13.199282,12.625 z" + id="path2392" + style="fill:#c4a000;fill-opacity:1;stroke:#a00000;stroke-width:1.5;stroke-linejoin:round;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 4.5650808,28.75 l 11.0502692,-11 21,0 -10.86535,11 -21.1849192,0 z" + id="path2388" + style="fill:#c4a000;fill-opacity:1;stroke:#a00000;stroke-width:1.5;stroke-linejoin:round;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 0.88464991,38.75 l 3.59066429,-10 21.1849188,0 -2.603231,10 -22.17235209,0 z" + id="path2384" + style="fill:#e0d000;fill-opacity:1;stroke:#a00000;stroke-width:1.5;stroke-linejoin:round;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/icons/eraseron.svg b/icons/eraseron.svg new file mode 100644 index 0000000..27a5ffd --- /dev/null +++ b/icons/eraseron.svg @@ -0,0 +1,38 @@ +<?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="50" + height="43" + id="svg2"> + <defs + id="defs5" /> + <g + transform="translate(0.61535009,0.25)" + id="g3589" + style="fill:#404040;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"> + <path + d="M 36,25.875 L 36,17.5 48.5,4 47,14.5 36,25.875 z" + id="path2394" + style="fill:#404040;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 15,17.5 L 28.5,4 48.5,4 36,17.5 l -21,0 z" + id="path2390" + style="fill:#404040;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 22.800718,38.5 L 25.493716,28.5 36,17.5 36,25.875 22.800718,38.5 z" + id="path2392" + style="fill:#404040;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 3.9497307,28.5 L 15,17.5 l 21,0 -10.86535,11 -21.1849193,0 z" + id="path2388" + style="fill:#404040;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 0.26929982,38.5 l 3.59066428,-10 21.1849189,0 -2.603231,10 -22.17235218,0 z" + id="path2384" + style="fill:#404040;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> +</svg> diff --git a/icons/expand-coordinates.svg b/icons/expand-coordinates.svg new file mode 100644 index 0000000..6be761e --- /dev/null +++ b/icons/expand-coordinates.svg @@ -0,0 +1,79 @@ +<?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="svg2384"> + <defs + id="defs2386" /> + <rect + width="50" + height="50" + x="2.5" + y="2.5" + id="rect2394" + style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 27.333333,1 C 28.083333,50.75 27.333333,54 27.333333,54" + id="path3168" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 54,27.333333 C 4.2499997,28.083333 1,27.333333 1,27.333333" + id="path3170" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <g + transform="translate(6.75,-6.75)" + id="g3161" + style="stroke:#ffffff;stroke-opacity:1"> + <path + d="M 28,27 L 37,18" + id="path2387" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 30,17 L 38,17 L 38,25" + id="path3159" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <g + transform="matrix(1,0,0,-1,6.75,62.25)" + id="g3167" + style="stroke:#ffffff;stroke-opacity:1"> + <path + d="M 28,27 L 37,18" + id="path3169" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 30,17 L 38,17 L 38,25" + id="path3171" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <g + transform="matrix(-1,0,0,1,47.75,-6.75)" + id="g3173" + style="stroke:#ffffff;stroke-opacity:1"> + <path + d="M 28,27 L 37,18" + id="path3175" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 30,17 L 38,17 L 38,25" + id="path3177" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <g + transform="matrix(-1,0,0,-1,47.75,62.25)" + id="g3179" + style="stroke:#ffffff;stroke-opacity:1"> + <path + d="M 28,27 L 37,18" + id="path3181" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 30,17 L 38,17 L 38,25" + id="path3183" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> +</svg> diff --git a/icons/filesaveoff.svg b/icons/filesaveoff.svg new file mode 100644 index 0000000..b9baa5c --- /dev/null +++ b/icons/filesaveoff.svg @@ -0,0 +1,201 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2" + xml:space="preserve" + inkscape:version="0.48.1 r9760" + sodipodi:docname="filesaveoff.svg"><sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1280" + inkscape:window-height="725" + id="namedview37" + showgrid="false" + inkscape:zoom="4.7090909" + inkscape:cx="-11.254826" + inkscape:cy="27.5" + inkscape:window-x="0" + inkscape:window-y="25" + inkscape:window-maximized="1" + inkscape:current-layer="svg2" /><metadata + id="metadata25"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs33"> + + + + + + + + + + + + + + + + + + + + + + + + + </defs><path + inkscape:connector-curvature="0" + style="fill:none;stroke:#ffffff;stroke-width:2.08759975;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path11" + d="m 15.046106,34.391188 c -0.384814,0 -0.764757,-0.02436 -1.139133,-0.06959 l 0.965862,1.634591 0.951946,-1.60954 c -0.258167,0.02088 -0.515637,0.04454 -0.778675,0.04454 z" /><g + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="g13" + transform="matrix(0.69586655,0,0,0.69586655,-4.0881364,0.79544654)"> + <path + inkscape:connector-curvature="0" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path15" + d="m 40.16,11.726 c -2.164,0 -3.958,1.555 -4.343,3.607 1.859,1.345 3.457,3.115 4.675,5.208 2.285,-0.172 4.094,-2.061 4.094,-4.39 0,-2.444 -1.982,-4.425 -4.426,-4.425 z" /> + <path + inkscape:connector-curvature="0" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path17" + d="m 40.713,39.887 c -1.224,2.232 -2.86,4.131 -4.797,5.556 0.521,1.864 2.213,3.239 4.244,3.239 2.443,0 4.426,-1.98 4.426,-4.424 0,-2.255 -1.693,-4.096 -3.873,-4.371 z" /> + <path + inkscape:connector-curvature="0" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path19" + d="m 14.273,39.871 c -2.253,0.206 -4.024,2.079 -4.024,4.387 0,2.443 1.98,4.424 4.424,4.424 2.064,0 3.784,-1.42 4.272,-3.332 -1.883,-1.416 -3.475,-3.289 -4.672,-5.479 z" /> + <path + inkscape:connector-curvature="0" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path21" + d="m 19.026,15.437 c -0.343,-2.103 -2.154,-3.711 -4.353,-3.711 -2.444,0 -4.424,1.981 -4.424,4.424 0,2.382 1.886,4.31 4.245,4.406 1.186,-2.043 2.732,-3.784 4.532,-5.119 z" /> + </g><path + inkscape:connector-curvature="0" + style="fill:none;stroke:#ffffff;stroke-width:2.08759975;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path23" + d="m 15.046106,9.537618 c 1.327714,0 2.594191,0.2860012 3.770205,0.784937 0.515637,-0.7487519 0.819731,-1.6540743 0.819731,-2.6324627 0,-2.5656599 -2.079945,-4.6463009 -4.646301,-4.6463009 -2.56566,0 -4.645605,2.080641 -4.645605,4.6463009 0,0.9936975 0.314531,1.9129372 0.846174,2.6679527 1.199674,-0.5212044 2.496073,-0.820427 3.855796,-0.820427 z" /><g + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="g25" + transform="matrix(0.69586655,0,0,0.69586655,-4.0881364,0.79544654)"> + <path + inkscape:connector-curvature="0" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path2988" + d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z" /> + </g><g + style="fill:#ffffff;stroke:none;stroke-width:1.50000000000000000;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" + id="g28" + transform="matrix(0.69586655,0,0,0.69586655,-4.0881364,0.79544654)"> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;stroke:none;stroke-width:1.50000000000000000;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" + id="path30" + d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 -3.75,-0.083 z" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;stroke:none;stroke-width:1.50000000000000000;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" + id="path32" + d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;stroke:none;stroke-width:1.50000000000000000;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" + id="path34" + d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;stroke:none;stroke-width:1.50000000000000000;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" + id="path2998" + d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;stroke:none;stroke-width:1.50000000000000000;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" + id="path37" + d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z" /> + <path + inkscape:connector-curvature="0" + style="fill:#ffffff;stroke:none;stroke-width:1.50000000000000000;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;fill-opacity:1" + id="path3002" + d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z" /> + </g><g + id="g3830"><g + id="g4382" + transform="matrix(0.55205508,0,0,0.55205508,75.618464,18.235971)"><g + style="fill:none;stroke:#ffffff;stroke-opacity:1" + id="g4308" + transform="translate(-80.093659,12.220029)"> + <g + style="fill:none;stroke:#ffffff;stroke-opacity:1" + id="g4310"> + <path + inkscape:connector-curvature="0" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path4312" + d="m 6.736,49.002 h 24.52 c 2.225,0 3.439,-1.447 3.439,-3.441 v -27.28 c 0,-1.73 -1.732,-3.441 -3.439,-3.441 h -4.389" /> + </g> + </g><g + style="fill:none;stroke:#ffffff;stroke-opacity:1" + id="g4314" + transform="translate(-80.093659,12.220029)"> + <g + style="fill:none;stroke:#ffffff;stroke-opacity:1" + id="g4316"> + <path + inkscape:connector-curvature="0" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path4318" + d="m 26.867,38.592 c 0,1.836 -1.345,3.201 -3.441,4.047 L 6.736,49.002 V 14.84 l 16.69,-8.599 c 2.228,-0.394 3.441,0.84 3.441,2.834 v 29.517 z" /> + </g> + </g><path + inkscape:connector-curvature="0" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path4320" + d="m -70.669659,54.827029 c 0,0 -1.351,-0.543 -2.702,-0.543 -1.351,0 -2.703,0.543 -2.703,0.543" /><path + inkscape:connector-curvature="0" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path4322" + d="m -70.669659,44.226029 c 0,0 -1.239,-0.543 -2.815,-0.543 -1.577,0 -2.59,0.543 -2.59,0.543" /><path + inkscape:connector-curvature="0" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + id="path4324" + d="m -70.669659,33.898029 c 0,0 -1.125,-0.544 -2.927,-0.544 -1.802,0 -2.478,0.544 -2.478,0.544" /><line + id="line4326" + y2="23.725029" + y1="58.753029" + x2="-66.884659" + x1="-66.884659" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g><g + id="g4770" + transform="matrix(1,0,0,-1,-30.386573,49.171266)"><g + id="g4772" + transform="translate(34.0803,-1006.42)"><polyline + id="polyline4774" + points="51.562,15.306 41.17,16.188 42.053,5.794" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" + transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" /><path + inkscape:connector-curvature="0" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path4776" + d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067" /></g></g></g></svg>
\ No newline at end of file diff --git a/icons/flowoff.svg b/icons/flowoff.svg new file mode 100644 index 0000000..13b11c5 --- /dev/null +++ b/icons/flowoff.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="55" + height="55" + id="svg2"> + <defs + id="defs5" /> + <path + d="M 14.85,27.1 l -0.45,13.15 4.35,-2.4 c 0,0 6.349418,4.294879 10.2,4.05 4.946317,-0.314563 11.65,-7.5 11.65,-7.5 l -2.25,-2.3 c 0,0 -5.615371,6.15399 -9.4,6.65 -2.286298,0.29964 -7.05,-2.5 -7.05,-2.5 L 26,34.1 14.85,27.1 z" + id="path3590" + style="fill:none;stroke:#ffffff;stroke-width:2.29999995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 40.15,28.955044 l 0.45,-13.150001 -4.35,2.4 c 0,0 -6.349418,-4.294879 -10.2,-4.05 -4.946317,0.314563 -11.65,7.5 -11.65,7.5 l 2.25,2.3 c 0,0 5.615371,-6.15399 9.4,-6.65 2.286298,-0.29964 7.05,2.5 7.05,2.5 l -4.1,2.15 11.15,7.000001 z" + id="path3590-4" + style="fill:none;stroke:#ffffff;stroke-width:2.29999995;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/icons/flowon.svg b/icons/flowon.svg new file mode 100644 index 0000000..b115fa7 --- /dev/null +++ b/icons/flowon.svg @@ -0,0 +1,43 @@ +<?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="defs5" /> + <rect + width="55" + height="55" + rx="0" + x="0" + y="0" + id="rect2839" + style="fill:#ffd200;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <g + transform="translate(4.9228669,-0.04294974)" + id="g3163"> + <path + d="M 27.560785,16.470589 l -1.511002,10.315514 -8.177996,-6.466322 9.688998,-3.849192 z" + transform="translate(8.1558824,1.1284313)" + id="path2386" + style="fill:#a06400;fill-opacity:1;stroke:#a06400;stroke-width:3;stroke-opacity:1" /> + <path + d="M 27.560785,16.470589 l -1.511002,10.315514 -8.177996,-6.466322 9.688998,-3.849192 z" + transform="matrix(-0.9848078,-0.1736482,-0.1736482,0.9848078,39.742987,17.127786)" + id="path2388" + style="fill:#a06400;fill-opacity:1;stroke:#a06400;stroke-width:3;stroke-opacity:1" /> + <path + d="M 14.52451,37.473529 c 0,0.101391 2.070056,1.496645 4.373345,2.252558 1.606134,0.527115 3.382089,0.517702 4.410968,0.492541 1.751835,-0.04284 3.76231,-1.081811 5.486138,-2.294795 2.373956,-1.670452 4.204281,-3.670923 4.066804,-3.854225 l 0,0 0.109804,0" + id="path2390" + style="fill:none;stroke:#a06400;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="M 30.716667,18.403553 c 0,-0.101391 -5.19216,-3.579099 -9.384313,-3.545099 -4.192153,0.034 -9.701252,5.965718 -9.552942,6.14902 0,0 0,0 0,0 -0.0366,0 -0.0732,0 -0.109804,0" + id="path3162" + style="fill:none;stroke:#a06400;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> +</svg> diff --git a/icons/help-off.svg b/icons/help-off.svg new file mode 100644 index 0000000..7a038b6 --- /dev/null +++ b/icons/help-off.svg @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2"> + <metadata + id="metadata11"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs9"> + +</defs> + <path + d="m 50,27.625 c 0,12.3431 -10.1569,22.5 -22.5,22.5 C 15.1569,50.125 5,39.9681 5,27.625 5,15.2819 15.1569,5.125 27.5,5.125 c 12.3431,0 22.5,10.1569 22.5,22.5 z" + id="path3" + style="fill:#ffffff" /> + <path + d="m 23.956,27.167 c 0,-1.621 1.8,-1.89 3.645,-2.386 1.8,-0.495 3.6,-1.215 3.6,-3.825 0,-1.98 -1.845,-3.42 -3.734,-3.42 -3.78,0 -4.365,4.455 -7.246,4.455 -1.62,0 -2.745,-1.26 -2.745,-3.24 0,-4.726 5.94,-7.425 9.991,-7.425 5.806,0 10.756,3.6 10.756,9.631 0,4.995 -3.15,7.921 -7.785,9.091 l 0,1.619 c 0,1.801 -1.351,3.105 -3.241,3.105 -2.025,0 -3.24,-1.305 -3.24,-3.105 l 0,-4.5 -0.001,0 z m -0.27,13.77 c 0,-1.935 1.575,-3.51 3.51,-3.51 1.936,0 3.51,1.575 3.51,3.51 0,1.936 -1.574,3.512 -3.51,3.512 -1.935,-10e-4 -3.51,-1.577 -3.51,-3.512 z" + id="path5" + style="fill:#282828;stroke:#282828;stroke-width:0.25;stroke-miterlimit:4" /> + <g + transform="matrix(0.90000005,0,0,0.90000005,1.5999984,5.2999976)" + id="g3850"> + <rect + width="12" + height="12" + x="40" + y="37" + id="rect3848" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="M 45.999999,33 C 40.475555,33 36,37.478222 36,42.998666 36,48.524 40.475555,53 45.999999,53 c 5.524889,0 10,-4.476 10,-10.001334 0,-5.520444 -4.475555,-9.998666 -10,-9.998666 z m 4.532889,12.515111 c 0.557334,0.558222 0.558667,1.462666 0,2.02 -0.279111,0.279555 -0.644889,0.419111 -1.010666,0.419111 -0.365334,0 -0.730667,-0.139556 -1.008889,-0.417778 l -2.56,-2.560444 -2.56,2.560444 c -0.278667,0.278222 -0.644,0.417778 -1.009334,0.417778 -0.365777,0 -0.732,-0.139556 -1.011111,-0.419111 -0.557333,-0.557334 -0.557333,-1.461778 0.0018,-2.02 L 43.933777,42.956 41.374666,40.396889 c -0.559111,-0.557334 -0.559111,-1.463112 -0.0018,-2.020445 0.557778,-0.557333 1.463111,-0.559555 2.020445,0 l 2.56,2.559556 2.56,-2.559556 c 0.556444,-0.559555 1.461333,-0.557333 2.019555,0 0.558667,0.557333 0.557334,1.463111 0,2.020445 l -2.559111,2.559111 2.559111,2.559111 z" + id="path3067" + style="fill:#282828;fill-opacity:1;display:inline" /> + </g> +</svg> diff --git a/icons/help-on.svg b/icons/help-on.svg new file mode 100644 index 0000000..c818f84 --- /dev/null +++ b/icons/help-on.svg @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2"> + <metadata + id="metadata3971"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs3969" /> + <path + d="m 50,27.625 c 0,12.3431 -10.1569,22.5 -22.5,22.5 C 15.1569,50.125 5,39.9681 5,27.625 5,15.2819 15.1569,5.125 27.5,5.125 c 12.3431,0 22.5,10.1569 22.5,22.5 z" + id="path3963" + style="fill:#ffffff" /> + <path + d="m 23.956,27.167 c 0,-1.621 1.8,-1.89 3.645,-2.386 1.8,-0.495 3.6,-1.215 3.6,-3.825 0,-1.98 -1.845,-3.42 -3.734,-3.42 -3.78,0 -4.365,4.455 -7.246,4.455 -1.62,0 -2.745,-1.26 -2.745,-3.24 0,-4.726 5.94,-7.425 9.991,-7.425 5.806,0 10.756,3.6 10.756,9.631 0,4.995 -3.15,7.921 -7.785,9.091 l 0,1.619 c 0,1.801 -1.351,3.105 -3.241,3.105 -2.025,0 -3.24,-1.305 -3.24,-3.105 l 0,-4.5 -0.001,0 z m -0.27,13.77 c 0,-1.935 1.575,-3.51 3.51,-3.51 1.936,0 3.51,1.575 3.51,3.51 0,1.936 -1.574,3.512 -3.51,3.512 -1.935,-10e-4 -3.51,-1.577 -3.51,-3.512 z" + id="path3965" + style="fill:#282828;stroke:#282828;stroke-width:0.25;stroke-miterlimit:4" /> + <g + id="g4559"> + <rect + width="12" + height="12" + x="37" + y="38" + id="rect3848" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <g + transform="matrix(0.4,0,0,0.4,32,33)" + id="dialog-ok" + style="fill:#282828;fill-opacity:1;display:block"> + <path + d="M 27.498,5 C 15.071,5 5,15.071 5,27.498 5,39.923 15.071,50 27.498,50 39.927,50 50,39.923 50,27.498 50,15.071 39.927,5 27.498,5 z M 41.419,19.886 24.706,40.208 13.789,29.29 c -1.258,-1.254 -1.258,-3.292 -0.003,-4.546 1.254,-1.255 3.292,-1.255 4.547,0 L 24.241,30.648 36.452,15.8 c 1.127,-1.368 3.153,-1.568 4.525,-0.438 1.37,1.127 1.569,3.153 0.442,4.524 z" + id="path4021" + style="fill:#282828;fill-opacity:1;display:inline" /> + +</g> + </g> +</svg> diff --git a/icons/help-toolbar.svg b/icons/help-toolbar.svg new file mode 100644 index 0000000..787b797 --- /dev/null +++ b/icons/help-toolbar.svg @@ -0,0 +1,18 @@ +<?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" + viewBox="0 0 55 55" + id="svg2" > + <path + d="m 50,27.625 c 0,12.3431 -10.1569,22.5 -22.5,22.5 C 15.1569,50.125 5,39.9681 5,27.625 5,15.2819 15.1569,5.125 27.5,5.125 c 12.3431,0 22.5,10.1569 22.5,22.5 z" + style="fill:#FFFFFF" /> + <path + d="m 23.956,27.167 c 0,-1.621 1.8,-1.89 3.645,-2.386 1.8,-0.495 3.6,-1.215 3.6,-3.825 0,-1.98 -1.845,-3.42 -3.734,-3.42 -3.78,0 -4.365,4.455 -7.246,4.455 -1.62,0 -2.745,-1.26 -2.745,-3.24 0,-4.726 5.94,-7.425 9.991,-7.425 5.806,0 10.756,3.6 10.756,9.631 0,4.995 -3.15,7.921 -7.785,9.091 l 0,1.619 c 0,1.801 -1.351,3.105 -3.241,3.105 -2.025,0 -3.24,-1.305 -3.24,-3.105 l 0,-4.5 -0.001,0 z m -0.27,13.77 c 0,-1.935 1.575,-3.51 3.51,-3.51 1.936,0 3.51,1.575 3.51,3.51 0,1.936 -1.574,3.512 -3.51,3.512 -1.935,-10e-4 -3.51,-1.577 -3.51,-3.512 z" + style="fill:#282828;stroke:#282828;stroke-width:0.25;stroke-miterlimit:4;" /> +</svg> diff --git a/icons/hideshowoff.svg b/icons/hideshowoff.svg new file mode 100644 index 0000000..3db14c9 --- /dev/null +++ b/icons/hideshowoff.svg @@ -0,0 +1,28 @@ +<?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="defs6" /> + <path + d="m 1.5,25.5 0,-8 a 8,8 0 0 1 8,-8 l 8,0 0,4 20,0 0,-4 8,0 a 8,8 0 0 1 8,8 l 0,8 0,8 a 8,8 0 0 1 -8,8 l -8,0 -2,0 0,4 -16,0 0,-4 -2,0 -8,0 a 8,8 0 0 1 -8,-8 l 0,-8 z" + id="path2882" + style="fill:#404040;fill-opacity:1;stroke:#ffffff;stroke-width:2.5;stroke-linecap:square;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 35.875,27.5 c 0,4.62493 -3.74962,8.374182 -8.375,8.374182 -4.62538,0 -8.375,-3.749252 -8.375,-8.374182 0,-4.624929 3.74962,-8.374182 8.375,-8.374182 4.62538,0 8.375,3.749253 8.375,8.374182 l 0,0 z" + id="path5" + style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1px;stroke-opacity:1" /> + <rect + width="10" + height="2" + x="22.5" + y="26.5" + id="rect2844" + style="fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:#404040;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/icons/hideshowon.svg b/icons/hideshowon.svg new file mode 100644 index 0000000..326b32c --- /dev/null +++ b/icons/hideshowon.svg @@ -0,0 +1,39 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="55" + height="55" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3689"> + <stop + id="stop3691" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3693" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="19" + x2="54" + y2="19" + id="linearGradient3695" + xlink:href="#linearGradient3689" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0.5,8.5)" /> + </defs> + <path + d="m 1.5,25.5 0,-8 a 8,8 0 0 1 8,-8 l 8,0 0,4 20,0 0,-4 8,0 a 8,8 0 0 1 8,8 l 0,8 0,8 a 8,8 0 0 1 -8,8 l -8,0 -2,0 0,4 -16,0 0,-4 -2,0 -8,0 a 8,8 0 0 1 -8,-8 l 0,-8 z" + id="path2882" + style="fill:url(#linearGradient3695);fill-opacity:1;stroke:#a08000;stroke-width:2;stroke-linecap:square;stroke-opacity:1" /> +</svg> diff --git a/icons/htmloff.svg b/icons/htmloff.svg new file mode 100644 index 0000000..92f1fd2 --- /dev/null +++ b/icons/htmloff.svg @@ -0,0 +1,128 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2" + xml:space="preserve"><metadata + id="metadata25"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs33"> + + + + + + + + + + + + + + + + + + + + + + + + + </defs><g + transform="translate(-24.072147,0)" + id="g3014"><g + transform="matrix(1.1623273,0,0,1.1623273,5.8946433,-8.9787622)" + id="g3116" + style="fill:none;stroke:#ffffff;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><polygon + points="39.811,18.343 39.811,38.42 18.435,38.42 18.435,10.583 32.046,10.583 " + id="polygon3118" + style="fill:none;stroke:#ffffff;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><polyline + id="polyline3120" + points="39.811,18.343 32.046,18.343 32.046,10.583 " + style="fill:none;stroke:#ffffff;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g + transform="matrix(1.1623273,0,0,1.1623273,5.8946433,-8.9787622)" + id="g3122" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><circle + cx="29.122999" + cy="28.4" + r="6.4689999" + id="circle3124" + style="fill:none;stroke:#ffffff;stroke-opacity:1" /><g + id="g3126" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><path + d="m 29.124,21.932 c 0,0 3.596,2.971 3.596,6.492 0,3.523 -3.596,6.445 -3.596,6.445" + id="path3128" + style="fill:none;stroke:#ffffff;stroke-width:0.97500002;stroke-opacity:1" /><path + d="m 29.124,21.932 c 0,0 -3.642,2.728 -3.642,6.492 0,3.765 3.642,6.445 3.642,6.445" + id="path3130" + style="fill:none;stroke:#ffffff;stroke-width:0.97500002;stroke-opacity:1" /><line + style="fill:none;stroke:#ffffff;stroke-width:0.97500002;stroke-opacity:1" + x1="29.124001" + x2="29.124001" + y1="21.931999" + y2="34.868999" + id="line3132" /><line + style="fill:none;stroke:#ffffff;stroke-width:0.97500002;stroke-opacity:1" + x1="22.653999" + x2="35.591" + y1="28.4" + y2="28.4" + id="line3134" /></g></g></g><g + id="g3830"><g + transform="matrix(0.55205508,0,0,0.55205508,75.618464,18.235971)" + id="g4382"><g + transform="translate(-80.093659,12.220029)" + id="g4308" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><g + id="g4310" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><path + d="m 6.736,49.002 h 24.52 c 2.225,0 3.439,-1.447 3.439,-3.441 v -27.28 c 0,-1.73 -1.732,-3.441 -3.439,-3.441 h -4.389" + id="path4312" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g></g><g + transform="translate(-80.093659,12.220029)" + id="g4314" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><g + id="g4316" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><path + d="m 26.867,38.592 c 0,1.836 -1.345,3.201 -3.441,4.047 L 6.736,49.002 V 14.84 l 16.69,-8.599 c 2.228,-0.394 3.441,0.84 3.441,2.834 v 29.517 z" + id="path4318" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g></g><path + d="m -70.669659,54.827029 c 0,0 -1.351,-0.543 -2.702,-0.543 -1.351,0 -2.703,0.543 -2.703,0.543" + id="path4320" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,44.226029 c 0,0 -1.239,-0.543 -2.815,-0.543 -1.577,0 -2.59,0.543 -2.59,0.543" + id="path4322" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,33.898029 c 0,0 -1.125,-0.544 -2.927,-0.544 -1.802,0 -2.478,0.544 -2.478,0.544" + id="path4324" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><line + id="line4326" + y2="23.725029" + y1="58.753029" + x2="-66.884659" + x1="-66.884659" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g><g + transform="matrix(1,0,0,-1,-30.386573,49.171266)" + id="g4770"><g + transform="translate(34.0803,-1006.42)" + id="g4772"><polyline + id="polyline4774" + points="51.562,15.306 41.17,16.188 42.053,5.794" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" + transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" /><path + d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067" + id="path4776" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></g></svg>
\ No newline at end of file diff --git a/icons/htmlon.svg b/icons/htmlon.svg new file mode 100644 index 0000000..fe8fa71 --- /dev/null +++ b/icons/htmlon.svg @@ -0,0 +1,128 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2" + xml:space="preserve"><metadata + id="metadata25"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs33"> + + + + + + + + + + + + + + + + + + + + + + + + + </defs><g + transform="translate(-24.072147,0)" + id="g4121"><g + transform="matrix(1.1623273,0,0,1.1623273,5.8946433,-8.9787622)" + id="g3116" + style="fill:none;stroke:#00ff00;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><polygon + points="39.811,38.42 18.435,38.42 18.435,10.583 32.046,10.583 39.811,18.343 " + id="polygon3118" + style="fill:none;stroke:#00ff00;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><polyline + id="polyline3120" + points="39.811,18.343 32.046,18.343 32.046,10.583 " + style="fill:none;stroke:#00ff00;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g + transform="matrix(1.1623273,0,0,1.1623273,5.8946433,-8.9787622)" + id="g3122" + style="fill:none;stroke:#00ff00;stroke-opacity:1"><circle + cx="29.122999" + cy="28.4" + r="6.4689999" + id="circle3124" + style="fill:none;stroke:#00ff00;stroke-opacity:1" /><g + id="g3126" + style="fill:none;stroke:#00ff00;stroke-opacity:1"><path + d="m 29.124,21.932 c 0,0 3.596,2.971 3.596,6.492 0,3.523 -3.596,6.445 -3.596,6.445" + id="path3128" + style="fill:none;stroke:#00ff00;stroke-width:0.97500002;stroke-opacity:1" /><path + d="m 29.124,21.932 c 0,0 -3.642,2.728 -3.642,6.492 0,3.765 3.642,6.445 3.642,6.445" + id="path3130" + style="fill:none;stroke:#00ff00;stroke-width:0.97500002;stroke-opacity:1" /><line + style="fill:none;stroke:#00ff00;stroke-width:0.97500002;stroke-opacity:1" + x1="29.124001" + x2="29.124001" + y1="21.931999" + y2="34.868999" + id="line3132" /><line + style="fill:none;stroke:#00ff00;stroke-width:0.97500002;stroke-opacity:1" + x1="22.653999" + x2="35.591" + y1="28.4" + y2="28.4" + id="line3134" /></g></g></g><g + id="g3830"><g + transform="matrix(0.55205508,0,0,0.55205508,75.618464,18.235971)" + id="g4382"><g + transform="translate(-80.093659,12.220029)" + id="g4308" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><g + id="g4310" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><path + d="m 6.736,49.002 h 24.52 c 2.225,0 3.439,-1.447 3.439,-3.441 v -27.28 c 0,-1.73 -1.732,-3.441 -3.439,-3.441 h -4.389" + id="path4312" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g></g><g + transform="translate(-80.093659,12.220029)" + id="g4314" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><g + id="g4316" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><path + d="m 26.867,38.592 c 0,1.836 -1.345,3.201 -3.441,4.047 L 6.736,49.002 V 14.84 l 16.69,-8.599 c 2.228,-0.394 3.441,0.84 3.441,2.834 v 29.517 z" + id="path4318" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g></g><path + d="m -70.669659,54.827029 c 0,0 -1.351,-0.543 -2.702,-0.543 -1.351,0 -2.703,0.543 -2.703,0.543" + id="path4320" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,44.226029 c 0,0 -1.239,-0.543 -2.815,-0.543 -1.577,0 -2.59,0.543 -2.59,0.543" + id="path4322" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,33.898029 c 0,0 -1.125,-0.544 -2.927,-0.544 -1.802,0 -2.478,0.544 -2.478,0.544" + id="path4324" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><line + id="line4326" + y2="23.725029" + y1="58.753029" + x2="-66.884659" + x1="-66.884659" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g><g + transform="matrix(1,0,0,-1,-30.386573,49.171266)" + id="g4770"><g + transform="translate(34.0803,-1006.42)" + id="g4772"><polyline + id="polyline4774" + points="51.562,15.306 41.17,16.188 42.053,5.794" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" + transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" /><path + d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067" + id="path4776" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></g></svg>
\ No newline at end of file diff --git a/icons/image-saveoff.svg b/icons/image-saveoff.svg new file mode 100644 index 0000000..365f578 --- /dev/null +++ b/icons/image-saveoff.svg @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2" + xml:space="preserve"><metadata + id="metadata25"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs33"> + + + + + + + + + + + + + + + + + + + + + + + + + </defs><g + transform="matrix(0.55205508,0,0,0.55205508,77.118464,18.235971)" + id="g4382"><g + transform="translate(-80.093659,12.220029)" + id="g4308" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <g + id="g4310" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <path + d="m 6.736,49.002 h 24.52 c 2.225,0 3.439,-1.447 3.439,-3.441 v -27.28 c 0,-1.73 -1.732,-3.441 -3.439,-3.441 h -4.389" + id="path4312" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + </g><g + transform="translate(-80.093659,12.220029)" + id="g4314" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <g + id="g4316" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <path + d="m 26.867,38.592 c 0,1.836 -1.345,3.201 -3.441,4.047 L 6.736,49.002 V 14.84 l 16.69,-8.599 c 2.228,-0.394 3.441,0.84 3.441,2.834 v 29.517 z" + id="path4318" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + </g><path + d="m -70.669659,54.827029 c 0,0 -1.351,-0.543 -2.702,-0.543 -1.351,0 -2.703,0.543 -2.703,0.543" + id="path4320" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,44.226029 c 0,0 -1.239,-0.543 -2.815,-0.543 -1.577,0 -2.59,0.543 -2.59,0.543" + id="path4322" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,33.898029 c 0,0 -1.125,-0.544 -2.927,-0.544 -1.802,0 -2.478,0.544 -2.478,0.544" + id="path4324" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><line + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + x1="-66.884659" + x2="-66.884659" + y1="58.753029" + y2="23.725029" + id="line4326" /></g><g + transform="matrix(1.1623273,0,0,1.1623273,-14.422024,-12.63995)" + id="g3882" + style="fill:none;stroke:#ffffff;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"><g + id="g3884" + style="fill:none;stroke:#ffffff;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><polygon + points="43.041,21.577 35.281,13.812 15.204,13.812 15.204,35.189 43.041,35.189 " + id="polygon3886" + style="fill:none;stroke:#ffffff;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><polyline + id="polyline3888" + points="35.281,13.812 35.281,21.577 43.041,21.577 " + style="fill:none;stroke:#ffffff;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g><path + d="m 19.426691,12.275117 c -4.727185,0 -8.666312,4.714399 -8.666312,4.714399 0,0 3.939127,4.737646 8.666312,4.735322 4.729509,-0.0046 8.668637,-4.739971 8.668637,-4.739971 0,0 -3.939128,-4.713237 -8.668637,-4.70975 z m 0,8.039818 c -1.830666,0 -3.314958,-1.484292 -3.314958,-3.31612 0,-1.827179 1.484292,-3.314958 3.314958,-3.314958 1.828341,0 3.312632,1.487779 3.312632,3.314958 0,1.831828 -1.484291,3.31612 -3.312632,3.31612 z" + id="path3890" + style="fill:#ffffff;fill-opacity:1;stroke:none;display:inline" /><circle + cx="29.207001" + cy="25.863001" + r="1.294" + transform="matrix(1.1623273,0,0,1.1623273,-14.520241,-13.061294)" + id="circle3892" + style="fill:#ffffff;fill-opacity:1;stroke:none;display:inline" /><g + transform="matrix(1,0,0,-1,-24.850339,47.707501)" + id="g4770"><g + transform="translate(34.0803,-1006.42)" + id="g4772"><polyline + transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" + points="51.562,15.306 41.17,16.188 42.053,5.794" + id="polyline4774" /><path + d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067" + id="path4776" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></svg>
\ No newline at end of file diff --git a/icons/image-saveon.svg b/icons/image-saveon.svg new file mode 100644 index 0000000..71a91ff --- /dev/null +++ b/icons/image-saveon.svg @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2" + xml:space="preserve"><metadata + id="metadata25"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs33"> + + + + + + + + + + + + + + + + + + + + + + + + + </defs><g + transform="matrix(0.55205508,0,0,0.55205508,77.118464,18.235971)" + id="g4382"><g + transform="translate(-80.093659,12.220029)" + id="g4308" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <g + id="g4310" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <path + d="m 6.736,49.002 h 24.52 c 2.225,0 3.439,-1.447 3.439,-3.441 v -27.28 c 0,-1.73 -1.732,-3.441 -3.439,-3.441 h -4.389" + id="path4312" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + </g><g + transform="translate(-80.093659,12.220029)" + id="g4314" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <g + id="g4316" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <path + d="m 26.867,38.592 c 0,1.836 -1.345,3.201 -3.441,4.047 L 6.736,49.002 V 14.84 l 16.69,-8.599 c 2.228,-0.394 3.441,0.84 3.441,2.834 v 29.517 z" + id="path4318" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + </g><path + d="m -70.669659,54.827029 c 0,0 -1.351,-0.543 -2.702,-0.543 -1.351,0 -2.703,0.543 -2.703,0.543" + id="path4320" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,44.226029 c 0,0 -1.239,-0.543 -2.815,-0.543 -1.577,0 -2.59,0.543 -2.59,0.543" + id="path4322" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,33.898029 c 0,0 -1.125,-0.544 -2.927,-0.544 -1.802,0 -2.478,0.544 -2.478,0.544" + id="path4324" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><line + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + x1="-66.884659" + x2="-66.884659" + y1="58.753029" + y2="23.725029" + id="line4326" /></g><g + transform="matrix(1.1623273,0,0,1.1623273,-14.422024,-12.63995)" + id="g3882" + style="fill:none;stroke:#00ff00;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"><g + id="g3884" + style="fill:none;stroke:#00ff00;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><polygon + points="43.041,21.577 35.281,13.812 15.204,13.812 15.204,35.189 43.041,35.189 " + id="polygon3886" + style="fill:none;stroke:#00ff00;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><polyline + id="polyline3888" + points="35.281,13.812 35.281,21.577 43.041,21.577 " + style="fill:none;stroke:#00ff00;stroke-width:2.15085721;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g><path + d="m 19.426691,12.275117 c -4.727185,0 -8.666312,4.714399 -8.666312,4.714399 0,0 3.939127,4.737646 8.666312,4.735322 4.729509,-0.0046 8.668637,-4.739971 8.668637,-4.739971 0,0 -3.939128,-4.713237 -8.668637,-4.70975 z m 0,8.039818 c -1.830666,0 -3.314958,-1.484292 -3.314958,-3.31612 0,-1.827179 1.484292,-3.314958 3.314958,-3.314958 1.828341,0 3.312632,1.487779 3.312632,3.314958 0,1.831828 -1.484291,3.31612 -3.312632,3.31612 z" + id="path3890" + style="fill:#00ff00;fill-opacity:1;stroke:none;display:inline" /><circle + cx="29.207001" + cy="25.863001" + r="1.294" + transform="matrix(1.1623273,0,0,1.1623273,-14.520241,-13.061294)" + id="circle3892" + style="fill:#00ff00;fill-opacity:1;stroke:#00ff00;stroke-opacity:1;display:inline" /><g + transform="matrix(1,0,0,-1,-24.850339,47.707501)" + id="g4770"><g + transform="translate(34.0803,-1006.42)" + id="g4772"><polyline + transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" + points="51.562,15.306 41.17,16.188 42.053,5.794" + id="polyline4774" /><path + d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067" + id="path4776" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></svg>
\ No newline at end of file diff --git a/icons/load-from-journal.svg b/icons/load-from-journal.svg new file mode 100644 index 0000000..d0869da --- /dev/null +++ b/icons/load-from-journal.svg @@ -0,0 +1,158 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2" + xml:space="preserve"><metadata + id="metadata25"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs33"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +</defs><g + transform="matrix(0.55205508,0,0,0.55205508,44.618464,18.235971)" + id="g4382"><g + transform="translate(-80.093659,12.220029)" + id="g4308" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <g + id="g4310" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <path + d="m 6.736,49.002 h 24.52 c 2.225,0 3.439,-1.447 3.439,-3.441 v -27.28 c 0,-1.73 -1.732,-3.441 -3.439,-3.441 h -4.389" + id="path4312" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + </g><g + transform="translate(-80.093659,12.220029)" + id="g4314" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <g + id="g4316" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <path + d="m 26.867,38.592 c 0,1.836 -1.345,3.201 -3.441,4.047 L 6.736,49.002 V 14.84 l 16.69,-8.599 c 2.228,-0.394 3.441,0.84 3.441,2.834 v 29.517 z" + id="path4318" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + </g><path + d="m -70.669659,54.827029 c 0,0 -1.351,-0.543 -2.702,-0.543 -1.351,0 -2.703,0.543 -2.703,0.543" + id="path4320" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,44.226029 c 0,0 -1.239,-0.543 -2.815,-0.543 -1.577,0 -2.59,0.543 -2.59,0.543" + id="path4322" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,33.898029 c 0,0 -1.125,-0.544 -2.927,-0.544 -1.802,0 -2.478,0.544 -2.478,0.544" + id="path4324" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><line + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + x1="-66.884659" + x2="-66.884659" + y1="58.753029" + y2="23.725029" + id="line4326" /></g><g + id="g4084"><path + d="m 40.046106,34.391197 c -0.384814,0 -0.764757,-0.02436 -1.139134,-0.06959 l 0.965863,1.634591 0.951946,-1.60954 c -0.258167,0.02088 -0.515638,0.04454 -0.778675,0.04454 z" + id="path11" + style="fill:none;stroke:#ffffff;stroke-width:2.08759975;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><g + transform="matrix(0.69586655,0,0,0.69586655,20.911863,0.79545554)" + id="g13" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path + d="m 40.16,11.726 c -2.164,0 -3.958,1.555 -4.343,3.607 1.859,1.345 3.457,3.115 4.675,5.208 2.285,-0.172 4.094,-2.061 4.094,-4.39 0,-2.444 -1.982,-4.425 -4.426,-4.425 z" + id="path15" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path + d="m 40.713,39.887 c -1.224,2.232 -2.86,4.131 -4.797,5.556 0.521,1.864 2.213,3.239 4.244,3.239 2.443,0 4.426,-1.98 4.426,-4.424 0,-2.255 -1.693,-4.096 -3.873,-4.371 z" + id="path17" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path + d="m 14.273,39.871 c -2.253,0.206 -4.024,2.079 -4.024,4.387 0,2.443 1.98,4.424 4.424,4.424 2.064,0 3.784,-1.42 4.272,-3.332 -1.883,-1.416 -3.475,-3.289 -4.672,-5.479 z" + id="path19" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path + d="m 19.026,15.437 c -0.343,-2.103 -2.154,-3.711 -4.353,-3.711 -2.444,0 -4.424,1.981 -4.424,4.424 0,2.382 1.886,4.31 4.245,4.406 1.186,-2.043 2.732,-3.784 4.532,-5.119 z" + id="path21" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><path + d="m 40.046106,9.537627 c 1.327713,0 2.59419,0.2860012 3.770205,0.784937 0.515637,-0.7487519 0.819731,-1.6540743 0.819731,-2.6324627 0,-2.5656599 -2.079945,-4.6463009 -4.646301,-4.6463009 -2.56566,0 -4.645605,2.080641 -4.645605,4.6463009 0,0.9936975 0.314531,1.9129372 0.846173,2.6679527 1.199674,-0.5212044 2.496074,-0.820427 3.855797,-0.820427 z" + id="path23" + style="fill:none;stroke:#ffffff;stroke-width:2.08759975;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><g + transform="matrix(0.69586655,0,0,0.69586655,20.911863,0.79545554)" + id="g25" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"><path + d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z" + id="path2988" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g + transform="matrix(0.69586655,0,0,0.69586655,20.911863,0.79545554)" + id="g28" + style="fill:#ffffff;fill-opacity:1;stroke:none"><path + d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 -3.75,-0.083 z" + id="path30" + style="fill:#ffffff;fill-opacity:1;stroke:none" /><path + d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z" + id="path32" + style="fill:#ffffff;fill-opacity:1;stroke:none" /><path + d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z" + id="path34" + style="fill:#ffffff;fill-opacity:1;stroke:none" /><path + d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z" + id="path2998" + style="fill:#ffffff;fill-opacity:1;stroke:none" /><path + d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z" + id="path37" + style="fill:#ffffff;fill-opacity:1;stroke:none" /><path + d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z" + id="path3002" + style="fill:#ffffff;fill-opacity:1;stroke:none" /></g></g><g + transform="matrix(0,-1,-1,0,43.9376,89.386573)" + id="g4770"><g + transform="translate(34.0803,-1006.42)" + id="g4772"><polyline + transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" + points="51.562,15.306 41.17,16.188 42.053,5.794" + id="polyline4774" /><path + d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067" + id="path4776" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></svg>
\ No newline at end of file diff --git a/icons/logo-saveoff.svg b/icons/logo-saveoff.svg new file mode 100644 index 0000000..0954a62 --- /dev/null +++ b/icons/logo-saveoff.svg @@ -0,0 +1,146 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2" + xml:space="preserve"><metadata + id="metadata25"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs33"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +</defs><g + transform="matrix(0.75578519,0,0,0.75578519,-4.9396196,-1.2911009)" + id="clipping-text" + style="fill:none;stroke:#ffffff;stroke-opacity:1;display:block"> + <g + id="g3152" + style="fill:none;stroke:#ffffff;stroke-opacity:1;display:inline"> + <g + id="g3154" + style="fill:none;stroke:#ffffff;stroke-opacity:1"> + <polygon + points="31.874,6.088 43.818,18.027 43.818,48.914 10.932,48.914 10.932,6.088 " + id="polygon3156" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-opacity:1" /> + <polyline + id="polyline3158" + points="43.818,18.027 31.874,18.027 31.874,6.088 " + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-opacity:1" /> + </g> + </g> + <line + id="line3160" + y2="26.25" + y1="26.25" + x2="36.875" + x1="17.875" + display="inline" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-opacity:1;display:inline" /> + <line + id="line3162" + y2="33.25" + y1="33.25" + x2="36.875" + x1="17.875" + display="inline" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-opacity:1;display:inline" /> + <line + id="line3164" + y2="40.25" + y1="40.25" + x2="36.875" + x1="17.875" + display="inline" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-opacity:1;display:inline" /> +</g><g + id="g3830"><g + transform="matrix(0.55205508,0,0,0.55205508,75.618464,18.235971)" + id="g4382"><g + transform="translate(-80.093659,12.220029)" + id="g4308" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><g + id="g4310" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><path + d="m 6.736,49.002 h 24.52 c 2.225,0 3.439,-1.447 3.439,-3.441 v -27.28 c 0,-1.73 -1.732,-3.441 -3.439,-3.441 h -4.389" + id="path4312" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g></g><g + transform="translate(-80.093659,12.220029)" + id="g4314" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><g + id="g4316" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><path + d="m 26.867,38.592 c 0,1.836 -1.345,3.201 -3.441,4.047 L 6.736,49.002 V 14.84 l 16.69,-8.599 c 2.228,-0.394 3.441,0.84 3.441,2.834 v 29.517 z" + id="path4318" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g></g><path + d="m -70.669659,54.827029 c 0,0 -1.351,-0.543 -2.702,-0.543 -1.351,0 -2.703,0.543 -2.703,0.543" + id="path4320" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,44.226029 c 0,0 -1.239,-0.543 -2.815,-0.543 -1.577,0 -2.59,0.543 -2.59,0.543" + id="path4322" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,33.898029 c 0,0 -1.125,-0.544 -2.927,-0.544 -1.802,0 -2.478,0.544 -2.478,0.544" + id="path4324" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><line + id="line4326" + y2="23.725029" + y1="58.753029" + x2="-66.884659" + x1="-66.884659" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g><g + transform="matrix(1,0,0,-1,-30.386573,49.171266)" + id="g4770"><g + transform="translate(34.0803,-1006.42)" + id="g4772"><polyline + id="polyline4774" + points="51.562,15.306 41.17,16.188 42.053,5.794" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" + transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" /><path + d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067" + id="path4776" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></g></svg>
\ No newline at end of file diff --git a/icons/logo-saveon.svg b/icons/logo-saveon.svg new file mode 100644 index 0000000..f2bfc31 --- /dev/null +++ b/icons/logo-saveon.svg @@ -0,0 +1,146 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2" + xml:space="preserve"><metadata + id="metadata25"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs33"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +</defs><g + transform="matrix(0.75578519,0,0,0.75578519,-4.9396196,-1.2911009)" + id="clipping-text" + style="fill:none;stroke:#00ff00;stroke-opacity:1;display:block"> + <g + id="g3152" + style="fill:none;stroke:#00ff00;stroke-opacity:1;display:inline"> + <g + id="g3154" + style="fill:none;stroke:#00ff00;stroke-opacity:1"> + <polygon + points="43.818,18.027 43.818,48.914 10.932,48.914 10.932,6.088 31.874,6.088 " + id="polygon3156" + style="fill:none;stroke:#00ff00;stroke-width:3.5;stroke-opacity:1" /> + <polyline + id="polyline3158" + points="43.818,18.027 31.874,18.027 31.874,6.088 " + style="fill:none;stroke:#00ff00;stroke-width:3.5;stroke-opacity:1" /> + </g> + </g> + <line + id="line3160" + y2="26.25" + y1="26.25" + x2="36.875" + x1="17.875" + display="inline" + style="fill:none;stroke:#00ff00;stroke-width:3.5;stroke-opacity:1;display:inline" /> + <line + id="line3162" + y2="33.25" + y1="33.25" + x2="36.875" + x1="17.875" + display="inline" + style="fill:none;stroke:#00ff00;stroke-width:3.5;stroke-opacity:1;display:inline" /> + <line + id="line3164" + y2="40.25" + y1="40.25" + x2="36.875" + x1="17.875" + display="inline" + style="fill:none;stroke:#00ff00;stroke-width:3.5;stroke-opacity:1;display:inline" /> +</g><g + id="g3830"><g + transform="matrix(0.55205508,0,0,0.55205508,75.618464,18.235971)" + id="g4382"><g + transform="translate(-80.093659,12.220029)" + id="g4308" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><g + id="g4310" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><path + d="m 6.736,49.002 h 24.52 c 2.225,0 3.439,-1.447 3.439,-3.441 v -27.28 c 0,-1.73 -1.732,-3.441 -3.439,-3.441 h -4.389" + id="path4312" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g></g><g + transform="translate(-80.093659,12.220029)" + id="g4314" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><g + id="g4316" + style="fill:none;stroke:#ffffff;stroke-opacity:1"><path + d="m 26.867,38.592 c 0,1.836 -1.345,3.201 -3.441,4.047 L 6.736,49.002 V 14.84 l 16.69,-8.599 c 2.228,-0.394 3.441,0.84 3.441,2.834 v 29.517 z" + id="path4318" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g></g><path + d="m -70.669659,54.827029 c 0,0 -1.351,-0.543 -2.702,-0.543 -1.351,0 -2.703,0.543 -2.703,0.543" + id="path4320" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,44.226029 c 0,0 -1.239,-0.543 -2.815,-0.543 -1.577,0 -2.59,0.543 -2.59,0.543" + id="path4322" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path + d="m -70.669659,33.898029 c 0,0 -1.125,-0.544 -2.927,-0.544 -1.802,0 -2.478,0.544 -2.478,0.544" + id="path4324" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><line + id="line4326" + y2="23.725029" + y1="58.753029" + x2="-66.884659" + x1="-66.884659" + style="fill:none;stroke:#ffffff;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /></g><g + transform="matrix(1,0,0,-1,-30.386573,49.171266)" + id="g4770"><g + transform="translate(34.0803,-1006.42)" + id="g4772"><polyline + id="polyline4774" + points="51.562,15.306 41.17,16.188 42.053,5.794" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" + transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" /><path + d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067" + id="path4776" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></g></svg>
\ No newline at end of file diff --git a/icons/numbersoff.svg b/icons/numbersoff.svg new file mode 100644 index 0000000..cffabf7 --- /dev/null +++ b/icons/numbersoff.svg @@ -0,0 +1,38 @@ +<?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="defs5" /> + <g + transform="translate(6.1026134,-1.6740561)" + id="g2392" + style="fill:#ffffff;fill-opacity:1"> + <text + x="3.9423084" + y="26.866751" + id="text2384" + xml:space="preserve" + style="font-size:12px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"><tspan + x="3.9423084" + y="26.866751" + id="tspan2386" + style="font-size:18px;font-weight:normal;fill:#ffffff;fill-opacity:1;-inkscape-font-specification:AlArabiya">123</tspan></text> + <text + x="1.8153553" + y="44.840736" + id="text2388" + xml:space="preserve" + style="font-size:12px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"><tspan + x="1.8153553" + y="44.840736" + id="tspan2390" + style="font-size:18px;font-weight:normal;fill:#ffffff;fill-opacity:1;-inkscape-font-specification:AlArabiya">+–=</tspan></text> + </g> +</svg> diff --git a/icons/numberson.svg b/icons/numberson.svg new file mode 100644 index 0000000..124994e --- /dev/null +++ b/icons/numberson.svg @@ -0,0 +1,46 @@ +<?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="defs5" /> + <rect + width="55" + height="55" + rx="0" + x="0" + y="0" + id="rect2839" + style="fill:#ffd200;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <g + transform="translate(6.1026134,-1.6740561)" + id="g2392" + style="fill:#a000a0;fill-opacity:1"> + <text + x="4.5171318" + y="26.866751" + id="text2384" + xml:space="preserve" + style="font-size:12px;fill:#a000a0;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"><tspan + x="4.5171318" + y="26.866751" + id="tspan2386" + style="font-size:18px;fill:#a000a0;fill-opacity:1">123</tspan></text> + <text + x="1.8153553" + y="44.840736" + id="text2388" + xml:space="preserve" + style="font-size:12px;fill:#a000a0;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"><tspan + x="1.8153553" + y="44.840736" + id="tspan2390" + style="font-size:18px;fill:#a000a0;fill-opacity:1">+–=</tspan></text> + </g> +</svg> diff --git a/icons/palette.svg b/icons/palette.svg new file mode 100644 index 0000000..48b4b36 --- /dev/null +++ b/icons/palette.svg @@ -0,0 +1,17 @@ +<?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="defs6" /> + <path + d="m 1.5,25.5 0,-8 a 8,8 0 0 1 8,-8 l 8,0 0,4 20,0 0,-4 8,0 a 8,8 0 0 1 8,8 l 0,8 0,8 a 8,8 0 0 1 -8,8 l -8,0 -2,0 0,4 -16,0 0,-4 -2,0 -8,0 a 8,8 0 0 1 -8,-8 l 0,-8 z" + id="path2882" + style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2.5;stroke-linecap:square;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/icons/paletteoff.svg b/icons/paletteoff.svg new file mode 100644 index 0000000..1964c0a --- /dev/null +++ b/icons/paletteoff.svg @@ -0,0 +1,28 @@ +<?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="45" + height="45" + id="svg2"> + <defs + id="defs13" /> + <path + d="m 0.5,36.5 c 0.25,-9 0,-27 0,-27 l 44,0 0,27 -44,0 z" + id="path3" + style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 30.875,22.999999 c 0,4.62493 -3.74962,8.374182 -8.375,8.374182 -4.62538,0 -8.375,-3.749252 -8.375,-8.374182 0,-4.624929 3.74962,-8.374182 8.375,-8.374182 4.62538,0 8.375,3.749253 8.375,8.374182 l 0,0 z" + id="path5" + style="fill:#404040;fill-opacity:1;stroke:#404040;stroke-width:1px;stroke-opacity:1" /> + <rect + width="10" + height="2" + x="17.5" + y="21.5" + id="rect2844" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/icons/paletteon.svg b/icons/paletteon.svg new file mode 100644 index 0000000..cd9f594 --- /dev/null +++ b/icons/paletteon.svg @@ -0,0 +1,36 @@ +<?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="45" + height="45" + id="svg2"> + <defs + id="defs13" /> + <path + d="m 0.5,36.5 c 0.25,-9 0,-27 0,-27 l 44,0 0,27 -44,0 z" + id="path3" + style="fill:#ffd000;fill-opacity:1;stroke:#a08000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 30.875,22.999999 c 0,4.62493 -3.74962,8.374182 -8.375,8.374182 -4.62538,0 -8.375,-3.749252 -8.375,-8.374182 0,-4.624929 3.74962,-8.374182 8.375,-8.374182 4.62538,0 8.375,3.749253 8.375,8.374182 l 0,0 z" + id="path5" + style="fill:#00ff00;fill-opacity:1;stroke:#00ff00;stroke-width:1px;stroke-opacity:1" /> + <rect + width="10" + height="2" + x="17.5" + y="21.5" + id="rect2844" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <rect + width="10" + height="2" + x="-27.5" + y="21.5" + transform="matrix(0,-1,1,0,0,0)" + id="rect2844-4" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/icons/penoff.svg b/icons/penoff.svg new file mode 100644 index 0000000..109c0d6 --- /dev/null +++ b/icons/penoff.svg @@ -0,0 +1,41 @@ +<?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="defs5" /> + <path + d="M 11.152285,41.709935 c 1.43401,0.788706 5.23977,1.402428 7.528553,1.290609 1.626167,-0.07945 3.914929,-0.479849 5.234137,-1.43401 2.238123,-1.618798 3.032695,-5.829627 5.090736,-7.671954 1.225701,-1.097229 3.231844,-2.444635 4.875634,-2.509518 2.003851,-0.07909 4.468168,1.514349 6.166244,2.581219 1.290216,0.810619 3.800127,3.369923 3.800127,3.369923" + id="path2471" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;" /> + <path + d="M 35.566307,13.352385 l 2.437818,-2.366117 1.200984,0.84248 1.416085,1.200984 0.985882,1.272684 0.914181,1.487786 -2.366117,2.509519 -0.896257,-1.505711 -2.186866,-2.366117 -1.50571,-1.075508 z" + id="path3255" + style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 32.877538,16.112854 l 2.294417,-2.079315 1.200984,0.84248 1.416085,1.200984 0.985882,1.272684 0.914181,1.487786 -2.079315,1.864214 -0.967957,-1.147208 -2.330267,-2.222716 -1.43401,-1.218909 z" + id="path3253" + style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 13.423248,38.807621 l 0.891754,-3.80169 18.820708,-18.21056 -0.469344,-0.680549 2.252852,-2.135517 5.115854,5.115853 -2.229385,2.135517 -0.774419,-0.539747 -19.05538,18.022823 -3.70782,0.657082 -0.84482,-0.563212 z" + id="path2822" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;" /> + <path + d="M 33.482432,17.358584 l 3.660886,3.473148" + id="path3596" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;" /> + <path + d="M 10.935723,41.905293 l 2.769132,-2.816066" + id="path3598" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;" /> + <path + d="M 14.690478,35.287537 c 0,0 1.594197,0.393866 2.158983,0.93869 0.574138,0.553844 1.032558,2.158984 1.032558,2.158984" + id="path3600" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;" /> +</svg> diff --git a/icons/penon.svg b/icons/penon.svg new file mode 100644 index 0000000..c717a9e --- /dev/null +++ b/icons/penon.svg @@ -0,0 +1,61 @@ +<?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="defs5" /> + <rect + width="55" + height="55" + rx="0" + x="0" + y="0" + id="rect2839" + style="fill:#ffd200;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <g + transform="translate(5.2499995,-0.75000033)" + id="g2824"> + <g + transform="translate(-31.525379,-20.795051)" + id="g2431"> + <path + d="M 37.427664,63.254986 c 1.43401,0.788706 5.23977,1.402428 7.528553,1.290609 1.626167,-0.07945 3.914929,-0.479849 5.234137,-1.43401 2.238123,-1.618798 3.032695,-5.829627 5.090736,-7.671954 1.225701,-1.097229 3.231844,-2.444635 4.875634,-2.509518 2.003851,-0.07909 4.468168,1.514349 6.166244,2.581219 1.290216,0.810619 3.800127,3.369923 3.800127,3.369923" + id="path2471" + style="fill:none;stroke:#0080ff;stroke-width:3;stroke-linecap:round;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 39.220176,61.820976 l 1.147208,-4.660533 1.935914,0.358503 1.218909,1.075507 0.286802,2.079315 -4.588833,1.147208 z" + id="path3245" + style="fill:#e0e0e0;fill-opacity:1;stroke:#e0e0e0;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 37.786166,63.039885 c 1.720812,-1.864213 1.864213,-1.720812 1.864213,-1.720812" + id="path3243" + style="fill:none;stroke:#0060ff;stroke-width:2;stroke-linecap:round;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 40.869288,56.443439 59.224617,38.374911 60.658628,39.73722 42.6618,57.303845 40.869288,56.443439 z" + id="path3247" + style="fill:#a0a0ff;fill-opacity:1;stroke:#a0a0ff;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 44.095811,58.307652 61.949237,41.09953 63.383248,42.461839 44.454312,60.530368 44.095811,58.307652 z" + id="path3249" + style="fill:#8080ff;fill-opacity:1;stroke:#8080ff;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 42.231598,57.232144 l 1.649111,1.649111 18.28363,-17.781726 -1.505711,-1.792512 -18.42703,17.925127 z" + id="path3251" + style="fill:#c4c4ff;fill-opacity:1;stroke:#c4c4ff;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 61.841686,34.897436 l 2.437818,-2.366117 1.200984,0.84248 1.416085,1.200984 0.985882,1.272684 0.914181,1.487786 -2.366117,2.509519 -0.896257,-1.505711 -2.186866,-2.366117 -1.50571,-1.075508 z" + id="path3255" + style="fill:#e0a040;fill-opacity:1;stroke:#e0a040;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 59.152917,37.657905 l 2.294417,-2.079315 1.200984,0.84248 1.416085,1.200984 0.985882,1.272684 0.914181,1.487786 -2.079315,1.864214 -0.967957,-1.147208 -2.330267,-2.222716 -1.43401,-1.218909 z" + id="path3253" + style="fill:#e0e0e0;fill-opacity:1;stroke:#c4c4c4;stroke-width:1px;stroke-opacity:1" /> + </g> + </g> +</svg> diff --git a/icons/pippy-openoff.svg b/icons/pippy-openoff.svg new file mode 100644 index 0000000..605e62a --- /dev/null +++ b/icons/pippy-openoff.svg @@ -0,0 +1,133 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.1" + width="55" + height="55" + viewBox="0 0 54.999998 55.000001" + id="Icon" + xml:space="preserve" + style="overflow:visible"><metadata + id="metadata26"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs24"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <linearGradient + id="linearGradient3166-6"><stop + id="stop3168-5" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /><stop + id="stop3170-6" + style="stop-color:#ff0000;stop-opacity:1" + offset="1" /></linearGradient><linearGradient + x1="0" + y1="22" + x2="74" + y2="22" + id="linearGradient3172-9" + xlink:href="#linearGradient3166-6" + gradientUnits="userSpaceOnUse" /><linearGradient + id="linearGradient3166"><stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /><stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /></linearGradient><linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + + + + + +</defs> + + + + +<g + transform="matrix(1.1181651,0,0,1.1181651,61.470731,-23.367585)" + id="g3348" + style="fill:none"><path + d="m -19.754174,46.744351 c 3.555069,0 8.83424,-1.56838 8.83424,-6.181226 0,-5.131219 -4.597011,-5.60538 -6.503378,-6.124857 -2.107038,-0.441556 -3.510542,-1.057744 -3.594847,-1.909356 -0.144269,-1.460061 0.687503,-2.028723 2.342736,-2.028723 0,0 3.937412,2.024856 7.282311,0.40895 0.942794,-0.454819 2.631273,-2.579702 2.631273,-4.04529 0,-1.466142 -5.450749,-3.160522 -7.104794,-3.160522 -1.655233,0 -3.062894,2.125988 -3.062894,2.125988 -3.309277,0 -6.619149,2.932283 -6.619149,5.864566 0,2.93173 3.166197,5.225166 6.950433,5.864565 1.759131,0.259187 3.230316,1.226851 2.896064,3.005231 -0.27132,1.444036 -1.778128,2.932283 -4.963917,2.932283 -2.524407,0 -7.896195,-0.121026 -8.75409,-2.254199 -0.551547,-1.373851 0.09974,-2.876467 0.927358,-2.876467 l -0.01603,-0.08842 c -0.843052,-0.08732 -3.293841,0.08842 -3.293841,3.020151 -5.94e-4,3.759026 5.428782,5.447327 12.048526,5.447327 z" + id="path2474" + style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path + d="m -11.393706,30.909692 c -1.557272,-0.158607 -3.924943,-1.105272 -4.43315,-2.775335" + id="path2476" + style="fill:none;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><circle + cx="35.805" + cy="10.96" + r="1.676" + transform="matrix(0.59369893,0,0,0.5526353,-36.672813,19.93767)" + id="circle2478" + style="fill:none;stroke-width:3.42034841;stroke-miterlimit:4;stroke-dasharray:none" /></g><g + transform="translate(-2.2743816,2.513511)" + id="g3036" + style="overflow:visible"><path + d="M 9.5689397,38.952218 9.3902171,32.897964 M 25.663656,50.969805 3.6345541,51.23649 3.5243801,39.2454 l 5.851406,-6.358972 21.2578909,0 -0.110174,12.124478 z M 3.6345541,39.378743 l 21.4782339,0.266685 0.33052,10.924347 m -0.306426,-11.052011 5.531132,-6.638311" + id="path3806" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" /><g + transform="matrix(0,-1,-1,0,47.3087,85.9835)" + id="g4770-9"><g + transform="translate(34.0803,-1006.42)" + id="g4772-6"><polyline + id="polyline4774-2" + points="51.562,15.306 41.17,16.188 42.053,5.794" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" + transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" /><path + d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067" + id="path4776-5" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></g></svg>
\ No newline at end of file diff --git a/icons/pippy-openon.svg b/icons/pippy-openon.svg new file mode 100644 index 0000000..a3bc335 --- /dev/null +++ b/icons/pippy-openon.svg @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.1" + width="55" + height="55" + viewBox="0 0 54.999998 55.000001" + id="Icon" + xml:space="preserve" + style="overflow:visible"><metadata + id="metadata26"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs24"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <linearGradient + id="linearGradient3166-6"><stop + id="stop3168-5" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /><stop + id="stop3170-6" + style="stop-color:#ff0000;stop-opacity:1" + offset="1" /></linearGradient><linearGradient + x1="0" + y1="22" + x2="74" + y2="22" + id="linearGradient3172-9" + xlink:href="#linearGradient3166-6" + gradientUnits="userSpaceOnUse" /><linearGradient + id="linearGradient3166"><stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /><stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /></linearGradient><linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + + + + + + + + + + + + + + + + + + + + + </defs> + + + + +<g + transform="matrix(1.1181651,0,0,1.1181651,61.470731,-23.367585)" + id="g3348" + style="fill:none;stroke:#00ff00;stroke-opacity:1"><path + d="m -19.754174,46.744351 c 3.555069,0 8.83424,-1.56838 8.83424,-6.181226 0,-5.131219 -4.597011,-5.60538 -6.503378,-6.124857 -2.107038,-0.441556 -3.510542,-1.057744 -3.594847,-1.909356 -0.144269,-1.460061 0.687503,-2.028723 2.342736,-2.028723 0,0 3.937412,2.024856 7.282311,0.40895 0.942794,-0.454819 2.631273,-2.579702 2.631273,-4.04529 0,-1.466142 -5.450749,-3.160522 -7.104794,-3.160522 -1.655233,0 -3.062894,2.125988 -3.062894,2.125988 -3.309277,0 -6.619149,2.932283 -6.619149,5.864566 0,2.93173 3.166197,5.225166 6.950433,5.864565 1.759131,0.259187 3.230316,1.226851 2.896064,3.005231 -0.27132,1.444036 -1.778128,2.932283 -4.963917,2.932283 -2.524407,0 -7.896195,-0.121026 -8.75409,-2.254199 -0.551547,-1.373851 0.09974,-2.876467 0.927358,-2.876467 l -0.01603,-0.08842 c -0.843052,-0.08732 -3.293841,0.08842 -3.293841,3.020151 -5.94e-4,3.759026 5.428782,5.447327 12.048526,5.447327 z" + id="path2474" + style="fill:none;stroke:#00ff00;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><path + d="m -11.393706,30.909692 c -1.557272,-0.158607 -3.924943,-1.105272 -4.43315,-2.775335" + id="path2476" + style="fill:none;stroke:#00ff00;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><circle + cx="35.805" + cy="10.96" + r="1.676" + transform="matrix(0.59369893,0,0,0.5526353,-36.672813,19.93767)" + id="circle2478" + style="fill:none;stroke:#00ff00;stroke-width:3.42034841;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g><g + transform="translate(-2.2743816,2.513511)" + id="g3036"><path + d="M 9.5689397,38.952218 9.3902171,32.897964 M 25.663656,50.969805 3.6345541,51.23649 3.5243801,39.2454 l 5.851406,-6.358972 21.2578909,0 -0.110174,12.124478 z M 3.6345541,39.378743 l 21.4782339,0.266685 0.33052,10.924347 m -0.306426,-11.052011 5.531132,-6.638311" + id="path3806" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" /><g + transform="matrix(0,-1,-1,0,47.3087,85.9835)" + id="g4770"><g + transform="translate(34.0803,-1006.42)" + id="g4772"><polyline + id="polyline4774" + points="51.562,15.306 41.17,16.188 42.053,5.794" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" + transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" /><path + d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067" + id="path4776" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></g></svg>
\ No newline at end of file diff --git a/icons/resize+.svg b/icons/resize+.svg new file mode 100644 index 0000000..0fae3c3 --- /dev/null +++ b/icons/resize+.svg @@ -0,0 +1,41 @@ +<?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.1" + width="55" + height="54.695999" + viewBox="0 0 55 54.696" + id="svg2" + xml:space="preserve"><defs + id="defs21"> + + + + + </defs><g + transform="translate(-0.4354,0)" + id="g7"> + <g + id="g9"> + <path + d="m 25.263,12.435 h 24.656 v 3.562 H 39.575 V 41.59 H 35.606 V 15.996 H 25.263 v -3.561 z" + id="path11" + style="fill:#ffffff" /> + </g> + </g><g + transform="translate(-8.4356,0)" + id="g13"> + <g + id="g15"> + <path + d="m 13.953,24.435 h 16.656 v 3.562 H 24.265 V 41.59 H 20.296 V 27.997 h -6.344 v -3.562 z" + id="path17" + style="fill:#ffffff" /> + </g> + </g><path + d="m 25.5774,23.677763 6,-6.000001 -4,0" + id="path3618" + style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></svg>
\ No newline at end of file diff --git a/icons/resize-.svg b/icons/resize-.svg new file mode 100644 index 0000000..e3b719e --- /dev/null +++ b/icons/resize-.svg @@ -0,0 +1,43 @@ +<?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.1" + width="55" + height="54.695999" + viewBox="0 0 55 54.696" + id="svg2" + xml:space="preserve"><defs + id="defs21"> + + + + + </defs><g + transform="translate(3.5644,0)" + id="g2821"><g + transform="matrix(-1,0,0,1,51.871,0)" + id="g7"> + <g + id="g9"> + <path + d="m 25.263,12.435 h 24.656 v 3.562 H 39.575 V 41.59 H 35.606 V 15.996 H 25.263 v -3.561 z" + id="path11" + style="fill:#ffffff" /> + </g> + </g><g + transform="matrix(-1,0,0,1,59.8712,0)" + id="g13"> + <g + id="g15"> + <path + d="m 13.953,24.435 h 16.656 v 3.562 H 24.265 V 41.59 H 20.296 V 27.997 h -6.344 v -3.562 z" + id="path17" + style="fill:#ffffff" /> + </g> + </g><path + d="m 19.8582,17.677762 6,6.000001 -4,0" + id="path3618" + style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></svg>
\ No newline at end of file diff --git a/icons/run-fastoff.svg b/icons/run-fastoff.svg new file mode 100644 index 0000000..5abee4e --- /dev/null +++ b/icons/run-fastoff.svg @@ -0,0 +1,36 @@ +<?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="45" + height="45" + id="svg2"> + <defs + id="defs5" /> +` <g + transform="translate(6.0193572e-8,-1.9999998)" + id="g3287"> + <path + d="m 37.158177,18.217157 c 0,7.129359 -4.73972,12.908847 -10.586461,12.908847 -5.846741,0 -10.586461,-5.779488 -10.586461,-12.908847 0,-7.129359 4.73972,-12.908847 10.586461,-12.908847 5.846741,0 10.586461,5.779488 10.586461,12.908847 l 0,0 z" + transform="matrix(0.9002849,0,0,0.6378505,-7.1526774,12.961276)" + id="path3173" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="m 37.158177,18.217157 c 0,7.129359 -4.73972,12.908847 -10.586461,12.908847 -5.846741,0 -10.586461,-5.779488 -10.586461,-12.908847 0,-7.129359 4.73972,-12.908847 10.586461,-12.908847 5.846741,0 10.586461,5.779488 10.586461,12.908847 l 0,0 z" + transform="matrix(0.34904,-0.8298699,0.4328947,0.1820738,8.5363479,48.352162)" + id="path3177" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="m 37.158177,18.217157 c 0,7.129359 -4.73972,12.908847 -10.586461,12.908847 -5.846741,0 -10.586461,-5.779488 -10.586461,-12.908847 0,-7.129359 4.73972,-12.908847 10.586461,-12.908847 5.846741,0 10.586461,5.779488 10.586461,12.908847 l 0,0 z" + transform="matrix(0.5612942,0.3544048,-0.1085241,0.1718767,9.8942224,-2.0522731)" + id="path3179" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="m 9.2958401,27.300367 c 0,0 0.6438297,-3.994201 1.6400319,-5.238518 0.833257,-1.040794 2.516695,-1.85759 3.762426,-2.031262 0.9968,-0.138967 2.383402,0.2462 3.280063,0.74836 1.042545,0.583861 2.271254,1.791474 2.894173,2.88653 0.98159,1.725581 1.256974,4.552031 1.736504,6.52142 0.380364,1.562127 0.284039,3.94213 1.157669,5.238518 0.721744,1.071004 2.287173,2.00041 3.473008,2.245082 1.78687,0.368683 4.166897,-1.188245 5.981292,-1.069088 0.84132,0.05525 2.27015,0.05272 2.701229,0.85527 0.272959,0.50817 -0.01689,1.497122 -0.38589,1.924349 -1.388344,1.60742 -4.484134,1.551863 -6.463654,1.924357 -1.54502,0.290727 -3.77056,1.115533 -5.209513,0.427635 -2.191386,-1.047611 -3.11186,-5.248556 -5.016567,-6.842148 C 18.494794,34.59652 17.932313,34.319138 17.495998,34.249421 16.284393,34.055824 14.659189,34.94909 13.444155,34.783964 12.553171,34.662876 11.3895,34.166119 10.646456,33.607971 9.4764934,32.729136 8.0161145,31.200596 7.4628632,29.759263 6.9180297,28.339853 7.0795774,26.166629 7.1734442,24.627654 c 0.04976,-0.815832 0.186147,-1.923803 0.4823635,-2.672713 0.4740893,-1.198617 1.3821263,-2.725983 2.3153404,-3.527981 1.3038139,-1.120492 3.4728879,-2.04627 5.1130389,-2.245079 1.631802,-0.197799 3.828032,0.447353 5.402457,0.962176 1.516337,0.49583 3.246091,2.236482 4.823622,2.351988 0.932208,0.06826 2.407938,-0.152939 2.990646,-0.962177 0.30741,-0.426916 0.343158,-1.344606 0.09647,-1.817445 -0.550654,-1.055475 -2.224944,-1.472146 -3.280064,-1.817445 -1.00539,-0.329024 -2.45155,-0.166363 -3.473007,-0.427634 -0.838456,-0.214462 -1.933408,-0.638591 -2.701229,-1.069086 -1.24629,-0.698755 -2.959159,-1.702648 -3.858898,-2.886529 -0.817776,-1.0760346 -2.317397,-3.0254485 -1.736505,-4.2763406 0.06753,-0.1454133 0.336585,-0.081478 0.482363,-0.1069088 0.748264,-0.1305312 2.147702,0.4174844 2.508284,-0.3207253 0.338874,-0.6937639 -1.483172,-1.7166452 -1.061197,-2.351988 0.851763,-1.2824449 3.329342,0.4862662 4.72715,0.8552682 1.121926,0.2961731 2.62592,0.7305046 3.665953,1.2829032 1.693816,0.8996449 3.826771,2.4399257 5.209512,3.8487057 1.197868,1.2204256 1.98772,3.7643616 3.376536,4.7039756 0.62978,0.426082 1.725087,0.235405 2.411811,0.534543 0.411153,0.179097 0.884057,0.587915 1.254142,0.855267 0.854101,0.61701 2.099953,1.314356 2.797701,2.13817 0.577461,0.681796 0,0.106909 1.447086,2.672714 1.447087,2.565804 1.501279,0.32572 1.832977,2.245079 0,0 -0.32328,1.512069 -0.675307,2.031262 -0.41031,0.605152 -1.195498,1.224871 -1.832977,1.496719 -0.271455,0.11576 -0.68249,0.18483 -0.964724,0.106908 -0.405023,-0.111822 -0.753667,-0.738998 -1.157669,-0.855267 -0.70255,-0.202189 -1.686925,0.255337 -2.411811,0.213817 -0.793655,-0.04546 -1.927833,-0.07316 -2.604757,-0.534543 -0.650834,-0.443601 -1.191753,-1.493431 -1.543559,-2.245079 -0.26551,-0.567275 -0.0089,-2.128616 -0.578834,-2.031262 -0.0286,0.0049 0,0.106909 0,0.106909 m 2.604756,4.383249 c 0,0 -0.67407,3.00661 -0.964725,4.294669 -0.259371,1.14942 -0.38119,2.775651 -0.868252,3.830379 -0.654999,1.418394 -3.087119,4.062526 -3.087119,4.062526 m -0.578834,-7.37669 c 0,0 -0.762223,2.02329 -1.254142,2.779621 -0.526506,0.80951 -1.777805,1.430082 -2.122394,2.351988 -0.01108,0.02963 0,0.106908 0,0.106908 m -3.858898,1.710538 c 0,0 -2.498343,0.09087 -3.56948,0.106905 -0.694537,0.01041 -1.848045,-0.569505 -2.31534,0 -0.410734,0.500573 -0.129138,1.670316 0.192948,2.245079 0.377101,0.672936 1.341866,1.159966 2.025922,1.389809 0.803679,0.270031 1.960108,0.174507 2.797698,0.106913 0.968172,-0.07813 3.18359,-0.641452 3.18359,-0.641452 M 7.3663896,23.237843 c 0,0 -2.1337626,-2.804738 -3.2800638,-2.458896 -0.6495254,0.195963 -0.8281117,1.514613 -0.9647234,2.245079 -0.1645596,0.879906 -0.1889559,2.152344 0.096474,2.993439 0.3548095,1.045538 1.2844064,2.265735 2.1223913,2.88653 0.5024007,0.372186 1.3315344,0.544203 1.9294505,0.641451 0.028634,0.0047 0.096471,0 0.096471,0 M 29.651526,14.04371 c 0,0 -3.058348,-4.1388306 -4.72715,-5.4523336 C 23.678488,7.6107444 21.770009,6.6768097 20.293698,6.2393884 19.086245,5.8816272 16.145385,5.8117543 16.145385,5.8117543 M 35.343402,20.030587 c 0.276872,0.284129 1.079502,0.263788 1.254141,-0.106908 0.264175,-0.56075 -0.52371,-1.415829 -0.964724,-1.817446 -0.473808,-0.431478 -1.46214,-1.188454 -1.929449,-0.748359 -0.380706,0.358535 -0.198367,1.697687 0.289416,1.817445 0.344916,0.08468 0.327116,-1.002886 0.675308,-1.069086 0.245381,-0.04665 0.561385,0.289224 0.675308,0.534543 0.172161,0.370733 -0.276058,1.106519 0,1.389811 z m -0.09647,-0.106908 c 0,0 0,0 0,0 z" + id="path2384" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> +</svg> diff --git a/icons/run-faston.svg b/icons/run-faston.svg new file mode 100644 index 0000000..33e8bbd --- /dev/null +++ b/icons/run-faston.svg @@ -0,0 +1,40 @@ +<?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="45" + height="45" + id="svg2"> + <defs + id="defs5" /> + <path + d="M 27.849263,20.597427 C 27.851349,29.203268 22.048546,36.18101 14.889706,36.18101 C 7.7308648,36.18101 1.9280624,29.203268 1.9301481,20.597427 C 1.9280624,11.991586 7.7308648,5.0138442 14.889706,5.0138442 C 22.048546,5.0138442 27.851349,11.991586 27.849263,20.597427 L 27.849263,20.597427 z" + transform="matrix(1.6011349,0,0,1.3319174,-1.3404274,-4.9340719)" + id="path2401" + style="opacity:1;fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:2.39670968;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <g + transform="translate(6.0193572e-8,-1.9999998)" + id="g3287"> + <path + d="M 37.158177,18.217157 C 37.158177,25.346516 32.418457,31.126004 26.571716,31.126004 C 20.724975,31.126004 15.985255,25.346516 15.985255,18.217157 C 15.985255,11.087798 20.724975,5.30831 26.571716,5.30831 C 32.418457,5.30831 37.158177,11.087798 37.158177,18.217157 L 37.158177,18.217157 z" + transform="matrix(0.9002849,0,0,0.6378505,-7.1526774,12.961276)" + id="path3173" + style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3.5;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 37.158177,18.217157 C 37.158177,25.346516 32.418457,31.126004 26.571716,31.126004 C 20.724975,31.126004 15.985255,25.346516 15.985255,18.217157 C 15.985255,11.087798 20.724975,5.30831 26.571716,5.30831 C 32.418457,5.30831 37.158177,11.087798 37.158177,18.217157 L 37.158177,18.217157 z" + transform="matrix(0.34904,-0.8298699,0.4328947,0.1820738,8.5363479,48.352162)" + id="path3177" + style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3.5;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 37.158177,18.217157 C 37.158177,25.346516 32.418457,31.126004 26.571716,31.126004 C 20.724975,31.126004 15.985255,25.346516 15.985255,18.217157 C 15.985255,11.087798 20.724975,5.30831 26.571716,5.30831 C 32.418457,5.30831 37.158177,11.087798 37.158177,18.217157 L 37.158177,18.217157 z" + transform="matrix(0.5612942,0.3544048,-0.1085241,0.1718767,9.8942224,-2.0522731)" + id="path3179" + style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:3.5;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 9.2958401,27.300367 C 9.2958401,27.300367 9.9396698,23.306166 10.935872,22.061849 C 11.769129,21.021055 13.452567,20.204259 14.698298,20.030587 C 15.695098,19.89162 17.0817,20.276787 17.978361,20.778947 C 19.020906,21.362808 20.249615,22.570421 20.872534,23.665477 C 21.854124,25.391058 22.129508,28.217508 22.609038,30.186897 C 22.989402,31.749024 22.893077,34.129027 23.766707,35.425415 C 24.488451,36.496419 26.05388,37.425825 27.239715,37.670497 C 29.026585,38.03918 31.406612,36.482252 33.221007,36.601409 C 34.062327,36.656661 35.491157,36.654128 35.922236,37.456679 C 36.195195,37.964849 35.905348,38.953801 35.536346,39.381028 C 34.148002,40.988448 31.052212,40.932891 29.072692,41.305385 C 27.527672,41.596112 25.302132,42.420918 23.863179,41.73302 C 21.671793,40.685409 20.751319,36.484464 18.846612,34.890872 C 18.494794,34.59652 17.932313,34.319138 17.495998,34.249421 C 16.284393,34.055824 14.659189,34.94909 13.444155,34.783964 C 12.553171,34.662876 11.3895,34.166119 10.646456,33.607971 C 9.4764934,32.729136 8.0161145,31.200596 7.4628632,29.759263 C 6.9180297,28.339853 7.0795774,26.166629 7.1734442,24.627654 C 7.2232038,23.811822 7.3595912,22.703851 7.6558077,21.954941 C 8.129897,20.756324 9.037934,19.228958 9.9711481,18.42696 C 11.274962,17.306468 13.444036,16.38069 15.084187,16.181881 C 16.715989,15.984082 18.912219,16.629234 20.486644,17.144057 C 22.002981,17.639887 23.732735,19.380539 25.310266,19.496045 C 26.242474,19.564301 27.718204,19.343106 28.300912,18.533868 C 28.608322,18.106952 28.64407,17.189262 28.397385,16.716423 C 27.846731,15.660948 26.172441,15.244277 25.117321,14.898978 C 24.111931,14.569954 22.665771,14.732615 21.644314,14.471344 C 20.805858,14.256882 19.710906,13.832753 18.943085,13.402258 C 17.696795,12.703503 15.983926,11.69961 15.084187,10.515729 C 14.266411,9.4396944 12.76679,7.4902805 13.347682,6.2393884 C 13.41521,6.0939751 13.684267,6.1579103 13.830045,6.1324796 C 14.578309,6.0019484 15.977747,6.549964 16.338329,5.8117543 C 16.677203,5.1179904 14.855157,4.0951091 15.277132,3.4597663 C 16.128895,2.1773214 18.606474,3.9460325 20.004282,4.3150345 C 21.126208,4.6112076 22.630202,5.0455391 23.670235,5.5979377 C 25.364051,6.4975826 27.497006,8.0378634 28.879747,9.4466434 C 30.077615,10.667069 30.867467,13.211005 32.256283,14.150619 C 32.886063,14.576701 33.98137,14.386024 34.668094,14.685162 C 35.079247,14.864259 35.552151,15.273077 35.922236,15.540429 C 36.776337,16.157439 38.022189,16.854785 38.719937,17.678599 C 39.297398,18.360395 38.719937,17.785508 40.167023,20.351313 C 41.61411,22.917117 41.668302,20.677033 42,22.596392 C 42,22.596392 41.67672,24.108461 41.324693,24.627654 C 40.914383,25.232806 40.129195,25.852525 39.491716,26.124373 C 39.220261,26.240133 38.809226,26.309203 38.526992,26.231281 C 38.121969,26.119459 37.773325,25.492283 37.369323,25.376014 C 36.666773,25.173825 35.682398,25.631351 34.957512,25.589831 C 34.163857,25.544373 33.029679,25.516672 32.352755,25.055288 C 31.701921,24.611687 31.161002,23.561857 30.809196,22.810209 C 30.543686,22.242934 30.800291,20.681593 30.230362,20.778947 C 30.201757,20.783833 30.230362,20.885856 30.230362,20.885856 M 32.835118,25.269105 C 32.835118,25.269105 32.161048,28.275715 31.870393,29.563774 C 31.611022,30.713194 31.489203,32.339425 31.002141,33.394153 C 30.347142,34.812547 27.915022,37.456679 27.915022,37.456679 M 27.336188,30.079989 C 27.336188,30.079989 26.573965,32.103279 26.082046,32.85961 C 25.55554,33.66912 24.304241,34.289692 23.959652,35.211598 C 23.948576,35.241229 23.959652,35.318506 23.959652,35.318506 M 20.100754,37.029044 C 20.100754,37.029044 17.602411,37.119914 16.531274,37.135949 C 15.836737,37.146354 14.683229,36.566444 14.215934,37.135949 C 13.8052,37.636522 14.086796,38.806265 14.408882,39.381028 C 14.785983,40.053964 15.750748,40.540994 16.434804,40.770837 C 17.238483,41.040868 18.394912,40.945344 19.232502,40.87775 C 20.200674,40.799617 22.416092,40.236298 22.416092,40.236298 M 7.3663896,23.237843 C 7.3663896,23.237843 5.232627,20.433105 4.0863258,20.778947 C 3.4368004,20.97491 3.2582141,22.29356 3.1216024,23.024026 C 2.9570428,23.903932 2.9326465,25.17637 3.2180769,26.017465 C 3.5728864,27.063003 4.5024833,28.2832 5.3404682,28.903995 C 5.8428689,29.276181 6.6720026,29.448198 7.2699187,29.545446 C 7.2985527,29.550103 7.3663896,29.545446 7.3663896,29.545446 M 29.651526,14.04371 C 29.651526,14.04371 26.593178,9.9048794 24.924376,8.5913764 C 23.678488,7.6107444 21.770009,6.6768097 20.293698,6.2393884 C 19.086245,5.8816272 16.145385,5.8117543 16.145385,5.8117543 M 35.343402,20.030587 C 35.620274,20.314716 36.422904,20.294375 36.597543,19.923679 C 36.861718,19.362929 36.073833,18.50785 35.632819,18.106233 C 35.159011,17.674755 34.170679,16.917779 33.70337,17.357874 C 33.322664,17.716409 33.505003,19.055561 33.992786,19.175319 C 34.337702,19.260001 34.319902,18.172433 34.668094,18.106233 C 34.913475,18.059581 35.229479,18.395457 35.343402,18.640776 C 35.515563,19.011509 35.067344,19.747295 35.343402,20.030587 z M 35.246929,19.923679 C 35.246929,19.923679 35.246929,19.923679 35.246929,19.923679 z" + id="path2384" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> +</svg> diff --git a/icons/run-slowoff.svg b/icons/run-slowoff.svg new file mode 100644 index 0000000..4402892 --- /dev/null +++ b/icons/run-slowoff.svg @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="45" + height="45" + id="svg2"> + <metadata + id="metadata8"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs6" /> + <path + d="" + id="path2385" + style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:1.22727275;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + transform="translate(0.11089571,-0.94841151)" + id="g3077"> + <g + transform="matrix(1.2218314,-0.18194175,0.15605166,1.5079605,-13.378376,-6.429867)" + id="g3947-5"> + <path + d="m 30.250756,30.836427 c 1.11555,0.348252 2.692035,-1.295228 2.692035,-1.295228 0,0 2.293876,-7.854931 3.487289,-9.113037 0.31287,-0.329828 0.755177,-0.501178 1.181359,-0.58803 1.01523,-0.206889 2.083898,0.322127 3.11125,0.193235 0.80574,-0.101093 1.661718,-0.246659 2.327669,-0.749722 0.438663,-0.331367 0.933055,-0.803906 0.976338,-1.401899 0.124424,-1.719054 -1.05927,-3.420325 -2.178863,-4.644042 -1.215594,-1.328645 -2.936447,-1.97793 -4.551658,-2.518425 -1.300507,-0.104493 -2.372926,0.194116 -2.868561,0.847395 -0.59567,0.767816 -1.129763,1.661019 -1.074287,2.552259 0.07463,1.198927 -0.664185,3.248385 -0.664185,3.248385 l -2.780379,6.877993 c 0,0 -0.145087,0.723462 -0.668916,1.136807 -1.096253,0.865034 -0.619332,3.445317 -0.619332,3.445317 0,0 0.514691,1.660737 1.630241,2.008992 z" + id="path3866-7" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 37.838255,17.606462 c 0,0 0.830992,0.285742 1.214045,0.144799 0.309562,-0.113904 0.679069,-0.727877 0.679069,-0.727877" + id="path3868-2" + style="fill:none;stroke:#000000;stroke-width:0.9375;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 39.151424,17.94393 0.713166,1.096988 1.013167,0.746988" + id="path3870-2" + style="fill:none;stroke:#000000;stroke-width:0.9375;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 42.62442,17.298048 a 0.04697844,0.16854352 9.385532 0 0 0.03495,0.227255 0.04697844,0.16854352 9.385532 1 0 -0.03495,-0.227255 z" + id="path3892-8" + style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.63433635;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 35.475,18.575 c 0,0 0.71966,0.565523 1.15,0.725 0.894503,0.396029 0.867077,0.407999 1.75,0.475" + id="path3905-2" + style="fill:none;stroke:#000000;stroke-width:1.25;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 38.35,13.8 c 0,0 -0.45201,-0.593612 -0.15,-0.85 0.375408,-0.318698 0.763331,0.09062 1.1,0.45 0.230721,0.246285 0.559852,0.685707 0.35,0.95 -0.167112,0.210465 -0.5,0.1 -0.5,0.1" + id="path3907-5" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" /> + </g> + <g + transform="matrix(1.0277554,0,0,1,-0.03770427,0)" + id="g4087"> + <path + d="M 3.233403,33.550298 C 5.096176,29.257229 5.051022,24.714332 6.458889,21.039 c 1.407868,-3.675332 5.077225,-6.720428 10.159991,-6.730298 5.082766,-0.0099 8.441665,3.273969 10.488217,6.730173 2.046552,3.456203 2.66156,11.657273 3.461887,11.905179 2.206168,0.435816 2.113926,2.297599 0.605863,3.135182 -7.133959,0.45665 -4.920065,0.02737 -10.314422,0.475485 l -9.324283,-0.04075 C 5.6539971,36.08591 8.7574769,36.860266 2.459469,36.041947 1.811911,35.45684 1.274155,35.258079 1.35845,34.327323 c 0.126607,-1.39795 0.895175,-1.113719 2.265315,-2.10834" + id="path3856-8" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.25;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 30.55,34 C 30.1,31.9 30.1,31.9 30.1,31.9" + id="path4009" + style="fill:none;stroke:#000000;stroke-width:1.25;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <path + d="m 6.6596827,35.622429 c -0.471371,1.233059 0.02336,2.603048 6.31e-4,3.904339 -0.02031,1.162467 -0.890882,2.559307 -0.122396,3.486139 0.82847,0.999176 2.628998,0.796844 3.9963373,0.902395 1.213468,0.09368 2.712886,0.471707 3.643453,-0.245805 0.564612,-0.435344 0.793241,-1.334241 0.531969,-1.965542 -0.235451,-0.568908 -1.278555,-0.529254 -1.642328,-1.038668 -0.611228,-0.855945 -0.159994,-2.0855 -0.636318,-3.010187 -0.558181,-1.083595 -1.439242,-2.069797 -2.5000913,-2.773487 -0.582305,-0.38626 -1.314901,-0.892712 -2.009537,-0.720895 -0.655669,0.162182 -1.039812,0.881221 -1.26172,1.461711 z" + id="path3876-8" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.35621119;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 21.91196,35.199701 c -0.471371,1.295915 0.02336,2.735739 6.31e-4,4.103363 -0.02031,1.221722 -0.890882,2.689766 -0.122396,3.663844 0.82847,1.050109 2.628998,0.837463 3.996337,0.948394 1.213468,0.09845 2.712886,0.495753 3.643453,-0.258336 0.564612,-0.457536 0.793241,-1.402253 0.531969,-2.065733 -0.235451,-0.59791 -1.278555,-0.556234 -1.642328,-1.091616 -0.611228,-0.899574 -0.159994,-2.191807 -0.636318,-3.163629 -0.558181,-1.13883 -1.439242,-2.175305 -2.500091,-2.914865 -0.582305,-0.405949 -1.314901,-0.938217 -2.009537,-0.757642 -0.655669,0.170448 -1.039812,0.926141 -1.26172,1.53622 z" + id="path3876-8-1" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.39034784;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + id="g3019"> + <path + d="m 11.777666,17.658989 c 0,0 3.082843,-1.459186 4.783966,-1.539572 1.878187,-0.08875 5.311177,1.24513 5.311177,1.24513 l -2.902353,1.472208 -4.626941,0.12619 z" + id="path3005" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 10.238095,19.150806 2.75102,1.295574 -0.515985,4.436234 -4.4335433,-0.737528 c 0,0 0.4347249,-3.264183 2.1985083,-4.99428 z" + id="path3007" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 14.764146,20.788421 -0.294442,4.273672 5.342013,-0.04206 -0.6534,-4.399862 z" + id="path3009" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 20.784704,20.294891 2.529477,-1.536726 c 0,0 1.090846,1.107713 1.672719,1.843818 0.581873,0.736104 1.162427,2.281211 1.162427,2.281211 l -4.276518,1.800331 z" + id="path3011" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 7.6189557,25.965027 -1.5730973,6.146591 5.8608426,0.218854 0.628101,-5.585855 z" + id="path3013" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="M 14.466859,27.013759 14.029465,32.21551 21.289462,32.15099 20.08655,26.84835 z" + id="path3015" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 22.049443,26.823052 1.578789,5.089634 5.128852,-0.04791 -1.730123,-7.142032 z" + id="path3017" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> + </g> +</svg> diff --git a/icons/run-slowon.svg b/icons/run-slowon.svg new file mode 100644 index 0000000..000f7d0 --- /dev/null +++ b/icons/run-slowon.svg @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="45" + height="45" + id="svg2"> + <metadata + id="metadata8"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs6" /> + <path + d="m -22.616925,21.840856 c 0,4.547465 -4.267099,8.233914 -9.530831,8.233914 -5.263733,0 -9.530831,-3.686449 -9.530831,-8.233914 0,-4.547466 4.267098,-8.233915 9.530831,-8.233915 5.263732,0 9.530831,3.686449 9.530831,8.233915 l 0,0 z" + id="path3173" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="m -19.525045,18.092333 c 3.086262,1.29807 3.933819,6.283714 1.893073,11.135749 -2.040747,4.852034 -6.197008,7.733092 -9.28327,6.435022 -3.086262,-1.298069 -3.933819,-6.283714 -1.893073,-11.135748 2.040746,-4.852034 6.197008,-7.733092 9.28327,-6.435023 l 0,0 z" + id="path3177" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="m -20.143303,11.507625 c -0.773708,1.225371 -4.061299,0.538951 -7.34304,-1.533163 -3.281742,-2.072113 -5.314906,-4.745251 -4.541199,-5.970622 0.773708,-1.225371 4.061299,-0.538951 7.343041,1.533162 3.281741,2.072113 5.314905,4.745252 4.541198,5.970623 l 0,0 z" + id="path3179" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="M 42.75,22.5 C 42.75,33.683767 33.683766,42.75 22.5,42.75 11.316234,42.75 2.2500001,33.683767 2.2500001,22.5 2.2500001,11.316234 11.316234,2.2499999 22.5,2.2499999 c 11.183766,0 20.25,9.0662341 20.25,20.2500001 l 0,0 z" + id="path2387" + style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:3.50000024;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none" /> + <path + d="" + id="path2385" + style="fill:#00d000;fill-opacity:1;stroke:#00d000;stroke-width:1.22727275;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + transform="translate(0.11089571,-0.94841151)" + id="g3077"> + <g + transform="matrix(1.2218314,-0.18194175,0.15605166,1.5079605,-13.378376,-6.429867)" + id="g3947-5"> + <path + d="m 30.250756,30.836427 c 1.11555,0.348252 2.692035,-1.295228 2.692035,-1.295228 0,0 2.293876,-7.854931 3.487289,-9.113037 0.31287,-0.329828 0.755177,-0.501178 1.181359,-0.58803 1.01523,-0.206889 2.083898,0.322127 3.11125,0.193235 0.80574,-0.101093 1.661718,-0.246659 2.327669,-0.749722 0.438663,-0.331367 0.933055,-0.803906 0.976338,-1.401899 0.124424,-1.719054 -1.05927,-3.420325 -2.178863,-4.644042 -1.215594,-1.328645 -2.936447,-1.97793 -4.551658,-2.518425 -1.300507,-0.104493 -2.372926,0.194116 -2.868561,0.847395 -0.59567,0.767816 -1.129763,1.661019 -1.074287,2.552259 0.07463,1.198927 -0.664185,3.248385 -0.664185,3.248385 l -2.780379,6.877993 c 0,0 -0.145087,0.723462 -0.668916,1.136807 -1.096253,0.865034 -0.619332,3.445317 -0.619332,3.445317 0,0 0.514691,1.660737 1.630241,2.008992 z" + id="path3866-7" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.25;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 37.838255,17.606462 c 0,0 0.830992,0.285742 1.214045,0.144799 0.309562,-0.113904 0.679069,-0.727877 0.679069,-0.727877" + id="path3868-2" + style="fill:none;stroke:#000000;stroke-width:0.9375;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 39.151424,17.94393 0.713166,1.096988 1.013167,0.746988" + id="path3870-2" + style="fill:none;stroke:#000000;stroke-width:0.9375;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 42.62442,17.298048 a 0.04697844,0.16854352 9.385532 0 0 0.03495,0.227255 0.04697844,0.16854352 9.385532 1 0 -0.03495,-0.227255 z" + id="path3892-8" + style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:0.63433635;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 35.475,18.575 c 0,0 0.71966,0.565523 1.15,0.725 0.894503,0.396029 0.867077,0.407999 1.75,0.475" + id="path3905-2" + style="fill:none;stroke:#000000;stroke-width:1.25;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 38.35,13.8 c 0,0 -0.45201,-0.593612 -0.15,-0.85 0.375408,-0.318698 0.763331,0.09062 1.1,0.45 0.230721,0.246285 0.559852,0.685707 0.35,0.95 -0.167112,0.210465 -0.5,0.1 -0.5,0.1" + id="path3907-5" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" /> + </g> + <g + transform="matrix(1.0277554,0,0,1,-0.03770427,0)" + id="g4087"> + <path + d="M 3.233403,33.550298 C 5.096176,29.257229 5.051022,24.714332 6.458889,21.039 c 1.407868,-3.675332 5.077225,-6.720428 10.159991,-6.730298 5.082766,-0.0099 8.441665,3.273969 10.488217,6.730173 2.046552,3.456203 2.66156,11.657273 3.461887,11.905179 2.206168,0.435816 2.113926,2.297599 0.605863,3.135182 -7.133959,0.45665 -4.920065,0.02737 -10.314422,0.475485 l -9.324283,-0.04075 C 5.6539971,36.08591 8.7574769,36.860266 2.459469,36.041947 1.811911,35.45684 1.274155,35.258079 1.35845,34.327323 c 0.126607,-1.39795 0.895175,-1.113719 2.265315,-2.10834" + id="path3856-8" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.25;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 30.55,34 C 30.1,31.9 30.1,31.9 30.1,31.9" + id="path4009" + style="fill:none;stroke:#000000;stroke-width:1.25;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <path + d="m 6.6596827,35.622429 c -0.471371,1.233059 0.02336,2.603048 6.31e-4,3.904339 -0.02031,1.162467 -0.890882,2.559307 -0.122396,3.486139 0.82847,0.999176 2.628998,0.796844 3.9963373,0.902395 1.213468,0.09368 2.712886,0.471707 3.643453,-0.245805 0.564612,-0.435344 0.793241,-1.334241 0.531969,-1.965542 -0.235451,-0.568908 -1.278555,-0.529254 -1.642328,-1.038668 -0.611228,-0.855945 -0.159994,-2.0855 -0.636318,-3.010187 -0.558181,-1.083595 -1.439242,-2.069797 -2.5000913,-2.773487 -0.582305,-0.38626 -1.314901,-0.892712 -2.009537,-0.720895 -0.655669,0.162182 -1.039812,0.881221 -1.26172,1.461711 z" + id="path3876-8" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.35621119;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 21.91196,35.199701 c -0.471371,1.295915 0.02336,2.735739 6.31e-4,4.103363 -0.02031,1.221722 -0.890882,2.689766 -0.122396,3.663844 0.82847,1.050109 2.628998,0.837463 3.996337,0.948394 1.213468,0.09845 2.712886,0.495753 3.643453,-0.258336 0.564612,-0.457536 0.793241,-1.402253 0.531969,-2.065733 -0.235451,-0.59791 -1.278555,-0.556234 -1.642328,-1.091616 -0.611228,-0.899574 -0.159994,-2.191807 -0.636318,-3.163629 -0.558181,-1.13883 -1.439242,-2.175305 -2.500091,-2.914865 -0.582305,-0.405949 -1.314901,-0.938217 -2.009537,-0.757642 -0.655669,0.170448 -1.039812,0.926141 -1.26172,1.53622 z" + id="path3876-8-1" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.39034784;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + id="g3019"> + <path + d="m 11.777666,17.658989 c 0,0 3.082843,-1.459186 4.783966,-1.539572 1.878187,-0.08875 5.311177,1.24513 5.311177,1.24513 l -2.902353,1.472208 -4.626941,0.12619 z" + id="path3005" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 10.238095,19.150806 2.75102,1.295574 -0.515985,4.436234 -4.4335433,-0.737528 c 0,0 0.4347249,-3.264183 2.1985083,-4.99428 z" + id="path3007" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 14.764146,20.788421 -0.294442,4.273672 5.342013,-0.04206 -0.6534,-4.399862 z" + id="path3009" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 20.784704,20.294891 2.529477,-1.536726 c 0,0 1.090846,1.107713 1.672719,1.843818 0.581873,0.736104 1.162427,2.281211 1.162427,2.281211 l -4.276518,1.800331 z" + id="path3011" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 7.6189557,25.965027 -1.5730973,6.146591 5.8608426,0.218854 0.628101,-5.585855 z" + id="path3013" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="M 14.466859,27.013759 14.029465,32.21551 21.289462,32.15099 20.08655,26.84835 z" + id="path3015" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="m 22.049443,26.823052 1.578789,5.089634 5.128852,-0.04791 -1.730123,-7.142032 z" + id="path3017" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + </g> + </g> +</svg> diff --git a/icons/stopitoff.svg b/icons/stopitoff.svg new file mode 100644 index 0000000..de041ea --- /dev/null +++ b/icons/stopitoff.svg @@ -0,0 +1,22 @@ +<?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="44" + height="44" + id="svg2"> + <defs + id="defs5" /> + <path + d="M 26.896078,11.635294 L 15.157342,23.955503 -1.8549019,24.366666 -14.175111,12.62793 -14.586274,-4.3843137 -2.8475378,-16.704523 14.164706,-17.115686 26.484915,-5.3769496 26.896078,11.635294 z" + transform="matrix(0.8982409,0.027775,-0.02744374,0.9090831,16.347508,18.533176)" + id="path3158" + style="fill:none;stroke:#ffffff;stroke-width:3.31833673;stroke-opacity:1" /> + <path + d="m 16.987782,36.466398 0,-5.405882 c 0,0 -1.533767,-0.676356 -2.023529,-1.180393 -0.662593,-0.681907 -1.517647,-2.782352 -1.517647,-2.782352 l -0.0184,-11.631373 c 0,0 0.687852,-1.032868 1.171258,-0.977718 0.498837,0.05691 0.976374,0.977718 0.976374,0.977718 l 0,6 c 0,0 0.688624,0.580651 0.906061,0.572549 0.197418,-0.0074 0.656111,-0.572549 0.656111,-0.572549 l 0.08431,-9.75 c 0,0 0.580108,-0.90735 1.030166,-0.891176 0.375782,0.01351 0.927452,0.891176 0.927452,0.891176 l 0.168627,6.75 c 0,0 0.405694,0.699955 0.67451,0.705882 0.161921,0.0036 0.722023,-0.705882 0.722023,-0.705882 L 20.613273,8.4663984 c 0,0 0.829327,-0.9980533 1.180391,-0.9294114 0.344867,0.06743 1.011766,0.9294114 1.011766,0.9294114 l 0.08431,10.2499996 c 0,0 0.449781,0.481964 0.674511,0.455882 0.196236,-0.02277 0.761584,-0.455882 0.761584,-0.455882 l 0,-7.25 c 0,0 0.663398,-0.932951 1.111446,-0.978431 0.450161,-0.04569 1.138554,1.091102 1.138554,1.091102 l 0,13.017647 1.878611,0.308898 c 0,0 1.288603,-2.469107 2.192157,-3.203922 0.765333,-0.622407 2.030021,-1.230804 2.997738,-1.039365 0.386002,0.07636 0.92745,0.852337 0.92745,0.852337 0,0 -2.251119,2.381719 -2.941781,3.653091 -0.51581,0.949505 -0.756638,2.771202 -1.452489,3.59789 -0.54755,0.650503 -1.598008,1.07997 -2.332428,1.508447 -0.783172,0.45692 -2.388385,1.179635 -2.388385,1.179635 l -0.03756,5.012671 -8.431372,0 z" + id="path3162" + style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.5;stroke-opacity:1" /> +</svg> diff --git a/icons/stopiton.svg b/icons/stopiton.svg new file mode 100644 index 0000000..af01208 --- /dev/null +++ b/icons/stopiton.svg @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.46" + width="44" + height="44" + version="1.0" + sodipodi:docname="stopiton.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs5"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective9" /> + </defs> + <sodipodi:namedview + inkscape:window-height="1000" + inkscape:window-width="1679" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + guidetolerance="10.0" + gridtolerance="10.0" + objecttolerance="10.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + showgrid="false" + inkscape:zoom="10" + inkscape:cx="24.924162" + inkscape:cy="3.0823126" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:current-layer="svg2" /> + <path + sodipodi:type="star" + style="opacity:1;fill:#d00000;fill-opacity:1;stroke:none;stroke-width:1.5;stroke-opacity:1" + id="path2386" + sodipodi:sides="8" + sodipodi:cx="6.154902" + sodipodi:cy="3.6254902" + sodipodi:r1="22.234058" + sodipodi:r2="20.541592" + sodipodi:arg1="0.36853512" + sodipodi:arg2="0.7612342" + inkscape:flatsided="true" + inkscape:rounded="0" + inkscape:randomized="0" + d="M 26.896078,11.635294 L 15.157342,23.955503 L -1.8549019,24.366666 L -14.175111,12.62793 L -14.586274,-4.3843137 L -2.8475378,-16.704523 L 14.164706,-17.115686 L 26.484915,-5.3769496 L 26.896078,11.635294 z" + transform="matrix(1.0676988,3.2621148e-2,-3.2621148e-2,1.0676988,15.546686,17.928289)" /> + <path + sodipodi:type="star" + style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:3.31833665000000000;stroke-opacity:1" + id="path3158" + sodipodi:sides="8" + sodipodi:cx="6.154902" + sodipodi:cy="3.6254902" + sodipodi:r1="22.234058" + sodipodi:r2="20.541592" + sodipodi:arg1="0.36853512" + sodipodi:arg2="0.7612342" + inkscape:flatsided="true" + inkscape:rounded="0" + inkscape:randomized="0" + d="M 26.896078,11.635294 L 15.157342,23.955503 L -1.8549019,24.366666 L -14.175111,12.62793 L -14.586274,-4.3843137 L -2.8475378,-16.704523 L 14.164706,-17.115686 L 26.484915,-5.3769496 L 26.896078,11.635294 z" + transform="matrix(0.8982409,2.7775002e-2,-2.7443742e-2,0.9090831,16.347508,18.533176)" /> + <path + style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.5;stroke-opacity:1" + d="M 16.987782,36.466398 L 16.987782,31.060516 C 16.987782,31.060516 15.454015,30.38416 14.964253,29.880123 C 14.30166,29.198216 13.446606,27.097771 13.446606,27.097771 L 13.428206,15.466398 C 13.428206,15.466398 14.116058,14.43353 14.599464,14.48868 C 15.098301,14.545591 15.575838,15.466398 15.575838,15.466398 L 15.575838,21.466398 C 15.575838,21.466398 16.264462,22.047049 16.481899,22.038947 C 16.679317,22.031591 17.13801,21.466398 17.13801,21.466398 L 17.222322,11.716398 C 17.222322,11.716398 17.80243,10.809048 18.252488,10.825222 C 18.62827,10.838727 19.17994,11.716398 19.17994,11.716398 L 19.348567,18.466398 C 19.348567,18.466398 19.754261,19.166353 20.023077,19.17228 C 20.184998,19.17585 20.7451,18.466398 20.7451,18.466398 L 20.613273,8.4663984 C 20.613273,8.4663984 21.4426,7.4683451 21.793664,7.536987 C 22.138531,7.604417 22.80543,8.4663984 22.80543,8.4663984 L 22.889742,18.716398 C 22.889742,18.716398 23.339523,19.198362 23.564253,19.17228 C 23.760489,19.149505 24.325837,18.716398 24.325837,18.716398 L 24.325837,11.466398 C 24.325837,11.466398 24.989235,10.533447 25.437283,10.487967 C 25.887444,10.442273 26.575837,11.579069 26.575837,11.579069 L 26.575837,24.596716 L 28.454448,24.905614 C 28.454448,24.905614 29.743051,22.436507 30.646605,21.701692 C 31.411938,21.079285 32.676626,20.470888 33.644343,20.662327 C 34.030345,20.738688 34.571793,21.514664 34.571793,21.514664 C 34.571793,21.514664 32.320674,23.896383 31.630012,25.167755 C 31.114202,26.11726 30.873374,27.938957 30.177523,28.765645 C 29.629973,29.416148 28.579515,29.845615 27.845095,30.274092 C 27.061923,30.731012 25.45671,31.453727 25.45671,31.453727 L 25.419154,36.466398 L 16.987782,36.466398 z" + id="path3162" + sodipodi:nodetypes="ccsccsccsccsccsccsccsccscccsscsssccc" /> +</svg> diff --git a/icons/ta-open.svg b/icons/ta-open.svg new file mode 100644 index 0000000..d7677e0 --- /dev/null +++ b/icons/ta-open.svg @@ -0,0 +1,183 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="55" + viewBox="0 0 54.999998 55.000001" + id="Icon" + xml:space="preserve" + style="overflow:visible"><metadata + id="metadata26"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs24"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + </defs> + + + + +<g + transform="translate(2,-2)" + id="g3829"><path + d="m 39.046105,34.391197 c -0.384814,0 -0.764757,-0.02436 -1.139134,-0.06959 l 0.965863,1.634591 0.951946,-1.60954 c -0.258167,0.02088 -0.515638,0.04454 -0.778675,0.04454 z" + id="path11-7" + style="fill:none;stroke:#ffffff;stroke-width:2.08759975;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><g + transform="matrix(0.69586655,0,0,0.69586655,19.911862,0.79545554)" + id="g13-6" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"> + <path + d="m 40.16,11.726 c -2.164,0 -3.958,1.555 -4.343,3.607 1.859,1.345 3.457,3.115 4.675,5.208 2.285,-0.172 4.094,-2.061 4.094,-4.39 0,-2.444 -1.982,-4.425 -4.426,-4.425 z" + id="path15-3" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 40.713,39.887 c -1.224,2.232 -2.86,4.131 -4.797,5.556 0.521,1.864 2.213,3.239 4.244,3.239 2.443,0 4.426,-1.98 4.426,-4.424 0,-2.255 -1.693,-4.096 -3.873,-4.371 z" + id="path17-1" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 14.273,39.871 c -2.253,0.206 -4.024,2.079 -4.024,4.387 0,2.443 1.98,4.424 4.424,4.424 2.064,0 3.784,-1.42 4.272,-3.332 -1.883,-1.416 -3.475,-3.289 -4.672,-5.479 z" + id="path19-7" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 19.026,15.437 c -0.343,-2.103 -2.154,-3.711 -4.353,-3.711 -2.444,0 -4.424,1.981 -4.424,4.424 0,2.382 1.886,4.31 4.245,4.406 1.186,-2.043 2.732,-3.784 4.532,-5.119 z" + id="path21-5" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g><path + d="m 39.046105,9.537627 c 1.327713,0 2.59419,0.2860012 3.770205,0.784937 0.515637,-0.7487519 0.819731,-1.6540743 0.819731,-2.6324627 0,-2.5656599 -2.079945,-4.6463009 -4.646301,-4.6463009 -2.56566,0 -4.645605,2.080641 -4.645605,4.6463009 0,0.9936975 0.314531,1.9129372 0.846173,2.6679527 1.199674,-0.5212044 2.496074,-0.820427 3.855797,-0.820427 z" + id="path23-9" + style="fill:none;stroke:#ffffff;stroke-width:2.08759975;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><g + transform="matrix(0.69586655,0,0,0.69586655,19.911862,0.79545554)" + id="g25-6" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"> + <path + d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z" + id="path2988-2" + style="fill:none;stroke:#ffffff;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g><g + transform="matrix(0.69586655,0,0,0.69586655,19.911862,0.79545554)" + id="g28-1" + style="fill:#ffffff;fill-opacity:1;stroke:none"> + <path + d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 -3.75,-0.083 z" + id="path30-7" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z" + id="path32-8" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z" + id="path34-5" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z" + id="path2998-7" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z" + id="path37-4" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z" + id="path3002-1" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + </g></g><g + transform="translate(-2.2743816,2.513511)" + id="g3036"><path + d="M 9.5689397,38.952218 9.3902171,32.897964 M 25.663656,50.969805 3.6345541,51.23649 3.5243801,39.2454 l 5.851406,-6.358972 21.2578909,0 -0.110174,12.124478 z M 3.6345541,39.378743 l 21.4782339,0.266685 0.33052,10.924347 m -0.306426,-11.052011 5.531132,-6.638311" + id="path3806" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" /><g + transform="matrix(0,-1,-1,0,47.3087,85.9835)" + id="g4770-9"><g + transform="translate(34.0803,-1006.42)" + id="g4772-6"><polyline + id="polyline4774-3" + points="51.562,15.306 41.17,16.188 42.053,5.794" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" + transform="matrix(-0.469241,0.469241,-0.469241,-0.469241,66.2906,1019.03)" /><path + d="m 39.363241,1033.1291 -0.05636,9.9115 -8.750608,0.067" + id="path4776-8" + style="fill:none;stroke:#ffffff;stroke-width:2.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /></g></g></g></svg>
\ No newline at end of file diff --git a/icons/trashoff.svg b/icons/trashoff.svg new file mode 100644 index 0000000..8ebfb39 --- /dev/null +++ b/icons/trashoff.svg @@ -0,0 +1,49 @@ +<?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="defs5" /> + <path + d="m 38.999052,40.01547 a 11.011069,3.4902595 0 1 1 -22.022137,0 11.011069,3.4902595 0 1 1 22.022137,0 z" + id="path2822" + style="fill:none;stroke:#ffffff;stroke-width:2.29999995;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 13.75483,14.61245 c 3.56733,24.489728 3.430201,24.354426 3.430201,24.354426 l 0,0" + id="path2820" + style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 41.24517,14.793462 c -2.625017,24.01617 -2.55771,24.314197 -2.55771,24.314197" + id="path2820-4" + style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 15.951887,16.457318 c 3.836562,25.030939 3.656235,25.621512 3.656235,25.621512" + id="path3620" + style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 39.328864,16.340019 c -2.902587,25.706467 -2.96102,25.806464 -2.96102,25.806464" + id="path3622" + style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 20.66094,17.470259 c 2.288476,25.03094 2.24528,25.62334 2.24528,25.62334" + id="path3624" + style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 34.281292,17.792054 C 31.790893,43.567158 32.084236,43.133828 32.084236,43.133828" + id="path3626" + style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 26.831688,18.009641 c 0.06731,24.963289 0.180327,25.396617 0.180327,25.396617" + id="path3628" + style="fill:none;stroke:#ffffff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 41.281336,14.477147 a 13.76451,3.1119547 0 0 1 -27.529019,0 13.76451,3.1119547 0 1 1 27.529019,0 z" + id="path2818" + style="fill:none;stroke:#ffffff;stroke-width:2.29999995;stroke-linecap:square;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/icons/trashon.svg b/icons/trashon.svg new file mode 100644 index 0000000..01e9cd2 --- /dev/null +++ b/icons/trashon.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="55" + height="55" + id="svg2"> + <defs + id="defs5" /> + <rect + width="55" + height="55" + rx="0" + x="0" + y="0" + id="rect2839" + style="fill:#ffd200;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + d="m 38.982225,40.079903 a 11.011069,3.4902595 0 1 1 -22.022137,0 11.011069,3.4902595 0 1 1 22.022137,0 z" + id="path2822-6" + style="fill:#808080;fill-opacity:1;stroke:#000000;stroke-width:2.29999995;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 13.738004,14.676883 c 3.567329,24.489728 3.4302,24.354426 3.4302,24.354426 l 0,0" + id="path2820-5" + style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 41.228343,14.857895 c -2.625016,24.01617 -2.55771,24.314197 -2.55771,24.314197" + id="path2820-4-6" + style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 15.93506,16.521751 c 3.836562,25.030939 3.656235,25.621512 3.656235,25.621512" + id="path3620-9" + style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 39.312038,16.404452 c -2.902587,25.706467 -2.96102,25.806464 -2.96102,25.806464" + id="path3622-3" + style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 20.644113,17.534692 c 2.288476,25.03094 2.24528,25.62334 2.24528,25.62334" + id="path3624-7" + style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 34.264465,17.856487 C 31.774066,43.631591 32.067409,43.198261 32.067409,43.198261" + id="path3626-4" + style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 26.814861,18.074074 c 0.06731,24.963289 0.180327,25.396617 0.180327,25.396617" + id="path3628-5" + style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 41.26451,14.54158 a 13.76451,3.1119547 0 0 1 -27.529019,0 13.76451,3.1119547 0 1 1 27.529019,0 z" + id="path2818-2" + style="fill:none;stroke:#000000;stroke-width:2.29999995;stroke-linecap:square;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/icons/turtleoff.svg b/icons/turtleoff.svg new file mode 100644 index 0000000..f3d721f --- /dev/null +++ b/icons/turtleoff.svg @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="55" + height="55" + id="svg2"> + <metadata + id="metadata3044"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs5" /> + <path + d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z" + id="path3003" + style="fill:none;stroke:#ffffff;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 38.317981,14.929279 c -1.837168,0 -3.360217,1.289964 -3.68707,2.992219 1.578232,1.115757 2.934884,2.584076 3.968928,4.320343 1.939893,-0.142684 3.475677,-1.709721 3.475677,-3.641764 0,-2.027442 -1.682656,-3.670798 -3.757535,-3.670798 z" + id="path3007" + style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 38.787461,38.290488 c -1.039138,1.851575 -2.42805,3.426908 -4.072502,4.609029 0.442312,1.546298 1.878767,2.686942 3.603022,2.686942 2.07403,0 3.757535,-1.642527 3.757535,-3.669969 0,-1.870656 -1.437304,-3.397874 -3.288055,-3.626002 z" + id="path3009" + style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 16.340734,38.277215 c -1.912727,0.170889 -3.41625,1.724653 -3.41625,3.639275 0,2.026612 1.680958,3.669969 3.755837,3.669969 1.752271,0 3.212497,-1.177974 3.626793,-2.764091 -1.598607,-1.174655 -2.950165,-2.728419 -3.96638,-4.545153 z" + id="path3011" + style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 20.375881,18.007772 c -0.291196,-1.744563 -1.828678,-3.078493 -3.69556,-3.078493 -2.074879,0 -3.755837,1.643356 -3.755837,3.669968 0,1.97601 1.601155,3.575399 3.603872,3.655037 1.006876,-1.694789 2.319381,-3.139051 3.847525,-4.246512 z" + id="path3013" + style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z" + id="path3015" + style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:2.29999995;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)" + id="g3017" + style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"> + <path + d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z" + id="path3019" + style="fill:#686868;fill-opacity:1;stroke:#ffffff;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)" + id="g3021" + style="fill:#ffffff;fill-opacity:1;stroke:none"> + <path + d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z" + id="path3023" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z" + id="path3025" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z" + id="path3027" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z" + id="path3029" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z" + id="path3031" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z" + id="path3033" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + </g> +</svg> diff --git a/icons/turtleon.svg b/icons/turtleon.svg new file mode 100644 index 0000000..4d955de --- /dev/null +++ b/icons/turtleon.svg @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="55" + height="55" + id="svg2"> + <metadata + id="metadata3068"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs5" /> + <rect + width="55" + height="55" + rx="0" + x="0" + y="0" + id="rect2839" + style="fill:#ffd200;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <g + id="g3854"> + <path + d="m 27.567493,45.252146 c -0.46948,0 -0.933016,-0.02903 -1.389761,-0.08296 l 1.178368,1.948634 1.161389,-1.918769 c -0.314968,0.02489 -0.629086,0.05309 -0.949996,0.05309 z" + id="path3003" + style="fill:none;stroke:#00ff00;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)" + id="g3005" + style="fill:#00d000;fill-opacity:1;stroke:#00ff00;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"> + <path + d="m 40.16,11.726 c -2.164,0 -3.958,1.555 -4.343,3.607 1.859,1.345 3.457,3.115 4.675,5.208 2.285,-0.172 4.094,-2.061 4.094,-4.39 0,-2.444 -1.982,-4.425 -4.426,-4.425 z" + id="path3007" + style="fill:#00d000;fill-opacity:1;stroke:#00ff00;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 40.713,39.887 c -1.224,2.232 -2.86,4.131 -4.797,5.556 0.521,1.864 2.213,3.239 4.244,3.239 2.443,0 4.426,-1.98 4.426,-4.424 0,-2.255 -1.693,-4.096 -3.873,-4.371 z" + id="path3009" + style="fill:#00d000;fill-opacity:1;stroke:#00ff00;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 14.273,39.871 c -2.253,0.206 -4.024,2.079 -4.024,4.387 0,2.443 1.98,4.424 4.424,4.424 2.064,0 3.784,-1.42 4.272,-3.332 -1.883,-1.416 -3.475,-3.289 -4.672,-5.479 z" + id="path3011" + style="fill:#00d000;fill-opacity:1;stroke:#00ff00;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 19.026,15.437 c -0.343,-2.103 -2.154,-3.711 -4.353,-3.711 -2.444,0 -4.424,1.981 -4.424,4.424 0,2.382 1.886,4.31 4.245,4.406 1.186,-2.043 2.732,-3.784 4.532,-5.119 z" + id="path3013" + style="fill:#00d000;fill-opacity:1;stroke:#00ff00;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <path + d="m 27.567493,15.62362 c 1.619832,0 3.164955,0.340948 4.599711,0.935742 0.629086,-0.892605 1.000085,-1.971862 1.000085,-3.138221 0,-3.058584 -2.537567,-5.5389654 -5.668563,-5.5389654 -3.130146,0 -5.667713,2.4803814 -5.667713,5.5389654 0,1.18461 0.383734,2.280457 1.032345,3.180529 1.463622,-0.62134 3.04525,-0.97805 4.704135,-0.97805 z" + id="path3015" + style="fill:#00d000;fill-opacity:1;stroke:#00ff00;stroke-width:1.20000005;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)" + id="g3017" + style="fill:#00d000;fill-opacity:1;stroke:#00ff00;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"> + <path + d="m 43.102,30.421 c 0,4.7344 -1.6452,9.2798 -4.5706,12.6275 -2.9254,3.3478 -6.8973,5.2305 -11.0344,5.2305 -4.1371,0 -8.109,-1.8827 -11.0344,-5.2305 -2.9254,-3.3477 -4.5706,-7.8931 -4.5706,-12.6275 0,-9.7966 7.0444,-17.858 15.605,-17.858 8.5606,0 15.605,8.0614 15.605,17.858 z" + id="path3019" + style="fill:#00d000;fill-opacity:1;stroke:#00ff00;stroke-width:1.42992032;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.8489685,0,0,0.82955893,4.2234061,5.2018707)" + id="g3021" + style="fill:#00ff00;fill-opacity:1;stroke:none"> + <path + d="m 25.875,33.75 -1.542,-4.625 3.164,-2.587 3.615,2.626 -1.487,4.669 z" + id="path3023" + style="fill:#00ff00;fill-opacity:1;stroke:none" /> + <path + d="m 27.501,41.551 c -3.968,-0.16 -5.543,-2.009 -5.543,-2.009 l 3.57,-4.163 4.465,0.168 3.132,4.12 c 0,0 -2.89,1.994 -5.624,1.884 z" + id="path3025" + style="fill:#00ff00;fill-opacity:1;stroke:none" /> + <path + d="m 18.453,33.843 c -0.849,-2.968 0.172,-6.884 0.172,-6.884 l 4,2.167 1.493,4.629 -3.582,4.233 c 0,-10e-4 -1.465,-1.99 -2.083,-4.145 z" + id="path3027" + style="fill:#00ff00;fill-opacity:1;stroke:none" /> + <path + d="m 19.458,25.125 c 0,0 0.5,-1.958 3.039,-3.822 2.237,-1.643 4.465,-1.72 4.465,-1.72 l -0.037,4.981 -3.521,2.75 -3.946,-2.189 z" + id="path3029" + style="fill:#00ff00;fill-opacity:1;stroke:none" /> + <path + d="M 32.084,27.834 28.625,24.959 29,19.75 c 0,0 1.834,-0.042 3.959,1.667 2.228,1.791 3.362,4.983 3.362,4.983 l -4.237,1.434 z" + id="path3031" + style="fill:#00ff00;fill-opacity:1;stroke:none" /> + <path + d="m 31.292,34.042 1.313,-4.464 4.187,-1.536 c 0,0 0.677,2.663 -0.042,5.667 -0.54,2.256 -2.084,4.361 -2.084,4.361 l -3.374,-4.028 z" + id="path3033" + style="fill:#00ff00;fill-opacity:1;stroke:none" /> + </g> + </g> +</svg> diff --git a/icons/view-Cartesian.svg b/icons/view-Cartesian.svg new file mode 100644 index 0000000..3d0e210 --- /dev/null +++ b/icons/view-Cartesian.svg @@ -0,0 +1,30 @@ +<?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="svg2384"> + <defs + id="defs2386" /> + <g + id="layer1"> + <rect + width="50" + height="50" + x="2.5" + y="2.5" + id="rect2394" + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 27.333333,1 C 28.083333,50.75 27.333333,54 27.333333,54" + id="path3168" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 54,27.333333 C 4.2499997,28.083333 1,27.333333 1,27.333333" + id="path3170" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> +</svg> diff --git a/icons/view-metric.svg b/icons/view-metric.svg new file mode 100644 index 0000000..c91675d --- /dev/null +++ b/icons/view-metric.svg @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="55" + height="55" + id="svg2384"> + <rect + width="50" + height="50" + x="2.5" + y="2.5" + id="rect2394" + style="fill:none;stroke:#ffffff;stroke-width:3.5;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 27.5,40.877276 0,12.716411" + id="path3168" + style="fill:none;stroke:#ffffff;stroke-width:2.81262541;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 9.8582187,27.5 -8.4776076,0" + id="path3170" + style="fill:none;stroke:#ffffff;stroke-width:2.76122212;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + x="9.2539062" + y="36.236328" + id="text2989" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan + x="9.2539062" + y="36.236328" + id="tspan2991" + style="font-size:24px;fill:#ffffff">CM</tspan></text> + <path + d="m 27.5,1.4062879 0,12.7164111" + id="path3168-0" + style="fill:none;stroke:#ffffff;stroke-width:2.81257582;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 53.729275,27.5 -8.477607,0" + id="path3170-7" + style="fill:none;stroke:#ffffff;stroke-width:2.54144907;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/icons/view-polar.svg b/icons/view-polar.svg new file mode 100644 index 0000000..85fcb12 --- /dev/null +++ b/icons/view-polar.svg @@ -0,0 +1,25 @@ +<?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="svg2384"> + <defs + id="defs2386" /> + <path + d="M 50.991903,28.836033 A 22.935223,21.821863 0 1 1 5.1214581,28.836033 A 22.935223,21.821863 0 1 1 50.991903,28.836033 z" + transform="matrix(0.9819585,0,0,1.0009824,-5.0496075e-2,-1.3643614)" + id="path3157" + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:3.53027272;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 27.333333,1 C 28.083333,50.75 27.333333,54 27.333333,54" + id="path3168" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 54,27.333333 C 4.2499997,28.083333 1,27.333333 1,27.333333" + id="path3170" + style="fill:none;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> +</svg> diff --git a/images/1x1.svg b/images/1x1.svg new file mode 100644 index 0000000..3742c13 --- /dev/null +++ b/images/1x1.svg @@ -0,0 +1,107 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="36.914501" + height="20.12108" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172-9" + xlink:href="#linearGradient3166-6" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + id="linearGradient3166-6"> + <stop + id="stop3168-5" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170-6" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + </defs> + <g + transform="matrix(0.44910476,0,0,0.43207674,-2.5452997,-1.8215706)" + id="activity-journal" + style="stroke:#000000;stroke-opacity:1;display:block"> + <path + d="M 45.866,44.669 C 45.866,47.18 44.338,49 41.534,49 l -29.457,0 0,-43 29.458,0 c 2.15,0 4.332,2.154 4.332,4.33 l -10e-4,34.339 0,0 z" + id="path2458" + style="fill:#ffffff;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <line + id="line2460" + y2="48.881001" + y1="6.1209998" + x2="21.341" + x1="21.341" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,14.464 c 0,0 2.084,0.695 4.17,0.695 2.086,0 4.173,-0.695 4.173,-0.695" + id="path2462" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,28.021 c 0,0 1.912,0.695 4.345,0.695 2.433,0 3.999,-0.695 3.999,-0.695" + id="path2464" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,41.232 c 0,0 1.736,0.695 4.518,0.695 2.781,0 3.825,-0.695 3.825,-0.695" + id="path2466" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + <g + transform="matrix(0.4489,0,0,0.44175824,21.433726,0.01485409)" + id="g2823"> + <path + d="m 1.75,43.75 l 0,-42 21,0 10,11 0,31 -31,0 z" + id="path3199" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#00000f;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none" /> + <path + d="m 10,26.75 c 14.5,0 14.5,0 14.5,0" + id="path3163" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,32.75 c 14.5,0 14.5,0 14.5,0" + id="path3165" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,20.75 c 14.5,0 14.5,0 14.5,0" + id="path3167" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 21.5,2.5000001 l 0,10.2499999 9.5,0" + id="path3201" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> +</svg> diff --git a/images/1x1a.svg b/images/1x1a.svg new file mode 100644 index 0000000..5b93089 --- /dev/null +++ b/images/1x1a.svg @@ -0,0 +1,63 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="28.128611" + height="31.155001" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + </defs> + <g + transform="matrix(0.67,0,0,0.67,-3.77478,-2.8475)" + id="activity-journal" + style="stroke:#000000;stroke-opacity:1;display:block"> + <path + d="M 45.866,44.669 C 45.866,47.18 44.338,49 41.534,49 l -29.457,0 0,-43 29.458,0 c 2.15,0 4.332,2.154 4.332,4.33 l -10e-4,34.339 0,0 z" + id="path2458" + style="fill:#ffffff;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <line + id="line2460" + y2="48.881001" + y1="6.1209998" + x2="21.341" + x1="21.341" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,14.464 c 0,0 2.084,0.695 4.17,0.695 2.086,0 4.173,-0.695 4.173,-0.695" + id="path2462" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,28.021 c 0,0 1.912,0.695 4.345,0.695 2.433,0 3.999,-0.695 3.999,-0.695" + id="path2464" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,41.232 c 0,0 1.736,0.695 4.518,0.695 2.781,0 3.825,-0.695 3.825,-0.695" + id="path2466" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> +</svg> diff --git a/images/1x2.svg b/images/1x2.svg new file mode 100644 index 0000000..c4358b3 --- /dev/null +++ b/images/1x2.svg @@ -0,0 +1,163 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="36.914501" + height="41.561081" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172-9" + xlink:href="#linearGradient3166-6" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + id="linearGradient3166-6"> + <stop + id="stop3168-5" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170-6" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + </defs> + <g + transform="scale(0.67,0.67)" + id="g2846"> + <g + transform="matrix(0.67030561,0,0,0.64489065,-3.7989548,-2.7187621)" + id="activity-journal" + style="stroke:#000000;stroke-opacity:1;display:block"> + <path + d="M 45.866,44.669 C 45.866,47.18 44.338,49 41.534,49 l -29.457,0 0,-43 29.458,0 c 2.15,0 4.332,2.154 4.332,4.33 l -10e-4,34.339 0,0 z" + id="path2458" + style="fill:#ffffff;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <line + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + x1="21.341" + x2="21.341" + y1="6.1209998" + y2="48.881001" + id="line2460" /> + <path + d="m 7.384,14.464 c 0,0 2.084,0.695 4.17,0.695 2.086,0 4.173,-0.695 4.173,-0.695" + id="path2462" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,28.021 c 0,0 1.912,0.695 4.345,0.695 2.433,0 3.999,-0.695 3.999,-0.695" + id="path2464" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,41.232 c 0,0 1.736,0.695 4.518,0.695 2.781,0 3.825,-0.695 3.825,-0.695" + id="path2466" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + <g + transform="matrix(0.67,0,0,0.65934066,31.990636,0.02217029)" + id="g2823"> + <path + d="m 1.75,43.75 l 0,-42 21,0 10,11 0,31 -31,0 z" + id="path3199" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#00000f;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none" /> + <path + d="m 10,26.75 c 14.5,0 14.5,0 14.5,0" + id="path3163" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,32.75 c 14.5,0 14.5,0 14.5,0" + id="path3165" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,20.75 c 14.5,0 14.5,0 14.5,0" + id="path3167" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 21.5,2.5000001 l 0,10.2499999 9.5,0" + id="path3201" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.67030561,0,0,0.64489065,-3.7989548,29.281238)" + id="activity-journal-4" + style="stroke:#000000;stroke-opacity:1;display:block"> + <path + d="M 45.866,44.669 C 45.866,47.18 44.338,49 41.534,49 l -29.457,0 0,-43 29.458,0 c 2.15,0 4.332,2.154 4.332,4.33 l -10e-4,34.339 0,0 z" + id="path2458-7" + style="fill:#ffffff;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <line + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + x1="21.341" + x2="21.341" + y1="6.1209998" + y2="48.881001" + id="line2460-6" /> + <path + d="m 7.384,14.464 c 0,0 2.084,0.695 4.17,0.695 2.086,0 4.173,-0.695 4.173,-0.695" + id="path2462-5" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,28.021 c 0,0 1.912,0.695 4.345,0.695 2.433,0 3.999,-0.695 3.999,-0.695" + id="path2464-6" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,41.232 c 0,0 1.736,0.695 4.518,0.695 2.781,0 3.825,-0.695 3.825,-0.695" + id="path2466-9" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + <g + transform="matrix(0.67,0,0,0.65934066,31.990636,32.02217)" + id="g2823-3"> + <path + d="m 1.75,43.75 l 0,-42 21,0 10,11 0,31 -31,0 z" + id="path3199-7" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#00000f;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none" /> + <path + d="m 10,26.75 c 14.5,0 14.5,0 14.5,0" + id="path3163-4" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,32.75 c 14.5,0 14.5,0 14.5,0" + id="path3165-5" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,20.75 c 14.5,0 14.5,0 14.5,0" + id="path3167-2" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 21.5,2.5000001 l 0,10.2499999 9.5,0" + id="path3201-5" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + </g> +</svg> diff --git a/images/2x1.svg b/images/2x1.svg new file mode 100644 index 0000000..c7d92c4 --- /dev/null +++ b/images/2x1.svg @@ -0,0 +1,159 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="40.264679" + height="41.561081" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172-9" + xlink:href="#linearGradient3166-6" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + id="linearGradient3166-6"> + <stop + id="stop3168-5" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170-6" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + </defs> + <g + transform="matrix(0.44910476,0,0,0.43207674,-2.5452997,-1.8215706)" + id="activity-journal" + style="stroke:#000000;stroke-opacity:1;display:block"> + <path + d="M 45.866,44.669 C 45.866,47.18 44.338,49 41.534,49 l -29.457,0 0,-43 29.458,0 c 2.15,0 4.332,2.154 4.332,4.33 l -10e-4,34.339 0,0 z" + id="path2458" + style="fill:#ffffff;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <line + id="line2460" + y2="48.881001" + y1="6.1209998" + x2="21.341" + x1="21.341" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,14.464 c 0,0 2.084,0.695 4.17,0.695 2.086,0 4.173,-0.695 4.173,-0.695" + id="path2462" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,28.021 c 0,0 1.912,0.695 4.345,0.695 2.433,0 3.999,-0.695 3.999,-0.695" + id="path2464" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,41.232 c 0,0 1.736,0.695 4.518,0.695 2.781,0 3.825,-0.695 3.825,-0.695" + id="path2466" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + <g + transform="matrix(0.4489,0,0,0.44175824,1.6688141,21.454857)" + id="g2823"> + <path + d="m 1.75,43.75 l 0,-42 21,0 10,11 0,31 -31,0 z" + id="path3199" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#00000f;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none" /> + <path + d="m 10,26.75 c 14.5,0 14.5,0 14.5,0" + id="path3163" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,32.75 c 14.5,0 14.5,0 14.5,0" + id="path3165" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,20.75 c 14.5,0 14.5,0 14.5,0" + id="path3167" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 21.5,2.5000001 l 0,10.2499999 9.5,0" + id="path3201" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> + <g + transform="matrix(0.44910476,0,0,0.43207674,18.8947,-1.8215706)" + id="activity-journal-4" + style="stroke:#000000;stroke-opacity:1;display:block"> + <path + d="M 45.866,44.669 C 45.866,47.18 44.338,49 41.534,49 l -29.457,0 0,-43 29.458,0 c 2.15,0 4.332,2.154 4.332,4.33 l -10e-4,34.339 0,0 z" + id="path2458-7" + style="fill:#ffffff;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <line + id="line2460-6" + y2="48.881001" + y1="6.1209998" + x2="21.341" + x1="21.341" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,14.464 c 0,0 2.084,0.695 4.17,0.695 2.086,0 4.173,-0.695 4.173,-0.695" + id="path2462-5" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,28.021 c 0,0 1.912,0.695 4.345,0.695 2.433,0 3.999,-0.695 3.999,-0.695" + id="path2464-6" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,41.232 c 0,0 1.736,0.695 4.518,0.695 2.781,0 3.825,-0.695 3.825,-0.695" + id="path2466-9" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + <g + transform="matrix(0.4489,0,0,0.44175824,23.108814,21.454854)" + id="g2823-3"> + <path + d="m 1.75,43.75 l 0,-42 21,0 10,11 0,31 -31,0 z" + id="path3199-7" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#00000f;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none" /> + <path + d="m 10,26.75 c 14.5,0 14.5,0 14.5,0" + id="path3163-4" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,32.75 c 14.5,0 14.5,0 14.5,0" + id="path3165-5" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,20.75 c 14.5,0 14.5,0 14.5,0" + id="path3167-2" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 21.5,2.5000001 l 0,10.2499999 9.5,0" + id="path3201-5" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> +</svg> diff --git a/images/2x2.svg b/images/2x2.svg new file mode 100644 index 0000000..93a8b82 --- /dev/null +++ b/images/2x2.svg @@ -0,0 +1,171 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="38.924679" + height="41.561081" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172-9" + xlink:href="#linearGradient3166-6" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + id="linearGradient3166-6"> + <stop + id="stop3168-5" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170-6" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + </defs> + <g + transform="scale(0.67,0.67)" + id="g2846"> + <g + transform="matrix(0.67030561,0,0,0.64489065,-3.7989548,-2.7187603)" + id="activity-journal" + style="stroke:#000000;stroke-opacity:1;display:block"> + <path + d="M 45.866,44.669 C 45.866,47.18 44.338,49 41.534,49 l -29.457,0 0,-43 29.458,0 c 2.15,0 4.332,2.154 4.332,4.33 l -10e-4,34.339 0,0 z" + id="path2458" + style="fill:#ffffff;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <line + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + x1="21.341" + x2="21.341" + y1="6.1209998" + y2="48.881001" + id="line2460" /> + <path + d="m 7.384,14.464 c 0,0 2.084,0.695 4.17,0.695 2.086,0 4.173,-0.695 4.173,-0.695" + id="path2462" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,28.021 c 0,0 1.912,0.695 4.345,0.695 2.433,0 3.999,-0.695 3.999,-0.695" + id="path2464" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,41.232 c 0,0 1.736,0.695 4.518,0.695 2.781,0 3.825,-0.695 3.825,-0.695" + id="path2466" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + <g + transform="matrix(0.67030561,0,0,0.64489065,26.201045,-2.7187621)" + id="activity-journal-7" + style="stroke:#000000;stroke-opacity:1;display:block"> + <path + d="M 45.866,44.669 C 45.866,47.18 44.338,49 41.534,49 l -29.457,0 0,-43 29.458,0 c 2.15,0 4.332,2.154 4.332,4.33 l -10e-4,34.339 0,0 z" + id="path2458-4" + style="fill:#ffffff;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <line + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + x1="21.341" + x2="21.341" + y1="6.1209998" + y2="48.881001" + id="line2460-5" /> + <path + d="m 7.384,14.464 c 0,0 2.084,0.695 4.17,0.695 2.086,0 4.173,-0.695 4.173,-0.695" + id="path2462-2" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,28.021 c 0,0 1.912,0.695 4.345,0.695 2.433,0 3.999,-0.695 3.999,-0.695" + id="path2464-5" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,41.232 c 0,0 1.736,0.695 4.518,0.695 2.781,0 3.825,-0.695 3.825,-0.695" + id="path2466-4" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + <g + transform="matrix(0.67030561,0,0,0.64489065,-3.7989548,29.28124)" + id="activity-journal-8" + style="stroke:#000000;stroke-opacity:1;display:block"> + <path + d="M 45.866,44.669 C 45.866,47.18 44.338,49 41.534,49 l -29.457,0 0,-43 29.458,0 c 2.15,0 4.332,2.154 4.332,4.33 l -10e-4,34.339 0,0 z" + id="path2458-6" + style="fill:#ffffff;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <line + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + x1="21.341" + x2="21.341" + y1="6.1209998" + y2="48.881001" + id="line2460-8" /> + <path + d="m 7.384,14.464 c 0,0 2.084,0.695 4.17,0.695 2.086,0 4.173,-0.695 4.173,-0.695" + id="path2462-8" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,28.021 c 0,0 1.912,0.695 4.345,0.695 2.433,0 3.999,-0.695 3.999,-0.695" + id="path2464-4" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,41.232 c 0,0 1.736,0.695 4.518,0.695 2.781,0 3.825,-0.695 3.825,-0.695" + id="path2466-3" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + <g + transform="matrix(0.67030561,0,0,0.64489065,26.201045,29.281238)" + id="activity-journal-7-1" + style="stroke:#000000;stroke-opacity:1;display:block"> + <path + d="M 45.866,44.669 C 45.866,47.18 44.338,49 41.534,49 l -29.457,0 0,-43 29.458,0 c 2.15,0 4.332,2.154 4.332,4.33 l -10e-4,34.339 0,0 z" + id="path2458-4-4" + style="fill:#ffffff;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <line + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + x1="21.341" + x2="21.341" + y1="6.1209998" + y2="48.881001" + id="line2460-5-9" /> + <path + d="m 7.384,14.464 c 0,0 2.084,0.695 4.17,0.695 2.086,0 4.173,-0.695 4.173,-0.695" + id="path2462-2-2" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,28.021 c 0,0 1.912,0.695 4.345,0.695 2.433,0 3.999,-0.695 3.999,-0.695" + id="path2464-5-0" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,41.232 c 0,0 1.736,0.695 4.518,0.695 2.781,0 3.825,-0.695 3.825,-0.695" + id="path2466-4-6" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> + </g> +</svg> diff --git a/images/Cartesian.svg b/images/Cartesian.svg new file mode 100644 index 0000000..7a29e22 --- /dev/null +++ b/images/Cartesian.svg @@ -0,0 +1,211 @@ +<?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="1200" + height="900" + id="svg2"> + <defs + id="defs4" /> + <g + id="layer1"> + <path + d="M 0,850 L 1200,850" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 0,750 L 1200,750" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 0,650 L 1200,650" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 0,550 L 1200,550" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 0,350 L 1200,350" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 0,250 L 1200,250" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 0,150 L 1200,150" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 0,50 L 1200,50" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 1100,0 L 1100,900" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 1000,0 L 1000,900" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 900,0 L 900,900" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 800,0 L 800,900" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 700,0 L 700,900" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 500,0 L 500,900" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 400,0 L 400,900" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 300,0 L 300,900" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 200,0 L 200,900" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 100,0 L 100,900" + style="fill:none;stroke:#AAAAAA;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 590,850 L 610,850" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 590,750 L 610,750" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 590,650 L 610,650" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 590,550 L 610,550" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 0,450 L 1200,450" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 590,350 L 610,350" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 590,250 L 610,250" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 590,150 L 610,150" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 590,50 L 610,50" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 1100,440 L 1100,460" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 1000,440 L 1000,460" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 900,440 L 900,460" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 800,440 L 800,460" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 700,440 L 700,460" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 600,0 L 600,900" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 500,440 L 500,460" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 400,440 L 400,460" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 300,440 L 300,460" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 200,440 L 200,460" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 100,440 L 100,460" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> +<!-- + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#0000FF;fill-opacity:1;stroke:none;text-anchor:middle;text-align:center;font-family:Bitstream Vera Sans"><tspan + x="95" + y="480">–500</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#0000FF;fill-opacity:1;stroke:none;text-anchor:middle;text-align:center;font-family:Bitstream Vera Sans"><tspan + x="195" + y="480">–400</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#0000FF;fill-opacity:1;stroke:none;text-anchor:middle;text-align:center;font-family:Bitstream Vera Sans"><tspan + x="295" + y="480">–300</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#0000FF;fill-opacity:1;stroke:none;text-anchor:middle;text-align:center;font-family:Bitstream Vera Sans"><tspan + x="395" + y="480">–200</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#0000FF;fill-opacity:1;stroke:none;text-anchor:middle;text-align:center;font-family:Bitstream Vera Sans"><tspan + x="495" + y="480">–100</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#0000FF;fill-opacity:1;stroke:none;text-anchor:middle;text-align:center;font-family:Bitstream Vera Sans"><tspan + x="650" + y="480">x</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#0000FF;fill-opacity:1;stroke:none;text-anchor:middle;text-align:center;font-family:Bitstream Vera Sans"><tspan + x="700" + y="480">100</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#0000FF;fill-opacity:1;stroke:none;text-anchor:middle;text-align:center;font-family:Bitstream Vera Sans"><tspan + x="800" + y="480">200</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#0000FF;fill-opacity:1;stroke:none;text-anchor:middle;text-align:center;font-family:Bitstream Vera Sans"><tspan + x="900" + y="480">300</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#0000FF;fill-opacity:1;stroke:none;text-anchor:middle;text-align:center;font-family:Bitstream Vera Sans"><tspan + x="1000" + y="480">400</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#0000FF;fill-opacity:1;stroke:none;text-anchor:middle;text-align:center;font-family:Bitstream Vera Sans"><tspan + x="1100" + y="480">500</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#00AA00;fill-opacity:1;stroke:none;text-anchor:end;text-align:end;font-family:Bitstream Vera Sans"><tspan + x="590" + y="58">400</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#00AA00;fill-opacity:1;stroke:none;text-anchor:end;text-align:end;font-family:Bitstream Vera Sans"><tspan + x="590" + y="158">300</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#00AA00;fill-opacity:1;stroke:none;text-anchor:end;text-align:end;font-family:Bitstream Vera Sans"><tspan + x="590" + y="258">200</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#00AA00;fill-opacity:1;stroke:none;text-anchor:end;text-align:end;font-family:Bitstream Vera Sans"><tspan + x="590" + y="358">100</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#00AA00;fill-opacity:1;stroke:none;text-anchor:end;text-align:end;font-family:Bitstream Vera Sans"><tspan + x="590" + y="408">y</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#00AA00;fill-opacity:1;stroke:none;text-anchor:end;text-align:end;font-family:Bitstream Vera Sans"><tspan + x="590" + y="558">–100</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#00AA00;fill-opacity:1;stroke:none;text-anchor:end;text-align:end;font-family:Bitstream Vera Sans"><tspan + x="590" + y="658">–200</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#00AA00;fill-opacity:1;stroke:none;text-anchor:end;text-align:end;font-family:Bitstream Vera Sans"><tspan + x="590" + y="758">–300</tspan></text> + <text + style="font-size:20px;font-style:normal;font-weight:normal;fill:#00AA00;fill-opacity:1;stroke:none;text-anchor:end;text-align:end;font-family:Bitstream Vera Sans"><tspan + x="590" + y="858">–400</tspan></text> +--> + </g> +</svg> diff --git a/images/Cartesian_labeled.svg b/images/Cartesian_labeled.svg new file mode 100644 index 0000000..e70bb9b --- /dev/null +++ b/images/Cartesian_labeled.svg @@ -0,0 +1,375 @@ +<?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="1200" + height="900" + id="svg2"> + <defs + id="defs4" /> + <g + id="layer1"> + <path + d="m 0,850 1200,0" + id="path5" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,750 1200,0" + id="path7" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,650 1200,0" + id="path9" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,550 1200,0" + id="path11" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,350 1200,0" + id="path13" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,250 1200,0" + id="path15" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,150 1200,0" + id="path17" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,50 1200,0" + id="path19" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 1100,0 0,900" + id="path21" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 1000,0 0,900" + id="path23" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 900,0 0,900" + id="path25" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 800,0 0,900" + id="path27" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 700,0 0,900" + id="path29" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 500,0 0,900" + id="path31" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 400,0 0,900" + id="path33" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 300,0 0,900" + id="path35" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 200,0 0,900" + id="path37" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 100,0 0,900" + id="path39" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,850 20,0" + id="path41" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,750 20,0" + id="path43" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,650 20,0" + id="path45" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,550 20,0" + id="path47" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,450 1200,0" + id="path49" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,350 20,0" + id="path51" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,250 20,0" + id="path53" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,150 20,0" + id="path55" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,50 20,0" + id="path57" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 1100,440 0,20" + id="path59" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 1000,440 0,20" + id="path61" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 900,440 0,20" + id="path63" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 800,440 0,20" + id="path65" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 700,440 0,20" + id="path67" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 600,0 0,900" + id="path69" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 500,440 0,20" + id="path71" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 400,440 0,20" + id="path73" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 300,440 0,20" + id="path75" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 200,440 0,20" + id="path77" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 100,440 0,20" + id="path79" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + </g> + <text + x="603.90137" + y="344.8584" + id="text3218" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="603.90137" + y="344.8584" + id="tspan3220">100</tspan></text> + <text + x="604.26758" + y="244.8584" + id="text3218-8" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="604.26758" + y="244.8584" + id="tspan3220-7">200</tspan></text> + <text + x="604.23828" + y="144.8584" + id="text3218-7" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="604.23828" + y="144.8584" + id="tspan3220-2">300</tspan></text> + <text + x="604.51172" + y="44.858398" + id="text3218-2" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="604.51172" + y="44.858398" + id="tspan3220-26">400</tspan></text> + <text + x="1104.2285" + y="444.8584" + id="text3218-6" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="1104.2285" + y="444.8584" + id="tspan3220-1">500</tspan></text> + <text + x="1004.5117" + y="444.8584" + id="text3218-9" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="1004.5117" + y="444.8584" + id="tspan3220-4">400</tspan></text> + <text + x="904.23828" + y="444.8584" + id="text3218-0" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="904.23828" + y="444.8584" + id="tspan3220-9">300</tspan></text> + <text + x="804.26758" + y="444.8584" + id="text3218-71" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="804.26758" + y="444.8584" + id="tspan3220-15">200</tspan></text> + <text + x="703.90137" + y="444.8584" + id="text3218-76" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="703.90137" + y="444.8584" + id="tspan3220-73">100</tspan></text> + <text + x="469.51172" + y="444.8584" + id="text3218-5" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="469.51172" + y="444.8584" + id="tspan3220-6">–100</tspan></text> + <text + x="369.51172" + y="444.8584" + id="text3218-94" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="369.51172" + y="444.8584" + id="tspan3220-8">–200</tspan></text> + <text + x="269.51172" + y="444.8584" + id="text3218-93" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="269.51172" + y="444.8584" + id="tspan3220-90">–300</tspan></text> + <text + x="169.51172" + y="444.8584" + id="text3218-85" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="169.51172" + y="444.8584" + id="tspan3220-0">–400</tspan></text> + <text + x="69.511719" + y="444.8584" + id="text3218-3" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="69.511719" + y="444.8584" + id="tspan3220-85">–500</tspan></text> + <text + x="571.51172" + y="544.8584" + id="text3218-1" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="571.51172" + y="544.8584" + id="tspan3220-5">–100</tspan></text> + <text + x="571.51172" + y="644.8584" + id="text3218-4" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="571.51172" + y="644.8584" + id="tspan3220-81">–200</tspan></text> + <text + x="571.51172" + y="744.8584" + id="text3218-30" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="571.51172" + y="744.8584" + id="tspan3220-44">–300</tspan></text> + <text + x="571.51172" + y="844.8584" + id="text3218-47" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="571.51172" + y="844.8584" + id="tspan3220-63">–400</tspan></text> + <text + x="604.34082" + y="444.8584" + id="text3218-96" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="604.34082" + y="444.8584" + id="tspan3220-21">0</tspan></text> + <text + x="69.140625" + y="43.681641" + id="text3218-2-7" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="69.140625" + y="43.681641" + id="tspan3220-26-8">(–500, 400)</tspan></text> + <text + x="1074.1406" + y="43.681641" + id="text3218-2-7-5" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="1074.1406" + y="43.681641" + id="tspan3220-26-8-7">(500, 400)</tspan></text> + <text + x="1074.1406" + y="843.68164" + id="text3218-2-7-1" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="1074.1406" + y="843.68164" + id="tspan3220-26-8-8">(500, –400)</tspan></text> + <text + x="69.140625" + y="843.68164" + id="text3218-2-7-1-5" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="69.140625" + y="843.68164" + id="tspan3220-26-8-8-9">(–500, –400)</tspan></text> +</svg> diff --git a/images/amazonas-0.jpg b/images/amazonas-0.jpg Binary files differnew file mode 100644 index 0000000..1b093ab --- /dev/null +++ b/images/amazonas-0.jpg diff --git a/images/amazonas-1.jpg b/images/amazonas-1.jpg Binary files differnew file mode 100644 index 0000000..a05f9d8 --- /dev/null +++ b/images/amazonas-1.jpg diff --git a/images/amazonas-2.jpg b/images/amazonas-2.jpg Binary files differnew file mode 100644 index 0000000..31968cc --- /dev/null +++ b/images/amazonas-2.jpg diff --git a/images/amazonas-3.jpg b/images/amazonas-3.jpg Binary files differnew file mode 100644 index 0000000..5a5c72c --- /dev/null +++ b/images/amazonas-3.jpg diff --git a/images/audiooff.svg b/images/audiooff.svg new file mode 100644 index 0000000..ca89538 --- /dev/null +++ b/images/audiooff.svg @@ -0,0 +1,71 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="60" + height="45" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="94.577461" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7750554,0,0,0.9997979,0.8784441,32.623865)" /> + </defs> + <g + transform="translate(2.625,-5.001)" + id="clipping-audio" + style="display:block"> + <g + id="g2758" + style="display:inline"> + <g + id="g2760"> + <polygon + points="31.874,6.088 43.818,18.027 43.818,48.914 10.932,48.914 10.932,6.088 10.932,6.088 " + id="polygon2762" + style="fill:#ffffff;stroke:#010101;stroke-width:3.5" /> + <polyline + id="polyline2764" + points="43.818,18.027 31.874,18.027 31.874,6.088 " + style="fill:none;stroke:#010101;stroke-width:3.5" /> + </g> + </g> + <path + d="m 28.325,39.697 c -0.511,-1.457 -3.21,-1.073 -4.41,-0.07 -2.4,2.009 -0.424,4.396 2.324,3.277 1.564,-0.638 2.596,-1.748 2.086,-3.207 z" + id="path2766" + style="fill:#010101;stroke:#010101;stroke-width:3.5;display:inline" /> + <line + id="line2768" + y2="26.966999" + y1="39.806" + x2="28.941" + x1="28.941" + display="inline" + style="fill:none;stroke:#010101;stroke-width:2.25;display:inline" /> + <polygon + points="35.047,21.166 35.047,25.036 35.047,25.036 27.838,28.595 27.838,24.728 " + id="polygon2770" + style="fill:#010101;display:inline" /> + </g> +</svg> diff --git a/images/audioon.svg b/images/audioon.svg new file mode 100644 index 0000000..f71bd06 --- /dev/null +++ b/images/audioon.svg @@ -0,0 +1,80 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="60" + height="45" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="94.577461" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7750554,0,0,0.9997979,0.8784441,32.623865)" /> + </defs> + <rect + width="32.5" + height="42.499996" + x="13.75" + y="1.2500019" + id="rect2426" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + transform="translate(-9.372241,-9.2260522)" + id="g3201"> + <path + d="m 36.843,39.696 c -0.511,-1.457 -3.21,-1.073 -4.41,-0.07 -2.4,2.009 -0.424,4.396 2.324,3.277 1.564,-0.638 2.596,-1.748 2.086,-3.207 z" + id="path2766" + style="fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-width:3.5;stroke-opacity:1;display:inline" /> + <line + id="line2768" + y2="26.966" + y1="39.805" + x2="37.459" + x1="37.459" + display="inline" + style="fill:none;stroke:#ff0000;stroke-width:2.25;stroke-opacity:1;display:inline" /> + <polygon + points="35.047,21.166 35.047,25.036 35.047,25.036 27.838,28.595 27.838,24.728 " + transform="translate(8.518,-0.001)" + id="polygon2770" + style="fill:#ff0000;fill-opacity:1;display:inline" /> + <path + d="m 47.25801,34.943896 c -0.511,-1.457 -3.21,-1.073 -4.41,-0.07 -2.4,2.009 -0.424,4.396 2.324,3.277 1.564,-0.638 2.596,-1.748 2.086,-3.207 z" + id="path2412" + style="fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-width:3.5;stroke-opacity:1;display:inline" /> + <line + id="line2414" + y2="21.713896" + y1="34.552895" + x2="47.674007" + x1="47.674007" + display="inline" + style="fill:none;stroke:#ff0000;stroke-width:2.25;stroke-opacity:1;display:inline" /> + <polygon + points="35.047,21.166 35.047,25.036 35.047,25.036 27.838,28.595 27.838,24.728 " + transform="translate(13.73301,-2.653104)" + id="polygon2416" + style="fill:#ff0000;fill-opacity:1;display:inline" /> + </g> +</svg> diff --git a/images/audiosmall.svg b/images/audiosmall.svg new file mode 100644 index 0000000..f922aac --- /dev/null +++ b/images/audiosmall.svg @@ -0,0 +1,71 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="24.37862" + height="31.03842" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="94.577461" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7750554,0,0,0.9997979,0.8784441,32.623865)" /> + </defs> + <g + transform="matrix(0.67,0,0,0.67,-6.15194,-2.90646)" + id="clipping-audio" + style="display:block"> + <g + id="g2758" + style="display:inline"> + <g + id="g2760"> + <polygon + points="43.818,48.914 10.932,48.914 10.932,6.088 10.932,6.088 31.874,6.088 43.818,18.027 " + id="polygon2762" + style="fill:#ffffff;stroke:#010101;stroke-width:3.5" /> + <polyline + id="polyline2764" + points="43.818,18.027 31.874,18.027 31.874,6.088 " + style="fill:none;stroke:#010101;stroke-width:3.5" /> + </g> + </g> + <path + d="m 28.325,39.697 c -0.511,-1.457 -3.21,-1.073 -4.41,-0.07 -2.4,2.009 -0.424,4.396 2.324,3.277 1.564,-0.638 2.596,-1.748 2.086,-3.207 z" + id="path2766" + style="fill:#010101;stroke:#010101;stroke-width:3.5;display:inline" /> + <line + id="line2768" + y2="26.966999" + y1="39.806" + x2="28.941" + x1="28.941" + display="inline" + style="fill:none;stroke:#010101;stroke-width:2.25;display:inline" /> + <polygon + points="35.047,25.036 35.047,25.036 27.838,28.595 27.838,24.728 35.047,21.166 " + id="polygon2770" + style="fill:#010101;display:inline" /> + </g> +</svg> diff --git a/images/cameraoff.svg b/images/cameraoff.svg new file mode 100644 index 0000000..54d9c86 --- /dev/null +++ b/images/cameraoff.svg @@ -0,0 +1,15 @@ +<?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 "#010101"> + <!ENTITY fill_color "#ffffff"> +]><svg enable-background="new 0 0 55 55" height="55px" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="camera-external"> + <g display="inline"> + <g> + <polygon fill="&fill_color;" points="38.532,14.52 34.904,9.862 18.783,9.862 15.155,14.52 6.29,14.52 6.29,38.973 48.209,38.973 48.209,14.52 "/> + </g> + <g> + <polygon fill="none" points="38.532,14.52 34.904,9.862 18.783,9.862 15.155,14.52 6.29,14.52 6.29,38.973 48.209,38.973 48.209,14.52 " stroke="&stroke_color;" stroke-width="3.5"/> + </g> + </g> + <path d="M20.601,26.441c0,3.67,2.979,6.648,6.65,6.648 c3.667,0,6.646-2.979,6.646-6.648c0-3.668-2.979-6.652-6.646-6.652C23.581,19.789,20.601,22.775,20.601,26.441z" display="inline" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5"/> + <rect display="inline" fill="&stroke_color;" height="4.193" width="6.287" x="38.099" y="18.418"/> +</g></svg>
\ No newline at end of file diff --git a/images/camerasmall.svg b/images/camerasmall.svg new file mode 100644 index 0000000..690e940 --- /dev/null +++ b/images/camerasmall.svg @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="26" + height="18.668091" + viewBox="0 0 26 18.668091" + id="svg2" + xml:space="preserve"><metadata + id="metadata29"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs27"> + + + + + + + + + + </defs><g + transform="matrix(0.57244766,0,0,0.57244766,-2.5989125,-4.6436954)" + id="camera-external" + style="display:block"><g + id="g5" + style="display:inline"><g + id="g7"><polygon + points="48.209,14.52 38.532,14.52 34.904,9.862 18.783,9.862 15.155,14.52 6.29,14.52 6.29,38.973 48.209,38.973 " + id="polygon9" + style="fill:#ffffff" /></g><g + id="g11"><polygon + points="48.209,14.52 38.532,14.52 34.904,9.862 18.783,9.862 15.155,14.52 6.29,14.52 6.29,38.973 48.209,38.973 " + id="polygon13" + style="fill:none;stroke:#010101;stroke-width:3.5" /></g></g><path + d="m 20.601,26.441 c 0,3.67 2.979,6.648 6.65,6.648 3.667,0 6.646,-2.979 6.646,-6.648 0,-3.668 -2.979,-6.652 -6.646,-6.652 -3.67,0 -6.65,2.986 -6.65,6.652 z" + id="path15" + style="fill:#ffffff;stroke:#010101;stroke-width:3.5;display:inline" /><rect + width="6.2870002" + height="4.1929998" + x="38.098999" + y="18.417999" + id="rect17" + style="fill:#010101;display:inline" /></g></svg>
\ No newline at end of file diff --git a/images/descriptionoff.svg b/images/descriptionoff.svg new file mode 100644 index 0000000..4966738 --- /dev/null +++ b/images/descriptionoff.svg @@ -0,0 +1,59 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="60" + height="45" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + </defs> + <g + transform="translate(12.75,0.25)" + id="g3040"> + <path + d="m 1.75,43.25 l 0,-42 21,0 10,11 0,31 -31,0 z" + id="path3199" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#00000f;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none" /> + <path + d="m 10,26.25 c 14.5,0 14.5,0 14.5,0" + id="path3163" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,32.25 c 14.5,0 14.5,0 14.5,0" + id="path3165" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,20.25 c 14.5,0 14.5,0 14.5,0" + id="path3167" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 21.5,2.0000001 l 0,10.2499999 9.5,0" + id="path3201" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> +</svg> diff --git a/images/descriptionon.svg b/images/descriptionon.svg new file mode 100644 index 0000000..07edcdd --- /dev/null +++ b/images/descriptionon.svg @@ -0,0 +1,58 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="60" + height="45" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + </defs> + <g + transform="translate(12.750001,-0.25)" + id="g3149"> + <rect + width="30.999998" + height="42" + x="1.75" + y="1.75" + id="rect2391" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,26.75 c 14.5,0 14.5,0 14.5,0" + id="path3163" + style="fill:none;stroke:#ff0000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,32.75 c 14.5,0 14.5,0 14.5,0" + id="path3165" + style="fill:none;stroke:#ff0000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,20.75 c 14.5,0 14.5,0 14.5,0" + id="path3167" + style="fill:none;stroke:#ff0000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> +</svg> diff --git a/images/descriptionsmall.svg b/images/descriptionsmall.svg new file mode 100644 index 0000000..93c52d8 --- /dev/null +++ b/images/descriptionsmall.svg @@ -0,0 +1,59 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="23.115" + height="30.485001" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + </defs> + <g + transform="scale(0.67,0.67)" + id="g2823"> + <path + d="m 1.75,43.75 l 0,-42 21,0 10,11 0,31 -31,0 z" + id="path3199" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#00000f;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none" /> + <path + d="m 10,26.75 c 14.5,0 14.5,0 14.5,0" + id="path3163" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,32.75 c 14.5,0 14.5,0 14.5,0" + id="path3165" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10,20.75 c 14.5,0 14.5,0 14.5,0" + id="path3167" + style="fill:none;stroke:#000000;stroke-width:3.49999976;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 21.5,2.5000001 l 0,10.2499999 9.5,0" + id="path3201" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> +</svg> diff --git a/images/dupstack.svg b/images/dupstack.svg new file mode 100644 index 0000000..6a0f3fd --- /dev/null +++ b/images/dupstack.svg @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="767" + height="38" + id="svg2467"> + <metadata + id="metadata20"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs2493" /> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 3,30 0.5,26.5 0.5,23 l 0,-8 c 0,-3.25 2.5,-8.5 5,-10.5 2.5,-2 6,-4 9.5,-4 l 736.5,0 c 2.5,0 7,1 10.5,4 3.5,2.75 4.5,7.5 4.5,10.5 l 0,8 c 0,3.5 -2,7 -4.5,9.5 -2.5,2.5 -6.5,5 -10.5,5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="m 79.5,438.5 c 0,4.5 -3.75,8 -8.5,8 -4.5,0 -8.25,-3.5 -8.25,-8 0,-4.5 3.75,-8.25 8.25,-8.25 4.75,0 8.5,3.75 8.5,8.25 l 0,0 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <path + d="m 222.97818,18.999999 0,0 -26,15.000001 0,0 0,3 -13.50001,0 0,-3 c 0,0 -26,-15.000001 -26,-15.000001 0,0 33.00001,-17.9999992 33.00001,-17.9999992 0,0 32.5,17.9999992 32.5,17.9999992 z" + id="path2490-6" + style="fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:#c0a000;stroke-width:1.33340001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + x="6.1187973" + y="4.1250014" + id="text2474" + style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="176.1188" + y="32.125" + id="tspan2476" + style="font-size:48px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">x</tspan> + </text> + <g + transform="translate(6,0)" + id="g2478"> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-4,20)" + id="path2480" + style="fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(1,17)" + id="path2482" + style="fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-1,18)" + id="path2484" + style="fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <text + x="6" + id="text2486" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="27" + y="29" + id="tspan2488" + style="font-size:24px">!</tspan> + </text> + <path + d="m 148.5,19 0,0 -26,15 0,0 0,3 -13.5,0 0,-3 c 0,0 -26,-15 -26,-15 0,0 33,-18 33,-18 0,0 32.5,18 32.5,18 z" + id="path2490" + style="fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:#c0a000;stroke-width:1.33340001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/images/emptybox.svg b/images/emptybox.svg new file mode 100644 index 0000000..323cff9 --- /dev/null +++ b/images/emptybox.svg @@ -0,0 +1,356 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="767" + height="38" + id="svg2"> + <defs + id="defs32"> + <linearGradient + x1="0" + y1="0" + x2="64" + y2="0" + id="linearGradient2540" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(34.404412,58.027574)" /> + <linearGradient + id="linearGradient2504"> + <stop + id="stop2506" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2508" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="0" + x2="64" + y2="0" + id="linearGradient2510" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,4.96875)" /> + <linearGradient + x1="210" + y1="10.5" + x2="0" + y2="10.5" + id="linearGradient2512" + xlink:href="#linearGradient3886" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient2514"> + <stop + id="stop2516" + style="stop-color:#0000ff;stop-opacity:1" + offset="0" /> + <stop + id="stop2518" + style="stop-color:#ffffff;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="210" + y1="10.5" + x2="0" + y2="10.5" + id="linearGradient2520" + xlink:href="#linearGradient3886" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="0" + y1="0" + x2="64" + y2="0" + id="linearGradient2522" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,4.96875)" /> + <linearGradient + x1="0" + y1="0" + x2="104" + y2="21" + id="linearGradient2524" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,5.4999997)" /> + <linearGradient + id="linearGradient2492"> + <stop + id="stop2494" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2496" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="0" + x2="104" + y2="21" + id="linearGradient2493" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient2486"> + <stop + id="stop2488" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2490" + style="stop-color:#0000ff;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient2509"> + <stop + id="stop2511" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2513" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="22" + x2="74" + y2="22" + id="linearGradient2515" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="0" + y1="22" + x2="128.68382" + y2="22" + id="linearGradient2608" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient2595"> + <stop + id="stop2597" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2599" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="22" + x2="74" + y2="22" + id="linearGradient2601" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient2473"> + <stop + id="stop2475" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2477" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="0" + x2="64" + y2="0" + id="linearGradient4238" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,4.96875)" /> + <linearGradient + x1="210" + y1="10.5" + x2="0" + y2="10.5" + id="linearGradient4211" + xlink:href="#linearGradient3886" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient3886"> + <stop + id="stop3888" + style="stop-color:#0000ff;stop-opacity:1" + offset="0" /> + <stop + id="stop3890" + style="stop-color:#ffffff;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="210" + y1="10.5" + x2="0" + y2="10.5" + id="linearGradient2496" + xlink:href="#linearGradient3886" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="0" + y1="0" + x2="64" + y2="0" + id="linearGradient2501" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,4.96875)" /> + <linearGradient + x1="0" + y1="22" + x2="128.68382" + y2="22" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="0" + x2="104" + y2="21" + id="linearGradient2539" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient2533"> + <stop + id="stop2535" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2537" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="22" + x2="128.68382" + y2="22" + id="linearGradient2543" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.75,0,0,0.75,160.75,11.125)" /> + </defs> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 C 3,30 0.5,26.5 0.5,23 L 0.5,15 C 0.5,11.75 3,6.5 5.5,4.5 C 8,2.5 11.5,0.5 15,0.5 L 751.5,0.5 C 754,0.5 758.5,1.5 762,4.5 C 765.5,7.25 766.5,12 766.5,15 L 766.5,23 C 766.5,26.5 764.5,30 762,32.5 C 759.5,35 755.5,37.5 751.5,37.5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="M 79.5,438.5 C 79.5,443 75.75,446.5 71,446.5 C 66.5,446.5 62.75,443 62.75,438.5 C 62.75,434 66.5,430.25 71,430.25 C 75.75,430.25 79.5,434 79.5,438.5 L 79.5,438.5 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <g + transform="translate(6,0)" + id="g17"> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-4,20)" + id="path19" + style="opacity:1;fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(1,17)" + id="path21" + style="opacity:1;fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-1,18)" + id="path23" + style="opacity:1;fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <text + x="6" + id="text25" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"> + <tspan + x="27" + y="29" + id="tspan27" + style="font-size:24px">!</tspan> + </text> + <g + transform="matrix(0.75,0,0,0.75,63.573764,3.5)" + id="g2611"> + <g + transform="translate(59.878677,45.67647)" + id="g2533"> + <path + d="M 64.871323,-38.92647 L 81.371323,-38.92647 L 81.371323,-32.92647 L 77.371323,-32.92647 L 77.371323,-35.92647 L 66.871323,-35.92647" + id="path2493" + style="fill:#e0e000;fill-opacity:1;stroke:#a08000;stroke-width:1.5;stroke-opacity:1" /> + <path + d="M 64.871323,-11.42647 L 81.371323,-11.42647 L 81.371323,-17.42647 L 77.371323,-17.42647 L 77.371323,-14.42647 L 66.871323,-14.42647" + id="path2495" + style="fill:#e0e000;fill-opacity:1;stroke:#908000;stroke-width:1.5;stroke-opacity:1" /> + </g> + <path + d="M 47,1 C 63,1 120,1 120,1 C 120,1 124.1318,3.4865526 125.5,5 C 126.89747,6.5458243 129,11 129,11 L 129,30 C 129,30 126.78295,33.693654 125.5,35 C 124.07044,36.455629 120,39 120,39 L 47,39 L 47,39 L 47,43 L 27,43 L 27,39 L 10,39 C 10,39 5.9295605,36.455629 4.5,35 C 3.2170498,33.693654 1,30 1,30 L 1,11 C 1,11 3.1025283,6.5458243 4.5,5 C 5.8682021,3.4865526 10,1 10,1 L 27,1 L 27,6 L 47,6 L 47,1 z" + id="path10" + style="fill:url(#linearGradient3172);fill-opacity:1;stroke:#c0a000;stroke-width:2;stroke-opacity:1" /> + <path + d="M 13,12 L 18,12 L 18,16 L 24.999999,16 L 24.999999,12 L 116.50001,12 L 116.50001,32 L 24.999999,32 L 24.999999,28 L 18,28 L 18,32 L 13,32 L 13,12 z" + id="path9" + style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-opacity:1" /> + </g> + <text + x="95.277344" + y="29" + id="text2618" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"><tspan + x="95.277344" + y="29" + id="tspan2620" + style="font-size:24px;fill:#ff0000;fill-opacity:1">???</tspan></text> + <path + d="M 161.5,11.5 L 165.25,11.5 L 165.25,14.5 L 170.5,14.5 L 170.5,11.5 L 239.125,11.5 L 239.125,26.5 L 170.5,26.5 L 170.5,23.5 L 165.25,23.5 L 165.25,26.5 L 161.5,26.5 L 161.5,11.5 z" + id="path2541" + style="fill:url(#linearGradient2543);fill-opacity:1;stroke:none;stroke-width:2;stroke-opacity:1" /> +</svg> diff --git a/images/emptyheap.svg b/images/emptyheap.svg new file mode 100644 index 0000000..8ad93ef --- /dev/null +++ b/images/emptyheap.svg @@ -0,0 +1,73 @@ +<?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="767" + height="38" + id="svg2"> + <defs + id="defs32" /> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 C 3,30 0.5,26.5 0.5,23 L 0.5,15 C 0.5,11.75 3,6.5 5.5,4.5 C 8,2.5 11.5,0.5 15,0.5 L 751.5,0.5 C 754,0.5 758.5,1.5 762,4.5 C 765.5,7.25 766.5,12 766.5,15 L 766.5,23 C 766.5,26.5 764.5,30 762,32.5 C 759.5,35 755.5,37.5 751.5,37.5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="M 79.5,438.5 C 79.5,443 75.75,446.5 71,446.5 C 66.5,446.5 62.75,443 62.75,438.5 C 62.75,434 66.5,430.25 71,430.25 C 75.75,430.25 79.5,434 79.5,438.5 L 79.5,438.5 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <text + x="-108" + id="text13" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"> + <tspan + x="62" + y="28" + id="tspan15" + style="font-size:24px">[]</tspan> + </text> + <g + transform="translate(6,0)" + id="g17"> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-4,20)" + id="path19" + style="opacity:1;fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(1,17)" + id="path21" + style="opacity:1;fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-1,18)" + id="path23" + style="opacity:1;fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <text + x="6" + id="text25" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"> + <tspan + x="27" + y="29" + id="tspan27" + style="font-size:24px">!</tspan> + </text> +</svg> diff --git a/images/fileoff.svg b/images/fileoff.svg new file mode 100644 index 0000000..d19b61e --- /dev/null +++ b/images/fileoff.svg @@ -0,0 +1,67 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="60" + height="45" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172-9" + xlink:href="#linearGradient3166-6" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + id="linearGradient3166-6"> + <stop + id="stop3168-5" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170-6" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + </defs> + <g + transform="matrix(1.33,0,0,1.33,11.38,0.3488486)" + id="g3675"> + <path + d="m 27,27.08073 c 0,1.68237 -1.12132,3.074271 -3,3.074271 l -23,0 0,-26.9999999 8.8039216,0 1.6960784,2 15.5,0 0,21.9257289 0,0 z" + id="path2458-4" + style="fill:#ffffff;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 27,27.08073 c 0,1.68237 -1.12132,3.074271 -3,3.074271 l -23,0 0,-17 8.4852943,0 L 11.5,9.1550006 l 15.5,0 0,17.9257294 0,0 z" + id="path2458" + style="fill:#ffffff;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> +</svg> diff --git a/images/fileon.svg b/images/fileon.svg new file mode 100644 index 0000000..f718dbc --- /dev/null +++ b/images/fileon.svg @@ -0,0 +1,63 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="60" + height="45" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172-9" + xlink:href="#linearGradient3166-6" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + id="linearGradient3166-6"> + <stop + id="stop3168-5" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170-6" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + </defs> + <path + d="m 43.29,36.366219 c 0,2.237553 -1.491356,4.088781 -3.99,4.088781 l -30.5900003,0 0,-35.9099999 11.7092153,0 2.255785,2.66 20.615,0 0,29.1612189 0,0 z" + id="path2458-4" + style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:2.66000009;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 43.29,36.366219 c 0,2.237553 -1.491356,4.088781 -3.99,4.088781 l -30.5900003,0 8.0000003,-18.61 11.285441,0 2.679559,-5.320001 20.615,0 -8,19.84122 0,0 z" + id="path2458" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.66000009;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/images/filesmall.svg b/images/filesmall.svg new file mode 100644 index 0000000..a259ac0 --- /dev/null +++ b/images/filesmall.svg @@ -0,0 +1,43 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="28.128611" + height="31.155001" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + </defs> + <path + d="m 27,27.08073 c 0,1.68237 -1.12132,3.074271 -3,3.074271 l -23,0 0,-26.9999999 8.8039216,0 1.6960784,2 15.5,0 0,21.9257289 0,0 z" + id="path2458-4" + style="fill:#ffffff;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 27,27.08073 c 0,1.68237 -1.12132,3.074271 -3,3.074271 l -23,0 0,-17 8.4852943,0 L 11.5,9.1550006 l 15.5,0 0,17.9257294 0,0 z" + id="path2458" + style="fill:#ffffff;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/images/help.svg b/images/help.svg new file mode 100644 index 0000000..3281351 --- /dev/null +++ b/images/help.svg @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="767" + height="38" + id="svg2"> + <metadata + id="metadata17"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs27" /> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 3,30 0.5,26.5 0.5,23 l 0,-8 c 0,-3.25 2.5,-8.5 5,-10.5 2.5,-2 6,-4 9.5,-4 l 736.5,0 c 2.5,0 7,1 10.5,4 3.5,2.75 4.5,7.5 4.5,10.5 l 0,8 c 0,3.5 -2,7 -4.5,9.5 -2.5,2.5 -6.5,5 -10.5,5 L 15,37.5 z" + id="path4" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#e0e0e0;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="m 79.5,438.5 c 0,4.5 -3.75,8 -8.5,8 -4.5,0 -8.25,-3.5 -8.25,-8 0,-4.5 3.75,-8.25 8.25,-8.25 4.75,0 8.5,3.75 8.5,8.25 l 0,0 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> +</svg> diff --git a/images/help1200.svg b/images/help1200.svg new file mode 100644 index 0000000..a284973 --- /dev/null +++ b/images/help1200.svg @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="1167" + height="38" + id="svg2"> + <metadata + id="metadata17"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs27" /> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 3,30 0.5,26.5 0.5,23 l 0,-8 c 0,-3.25 2.5,-8.5 5,-10.5 2.5,-2 6,-4 9.5,-4 l 1136.5,0 c 2.5,0 7,1 10.5,4 3.5,2.75 4.5,7.5 4.5,10.5 l 0,8 c 0,3.5 -2,7 -4.5,9.5 -2.5,2.5 -6.5,5 -10.5,5 z" + id="path4" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#e0e0e0;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(1053.75,65.625)" + id="g6"> + <path + d="m 79.5,438.5 c 0,4.5 -3.75,8 -8.5,8 -4.5,0 -8.25,-3.5 -8.25,-8 0,-4.5 3.75,-8.25 8.25,-8.25 4.75,0 8.5,3.75 8.5,8.25 l 0,0 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> +</svg> diff --git a/images/incompatible.svg b/images/incompatible.svg new file mode 100644 index 0000000..433bf4d --- /dev/null +++ b/images/incompatible.svg @@ -0,0 +1,381 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="767" + height="38" + id="svg2"> + <metadata + id="metadata73"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs32"> + <linearGradient + x1="0" + y1="0" + x2="64" + y2="0" + id="linearGradient2540" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(34.404412,58.027574)" /> + <linearGradient + id="linearGradient2504"> + <stop + id="stop2506" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2508" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="0" + x2="64" + y2="0" + id="linearGradient2510" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,4.96875)" /> + <linearGradient + x1="210" + y1="10.5" + x2="0" + y2="10.5" + id="linearGradient2512" + xlink:href="#linearGradient3886" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient2514"> + <stop + id="stop2516" + style="stop-color:#0000ff;stop-opacity:1" + offset="0" /> + <stop + id="stop2518" + style="stop-color:#ffffff;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="210" + y1="10.5" + x2="0" + y2="10.5" + id="linearGradient2520" + xlink:href="#linearGradient3886" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="0" + y1="0" + x2="64" + y2="0" + id="linearGradient2522" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,4.96875)" /> + <linearGradient + x1="0" + y1="0" + x2="104" + y2="21" + id="linearGradient2524" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,5.4999997)" /> + <linearGradient + id="linearGradient2492"> + <stop + id="stop2494" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2496" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="0" + x2="104" + y2="21" + id="linearGradient2493" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient2486"> + <stop + id="stop2488" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2490" + style="stop-color:#0000ff;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient2509"> + <stop + id="stop2511" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2513" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="22" + x2="74" + y2="22" + id="linearGradient2515" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="0" + y1="22" + x2="128.68382" + y2="22" + id="linearGradient2608" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient2595"> + <stop + id="stop2597" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2599" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="22" + x2="74" + y2="22" + id="linearGradient2601" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient2473"> + <stop + id="stop2475" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2477" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="0" + x2="64" + y2="0" + id="linearGradient4238" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,4.96875)" /> + <linearGradient + x1="210" + y1="10.5" + x2="0" + y2="10.5" + id="linearGradient4211" + xlink:href="#linearGradient3886" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient3886"> + <stop + id="stop3888" + style="stop-color:#0000ff;stop-opacity:1" + offset="0" /> + <stop + id="stop3890" + style="stop-color:#ffffff;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="210" + y1="10.5" + x2="0" + y2="10.5" + id="linearGradient2496" + xlink:href="#linearGradient3886" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="0" + y1="0" + x2="64" + y2="0" + id="linearGradient2501" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,4.96875)" /> + <linearGradient + x1="0" + y1="22" + x2="128.68382" + y2="22" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ff0000;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="0" + x2="104" + y2="21" + id="linearGradient2539" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient2533"> + <stop + id="stop2535" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2537" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="22" + x2="128.68382" + y2="22" + id="linearGradient2543" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.75,0,0,0.75,79.98708,11.125)" /> + <linearGradient + x1="0" + y1="22" + x2="128.68382" + y2="22" + id="linearGradient2543-4" + xlink:href="#linearGradient3166-4" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.75,0,0,0.75,160.75,11.125)" /> + <linearGradient + id="linearGradient3166-4"> + <stop + id="stop3168-3" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170-0" + style="stop-color:#ff0000;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="22" + x2="128.68382" + y2="22" + id="linearGradient3833" + xlink:href="#linearGradient3166-4" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.75,0,0,0.75,207.68104,11.125001)" /> + </defs> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 3,30 0.5,26.5 0.5,23 l 0,-8 c 0,-3.25 2.5,-8.5 5,-10.5 2.5,-2 6,-4 9.5,-4 l 736.5,0 c 2.5,0 7,1 10.5,4 3.5,2.75 4.5,7.5 4.5,10.5 l 0,8 c 0,3.5 -2,7 -4.5,9.5 -2.5,2.5 -6.5,5 -10.5,5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="m 79.5,438.5 c 0,4.5 -3.75,8 -8.5,8 -4.5,0 -8.25,-3.5 -8.25,-8 0,-4.5 3.75,-8.25 8.25,-8.25 4.75,0 8.5,3.75 8.5,8.25 l 0,0 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <g + transform="translate(6,0)" + id="g17"> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-4,20)" + id="path19" + style="fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(1,17)" + id="path21" + style="fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-1,18)" + id="path23" + style="fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <text + x="6" + id="text25" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="27" + y="29" + id="tspan27" + style="font-size:24px">!</tspan> + </text> + <text + x="176.34187" + y="25.5625" + id="text2618" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"><tspan + x="176.34187" + y="25.5625" + id="tspan2620" + style="font-size:24px;fill:#ff0000;fill-opacity:1">x</tspan></text> + <path + d="m 80.73708,11.5 3.75,0 0,3 5.25,0 0,-3 68.625,0 0,15 -68.625,0 0,-3 -5.25,0 0,3 -3.75,0 0,-15 z" + id="path2541" + style="fill:url(#linearGradient2543);fill-opacity:1;stroke:#ff0000;stroke-width:2;stroke-opacity:1" /> + <path + d="m 208.43104,11.500001 3.75,0 0,2.999999 5.25,0 0,-2.999999 68.625,0 0,14.999999 -68.625,0 0,-3 -5.25,0 0,3 -3.75,0 0,-14.999999 z" + id="path2541-7" + style="fill:url(#linearGradient3833);fill-opacity:1;stroke:#ff0000;stroke-width:2;stroke-opacity:1" /> +</svg> diff --git a/images/info.svg b/images/info.svg new file mode 100644 index 0000000..3b32b93 --- /dev/null +++ b/images/info.svg @@ -0,0 +1,35 @@ +<?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="240" + height="360" + id="svg2"> + <defs + id="defs27" /> + <path + d="m 1.0120134,358.98799 c 0,0 0,-357.9759766 0,-357.9759766 l 237.9759766,0 c 0,0 0,357.9759766 0,357.9759766 l -237.9759766,0 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:2.02402687px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(129.51998,60.625002)" + id="g6"> + <path + d="m 79.5,438.5 c 0,4.5 -3.75,8 -8.5,8 -4.5,0 -8.25,-3.5 -8.25,-8 0,-4.5 3.75,-8.25 8.25,-8.25 4.75,0 8.5,3.75 8.5,8.25 l 0,0 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> +</svg> diff --git a/images/journaloff.svg b/images/journaloff.svg new file mode 100644 index 0000000..7123f98 --- /dev/null +++ b/images/journaloff.svg @@ -0,0 +1,63 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="60" + height="45" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + </defs> + <g + transform="translate(3.3745,-5)" + id="activity-journal" + style="stroke:#000000;stroke-opacity:1;display:block"> + <path + d="M 45.866,44.669 C 45.866,47.18 44.338,49 41.534,49 l -29.457,0 0,-43 29.458,0 c 2.15,0 4.332,2.154 4.332,4.33 l -10e-4,34.339 0,0 z" + id="path2458" + style="fill:#ffffff;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <line + id="line2460" + y2="48.881001" + y1="6.1209998" + x2="21.341" + x1="21.341" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,14.464 c 0,0 2.084,0.695 4.17,0.695 2.086,0 4.173,-0.695 4.173,-0.695" + id="path2462" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,28.021 c 0,0 1.912,0.695 4.345,0.695 2.433,0 3.999,-0.695 3.999,-0.695" + id="path2464" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,41.232 c 0,0 1.736,0.695 4.518,0.695 2.781,0 3.825,-0.695 3.825,-0.695" + id="path2466" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> +</svg> diff --git a/images/journalon.svg b/images/journalon.svg new file mode 100644 index 0000000..1cac534 --- /dev/null +++ b/images/journalon.svg @@ -0,0 +1,62 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="60" + height="45" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + </defs> + <path + d="m 17.066502,43.917067 24.519997,0 c 2.225,0 3.439,-1.447 3.439,-3.441 l 0,-27.28 c 0,-1.73 -1.732,-3.4410005 -3.439,-3.4410005 l -4.388997,0" + id="path2999" + style="fill:#ff0000;fill-opacity:1;stroke:#010101;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" /> + <path + d="m 37.197502,33.507067 c 0,1.836 -1.345,3.201 -3.441,4.047 l -16.69,6.363 0,-34.1620005 16.69,-8.5990001 c 2.228,-0.39399999 3.441,0.8400001 3.441,2.8340001 l 0,29.5170005 z" + id="path3005" + style="fill:#ffffff;fill-opacity:1;stroke:#010101;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" /> + <path + d="m 19.754502,37.522067 c 0,0 -1.351,-0.543 -2.702,-0.543 -1.351,0 -2.703,0.543 -2.703,0.543" + id="path3007" + style="fill:none;stroke:#010101;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round" /> + <path + d="m 19.754502,26.921067 c 0,0 -1.239,-0.543 -2.815,-0.543 -1.577,0 -2.59,0.543 -2.59,0.543" + id="path3009" + style="fill:none;stroke:#010101;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round" /> + <path + d="m 19.754502,16.593067 c 0,0 -1.125,-0.544 -2.927,-0.544 -1.802,0 -2.478,0.544 -2.478,0.544" + id="path3011" + style="fill:none;stroke:#010101;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round" /> + <line + id="line3013" + y2="6.4200654" + y1="41.448067" + x2="23.539497" + x1="23.539497" + style="fill:none;stroke:#010101;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round" /> +</svg> diff --git a/images/journalsmall.svg b/images/journalsmall.svg new file mode 100644 index 0000000..5b93089 --- /dev/null +++ b/images/journalsmall.svg @@ -0,0 +1,63 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="28.128611" + height="31.155001" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + </defs> + <g + transform="matrix(0.67,0,0,0.67,-3.77478,-2.8475)" + id="activity-journal" + style="stroke:#000000;stroke-opacity:1;display:block"> + <path + d="M 45.866,44.669 C 45.866,47.18 44.338,49 41.534,49 l -29.457,0 0,-43 29.458,0 c 2.15,0 4.332,2.154 4.332,4.33 l -10e-4,34.339 0,0 z" + id="path2458" + style="fill:#ffffff;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <line + id="line2460" + y2="48.881001" + y1="6.1209998" + x2="21.341" + x1="21.341" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,14.464 c 0,0 2.084,0.695 4.17,0.695 2.086,0 4.173,-0.695 4.173,-0.695" + id="path2462" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,28.021 c 0,0 1.912,0.695 4.345,0.695 2.433,0 3.999,-0.695 3.999,-0.695" + id="path2464" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,41.232 c 0,0 1.736,0.695 4.518,0.695 2.781,0 3.825,-0.695 3.825,-0.695" + id="path2466" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> +</svg> diff --git a/images/list.svg b/images/list.svg new file mode 100644 index 0000000..f6cd83b --- /dev/null +++ b/images/list.svg @@ -0,0 +1,66 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="23.115" + height="30.485001" + id="svg2"> + <defs + id="defs5"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + </defs> + <path + d="m 1.1725,29.3125 0,-28.14 20.77,-4.994e-4 0,28.1404994 -20.77,0 z" + id="path3199" + style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#00000f;stroke-width:2.34500003;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.94117647;stroke-dasharray:none" /> + <path + d="m 10.163613,13.9225 c 6.445974,0 6.445974,0 6.445974,0" + id="path3163" + style="fill:none;stroke:#000000;stroke-width:1.95582581;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10.163613,18.137087 c 6.445974,0 6.445974,0 6.445974,0" + id="path3165" + style="fill:none;stroke:#000000;stroke-width:1.95582581;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 10.163613,9.707913 c 6.445974,0 6.445974,0 6.445974,0" + id="path3167" + style="fill:none;stroke:#000000;stroke-width:1.95582581;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -8.0732694,14.864066 a 1.0091586,0.90403795 0 1 1 -2.0183176,0 1.0091586,0.90403795 0 1 1 2.0183176,0 z" + transform="matrix(0.44960373,0,0,0.50188322,10.685073,2.2478876)" + id="path2850" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.29999995;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -8.0732694,14.864066 a 1.0091586,0.90403795 0 1 1 -2.0183176,0 1.0091586,0.90403795 0 1 1 2.0183176,0 z" + transform="matrix(0.44960373,0,0,0.50188322,10.685073,10.677062)" + id="path2850-6" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.29999995;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m -8.0732694,14.864066 a 1.0091586,0.90403795 0 1 1 -2.0183176,0 1.0091586,0.90403795 0 1 1 2.0183176,0 z" + transform="matrix(0.44960373,0,0,0.50188322,10.685073,6.462475)" + id="path2850-69" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.29999995;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> +</svg> diff --git a/images/metric.svg b/images/metric.svg new file mode 100644 index 0000000..33f6d3d --- /dev/null +++ b/images/metric.svg @@ -0,0 +1,489 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="1200" + height="900" + id="svg2"> + <metadata + id="metadata91"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs4" /> + <path + d="m 0,764.8 1200,0" + id="path5" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,686.1 1200,0" + id="path7" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,607.4 1200,0" + id="path9" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,528.7 1200,0" + id="path11" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,371.3 1200,0" + id="path13" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,292.6 1200,0" + id="path15" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,213.9 1200,0" + id="path17" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,135.2 1200,0" + id="path19" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 993.5,0 0,900" + id="path21" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 914.8,0 0,900" + id="path23" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 836.1,0 0,900" + id="path25" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 757.4,0 0,900" + id="path27" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 678.7,0 0,900" + id="path29" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 521.3,0 0,900" + id="path31" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 442.6,0 0,900" + id="path33" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 363.9,0 0,900" + id="path35" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 285.2,0 0,900" + id="path37" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 206.5,0 0,900" + id="path39" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,764.8 20,0" + id="path41" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,686.1 20,0" + id="path43" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,607.4 20,0" + id="path45" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,528.7 20,0" + id="path47" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,450 1200,0" + id="path49" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,371.3 20,0" + id="path51" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,292.6 20,0" + id="path53" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,213.9 20,0" + id="path55" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 0,56.5 1200,0" + id="path19-8" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,56.5 20,0" + id="path57" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 600,0 0,900" + id="path69" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="603.90137" + y="365.79999" + id="text3218" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="603.90137" + y="365.79999" + id="tspan3220">1</tspan></text> + <text + x="604.26758" + y="287.10001" + id="text3218-8" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="604.26758" + y="287.10001" + id="tspan3220-7">2</tspan></text> + <text + x="604.23828" + y="208.25839" + id="text3218-7" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="604.23828" + y="208.25839" + id="tspan3220-2">3</tspan></text> + <text + x="604.51172" + y="51" + id="text3218-2" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="604.51172" + y="51" + id="tspan3220-26">5</tspan></text> + <path + d="m 993.5,440 0,20" + id="path59" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="997.72852" + y="444.8584" + id="text3218-6" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="997.72852" + y="444.8584" + id="tspan3220-1">5</tspan></text> + <path + d="m 914.8,440 0,20" + id="path61" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="919.31171" + y="444.8584" + id="text3218-9" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="919.31171" + y="444.8584" + id="tspan3220-4">4</tspan></text> + <path + d="m 836.1,440 0,20" + id="path63" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="840.33826" + y="444.8584" + id="text3218-0" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="840.33826" + y="444.8584" + id="tspan3220-9">3</tspan></text> + <path + d="m 757.4,440 0,20" + id="path65" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="761.6676" + y="444.8584" + id="text3218-71" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="761.6676" + y="444.8584" + id="tspan3220-15">2</tspan></text> + <path + d="m 678.7,440 0,20" + id="path67" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="682.60138" + y="444.8584" + id="text3218-76" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="682.60138" + y="444.8584" + id="tspan3220-73">1</tspan></text> + <path + d="m 521.3,440 0,20" + id="path71" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="506.81171" + y="444.8584" + id="text3218-5" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="506.81171" + y="444.8584" + id="tspan3220-6">–1</tspan></text> + <path + d="m 442.6,440 0,20" + id="path73" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="428.11172" + y="444.8584" + id="text3218-94" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="428.11172" + y="444.8584" + id="tspan3220-8">–2</tspan></text> + <path + d="m 363.9,440 0,20" + id="path75" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="349.41171" + y="444.8584" + id="text3218-93" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="349.41171" + y="444.8584" + id="tspan3220-90">–3</tspan></text> + <path + d="m 285.2,440 0,20" + id="path77" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="270.71173" + y="444.8584" + id="text3218-85" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="270.71173" + y="444.8584" + id="tspan3220-0">–4</tspan></text> + <text + x="583.51172" + y="540.8584" + id="text3218-1" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="583.51172" + y="540.8584" + id="tspan3220-5">–1</tspan></text> + <text + x="583.51172" + y="618.8584" + id="text3218-4" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="583.51172" + y="618.8584" + id="tspan3220-81">–2</tspan></text> + <text + x="583.51172" + y="698.8584" + id="text3218-30" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="583.51172" + y="698.8584" + id="tspan3220-44">–3</tspan></text> + <text + x="583.51172" + y="776.8584" + id="text3218-47" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="583.51172" + y="776.8584" + id="tspan3220-63">–4</tspan></text> + <text + x="604.34082" + y="444.8584" + id="text3218-96" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="604.34082" + y="444.8584" + id="tspan3220-21">0</tspan></text> + <text + x="15.140625" + y="51.681641" + id="text3218-2-7" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="15.140625" + y="51.681641" + id="tspan3220-26-8">(–7, 5)</tspan></text> + <text + x="1154.1406" + y="51.681641" + id="text3218-2-7-5" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="1154.1406" + y="51.681641" + id="tspan3220-26-8-7">(7, 5)</tspan></text> + <text + x="1154.1406" + y="839.68164" + id="text3218-2-7-1" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="1154.1406" + y="839.68164" + id="tspan3220-26-8-8">(7, –5)</tspan></text> + <text + x="9.140625" + y="853.68164" + id="text3218-2-7-1-5" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="9.140625" + y="853.68164" + id="tspan3220-26-8-8-9">(–7, –5)</tspan></text> + <path + d="m 0,843.5 1200,0" + id="path5-7" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 590,135.2 20,0" + id="path57-8" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="604.51172" + y="130.0584" + id="text3218-2-5" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="604.51172" + y="130.0584" + id="tspan3220-26-3">4</tspan></text> + <path + d="m 590,843.5 20,0" + id="path41-6" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="583.51172" + y="856.74347" + id="text3218-47-2" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="583.51172" + y="856.74347" + id="tspan3220-63-0">–5</tspan></text> + <path + d="m 1072.2,0 0,900" + id="path21-1" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 1150.9,0 0,900" + id="path21-1-1" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 127.8,0 0,900" + id="path39-3" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 127.8,440 0,20" + id="path79" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="113.31172" + y="444.8584" + id="text3218-3" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="113.31172" + y="444.8584" + id="tspan3220-85">–6</tspan></text> + <path + d="m 49.1,0 0,900" + id="path39-3-8" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="m 1072.2,440 0,20" + id="path59-9" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="1076.4286" + y="444.8584" + id="text3218-6-6" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="1076.4286" + y="444.8584" + id="tspan3220-1-5">6</tspan></text> + <path + d="m 1150.9,439.99999 0,20" + id="path59-5" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="1155.1285" + y="444.8584" + id="text3218-6-3" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="1155.1285" + y="444.8584" + id="tspan3220-1-8">7</tspan></text> + <path + d="m 206.5,440 0,20" + id="path79-4" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="192.01172" + y="444.8584" + id="text3218-3-1" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="192.01172" + y="444.8584" + id="tspan3220-85-9">–5</tspan></text> + <path + d="m 49.1,440.00001 0,20" + id="path79-3" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-opacity:1" /> + <text + x="34.611721" + y="444.8584" + id="text3218-3-6" + xml:space="preserve" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans"><tspan + x="34.611721" + y="444.8584" + id="tspan3220-85-4">–7</tspan></text> +</svg> diff --git a/images/negroot.svg b/images/negroot.svg new file mode 100644 index 0000000..43b6eb1 --- /dev/null +++ b/images/negroot.svg @@ -0,0 +1,74 @@ +<?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="767" + height="38" + id="svg2"> + <defs + id="defs32" /> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 3,30 0.5,26.5 0.5,23 l 0,-8 c 0,-3.25 2.5,-8.5 5,-10.5 2.5,-2 6,-4 9.5,-4 l 736.5,0 c 2.5,0 7,1 10.5,4 3.5,2.75 4.5,7.5 4.5,10.5 l 0,8 c 0,3.5 -2,7 -4.5,9.5 -2.5,2.5 -6.5,5 -10.5,5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="m 79.5,438.5 c 0,4.5 -3.75,8 -8.5,8 -4.5,0 -8.25,-3.5 -8.25,-8 0,-4.5 3.75,-8.25 8.25,-8.25 4.75,0 8.5,3.75 8.5,8.25 l 0,0 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <text + x="-108" + id="text13" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="62" + y="28" + id="tspan15" + style="font-size:24px">√–1</tspan> + </text> + <g + transform="translate(6,0)" + id="g17"> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-4,20)" + id="path19" + style="fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(1,17)" + id="path21" + style="fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-1,18)" + id="path23" + style="fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <text + x="6" + id="text25" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="27" + y="29" + id="tspan27" + style="font-size:24px">!</tspan> + </text> +</svg> diff --git a/images/nocode.svg b/images/nocode.svg new file mode 100644 index 0000000..6c71f30 --- /dev/null +++ b/images/nocode.svg @@ -0,0 +1,125 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="767" + height="38" + id="svg2"> + <defs + id="defs41"> + <linearGradient + id="linearGradient2492"> + <stop + id="stop2494" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop2496" + style="stop-color:#ff0000;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient2508" + xlink:href="#linearGradient2492" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.4746037,0,0,0.6708419,62.671562,26.937823)" /> + </defs> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 C 3,30 0.5,26.5 0.5,23 L 0.5,15 C 0.5,11.75 3,6.5 5.5,4.5 C 8,2.5 11.5,0.5 15,0.5 L 751.5,0.5 C 754,0.5 758.5,1.5 762,4.5 C 765.5,7.25 766.5,12 766.5,15 L 766.5,23 C 766.5,26.5 764.5,30 762,32.5 C 759.5,35 755.5,37.5 751.5,37.5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="M 79.5,438.5 C 79.5,443 75.75,446.5 71,446.5 C 66.5,446.5 62.75,443 62.75,438.5 C 62.75,434 66.5,430.25 71,430.25 C 75.75,430.25 79.5,434 79.5,438.5 L 79.5,438.5 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <text + id="text13" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="128" + y="28" + id="tspan26" + style="font-size:24px">???</tspan> + </text> + <g + transform="translate(6,0)" + id="g28"> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-4,20)" + id="path30" + style="opacity:1;fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(1,17)" + id="path32" + style="opacity:1;fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-1,18)" + id="path34" + style="opacity:1;fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <text + x="6" + id="text20" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="27" + y="29" + id="tspan22" + style="font-size:24px">!</tspan> + </text> + <path + d="M 109.48191,9.094338 L 120.53691,9.094338 L 120.53691,13.114338 L 117.85691,13.114338 L 117.85691,11.104338 L 110.82191,11.104338" + id="path10" + style="fill:#e00000;fill-opacity:1;stroke:#800000;stroke-width:1.5;stroke-opacity:1" /> + <path + d="M 109.48191,27.519338 L 120.53691,27.519338 L 120.53691,23.499338 L 117.85691,23.499338 L 117.85691,25.509338 L 110.82191,25.509338" + id="path12" + style="fill:#e00000;fill-opacity:1;stroke:#800000;stroke-width:1.5;stroke-opacity:1" /> + <path + d="M 94.74191,5.744338 C 105.46191,5.744338 105.46191,5.744338 105.46191,5.744338 C 105.46191,5.744338 108.23021,7.4103282 109.14691,8.424338 C 110.08322,9.4600403 111.49191,12.444338 111.49191,12.444338 L 111.49191,25.174338 C 111.49191,25.174338 110.00649,27.649086 109.14691,28.524338 C 108.1891,29.499609 105.46191,31.204338 105.46191,31.204338 L 94.07191,31.204338 L 94.07191,31.204338 L 94.07191,33.884338 L 80.67191,33.884338 L 80.67191,31.204338 L 69.28191,31.204338 C 69.28191,31.204338 66.554716,29.499609 65.59691,28.524338 C 64.737333,27.649086 63.25191,25.174338 63.25191,25.174338 L 63.25191,12.444338 C 63.25191,12.444338 64.660604,9.4600403 65.59691,8.424338 C 66.513605,7.4103282 69.28191,5.744338 69.28191,5.744338 L 80.00191,5.744338 L 80.00191,9.094338 L 94.74191,9.094338 L 94.74191,5.744338 z" + id="path14" + style="fill:url(#linearGradient2508);fill-opacity:1;stroke:#a00000;stroke-width:1.99999988;stroke-opacity:1" /> + <g + transform="matrix(0.75,0,0,0.75,60.994782,-2.8023809)" + id="g2503"> + <path + d="M 36.900421,42.139076 C 40.57847,42.139076 46.040263,40.559298 46.040263,35.912927 C 46.040263,30.744416 41.284228,30.266809 39.311914,29.743556 C 37.131988,29.298791 35.679932,28.678125 35.592711,27.820324 C 35.443451,26.349651 36.303997,25.776856 38.016489,25.776856 C 38.016489,25.776856 42.090107,27.816428 45.550716,26.188778 C 46.526124,25.730654 48.273013,23.590328 48.273013,22.114088 C 48.273013,20.637291 42.633706,18.930597 40.922443,18.930597 C 39.209951,18.930597 37.753595,21.072036 37.753595,21.072036 C 34.32984,21.072036 30.90547,24.02563 30.90547,26.979224 C 30.90547,29.932261 34.181195,32.242365 38.096339,32.886411 C 39.916323,33.147481 41.438401,34.122178 41.092586,35.913483 C 40.81188,37.368014 39.252947,38.867077 35.956953,38.867077 C 33.345219,38.867077 27.787605,38.745171 26.900033,36.596495 C 26.329407,35.212659 27.003225,33.699123 27.859471,33.699123 L 27.842886,33.610059 C 26.97067,33.522108 24.435101,33.699123 24.435101,36.65216 C 24.434487,40.438505 30.051681,42.139076 36.900421,42.139076 z" + id="path2474" + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 45.550102,26.189335 C 43.938959,26.029576 41.489383,25.076031 40.963596,23.39383" + id="path3615" + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <circle + cx="35.805" + cy="10.96" + r="1.676" + transform="matrix(0.6142367,0,0,0.5566517,19.396517,15.137572)" + id="circle2478" + style="fill:#000000;fill-opacity:1;stroke-width:3.42034841;stroke-miterlimit:4;stroke-dasharray:none" /> + </g> +</svg> diff --git a/images/nofile.svg b/images/nofile.svg new file mode 100644 index 0000000..e46c576 --- /dev/null +++ b/images/nofile.svg @@ -0,0 +1,108 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="767" + height="38" + id="svg2467"> + <defs + id="defs2493"> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + </defs> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 3,30 0.5,26.5 0.5,23 l 0,-8 c 0,-3.25 2.5,-8.5 5,-10.5 2.5,-2 6,-4 9.5,-4 l 736.5,0 c 2.5,0 7,1 10.5,4 3.5,2.75 4.5,7.5 4.5,10.5 l 0,8 c 0,3.5 -2,7 -4.5,9.5 -2.5,2.5 -6.5,5 -10.5,5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="m 79.5,438.5 c 0,4.5 -3.75,8 -8.5,8 -4.5,0 -8.25,-3.5 -8.25,-8 0,-4.5 3.75,-8.25 8.25,-8.25 4.75,0 8.5,3.75 8.5,8.25 l 0,0 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <text + x="-48" + id="text2474" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="122" + y="28" + id="tspan2476" + style="font-size:24px">???</tspan> + </text> + <g + transform="translate(6,0)" + id="g2478"> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-4,20)" + id="path2480" + style="fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(1,17)" + id="path2482" + style="fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-1,18)" + id="path2484" + style="fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <text + x="6" + id="text2486" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="27" + y="29" + id="tspan2488" + style="font-size:24px">!</tspan> + </text> + <g + transform="translate(73.5,2.344999)" + id="g3009"> + <path + d="m 27,27.08073 c 0,1.68237 -1.12132,3.074271 -3,3.074271 l -23,0 0,-26.9999999 8.8039216,0 1.6960784,2 15.5,0 0,21.9257289 0,0 z" + id="path2458-4" + style="fill:#ffffff;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 27,27.08073 c 0,1.68237 -1.12132,3.074271 -3,3.074271 l -23,0 0,-17 8.4852943,0 L 11.5,9.1550006 l 15.5,0 0,17.9257294 0,0 z" + id="path2458" + style="fill:#ffffff;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> +</svg> diff --git a/images/noinput.svg b/images/noinput.svg new file mode 100644 index 0000000..eee29e2 --- /dev/null +++ b/images/noinput.svg @@ -0,0 +1,93 @@ +<?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="767" + height="38" + id="svg2393"> + <defs + id="defs2427" /> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 C 3,30 0.5,26.5 0.5,23 L 0.5,15 C 0.5,11.75 3,6.5 5.5,4.5 C 8,2.5 11.5,0.5 15,0.5 L 751.5,0.5 C 754,0.5 758.5,1.5 762,4.5 C 765.5,7.25 766.5,12 766.5,15 L 766.5,23 C 766.5,26.5 764.5,30 762,32.5 C 759.5,35 755.5,37.5 751.5,37.5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="M 79.5,438.5 C 79.5,443 75.75,446.5 71,446.5 C 66.5,446.5 62.75,443 62.75,438.5 C 62.75,434 66.5,430.25 71,430.25 C 75.75,430.25 79.5,434 79.5,438.5 L 79.5,438.5 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <g + transform="translate(0,-0.25)" + id="g2400"> + <path + d="M 122.5,8.5 L 133.5,8.5 L 133.5,12.5 L 131,12.5 L 131,10.5 L 124,10.5" + id="path2402" + style="fill:#a0a0a0;fill-opacity:1;stroke:#808080;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 122.5,27 L 133.5,27 L 133.5,23 L 131,23 L 131,25 L 124,25" + id="path2404" + style="fill:#a0a0a0;fill-opacity:1;stroke:#808080;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 108,5.25 C 118.5,5.25 118.5,5.25 118.5,5.25 C 118.5,5.25 121.5,7 122.25,8 C 123,9 124.5,12 124.5,12 L 124.5,24.5 C 124.5,24.5 123,27 122.25,28 C 121.25,29 118.5,30.5 118.5,30.5 L 107.25,30.5 L 107.25,30 L 107.25,33.25 L 94,33.25 L 94,30.5 L 82.5,30.5 C 82.5,30.5 80,29 79,28 C 78,27 76.5,24.5 76.5,24.5 L 76.5,12 C 76.5,12 78,9 79,8 C 80,7 82.5,5.25 82.5,5.25 L 93.25,5.25 L 93.25,8.5 L 108,8.5 L 108,5.25 z" + id="path2406" + style="fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:#808080;stroke-width:1.33340001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <path + d="M 151.5,17.875 C 151.5,26.780592 144.95216,34 136.875,34 C 128.79784,34 122.25,26.780592 122.25,17.875 C 122.25,8.9694084 128.79784,1.75 136.875,1.75 C 144.95216,1.75 151.5,8.9694084 151.5,17.875 L 151.5,17.875 z" + transform="matrix(0.934374,0,0,0.8474554,3.8575668,3.8517347)" + id="path2408" + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ff0000;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + id="text2410" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"> + <tspan + x="170" + y="28" + id="tspan2412" + style="font-size:24px">???</tspan> + </text> + <g + transform="translate(6,0)" + id="g2414"> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-4,20)" + id="path2416" + style="opacity:1;fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(1,17)" + id="path2418" + style="opacity:1;fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-1,18)" + id="path2420" + style="opacity:1;fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <text + x="6" + id="text2422" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"> + <tspan + x="27" + y="29" + id="tspan2424" + style="font-size:24px">!</tspan> + </text> +</svg> diff --git a/images/nojournal.svg b/images/nojournal.svg new file mode 100644 index 0000000..fd8ec5a --- /dev/null +++ b/images/nojournal.svg @@ -0,0 +1,144 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="767" + height="38" + id="svg2467"> + <defs + id="defs2493"> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172-5" + xlink:href="#linearGradient3166-4" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + id="linearGradient3166-4"> + <stop + id="stop3168-7" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170-6" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + </defs> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 3,30 0.5,26.5 0.5,23 l 0,-8 c 0,-3.25 2.5,-8.5 5,-10.5 2.5,-2 6,-4 9.5,-4 l 736.5,0 c 2.5,0 7,1 10.5,4 3.5,2.75 4.5,7.5 4.5,10.5 l 0,8 c 0,3.5 -2,7 -4.5,9.5 -2.5,2.5 -6.5,5 -10.5,5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="m 79.5,438.5 c 0,4.5 -3.75,8 -8.5,8 -4.5,0 -8.25,-3.5 -8.25,-8 0,-4.5 3.75,-8.25 8.25,-8.25 4.75,0 8.5,3.75 8.5,8.25 l 0,0 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <text + x="-48" + id="text2474" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="122" + y="28" + id="tspan2476" + style="font-size:24px">???</tspan> + </text> + <g + transform="translate(6,0)" + id="g2478"> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-4,20)" + id="path2480" + style="fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(1,17)" + id="path2482" + style="fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-1,18)" + id="path2484" + style="fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <text + x="6" + id="text2486" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="27" + y="29" + id="tspan2488" + style="font-size:24px">!</tspan> + </text> + <g + transform="matrix(0.67,0,0,0.67,67.66091,0.575)" + id="activity-journal" + style="stroke:#000000;stroke-opacity:1;display:block"> + <path + d="M 45.866,44.669 C 45.866,47.18 44.338,49 41.534,49 l -29.457,0 0,-43 29.458,0 c 2.15,0 4.332,2.154 4.332,4.33 l -10e-4,34.339 0,0 z" + id="path2458" + style="fill:#ffffff;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <line + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" + x1="21.341" + x2="21.341" + y1="6.1209998" + y2="48.881001" + id="line2460" /> + <path + d="m 7.384,14.464 c 0,0 2.084,0.695 4.17,0.695 2.086,0 4.173,-0.695 4.173,-0.695" + id="path2462" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,28.021 c 0,0 1.912,0.695 4.345,0.695 2.433,0 3.999,-0.695 3.999,-0.695" + id="path2464" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + <path + d="m 7.384,41.232 c 0,0 1.736,0.695 4.518,0.695 2.781,0 3.825,-0.695 3.825,-0.695" + id="path2466" + style="fill:none;stroke:#000000;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /> + </g> +</svg> diff --git a/images/nomedia.svg b/images/nomedia.svg new file mode 100644 index 0000000..b199b57 --- /dev/null +++ b/images/nomedia.svg @@ -0,0 +1,133 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="767" + height="38" + id="svg2"> + <defs + id="defs41"> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,0.1338084,32.632067)" /> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ffff00;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0.94254935" + y1="-31.669659" + x2="104.37702" + y2="20.434471" + id="linearGradient2558" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.7083638,0,0,1.0012565,346.13381,24.632067)" /> + </defs> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 C 3,30 0.5,26.5 0.5,23 L 0.5,15 C 0.5,11.75 3,6.5 5.5,4.5 C 8,2.5 11.5,0.5 15,0.5 L 751.5,0.5 C 754,0.5 758.5,1.5 762,4.5 C 765.5,7.25 766.5,12 766.5,15 L 766.5,23 C 766.5,26.5 764.5,30 762,32.5 C 759.5,35 755.5,37.5 751.5,37.5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="M 79.5,438.5 C 79.5,443 75.75,446.5 71,446.5 C 66.5,446.5 62.75,443 62.75,438.5 C 62.75,434 66.5,430.25 71,430.25 C 75.75,430.25 79.5,434 79.5,438.5 L 79.5,438.5 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <text + id="text2445" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="128" + y="28" + id="tspan2447" + style="font-size:24px">???</tspan> + </text> + <g + transform="translate(6,0)" + id="g28"> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-4,20)" + id="path30" + style="opacity:1;fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(1,17)" + id="path32" + style="opacity:1;fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-1,18)" + id="path34" + style="opacity:1;fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <text + x="6" + id="text36" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"> + <tspan + x="27" + y="29" + id="tspan38" + style="font-size:24px">!</tspan> + </text> + <g + transform="translate(64.520224,-8.9311472)" + id="clipping-image" + style="display:block"> + <g + id="g2859" + style="display:inline"> + <g + id="g2861"> + <polygon + points="48.788,43.944 48.788,23.002 36.849,11.058 5.962,11.058 5.962,43.944 48.788,43.944 " + id="polygon2863" + style="fill:#ffffff;stroke:#010101;stroke-width:3.5" /> + <polyline + id="polyline2865" + points="36.849,11.058 36.849,23.002 48.788,23.002 " + style="fill:none;stroke:#010101;stroke-width:3.5" /> + </g> + </g> + <path + d="M 27.504,23.342 C 21.246,23.342 16.033,29.583 16.033,29.583 C 16.033,29.583 21.246,35.854 27.504,35.85 C 33.763,35.845 38.979,29.576 38.979,29.576 C 38.979,29.576 33.763,23.338 27.504,23.342 z M 27.504,33.984 C 25.081,33.984 23.117,32.018 23.117,29.595 C 23.117,27.176 25.081,25.207 27.504,25.207 C 29.924,25.207 31.89,27.176 31.89,29.595 C 31.89,32.019 29.924,33.984 27.504,33.984 z" + id="path2867" + style="fill:#010101;display:inline" /> + <circle + cx="27.504" + cy="29.597" + r="1.9910001" + id="circle2869" + style="fill:#010101;display:inline" /> + </g> +</svg> diff --git a/images/nostack.svg b/images/nostack.svg new file mode 100644 index 0000000..838d061 --- /dev/null +++ b/images/nostack.svg @@ -0,0 +1,76 @@ +<?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="767" + height="38" + id="svg2467"> + <defs + id="defs2493" /> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 C 3,30 0.5,26.5 0.5,23 L 0.5,15 C 0.5,11.75 3,6.5 5.5,4.5 C 8,2.5 11.5,0.5 15,0.5 L 751.5,0.5 C 754,0.5 758.5,1.5 762,4.5 C 765.5,7.25 766.5,12 766.5,15 L 766.5,23 C 766.5,26.5 764.5,30 762,32.5 C 759.5,35 755.5,37.5 751.5,37.5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="M 79.5,438.5 C 79.5,443 75.75,446.5 71,446.5 C 66.5,446.5 62.75,443 62.75,438.5 C 62.75,434 66.5,430.25 71,430.25 C 75.75,430.25 79.5,434 79.5,438.5 L 79.5,438.5 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <text + id="text2474" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"> + <tspan + x="170" + y="28" + id="tspan2476" + style="font-size:24px">???</tspan> + </text> + <g + transform="translate(6,0)" + id="g2478"> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-4,20)" + id="path2480" + style="opacity:1;fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(1,17)" + id="path2482" + style="opacity:1;fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-1,18)" + id="path2484" + style="opacity:1;fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <text + x="6" + id="text2486" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"> + <tspan + x="27" + y="29" + id="tspan2488" + style="font-size:24px">!</tspan> + </text> + <path + d="M 148.5,19 L 148.5,19 L 122.5,34 L 122.5,34 L 122.5,37 L 109,37 L 109,34 C 109,34 83,19 83,19 C 83,19 116,1 116,1 C 116,1 148.5,19 148.5,19 z" + id="path2490" + style="fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:#c0a000;stroke-width:1.33340001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> +</svg> diff --git a/images/notanumber.svg b/images/notanumber.svg new file mode 100644 index 0000000..edf9a29 --- /dev/null +++ b/images/notanumber.svg @@ -0,0 +1,74 @@ +<?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="767" + height="38" + id="svg2"> + <defs + id="defs32" /> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 3,30 0.5,26.5 0.5,23 l 0,-8 c 0,-3.25 2.5,-8.5 5,-10.5 2.5,-2 6,-4 9.5,-4 l 736.5,0 c 2.5,0 7,1 10.5,4 3.5,2.75 4.5,7.5 4.5,10.5 l 0,8 c 0,3.5 -2,7 -4.5,9.5 -2.5,2.5 -6.5,5 -10.5,5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="m 79.5,438.5 c 0,4.5 -3.75,8 -8.5,8 -4.5,0 -8.25,-3.5 -8.25,-8 0,-4.5 3.75,-8.25 8.25,-8.25 4.75,0 8.5,3.75 8.5,8.25 l 0,0 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <text + x="-108" + id="text13" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="62" + y="28" + id="tspan15" + style="font-size:24px">NAN</tspan> + </text> + <g + transform="translate(6,0)" + id="g17"> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-4,20)" + id="path19" + style="fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(1,17)" + id="path21" + style="fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-1,18)" + id="path23" + style="fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <text + x="6" + id="text25" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="27" + y="29" + id="tspan27" + style="font-size:24px">!</tspan> + </text> +</svg> diff --git a/images/overflowerror.svg b/images/overflowerror.svg new file mode 100644 index 0000000..dd709bc --- /dev/null +++ b/images/overflowerror.svg @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + version="1.0" + width="767" + height="38" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.46" + sodipodi:docname="overflowerror.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <metadata + id="metadata18"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + inkscape:window-height="723" + inkscape:window-width="645" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + guidetolerance="10.0" + gridtolerance="10.0" + objecttolerance="10.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + showgrid="false" + inkscape:zoom="1" + inkscape:cx="186.88855" + inkscape:cy="17.535157" + inkscape:window-x="376" + inkscape:window-y="136" + inkscape:current-layer="svg2" /> + <defs + id="defs32"> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 19 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="767 : 19 : 1" + inkscape:persp3d-origin="383.5 : 12.666667 : 1" + id="perspective20" /> + </defs> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 C 3,30 0.5,26.5 0.5,23 L 0.5,15 C 0.5,11.75 3,6.5 5.5,4.5 C 8,2.5 11.5,0.5 15,0.5 L 751.5,0.5 C 754,0.5 758.5,1.5 762,4.5 C 765.5,7.25 766.5,12 766.5,15 L 766.5,23 C 766.5,26.5 764.5,30 762,32.5 C 759.5,35 755.5,37.5 751.5,37.5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="M 79.5,438.5 C 79.5,443 75.75,446.5 71,446.5 C 66.5,446.5 62.75,443 62.75,438.5 C 62.75,434 66.5,430.25 71,430.25 C 75.75,430.25 79.5,434 79.5,438.5 L 79.5,438.5 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <text + x="-124.76469" + id="text13" + style="font-size:13.12157726px;font-style:normal;font-weight:normal;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans" + y="-1.9127419"> + <tspan + x="61.124317" + y="28.704271" + id="tspan15" + style="font-size:26.24315453px">>1000000</tspan> + </text> + <g + transform="translate(6,0)" + id="g17"> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-4,20)" + id="path19" + style="opacity:1;fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(1,17)" + id="path21" + style="opacity:1;fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-1,18)" + id="path23" + style="opacity:1;fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <text + x="6" + id="text25" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"> + <tspan + x="27" + y="29" + id="tspan27" + style="font-size:24px">!</tspan> + </text> +</svg> diff --git a/images/palettehorizontal.svg b/images/palettehorizontal.svg new file mode 100644 index 0000000..6cc62bf --- /dev/null +++ b/images/palettehorizontal.svg @@ -0,0 +1,25 @@ +<?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="16" + height="16" + id="svg2"> + <defs + id="defs9" /> + <path + d="m 18.983051,7.5932202 a 10.915255,10.169492 0 1 1 -21.8305089,0 10.915255,10.169492 0 1 1 21.8305089,0 z" + transform="matrix(0.68421284,0,0,0.73438846,2.4799099,2.4236267)" + id="path2819" + style="fill:#00000f;fill-opacity:0.94117647;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <rect + width="5.3145914" + height="11.314592" + x="5.3427043" + y="2.3427038" + id="rect5" + style="fill:#ffd000;fill-opacity:1;stroke:none" /> +</svg> diff --git a/images/palettehshift.svg b/images/palettehshift.svg new file mode 100644 index 0000000..38158aa --- /dev/null +++ b/images/palettehshift.svg @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="16" + height="16" + id="svg2"> + <metadata + id="metadata8"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs9"> + <linearGradient + x1="0" + y1="17.200001" + x2="37" + y2="17.200001" + id="linearGradient5678" + xlink:href="#linearGradient1234" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient1234"> + <stop + id="stop3087" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3089" + style="stop-color:#a0ff00;stop-opacity:1" + offset="1" /> + </linearGradient> + </defs> + <path + d="m 18.983051,7.5932202 a 10.915255,10.169492 0 1 1 -21.8305089,0 10.915255,10.169492 0 1 1 21.8305089,0 z" + transform="matrix(0.68421284,0,0,0.73438846,2.4799099,2.4236267)" + id="path2819" + style="fill:#ffd000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + transform="matrix(0,-1.3333333,1.3333333,0,-2.6666664,18.666666)" + id="g3924"> + <path + d="m 8,4 0,8" + id="path3106" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(0.0303029,-0.060606)" + id="g3896"> + <path + d="M 7.939394,4.060606 6,6" + id="path3108" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="M 8,4.060606 9.9393942,6" + id="path3108-6" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" /> + </g> + <g + transform="matrix(1,0,0,-1,0.0303029,16.060606)" + id="g3896-4"> + <path + d="M 7.939394,4.060606 6,6" + id="path3108-0" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="M 8,4.060606 9.9393942,6" + id="path3108-6-8" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" /> + </g> + </g> +</svg> diff --git a/images/palettenext.svg b/images/palettenext.svg new file mode 100644 index 0000000..ccecdfa --- /dev/null +++ b/images/palettenext.svg @@ -0,0 +1,30 @@ +<?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="16" + height="16" + id="svg2"> + <defs + id="defs9" /> + <path + d="m 18.983051,7.5932202 a 10.915255,10.169492 0 1 1 -21.8305089,0 10.915255,10.169492 0 1 1 21.8305089,0 z" + transform="matrix(0.68421284,0,0,0.73438846,2.4799099,2.4236267)" + id="path2819" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <rect + width="5.3145914" + height="11.314592" + x="5.3427043" + y="-11.314592" + transform="matrix(0,1,-1,0,0,0)" + id="rect5" + style="fill:#00fe00;fill-opacity:1;stroke:none" /> + <path + d="M 15.5,8 L 10,2 10,14 15.5,8 z" + id="path2816" + style="fill:#00fe00;fill-opacity:1;stroke:#00fe00;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> +</svg> diff --git a/images/palettevertical.svg b/images/palettevertical.svg new file mode 100644 index 0000000..552ecdf --- /dev/null +++ b/images/palettevertical.svg @@ -0,0 +1,26 @@ +<?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="16" + height="16" + id="svg2"> + <defs + id="defs9" /> + <path + d="m 18.983051,7.5932202 a 10.915255,10.169492 0 1 1 -21.8305089,0 10.915255,10.169492 0 1 1 21.8305089,0 z" + transform="matrix(0.68421284,0,0,0.73438846,2.4799099,2.4236267)" + id="path2819" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <rect + width="5.3145914" + height="11.314592" + x="-10.657295" + y="2.3427038" + transform="matrix(0,-1,1,0,0,0)" + id="rect5" + style="fill:#ffd000;fill-opacity:1;stroke:none" /> +</svg> diff --git a/images/palettevshift.svg b/images/palettevshift.svg new file mode 100644 index 0000000..504272f --- /dev/null +++ b/images/palettevshift.svg @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="16" + height="16" + id="svg2"> + <metadata + id="metadata8"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs9"> + <linearGradient + x1="0" + y1="17.200001" + x2="37" + y2="17.200001" + id="linearGradient5678" + xlink:href="#linearGradient1234" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient1234"> + <stop + id="stop3087" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3089" + style="stop-color:#a0ff00;stop-opacity:1" + offset="1" /> + </linearGradient> + </defs> + <path + d="m 18.983051,7.5932202 a 10.915255,10.169492 0 1 1 -21.8305089,0 10.915255,10.169492 0 1 1 21.8305089,0 z" + transform="matrix(0.68421284,0,0,0.73438846,2.4799099,2.4236267)" + id="path2819" + style="fill:#ffd000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <g + transform="matrix(1.3333333,0,0,1.3333333,-2.6666664,-2.6666664)" + id="g3924"> + <path + d="m 8,4 0,8" + id="path3106" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(0.0303029,-0.060606)" + id="g3896"> + <path + d="M 7.939394,4.060606 6,6" + id="path3108" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="M 8,4.060606 9.9393942,6" + id="path3108-6" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" /> + </g> + <g + transform="matrix(1,0,0,-1,0.0303029,16.060606)" + id="g3896-4"> + <path + d="M 7.939394,4.060606 6,6" + id="path3108-0" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" /> + <path + d="M 8,4.060606 9.9393942,6" + id="path3108-6-8" + style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1" /> + </g> + </g> +</svg> diff --git a/images/polar.svg b/images/polar.svg new file mode 100644 index 0000000..40f5174 --- /dev/null +++ b/images/polar.svg @@ -0,0 +1,230 @@ +<?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="1200" + height="900" + id="svg2"> + <defs + id="defs4" /> + <path + d="M 899.66703,-69.03853 300.33297,969.03853" + id="path3403" + style="fill:none;stroke:#aaaaaa;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 600,-149.33408 0,1198.66818" + id="path69" + style="fill:none;stroke:#aaaaaa;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 300.33297,-69.03853 899.66703,969.03853" + id="path3397" + style="fill:none;stroke:#aaaaaa;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 176.2068,26.20681 847.5864,847.58638" + id="path3405" + style="fill:none;stroke:#aaaaaa;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 80.961482,150.33296 1119.0385,749.66704" + id="path3399" + style="fill:none;stroke:#aaaaaa;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 881.14902,435.72711 c 0,194.53909 -157.2228,352.24418 -351.16696,352.24418 -193.94417,0 -351.16697,-157.70509 -351.16697,-352.24418 0,-194.53909 157.2228,-352.244179 351.16696,-352.244179 193.94417,0 351.16697,157.705089 351.16697,352.244179 l 0,0 z" + transform="matrix(1.1334197,0,0,1.1299535,-0.6921025,-42.351375)" + id="path2537" + style="fill:none;stroke:#000000;stroke-width:0.88363791;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 881.14902,435.72711 c 0,194.53909 -157.2228,352.24418 -351.16696,352.24418 -193.94417,0 -351.16697,-157.70509 -351.16697,-352.24418 0,-194.53909 157.2228,-352.244179 351.16696,-352.244179 193.94417,0 351.16697,157.705089 351.16697,352.244179 l 0,0 z" + transform="matrix(0.8500647,0,0,0.8474652,149.48096,80.736436)" + id="path3311" + style="fill:none;stroke:#000000;stroke-width:1.17818391;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 881.14902,435.72711 c 0,194.53909 -157.2228,352.24418 -351.16696,352.24418 -193.94417,0 -351.16697,-157.70509 -351.16697,-352.24418 0,-194.53909 157.2228,-352.244179 351.16696,-352.244179 193.94417,0 351.16697,157.705089 351.16697,352.244179 l 0,0 z" + transform="matrix(0.5667098,0,0,0.5649768,299.65398,203.82429)" + id="path3313" + style="fill:none;stroke:#000000;stroke-width:1.76727581;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 881.14902,435.72711 c 0,194.53909 -157.2228,352.24418 -351.16696,352.24418 -193.94417,0 -351.16697,-157.70509 -351.16697,-352.24418 0,-194.53909 157.2228,-352.244179 351.16696,-352.244179 193.94417,0 351.16697,157.705089 351.16697,352.244179 l 0,0 z" + transform="matrix(0.2833549,0,0,0.2824884,449.82699,326.91215)" + id="path3315" + style="fill:none;stroke:#000000;stroke-width:3.53455162;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 881.14902,435.72711 c 0,194.53909 -157.2228,352.24418 -351.16696,352.24418 -193.94417,0 -351.16697,-157.70509 -351.16697,-352.24418 0,-194.53909 157.2228,-352.244179 351.16696,-352.244179 193.94417,0 351.16697,157.705089 351.16697,352.244179 l 0,0 z" + transform="matrix(1.4220377,0,0,1.417689,-153.65446,-167.72553)" + id="path3395" + style="fill:none;stroke:#000000;stroke-width:0.70429397;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="m 0,450 1200,0" + id="path49" + style="fill:none;stroke:#aaaaaa;stroke-width:1px;stroke-opacity:1" /> + <path + d="M 80.96149,749.66704 1119.0385,150.33296" + id="path3401" + style="fill:none;stroke:#aaaaaa;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 1023.7932,26.20681 176.2068,873.79319" + id="path3407" + style="fill:none;stroke:#aaaaaa;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + x="602.82129" + y="175.8584" + id="text3003" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="602.82129" + y="175.8584" + id="tspan3005" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">0</tspan></text> + <text + x="869.37012" + y="459.64014" + id="text3003-4" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="869.37012" + y="459.64014" + id="tspan3005-7" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">90</tspan></text> + <text + x="602.23438" + y="733.8584" + id="text3003-5" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="602.23438" + y="733.8584" + id="tspan3005-6" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">180</tspan></text> + <text + x="319.26758" + y="459.64014" + id="text3003-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="319.26758" + y="459.64014" + id="tspan3005-74" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">270</tspan></text> + <text + x="725.93848" + y="209.30679" + id="text3003-52" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="725.93848" + y="209.30679" + id="tspan3005-5" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">30</tspan></text> + <text + x="836.63684" + y="321.30682" + id="text3003-7" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="836.63684" + y="321.30682" + id="tspan3005-4" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">60</tspan></text> + <text + x="796.0752" + y="262.57425" + id="text3003-0" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="796.0752" + y="262.57425" + id="tspan3005-78" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">45</tspan></text> + <text + x="349.23846" + y="323.30682" + id="text3003-52-6" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="349.23846" + y="323.30682" + id="tspan3005-5-8" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">300</tspan></text> + <text + x="461.2384" + y="209.30679" + id="text3003-7-8" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="461.2384" + y="209.30679" + id="tspan3005-4-4" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">330</tspan></text> + <text + x="387.23846" + y="262.64017" + id="text3003-0-3" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="387.23846" + y="262.64017" + id="tspan3005-78-1" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">315</tspan></text> + <text + x="359.25311" + y="595.97345" + id="text3003-52-9" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="359.25311" + y="595.97345" + id="tspan3005-5-2" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">240</tspan></text> + <text + x="459.25305" + y="699.30682" + id="text3003-7-0" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="459.25305" + y="699.30682" + id="tspan3005-4-6" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">210</tspan></text> + <text + x="401.25311" + y="654.6402" + id="text3003-0-8" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="401.25311" + y="654.6402" + id="tspan3005-78-9" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">225</tspan></text> + <text + x="722.58643" + y="699.30682" + id="text3003-52-66" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="722.58643" + y="699.30682" + id="tspan3005-5-4" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">150</tspan></text> + <text + x="823.25305" + y="595.97345" + id="text3003-7-9" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="823.25305" + y="595.97345" + id="tspan3005-4-5" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">120</tspan></text> + <text + x="780.58643" + y="654.6402" + id="text3003-0-0" + xml:space="preserve" + style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;fill:#0000c0;fill-opacity:1;stroke:none;font-family:DejaVu Sans"><tspan + x="780.58643" + y="654.6402" + id="tspan3005-78-4" + style="font-size:10px;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;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans">135</tspan></text> +</svg> diff --git a/images/print.svg b/images/print.svg new file mode 100644 index 0000000..9f48a36 --- /dev/null +++ b/images/print.svg @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="767" + height="38" + id="svg2"> + <metadata + id="metadata17"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs27" /> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 3,30 0.5,26.5 0.5,23 l 0,-8 c 0,-3.25 2.5,-8.5 5,-10.5 2.5,-2 6,-4 9.5,-4 l 736.5,0 c 2.5,0 7,1 10.5,4 3.5,2.75 4.5,7.5 4.5,10.5 l 0,8 c 0,3.5 -2,7 -4.5,9.5 -2.5,2.5 -6.5,5 -10.5,5 L 15,37.5 z" + id="path4" + style="fill:#80ffff;fill-opacity:1;fill-rule:evenodd;stroke:#00e0e0;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="m 79.5,438.5 c 0,4.5 -3.75,8 -8.5,8 -4.5,0 -8.25,-3.5 -8.25,-8 0,-4.5 3.75,-8.25 8.25,-8.25 4.75,0 8.5,3.75 8.5,8.25 l 0,0 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> +</svg> diff --git a/images/print1200.svg b/images/print1200.svg new file mode 100644 index 0000000..e94402e --- /dev/null +++ b/images/print1200.svg @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="1167" + height="38" + id="svg2"> + <metadata + id="metadata17"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs27" /> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 3,30 0.5,26.5 0.5,23 l 0,-8 c 0,-3.25 2.5,-8.5 5,-10.5 2.5,-2 6,-4 9.5,-4 l 1136.5,0 c 2.5,0 7,1 10.5,4 3.5,2.75 4.5,7.5 4.5,10.5 l 0,8 c 0,3.5 -2,7 -4.5,9.5 -2.5,2.5 -6.5,5 -10.5,5 z" + id="path4" + style="fill:#80ffff;fill-opacity:1;fill-rule:evenodd;stroke:#00e0e0;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(1053.75,65.625)" + id="g6"> + <path + d="m 79.5,438.5 c 0,4.5 -3.75,8 -8.5,8 -4.5,0 -8.25,-3.5 -8.25,-8 0,-4.5 3.75,-8.25 8.25,-8.25 4.75,0 8.5,3.75 8.5,8.25 l 0,0 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> +</svg> diff --git a/images/pythonoff.svg b/images/pythonoff.svg new file mode 100644 index 0000000..ba30da0 --- /dev/null +++ b/images/pythonoff.svg @@ -0,0 +1,53 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="25" + height="25" + id="svg2"> + <defs + id="defs4"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ff0000;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="22" + x2="74" + y2="22" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" /> + </defs> + <g + transform="matrix(0.96656375,0,0,0.99278471,-22.651532,-17.827933)" + id="g2503"> + <path + d="m 36.900421,42.139076 c 3.678049,0 9.139842,-1.579778 9.139842,-6.226149 0,-5.168511 -4.756035,-5.646118 -6.728349,-6.169371 -2.179926,-0.444765 -3.631982,-1.065431 -3.719203,-1.923232 -0.14926,-1.470673 0.711286,-2.043468 2.423778,-2.043468 0,0 4.073618,2.039572 7.534227,0.411922 0.975408,-0.458124 2.722297,-2.59845 2.722297,-4.07469 0,-1.476797 -5.639307,-3.183491 -7.35057,-3.183491 -1.712492,0 -3.168848,2.141439 -3.168848,2.141439 -3.423755,0 -6.848125,2.953594 -6.848125,5.907188 0,2.953037 3.275725,5.263141 7.190869,5.907187 1.819984,0.26107 3.342062,1.235767 2.996247,3.027072 -0.280706,1.454531 -1.839639,2.953594 -5.135633,2.953594 -2.611734,0 -8.169348,-0.121906 -9.05692,-2.270582 -0.570626,-1.383836 0.103192,-2.897372 0.959438,-2.897372 l -0.01658,-0.08906 c -0.872216,-0.08795 -3.407785,0.08906 -3.407785,3.042101 -6.14e-4,3.786345 5.61658,5.486916 12.46532,5.486916 z" + id="path2474" + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 45.550102,26.189335 C 43.938959,26.029576 41.489383,25.076031 40.963596,23.39383" + id="path2476" + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <circle + cx="35.805" + cy="10.96" + r="1.676" + transform="matrix(0.6142367,0,0,0.5566517,19.396517,15.137572)" + id="circle2478" + style="fill:#000000;fill-opacity:1;stroke-width:3.42034841;stroke-miterlimit:4;stroke-dasharray:none" /> + </g> +</svg> diff --git a/images/pythonon.svg b/images/pythonon.svg new file mode 100644 index 0000000..00fb62c --- /dev/null +++ b/images/pythonon.svg @@ -0,0 +1,52 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="25" + height="25" + id="svg2"> + <defs + id="defs4"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ff0000;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="22" + x2="74" + y2="22" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" /> + </defs> + <g + id="g3597"> + <path + d="m 13.015077,24.007097 c 3.555069,0 8.83424,-1.568379 8.83424,-6.181225 0,-5.131219 -4.597011,-5.60538 -6.503378,-6.124857 -2.107037,-0.441556 -3.510542,-1.057744 -3.594847,-1.9093557 -0.144269,-1.4600617 0.687503,-2.0287238 2.342736,-2.0287238 0,0 3.937412,2.0248559 7.282311,0.4089499 0.942794,-0.4548185 2.631273,-2.5797015 2.631273,-4.04529 0,-1.4661414 -5.450749,-3.16052115 -7.104794,-3.16052115 -1.655233,0 -3.062894,2.12598785 -3.062894,2.12598785 -3.309277,0 -6.619149,2.932283 -6.619149,5.864566 0,2.9317299 3.166197,5.2251659 6.950433,5.8645649 1.759131,0.259186 3.230316,1.226851 2.896064,3.005231 -0.27132,1.444036 -1.778128,2.932283 -4.963917,2.932283 -2.5244071,0 -7.8961953,-0.121027 -8.7540902,-2.254199 -0.5515464,-1.373852 0.099742,-2.876467 0.927358,-2.876467 l -0.016026,-0.08842 c -0.843052,-0.08731 -3.29384111,0.08842 -3.29384111,3.020154 -5.9347e-4,3.759025 5.42878261,5.447326 12.04852631,5.447326 z" + id="path2474" + style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.95917296;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 21.375545,8.1724384 C 19.818273,8.0138321 17.450602,7.0671672 16.942395,5.3971037" + id="path2476" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:1.95917296;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <circle + cx="35.805" + cy="10.96" + r="1.676" + transform="matrix(0.59369893,0,0,0.5526353,-3.9035618,-2.799583)" + id="circle2478" + style="fill:#000000;fill-opacity:1;stroke-width:3.42034841;stroke-miterlimit:4;stroke-dasharray:none" /> + </g> +</svg> diff --git a/images/pythonsmall.svg b/images/pythonsmall.svg new file mode 100644 index 0000000..d84a976 --- /dev/null +++ b/images/pythonsmall.svg @@ -0,0 +1,53 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="18.750023" + height="18.750151" + id="svg2"> + <defs + id="defs4"> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#ff0000;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="0" + y1="22" + x2="74" + y2="22" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" /> + </defs> + <g + transform="matrix(0.72492281,0,0,0.74458853,-16.978876,-13.360816)" + id="g2503"> + <path + d="m 36.900421,42.139076 c 3.678049,0 9.139842,-1.579778 9.139842,-6.226149 0,-5.168511 -4.756035,-5.646118 -6.728349,-6.169371 -2.179926,-0.444765 -3.631982,-1.065431 -3.719203,-1.923232 -0.14926,-1.470673 0.711286,-2.043468 2.423778,-2.043468 0,0 4.073618,2.039572 7.534227,0.411922 0.975408,-0.458124 2.722297,-2.59845 2.722297,-4.07469 0,-1.476797 -5.639307,-3.183491 -7.35057,-3.183491 -1.712492,0 -3.168848,2.141439 -3.168848,2.141439 -3.423755,0 -6.848125,2.953594 -6.848125,5.907188 0,2.953037 3.275725,5.263141 7.190869,5.907187 1.819984,0.26107 3.342062,1.235767 2.996247,3.027072 -0.280706,1.454531 -1.839639,2.953594 -5.135633,2.953594 -2.611734,0 -8.169348,-0.121906 -9.05692,-2.270582 -0.570626,-1.383836 0.103192,-2.897372 0.959438,-2.897372 l -0.01658,-0.08906 c -0.872216,-0.08795 -3.407785,0.08906 -3.407785,3.042101 -6.14e-4,3.786345 5.61658,5.486916 12.46532,5.486916 z" + id="path2474" + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <path + d="M 45.550102,26.189335 C 43.938959,26.029576 41.489383,25.076031 40.963596,23.39383" + id="path2476" + style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <circle + cx="35.805" + cy="10.96" + r="1.676" + transform="matrix(0.6142367,0,0,0.5566517,19.396517,15.137572)" + id="circle2478" + style="fill:#000000;fill-opacity:1;stroke-width:3.42034841;stroke-miterlimit:4;stroke-dasharray:none" /> + </g> +</svg> diff --git a/images/status.svg b/images/status.svg new file mode 100644 index 0000000..cb72835 --- /dev/null +++ b/images/status.svg @@ -0,0 +1,63 @@ +<?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="767" + height="38" + id="svg2"> + <defs + id="defs27" /> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 C 3,30 0.5,26.5 0.5,23 L 0.5,15 C 0.5,11.75 3,6.5 5.5,4.5 C 8,2.5 11.5,0.5 15,0.5 L 751.5,0.5 C 754,0.5 758.5,1.5 762,4.5 C 765.5,7.25 766.5,12 766.5,15 L 766.5,23 C 766.5,26.5 764.5,30 762,32.5 C 759.5,35 755.5,37.5 751.5,37.5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="M 79.5,438.5 C 79.5,443 75.75,446.5 71,446.5 C 66.5,446.5 62.75,443 62.75,438.5 C 62.75,434 66.5,430.25 71,430.25 C 75.75,430.25 79.5,434 79.5,438.5 L 79.5,438.5 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <g + transform="translate(5.5,0)" + id="g14"> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-4,20)" + id="path16" + style="opacity:1;fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(1,17)" + id="path18" + style="opacity:1;fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-1,18)" + id="path20" + style="opacity:1;fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <text + x="5.5" + id="text22" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"> + <tspan + x="26.5" + y="29" + id="tspan24" + style="font-size:24px">!</tspan> + </text> +</svg> diff --git a/images/status1200.svg b/images/status1200.svg new file mode 100644 index 0000000..6b64812 --- /dev/null +++ b/images/status1200.svg @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="1167" + height="38" + id="svg2"> + <metadata + id="metadata17"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs27" /> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 3,30 0.5,26.5 0.5,23 l 0,-8 c 0,-3.25 2.5,-8.5 5,-10.5 2.5,-2 6,-4 9.5,-4 l 1136.5,0 c 2.5,0 7,1 10.5,4 3.5,2.75 4.5,7.5 4.5,10.5 l 0,8 c 0,3.5 -2,7 -4.5,9.5 -2.5,2.5 -6.5,5 -10.5,5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(1053.75,65.625)" + id="g6"> + <path + d="m 79.5,438.5 c 0,4.5 -3.75,8 -8.5,8 -4.5,0 -8.25,-3.5 -8.25,-8 0,-4.5 3.75,-8.25 8.25,-8.25 4.75,0 8.5,3.75 8.5,8.25 l 0,0 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <g + transform="translate(5.5,0)" + id="g14"> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-4,20)" + id="path16" + style="fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(1,17)" + id="path18" + style="fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-1,18)" + id="path20" + style="fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <text + x="5.5000076" + y="-8.4277344e-06" + id="text22" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="26.500023" + y="28.999992" + id="tspan24" + style="font-size:24px">!</tspan> + </text> +</svg> diff --git a/images/syntaxerror.svg b/images/syntaxerror.svg new file mode 100644 index 0000000..0963986 --- /dev/null +++ b/images/syntaxerror.svg @@ -0,0 +1,120 @@ +<?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" + xmlns:xlink="http://www.w3.org/1999/xlink" + version="1.0" + width="767" + height="38" + id="svg2"> + <defs + id="defs41"> + <linearGradient + x1="0" + y1="0" + x2="104" + y2="21" + id="linearGradient3172" + xlink:href="#linearGradient3166" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.67,0,0,0.67,125.79816,9.965)" /> + <linearGradient + id="linearGradient3166"> + <stop + id="stop3168" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3170" + style="stop-color:#0000ff;stop-opacity:1" + offset="1" /> + </linearGradient> + </defs> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 C 3,30 0.5,26.5 0.5,23 L 0.5,15 C 0.5,11.75 3,6.5 5.5,4.5 C 8,2.5 11.5,0.5 15,0.5 L 751.5,0.5 C 754,0.5 758.5,1.5 762,4.5 C 765.5,7.25 766.5,12 766.5,15 L 766.5,23 C 766.5,26.5 764.5,30 762,32.5 C 759.5,35 755.5,37.5 751.5,37.5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="M 79.5,438.5 C 79.5,443 75.75,446.5 71,446.5 C 66.5,446.5 62.75,443 62.75,438.5 C 62.75,434 66.5,430.25 71,430.25 C 75.75,430.25 79.5,434 79.5,438.5 L 79.5,438.5 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <g + transform="translate(0,-0.25)" + id="g14"> + <path + d="M 122.5,8.5 L 133.5,8.5 L 133.5,12.5 L 131,12.5 L 131,10.5 L 124,10.5" + id="path16" + style="fill:#a0a0a0;fill-opacity:1;stroke:#808080;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 122.5,27 L 133.5,27 L 133.5,23 L 131,23 L 131,25 L 124,25" + id="path18" + style="fill:#a0a0a0;fill-opacity:1;stroke:#808080;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 108,5.25 C 118.5,5.25 118.5,5.25 118.5,5.25 C 118.5,5.25 121.5,7 122.25,8 C 123,9 124.5,12 124.5,12 L 124.5,24.5 C 124.5,24.5 123,27 122.25,28 C 121.25,29 118.5,30.5 118.5,30.5 L 107.25,30.5 L 107.25,30 L 107.25,33.25 L 94,33.25 L 94,30.5 L 82.5,30.5 C 82.5,30.5 80,29 79,28 C 78,27 76.5,24.5 76.5,24.5 L 76.5,12 C 76.5,12 78,9 79,8 C 80,7 82.5,5.25 82.5,5.25 L 93.25,5.25 L 93.25,8.5 L 108,8.5 L 108,5.25 z" + id="path20" + style="fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:#808080;stroke-width:1.33340001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <path + d="M 126.46816,10.3 L 129.81816,10.3 L 129.81816,12.98 L 134.50816,12.98 L 134.50816,10.3 L 195.81316,10.3 L 195.81316,23.7 L 134.50816,23.7 L 134.50816,21.02 L 129.81816,21.02 L 129.81816,23.7 L 126.46816,23.7 L 126.46816,10.3 z" + id="path2498" + style="fill:url(#linearGradient3172);fill-opacity:1;stroke:#0000a0;stroke-width:1.29999995;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 205.82231,17.000001 C 205.82231,25.061518 185.73387,31.596667 160.95355,31.596667 C 136.17323,31.596667 116.08479,25.061518 116.08479,17.000001 C 116.08479,8.938484 136.17323,2.4033334 160.95355,2.4033334 C 185.73387,2.4033334 205.82231,8.938484 205.82231,17.000001 L 205.82231,17.000001 z" + id="path22" + style="opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#ff0000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <text + x="38" + y="-0.09375" + id="text24" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"> + <tspan + x="208" + y="27.90625" + id="tspan26" + style="font-size:24px">???</tspan> + </text> + <g + transform="translate(6,0)" + id="g28"> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-4,20)" + id="path30" + style="opacity:1;fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(1,17)" + id="path32" + style="opacity:1;fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + <path + d="M 44,15 L 10.5,15 L 27.5,-14 L 44,15 z" + transform="translate(-1,18)" + id="path34" + style="opacity:1;fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + </g> + <text + x="6" + id="text36" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"> + <tspan + x="27" + y="29" + id="tspan38" + style="font-size:24px">!</tspan> + </text> +</svg> diff --git a/images/videooff.svg b/images/videooff.svg new file mode 100644 index 0000000..a20349c --- /dev/null +++ b/images/videooff.svg @@ -0,0 +1,17 @@ +<?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 "#010101"> + <!ENTITY fill_color "#FFFFFF"> +]><svg enable-background="new 0 0 55 55" height="55px" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="clipping-video"> + <g display="inline"> + <g> + <polygon fill="&fill_color;" points="48.788,43.944 48.788,23.002 36.849,11.058 5.962,11.058 5.962,43.944 " stroke="&stroke_color;" stroke-width="3.5"/> + <polyline fill="none" points="36.849,11.058 36.849,23.002 48.788,23.002 " stroke="&stroke_color;" stroke-width="3.5"/> + </g> + </g> + <path d="M27.504,24.842c-4.757,0-8.72,4.744-8.72,4.744s3.963,4.767,8.72,4.764 c4.757-0.004,8.722-4.77,8.722-4.77S32.262,24.839,27.504,24.842z M27.504,32.932c-1.842,0-3.335-1.494-3.335-3.336 c0-1.839,1.493-3.336,3.335-3.336c1.839,0,3.333,1.497,3.333,3.336C30.838,31.438,29.344,32.932,27.504,32.932z" display="inline" fill="&stroke_color;"/> + <circle cx="27.505" cy="29.597" display="inline" fill="&stroke_color;" r="1.514"/> + <circle cx="14.875" cy="29.597" display="inline" fill="&stroke_color;" r="1.514"/> + <circle cx="10.375" cy="29.597" display="inline" fill="&stroke_color;" r="1.514"/> + <circle cx="43.875" cy="29.597" display="inline" fill="&stroke_color;" r="1.514"/> + <circle cx="39.375" cy="29.597" display="inline" fill="&stroke_color;" r="1.514"/> +</g></svg>
\ No newline at end of file diff --git a/images/videoon.svg b/images/videoon.svg new file mode 100644 index 0000000..59d0f31 --- /dev/null +++ b/images/videoon.svg @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2" + xml:space="preserve"><metadata + id="metadata29"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs27"> + + + + + + + +</defs><g + id="g5" + style="display:inline"> + <g + id="g7"> + <polygon + points="5.962,11.058 5.962,43.944 48.788,43.944 48.788,23.002 36.849,11.058 " + id="polygon9" + style="fill:#ffffff;stroke:#010101;stroke-width:3.5" /> + <polyline + style="fill:none;stroke:#010101;stroke-width:3.5" + id="polyline11" + points="36.849,11.058 36.849,23.002 48.788,23.002 " /> + </g> + </g><path + d="m 27.504,24.842 c -4.757,0 -8.72,4.744 -8.72,4.744 0,0 3.963,4.767 8.72,4.764 4.757,-0.004 8.722,-4.77 8.722,-4.77 0,0 -3.964,-4.741 -8.722,-4.738 z m 0,8.09 c -1.842,0 -3.335,-1.494 -3.335,-3.336 0,-1.839 1.493,-3.336 3.335,-3.336 1.839,0 3.333,1.497 3.333,3.336 0.001,1.842 -1.493,3.336 -3.333,3.336 z" + id="path13" + style="fill:#ff0101;fill-opacity:1;display:inline" /><circle + cx="27.504999" + cy="29.597" + r="1.5140001" + id="circle15" + style="fill:#ff0101;fill-opacity:1;display:inline" /><circle + cx="14.875" + cy="29.597" + r="1.5140001" + id="circle17" + style="fill:#ff0101;fill-opacity:1;display:inline" /><circle + cx="10.375" + cy="29.597" + r="1.5140001" + id="circle19" + style="fill:#ff0101;fill-opacity:1;display:inline" /><circle + cx="43.875" + cy="29.597" + r="1.5140001" + id="circle21" + style="fill:#ff0101;fill-opacity:1;display:inline" /><circle + cx="39.375" + cy="29.597" + r="1.5140001" + id="circle23" + style="fill:#ff0101;fill-opacity:1;display:inline" /></svg>
\ No newline at end of file diff --git a/images/videosmall.svg b/images/videosmall.svg new file mode 100644 index 0000000..d7758f5 --- /dev/null +++ b/images/videosmall.svg @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="55" + height="55" + viewBox="0 0 55 55" + id="svg2" + xml:space="preserve"><metadata + id="metadata29"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs27"> + + + + + + + +</defs><g + transform="matrix(0.5,0,0,0.5,13.6875,13.7505)" + id="g5" + style="stroke-width:3.5;stroke-miterlimit:4;stroke-dasharray:none;display:inline"> + <g + id="g7" + style="stroke-width:3.5;stroke-miterlimit:4;stroke-dasharray:none"> + <polygon + points="48.788,43.944 48.788,23.002 36.849,11.058 5.962,11.058 5.962,43.944 " + id="polygon9" + style="fill:#ffffff;stroke:#010101;stroke-width:3.5;stroke-miterlimit:4;stroke-dasharray:none" /> + <polyline + style="fill:none;stroke:#010101;stroke-width:3.5;stroke-miterlimit:4;stroke-dasharray:none" + id="polyline11" + points="36.849,11.058 36.849,23.002 48.788,23.002 " /> + </g> + </g><path + d="m 27.4395,26.1715 c -2.3785,0 -4.36,2.372 -4.36,2.372 0,0 1.9815,2.3835 4.36,2.382 2.3785,-0.002 4.361,-2.385 4.361,-2.385 0,0 -1.982,-2.3705 -4.361,-2.369 z m 0,4.045 c -0.921,0 -1.6675,-0.747 -1.6675,-1.668 0,-0.9195 0.7465,-1.668 1.6675,-1.668 0.9195,0 1.6665,0.7485 1.6665,1.668 5e-4,0.921 -0.7465,1.668 -1.6665,1.668 z" + id="path13" + style="fill:#010101;display:inline" /><circle + cx="27.504999" + cy="29.597" + r="1.5140001" + transform="matrix(0.5,0,0,0.5,13.6875,13.7505)" + id="circle15" + style="fill:#010101;display:inline" /><circle + cx="14.875" + cy="29.597" + r="1.5140001" + transform="matrix(0.5,0,0,0.5,13.6875,13.7505)" + id="circle17" + style="fill:#010101;display:inline" /><circle + cx="10.375" + cy="29.597" + r="1.5140001" + transform="matrix(0.5,0,0,0.5,13.6875,13.7505)" + id="circle19" + style="fill:#010101;display:inline" /><circle + cx="43.875" + cy="29.597" + r="1.5140001" + transform="matrix(0.5,0,0,0.5,13.6875,13.7505)" + id="circle21" + style="fill:#010101;display:inline" /><circle + cx="39.375" + cy="29.597" + r="1.5140001" + transform="matrix(0.5,0,0,0.5,13.6875,13.7505)" + id="circle23" + style="fill:#010101;display:inline" /></svg>
\ No newline at end of file diff --git a/images/zerodivide.svg b/images/zerodivide.svg new file mode 100644 index 0000000..f2aa30a --- /dev/null +++ b/images/zerodivide.svg @@ -0,0 +1,74 @@ +<?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="767" + height="38" + id="svg2"> + <defs + id="defs32" /> + <path + d="M 15,37.5 C 11.5,37.5 8,35 5.5,32.5 3,30 0.5,26.5 0.5,23 l 0,-8 c 0,-3.25 2.5,-8.5 5,-10.5 2.5,-2 6,-4 9.5,-4 l 736.5,0 c 2.5,0 7,1 10.5,4 3.5,2.75 4.5,7.5 4.5,10.5 l 0,8 c 0,3.5 -2,7 -4.5,9.5 -2.5,2.5 -6.5,5 -10.5,5 L 15,37.5 z" + id="path4" + style="fill:#ffd000;fill-opacity:1;fill-rule:evenodd;stroke:#e0a000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + <g + transform="translate(656,65.625)" + id="g6"> + <path + d="m 79.5,438.5 c 0,4.5 -3.75,8 -8.5,8 -4.5,0 -8.25,-3.5 -8.25,-8 0,-4.5 3.75,-8.25 8.25,-8.25 4.75,0 8.5,3.75 8.5,8.25 l 0,0 z" + transform="translate(24,-485)" + id="path8" + style="fill:#ff4040;fill-opacity:1;fill-rule:nonzero;stroke:#ff4040;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + <text + id="text10" + style="font-size:12px;font-weight:bold;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="91" + y="-42" + id="tspan12" + style="font-size:12px">X</tspan> + </text> + </g> + <text + x="-108" + id="text13" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="62" + y="28" + id="tspan15" + style="font-size:24px">/0</tspan> + </text> + <g + transform="translate(6,0)" + id="g17"> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-4,20)" + id="path19" + style="fill:#404040;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(1,17)" + id="path21" + style="fill:#e0e0e0;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 44,15 10.5,15 27.5,-14 44,15 z" + transform="translate(-1,18)" + id="path23" + style="fill:#ffe000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <text + x="6" + id="text25" + style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"> + <tspan + x="27" + y="29" + id="tspan27" + style="font-size:24px">!</tspan> + </text> +</svg> diff --git a/plugins/__init__.py b/plugins/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/plugins/__init__.py diff --git a/plugins/plugin.py b/plugins/plugin.py new file mode 100644 index 0000000..3065129 --- /dev/null +++ b/plugins/plugin.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +#Copyright (c) 2011 Walter Bender +#Copyright (c) 2011 Collabora Ltd. <http://www.collabora.co.uk/> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import gobject + + +class Plugin(gobject.GObject): + def __init__(self): + gobject.GObject.__init__(self) + + def setup(self): + """ Setup is called once, when the Turtle Window is created. """ + pass + + def start(self): + """ start is called when run button is pressed. """ + pass + + def stop(self): + """ stop is called when stop button is pressed. """ + pass + + def goto_background(self): + """ goto_background is called when the activity is sent to the + background. """ + pass + + def return_to_foreground(self): + """ return_to_foreground is called when the activity returns to + the foreground. """ + pass + + def quit(self): + """ cleanup is called when the activity is exiting. """ + pass diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..fd6521a --- /dev/null +++ b/setup.cfg @@ -0,0 +1,3 @@ +[install] +install_data=/usr/share/turtleart +install_scripts=/usr/bin diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..e5026ee --- /dev/null +++ b/setup.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +import os +import sys + +if len(sys.argv) > 1 and '--no-sugar' == sys.argv[1]: + # Remove the argument from the stack so we don't cause problems + # for distutils + sys.argv.pop(1) + + import glob, os.path, string + from distutils.core import setup + + DATA_FILES = [ + ('icons', glob.glob('icons/*')), + ('images', glob.glob('images/*')), + ('/usr/share/applications', ['turtleart.desktop']) + ] + + setup (name = 'Turtle Art', + description = "A LOGO-like tool for teaching programming", + author = "Walter Bender", + author_email = "walter.bender@gmail.com", + version = '0.9.4', + packages = ['TurtleArt'], + scripts = ['turtleart'], + data_files = DATA_FILES, + ) +else: + from sugar.activity import bundlebuilder + + if __name__ == "__main__": + bundlebuilder.start() diff --git a/util/RtfParser.py b/util/RtfParser.py new file mode 100644 index 0000000..9a141a4 --- /dev/null +++ b/util/RtfParser.py @@ -0,0 +1,150 @@ +#Copyright (c) 2010, Loic Fejoz +#Copyright (c) 2010, Walter Bender + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + + +import sys + + +class RtfException(Exception): + pass + +plaintext = 1 +control = 2 +argument = 3 +backslash = 4 +escapedChar = 5 + + +class RtfParser(object): + + def __init__(self, unicode=False): + self.state = plaintext + self.arg = '' + self.token = '' + self.unicode = unicode + self.par = False + self.output = '' + + def getChar(self, code): + """ called when an escaped char is found """ + return chr(code) + + def getNonBreakingSpace(self): + return ' ' + + def pushState(self): + pass + + def popState(self): + pass + + def putChar(self): + pass + + def doControl(self, token, arg): + pass + + def feed(self, txt): + for c in txt: + self.feedChar(c) + + def feedChar(self, char): + if self.state == plaintext: # this is just normal user content + if char == '\\': + self.state = backslash + elif char == '{': + self.pushState() + elif char == '}': + self.popState() + else: + self.putChar(char) + elif self.state == backslash: # a command or escape + if char == '\\' or char == '{' or char == '}': + self.putChar(char) + self.state = plaintext + else: + if char.isalpha() or char in ('*', '-', '|'): + self.state = control + self.token = char + elif char == "'": + self.state = escapedChar + self.escapedChar = '' + elif char in ['\\', '{', '}']: + self.putChar(char) + self.state = plaintext + elif char == "~": # non breaking space + self.putChar(self.getNonBreakingSpace()) + self.state = plaintext + else: + raise RtfException(('unexpected %s after \\' % char)) + elif self.state == escapedChar: + self.escapedChar = self.escapedChar + char + if len(self.escapedChar) == 2: + char = self.getChar(int(self.escapedChar, 16)) + self.putChar(char) + self.state = plaintext + elif self.state == control: # collecting the command token + if char.isalpha(): + self.token = self.token + char + elif char.isdigit() or char == '-': + self.state = argument + self.arg = char + else: + self.doControl(self.token, self.arg) + self.state = plaintext + if char == '\\': + self.state = backslash + elif char == '{': + self.pushState() + elif char == '}': + self.popState() + else: + if not char.isspace(): + self.putChar(char) + elif self.state == argument: # collecting the optional argument + if char.isdigit(): + self.arg = self.arg + char + else: + self.state = plaintext + self.doControl(self.token, self.arg) + if char == '\\': + self.state = backslash + elif char == '{': + self.pushState() + elif char == '}': + self.popState() + else: + if not char.isspace(): + self.putChar(char) + + +class RtfTextOnly(RtfParser): + + def __init__(self): + RtfParser.__init__(self) + self.level = 0 + + def pushState(self): + self.level = self.level + 1 + + def popState(self): + self.level = self.level - 1 + + def putChar(self, ch): + if self.par: + self.output += ch + + def doControl(self, token, arg): + if token[0:3] == 'par': + self.par = True + pass diff --git a/util/__init__.py b/util/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/util/__init__.py diff --git a/util/configfile.py b/util/configfile.py new file mode 100644 index 0000000..adabb34 --- /dev/null +++ b/util/configfile.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python +# +# Copyright (c) 2011 Collabora Ltd. <http://www.collabora.co.uk/> +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +import gobject + + +class ConfigFile(gobject.GObject): + """Load/save a simple (key = value) config file""" + + __gsignals__ = { + 'configuration-loaded': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ()), + 'configuration-saved': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ()), + } + + def __init__(self, config_file_path, valid_keys={}): + gobject.GObject.__init__(self) + + self._config_file_path = config_file_path + self._valid_keys = valid_keys + self._config_hash = {} + self._is_loaded = False + + def set_valid_keys(self, valid_keys): + self._valid_keys = valid_keys + + def is_loaded(self): + return self._is_loaded + + def get(self, key, empty_if_not_loaded=False): + if not key in self._valid_keys: + raise RuntimeError("Unknown config value %s" % key) + + if key in self._config_hash: + value = self._config_hash[key] + else: + if self._valid_keys[key]["type"] == "text": + value = "" + elif self._valid_keys[key]["type"] == "boolean": + value = False + elif self._valid_keys[key]["type"] == "integer": + value = 0 + + return value + + def set(self, key, value): + if not key in self._valid_keys: + raise RuntimeError("Unknown config value %s" % key) + + self._config_hash[key] = value + + def load(self): + try: + config_file = open(self._config_file_path, 'r') + lines = config_file.readlines() + config_file.close() + for line in lines: + line = line.strip() + k, v = line.split('=') + k = k.strip(' ') + v = v.strip(' ') + if not k in self._valid_keys: + raise RuntimeError("Unknown config value %s" % k) + value_type = self._valid_keys[k]["type"] + if value_type == "text": + value = v + elif value_type == "boolean": + value = eval(v) + elif value_type == "integer": + value = int(v) + self._config_hash[k] = value + self._is_loaded = True + self.emit('configuration-loaded') + except Exception, e: + print e + + return self._is_loaded + + def save(self): + config_file = open(self._config_file_path, 'w') + for k in self._config_hash.keys(): + v = self._config_hash[k] + l = "%s = %s\n" % (k, v) + config_file.write(l) + config_file.close() + self.emit('configuration-saved') + + def dump_keys(self): + print "\n\nDumping keys\n\n" + for k in self._config_hash.keys(): + v = self._config_hash[k] + l = "%s = %s\n" % (k, v) + print l + + +def test_save_load(test_config_file): + keys = {} + keys["nick"] = {"type": "text"} + keys["account_id"] = {"type": "text"} + keys["server"] = {"type": "text"} + keys["port"] = {"type": "text"} + keys["password"] = {"type": "text"} + keys["register"] = {"type": "text"} + + c = ConfigFile(test_config_file) + c.set_valid_keys(keys) + c.set("nick", "rgs") + c.set("account_id", "rgs@andromeda") + c.set("server", "andromeda") + c.set("port", 5223) + c.set("password", "97c74fa0dc3b39b8c87f119fa53cced2b7040786") + c.set("register", True) + + c.save() + + c = ConfigFile(test_config_file) + c.set_valid_keys(keys) + c.load() + c.dump_keys() + + +def _configuration_saved_cb(config_file_obj): + print "_configuration_saved_cb called" + config_file_obj.dump_keys() + + +def _configuration_loaded_cb(config_file_obj): + print "_configuration_loaded_cb called" + config_file_obj.dump_keys() + + +def test_signals(test_config_file): + keys = {} + keys["nick"] = {"type": "text"} + keys["account_id"] = {"type": "text"} + keys["server"] = {"type": "text"} + keys["port"] = {"type": "text"} + keys["password"] = {"type": "text"} + keys["register"] = {"type": "text"} + + c = ConfigFile(test_config_file) + c.connect('configuration-saved', _configuration_saved_cb) + c.set_valid_keys(keys) + c.set("nick", "rgs") + c.set("account_id", "rgs@andromeda") + c.set("server", "andromeda") + c.set("port", 5223) + c.set("password", "97c74fa0dc3b39b8c87f119fa53cced2b7040786") + c.set("register", True) + + c.save() + + c = ConfigFile(test_config_file) + c.connect('configuration-loaded', _configuration_loaded_cb) + c.set_valid_keys(keys) + c.load() + + +if __name__ == "__main__": + test_save_load("/tmp/configfile.0001") + test_signals("/tmp/configfile.0002") diff --git a/util/configwizard.py b/util/configwizard.py new file mode 100644 index 0000000..6c66bd1 --- /dev/null +++ b/util/configwizard.py @@ -0,0 +1,218 @@ +#!/usr/bin/python +# Copyright (c) 2011 Collabora Ltd. <http://www.collabora.co.uk/> +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +from configfile import ConfigFile +import gtk + + +class ConfigWizard(): + """Simple configuration wizard window.""" + + def __init__(self, config_file_path): + self._config_items = [] + self._config_entries = {} + self._config_file_path = config_file_path + self._config_file_obj = None + + """ + [ {item_label, item_type, item_name, item_with_value} , ... ] + """ + def set_config_items(self, items): + self._config_items = items + keys = {} + for i in self._config_items: + keys[i["item_name"]] = {"type": i["item_type"]} + self._valid_keys = keys + + def set_config_file_obj(self, obj): + self._config_file_obj = obj + + def get_config_file_obj(self, obj): + return self._config_file_obj + + def show(self, read_from_disc=False): + + if read_from_disc: + self._config_file_obj = ConfigFile(self._config_file_path) + self._config_file_obj.set_valid_keys(self._valid_keys) + self._config_file_obj.load() + else: + if self._config_file_obj is None: + raise RuntimeError("I need the run time obj") + + self._config_popup = gtk.Window() + self._config_popup.set_default_size(200, 200) + self._config_popup.connect('delete_event', self._close_config_cb) + table = gtk.Table(12, 1, True) + self._config_popup.add(table) + + row = 1 + for i in self._config_items: + hbox = self._create_param(i) + table.attach(hbox, 0, 1, row, row + 1, xpadding=5, ypadding=2) + row = row + 1 + + hbox = gtk.HBox() + save_button = gtk.Button('Save') + save_button.set_size_request(50, 15) + save_button.connect('pressed', self._save_config_cb) + hbox.add(save_button) + cancel_button = gtk.Button('Cancel') + cancel_button.set_size_request(50, 15) + cancel_button.connect('pressed', self._close_config_cb) + hbox.add(cancel_button) + table.attach(hbox, 0, 1, row, row + 1, xpadding=5, ypadding=2) + + self._config_popup.show_all() + + def _save_config_cb(self, widget): + try: + self._do_save_config() + except Exception, e: + w = gtk.Window() + l = gtk.Label(e.message) + w.add(l) + w.show_all() + finally: + self._config_popup.hide() + + def _do_save_config(self): + for i in self._config_items: + param_name = i["item_name"] + v = self._config_entries[param_name] + if v.__class__ is gtk.Entry: + value = v.get_text() + elif v.__class__ is gtk.CheckButton: + value = v.get_active() + else: + raise RuntimeError("Don't recognize the class %s" % type(v)) + self._config_file_obj.set(param_name, value) + + self._config_file_obj.save() + + """ + {item_label, item_type, item_name, item_with_value} + """ + def _create_param(self, opts): + param_name = opts["item_name"] + with_value = opts["item_with_value"] if "item_with_value" in opts \ + else True + hbox = gtk.HBox() + if opts["item_type"] == "text": + entry = gtk.Entry() + entry.set_size_request(150, 25) + if with_value: + value = self._config_file_obj.get(param_name, True) + entry.set_text(str(value)) + elif opts["item_type"] == "boolean": + entry = gtk.CheckButton() + if with_value: + value = self._config_file_obj.get(param_name, True) + entry.set_active(value) + self._config_entries[param_name] = entry + label = gtk.Label(opts["item_label"] + ': ') + label.set_alignment(1.0, 0.5) + label.set_size_request(100, 25) + hbox.add(label) + hbox.add(entry) + return hbox + + def _close_config_cb(self, widget, event=None): + self._config_popup.hide() + + +def test_wizard_from_config_file_obj(test_config_file): + keys = {} + keys["nick"] = {"type": "text"} + keys["account_id"] = {"type": "text"} + keys["server"] = {"type": "text"} + keys["port"] = {"type": "text"} + keys["password"] = {"type": "text"} + keys["register"] = {"type": "text"} + + c = ConfigFile(test_config_file) + c.set_valid_keys(keys) + c.set("nick", "rgs") + c.set("account_id", "rgs@andromeda") + c.set("server", "andromeda") + c.set("port", 5223) + c.set("password", "97c74fa0dc3b39b8c87f119fa53cced2b7040786") + c.set("register", True) + + c.save() + + c = ConfigFile(test_config_file) + c.set_valid_keys(keys) + c.load() + + config_w = ConfigWizard(test_config_file) + config_items = [ + {"item_label": "Nickname", "item_type": "text", "item_name": "nick"}, + {"item_label": "Account ID", "item_type": "text", + "item_name": "account_id"}, + {"item_label": "Server", "item_type": "text", "item_name": "server"}, + {"item_label": "Port", "item_type": "text", "item_name": "port"}, + {"item_label": "Password", "item_type": "text", + "item_name": "password"}, + {"item_label": "Register", "item_type": "text", + "item_name": "register"} + ] + config_w.set_config_items(config_items) + config_w.set_config_file_obj(c) + config_w.show() + + +def test_wizard_from_config_file_path(test_config_file): + keys = {} + keys["nick"] = {"type": "text"} + keys["account_id"] = {"type": "text"} + keys["server"] = {"type": "text"} + keys["port"] = {"type": "text"} + keys["password"] = {"type": "text"} + keys["register"] = {"type": "text"} + + c = ConfigFile(test_config_file) + c.set_valid_keys(keys) + c.set("nick", "rgs") + c.set("account_id", "rgs@andromeda") + c.set("server", "andromeda") + c.set("port", 5223) + c.set("password", "97c74fa0dc3b39b8c87f119fa53cced2b7040786") + c.set("register", True) + + c.save() + + config_w = ConfigWizard(test_config_file) + config_items = [ + {"item_label": "Nickname", "item_type": "text", "item_name": "nick"}, + {"item_label": "Account ID", "item_type": "text", + "item_name": "account_id"}, + {"item_label": "Server", "item_type": "text", "item_name": "server"}, + {"item_label": "Port", "item_type": "text", "item_name": "port"}, + {"item_label": "Password", "item_type": "text", + "item_name": "password"}, + {"item_label": "Register", "item_type": "text", + "item_name": "register"} + ] + config_w.set_config_items(config_items) + config_w.show(True) + + +if __name__ == "__main__": + #test_wizard_from_config_file_obj("/tmp/configwizard.test.0001") + test_wizard_from_config_file_path("/tmp/configwizard.test.0002") + gtk.main() diff --git a/util/helpbutton.py b/util/helpbutton.py new file mode 100644 index 0000000..47a36cd --- /dev/null +++ b/util/helpbutton.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2012, Gonzalo Odiard <godiard@gmail.com> +# Copyright (C) 2012, Walter Bender <walter@sugarlabs.org> + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +# HelpButton widget + +from gettext import gettext as _ + +import gtk + +from sugar.graphics.toolbutton import ToolButton +from sugar.graphics.icon import Icon +from sugar.graphics import style + +from TurtleArt.tapalette import palette_names, help_windows + +import logging +_logger = logging.getLogger('turtleart-activity') + + +class HelpButton(gtk.ToolItem): + + def __init__(self, activity): + self._activity = activity + self._current_palette = 'turtle' + + gtk.ToolItem.__init__(self) + + help_button = ToolButton('help-toolbar') + help_button.set_tooltip(_('Help')) + self.add(help_button) + help_button.show() + + self._palette = help_button.get_palette() + + help_button.connect('clicked', self.__help_button_clicked_cb) + + def set_current_palette(self, name): + self._current_palette = name + + def __help_button_clicked_cb(self, button): + if self._activity.palette_toolbar_button.is_expanded(): + if not (self._current_palette in help_windows): + _logger.debug('name %s not found' % (self._current_palette)) + return + self._palette.set_content(help_windows[self._current_palette]) + help_windows[self._current_palette].show_all() + elif self._activity.edit_toolbar_button.is_expanded(): + self._palette.set_content(help_windows['edit-toolbar']) + help_windows['edit-toolbar'].show_all() + elif self._activity.view_toolbar_button.is_expanded(): + self._palette.set_content(help_windows['view-toolbar']) + help_windows['view-toolbar'].show_all() + elif self._activity.activity_toolbar_button.is_expanded(): + self._palette.set_content(help_windows['activity-toolbar']) + help_windows['activity-toolbar'].show_all() + else: + self._palette.set_content(help_windows['main-toolbar']) + help_windows['main-toolbar'].show_all() + + self._palette.popup(immediate=True, state=1) + + +def add_section(help_box, section_text, icon=None): + ''' Add a section to the help palette. From helpbutton.py by + Gonzalo Odiard ''' + max_text_width = int(gtk.gdk.screen_width() / 3) - 20 + hbox = gtk.HBox() + label = gtk.Label() + label.set_use_markup(True) + label.set_markup('<b>%s</b>' % section_text) + label.set_line_wrap(True) + label.set_size_request(max_text_width, -1) + hbox.add(label) + if icon is not None: + _icon = Icon(icon_name=icon) + hbox.add(_icon) + label.set_size_request(max_text_width - 20, -1) + else: + label.set_size_request(max_text_width, -1) + + hbox.show_all() + help_box.pack_start(hbox, False, False, padding=5) + + +def add_paragraph(help_box, text, icon=None): + ''' Add an entry to the help palette. From helpbutton.py by + Gonzalo Odiard ''' + max_text_width = int(gtk.gdk.screen_width() / 3) - 20 + hbox = gtk.HBox() + label = gtk.Label(text) + label.set_justify(gtk.JUSTIFY_LEFT) + label.set_line_wrap(True) + hbox.add(label) + if icon is not None: + _icon = Icon(icon_name=icon) + hbox.add(_icon) + label.set_size_request(max_text_width - 20, -1) + else: + label.set_size_request(max_text_width, -1) + + hbox.show_all() + help_box.pack_start(hbox, False, False, padding=5) diff --git a/util/menubuilder.py b/util/menubuilder.py new file mode 100644 index 0000000..4ee4550 --- /dev/null +++ b/util/menubuilder.py @@ -0,0 +1,39 @@ +#!/usr/bin/python +# Copyright (c) 2011 Collabora Ltd. <http://www.collabora.co.uk/> +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +import gtk + + +class MenuBuilder(): + @classmethod + def make_sub_menu(cls, menu, name): + """ add a new submenu to the toolbar """ + sub_menu = gtk.MenuItem(name) + sub_menu.show() + sub_menu.set_submenu(menu) + return sub_menu + + @classmethod + def make_menu_item(cls, menu, tooltip, callback, arg=None): + """ add a new item to the submenu """ + menu_items = gtk.MenuItem(tooltip) + menu.append(menu_items) + if arg is None: + menu_items.connect('activate', callback) + else: + menu_items.connect('activate', callback, arg) + menu_items.show() |