tpclient-pywx-0.3.1.1/0000755000175000017500000000000010773624641012657 5ustar timtimtpclient-pywx-0.3.1.1/doc/0000755000175000017500000000000010773624641013424 5ustar timtimtpclient-pywx-0.3.1.1/doc/COPYING0000644000175000017500000004313110773624641014461 0ustar timtim GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. tpclient-pywx-0.3.1.1/doc/tp-pywx-installed0000755000175000017500000000052510773624641016761 0ustar timtim#! /bin/sh ARGS="" for ARG in "$@"; do ARGS="$ARGS \"$ARG\"" done echo "The client is installed in $$CODEPATH$$" export TPCLIENT_GRAPHICS=$$GRAPHICSPATH$$ export TPCLIENT_DOC=$$DOCPATH$$ echo "Graphics are installed in $TPCLIENT_GRAPHICS" echo "Documents are installed in $TPCLIENT_DOC" cd $$CODEPATH$$ $$CODEPATH$$/tpclient-pywx $ARGS tpclient-pywx-0.3.1.1/doc/tips.txt0000644000175000017500000000157310773624641015152 0ustar timtim_("Welcome to tpclient-pywx. This client is written in python using wxPython and should allow to connect to any Thousand Parsec server.") _("You can click on the star map to select objects!") _("The client has many shortcuts, check out the help file for more information.") _("You can quickly issue a move order by right clicking where you want an object to go.") _("The waypoint mode is a good way of setting up a large path quickly.") _("You can right click on the orders windows to access a bunch of quick functions including cut, copy and paste!") _("If the paste menu option is grayed out, the orders you are trying to paste are not valid on that object.") _("If you hold down shift a number of buttons change to allow you to quickly jump to first or last of things.") _("The system filter box uses standard matching pattern, you can use ? for a single character or * for any number.") tpclient-pywx-0.3.1.1/LICENSE0000644000175000017500000000027210773624641013665 0ustar timtimLicense ------- All files inside this repository are licensed under the GNU General Public License version 2 or later (your choice) unless otherwise stated (see COPYING for details). tpclient-pywx-0.3.1.1/AUTHORS0000644000175000017500000000004410773624641013725 0ustar timtimTim Ansell (tim@thousandparsec.net) tpclient-pywx-0.3.1.1/tpclient-pywx0000755000175000017500000002752010773624641015442 0ustar timtim#! /usr/bin/env python import os import os.path import sys # Ignore warnings when we are a binary if hasattr(sys, 'frozen'): import warnings warnings.simplefilter('ignore', DeprecationWarning) from requirements import location import extra # wx.Python imports import wx # Python Imports import time import threading import traceback # Local imports import utils from version import version from tp.netlib import failed from tp.client.threads import NotImportantEvent, Event from tp.client.ChangeList import ChangeNode pyid = id class ThreadExited(Exception): pass from tp.client.threads import ThreadStop def make(me, thread, method): def t(*args, **kw): if me.reset: raise ThreadStop("Should die now!") thread.Call(method, *args, **kw) return t class wxPyEvent(wx.PyEvent, Event): def __init__(self): self.source = None wx.PyEvent.__init__(self) Event.__init__(self) class EventBinder(dict): def __init__(self, *args, **kw): self.LastEvent = {} self.Preconditions = {} dict.__init__(self, *args, **kw) def Bind(self, event, function, precondition=None): if not issubclass(event, Event): raise TypeError("First argument must be an event object.") if not callable(function): raise TypeError("Second argument must be a callable.") if not precondition is None and not callable(precondition): raise TypeError("precondition must be a callable.") name = event.__name__ if not self.has_key(name): self[name] = [] self[name].append((function, precondition)) __call__ = Bind def Unbind(self, event, function, precondition=None): if not issubclass(event, Event): raise TypeError("First argument must be an event object.") if not callable(function): raise TypeError("Argument must be a callable.") if not precondition is None and not callable(precondition): raise TypeError("precondition must be a callable.") name = event.__name__ if not self.has_key(name) or not function in self[name]: raise KeyError("That function is not bound to that argument!") self[name].remove((function, precondition)) if len(self[name]) == 0: del self[name] def Post(self, event): # Make sure that this event has not already passed try: if self.LastEvent[event.type] > event.time: return except KeyError: pass self.LastEvent[event.type] = event.time # The people we have already sent the even too sentto = [event.source] # FIXME: This set does not guarentee the order! bases = set([event.__class__]) while len(bases) > 0: # Get the next base class cls = bases.pop() # Add this class bases to be checked bases.update(cls.__bases__) name = cls.__name__ # See if we have anyone who wants to be called for this type. if not self.has_key(name): continue for function, precondition in self[name]: # Source is a function if function in sentto: continue # If source is an class, get the function off the class so we can check if hasattr(event.source, function.__name__) and getattr(event.source, function.__name__) == function: continue try: if not precondition is None and not precondition(): continue function(event) except Exception, e: utils.do_traceback() sentto.append(function) #print "I sent the following event (from %r) %r to %r" % (event.source, event, sentto) class GUI(wx.App): ## These are window events class ShowWindowEvent(wxPyEvent): """\ Raised when the the windows are showed. """ pass class SelectObjectEvent(wxPyEvent): """\ Raised when an object is selected. """ def __init__(self, id): wxPyEvent.__init__(self) assert id >= 0 self.id = id def __str__(self): return "" % self.id __repr__ = __str__ class PreviewObjectEvent(SelectObjectEvent): pass class SelectPositionEvent(wxPyEvent): """\ Raised when a position is selected. """ def __init__(self, pos): wxPyEvent.__init__(self) self.x, self.y, self.z = pos def __str__(self): return "" % (self.x, self.y, self.z) __repr__ = __str__ class SelectOrderEvent(wxPyEvent): """\ Raised when an order is selected. """ def __init__(self, id, nodes): wxPyEvent.__init__(self) self.id = id if not hasattr(nodes, '__getitem__'): nodes = [nodes] for node in nodes: assert isinstance(node, ChangeNode) self.nodes = nodes def __str__(self): return "" % (pyid(self), self.id, self.nodes) __repr__ = __str__ class DirtyOrderEvent(wxPyEvent): """\ Raised when an order value changes but hasn't been saved yet. """ def __init__(self, id, node): wxPyEvent.__init__(self) self.id = id self.nodes = [node] self.order = node.pending def __str__(self): return "" % (self.id, self.nodes) __repr__ = __str__ ###################################### def __init__(self, application): if wx.Platform in ('__WXMSW__', '__WXMAC__'): #wx.App.__init__(self, redirect = True, filename = 'errors') wx.App.__init__(self, redirect=False) else: wx.App.__init__(self) self.Binder = EventBinder() ############ # Setup the translation stuff... import gettext # Hack to get the locale directory basepath = os.path.abspath(location()) localedir = os.path.join(basepath, "locale") langid = wx.LANGUAGE_DEFAULT # use OS default; or use LANGUAGE_JAPANESE, etc. domain = "tpclient-pywx" # the translation file is tpclient-pywx.mo # Set locale for wxWidgets mylocale = wx.Locale(langid) mylocale.AddCatalogLookupPathPrefix(localedir) mylocale.AddCatalog(domain) # Set up Python's gettext mytranslation = gettext.translation(domain, localedir, [mylocale.GetCanonicalName()], fallback = True) mytranslation.install() __builtins__._ = wx.GetTranslation ############## self.start = self.MainLoop self.application = application self.exit = False self.current = None # Show the splash screen from windows.winSplash import winSplash self.splash = winSplash(application) self.Show(self.splash) def Create(self): self.count = 0 self.UpdateUILock = threading.Lock() self.GUIThread = threading.currentThread() application = self.application try: wx.InitAllImageHandlers() # Load the other main windows from windows.winMain import winMain self.main = winMain(application) from windows.winConnect import winConnect self.connectto = winConnect(application) from windows.winServerBrowser import winServerBrowser self.servers = winServerBrowser(application) from windows.winAccount import winAccount self.account = winAccount(application) from windows.winUpdate import winUpdate self.update = winUpdate(application) self.windows = (self.main, self.connectto, self.update) from windows.winConfig import winConfig self.config = winConfig(application, self.windows) except: utils.do_traceback() self.Call(self.Show, self.connectto) def __str__(self): return "" % hex(pyid(self)) def Cleanup(self): for window in self.windows: window.Close() while self.application.network.isAlive() or self.application.media.isAlive(): time.sleep(0.1) sys.exit() # Config Functions ------------------------------------------------ def ConfigDisplay(self): """\ Display the configuration window. """ self.config.Show(True) def ConfigSave(self): """\ Display the configuration window. """ config = {} for window in self.windows: config[window.title] = window.ConfigSave() return config def ConfigLoad(self, config): """\ Display the configuration window. """ for window in self.windows: window.ConfigLoad(config.get(window.title, {})) # Inter-Thread Functions ------------------------------------------------ def Call(self, method, *args, **kw): """\ Call a method in this thread. """ if (threading.currentThread() == self.GUIThread): wx.CallAfter(method, *args, **kw) else: self.UpdateUILock.acquire() wx.CallAfter(method, *args, **kw) self.count += 1 if self.count % 5 == 0: wx.CallAfter(self.UpdateUI) else: self.UpdateUILock.release() def UpdateUI(self): wx.Yield() self.UpdateUILock.release() def Post(self, event): """ Post an Event the current window. """ func = 'On' + event.type if hasattr(self, func): try: getattr(self, func)(event) except Exception, e: utils.do_traceback() self.Binder.Post(event) def Show(self, window): """ Change to a certain main window. """ if window == self.current: self.current.Show() return if self.current != None: try: self.current.Hide() except Exception, e: utils.do_traceback() if isinstance(window, wx.Window): self.SetTopWindow(window) self.current = window r = self.current.Show() self.Post(self.ShowWindowEvent()) return r def OnNetworkFailure(self, evt): if hasattr(self.current, "OnNetworkFailure"): return else: print "OnNetworkFailure", evt self.Show(self.connectto) # When the network fails pop-up a dialog then go to the connectto screen dlg = wx.MessageDialog(self.application.gui.current, unicode(evt), _("Network Error"), wx.OK|wx.ICON_ERROR) dlg.ShowModal() dlg.Destroy() from tp.client.threads import NetworkThread class Network(NetworkThread): def ConnectTo(self, host, username, password, debug=False): """\ Connect to a given host using a certain username and password. """ # FIXME: This should be sending events really gui = self.application.gui up = make(self, gui, gui.update.Callback) # Show the Update window gui.Call(gui.Show, gui.update) if NetworkThread.ConnectTo(self, host, username, password, debug, up, cs="tpclient-pywx/%s.%s.%s" % version): self.CacheUpdate() media = self.application.media media.Call(media.ConnectTo, host, username) else: print "Connecting to failed" def CacheUpdate(self): gui = self.application.gui up = make(self, gui, gui.update.Callback) # Show the update window gui.Call(gui.Show, gui.update) while gui.current != gui.update: time.sleep(0.1) up("connecting", "start", "Connecting...") up("connecting", "finished", "") NetworkThread.CacheUpdate(self, up) up("finishing", "finished", "") self.EOTUpdate() def EOTUpdate(self): # FIXME: This should go away... # FIXME: This is bad :/ gui = self.application.gui timeRemaining = self.connection.time(), time.time() if failed(timeRemaining[0]): return gui.Call( gui.main.statusbar.SetEndTime, timeRemaining[0]+timeRemaining[1] ) from tp.client.threads import Application as ClientApplication class Application(ClientApplication): # We used custom GUI and Network threads GUIClass = GUI NetworkClass = Network # We just use the default threads from libtpclient-py from tp.client.threads import MediaThread, FinderThread MediaClass = MediaThread FinderClass = FinderThread ConfigFile = "pywx_preferences" def __init__(self, url=None): # self.gui is initialised from this Application.GUIClass # self.network is initialised from this Application.NetworkClass # self.media is initialised from this Application.MediaClass # self.finder is initialised from this Application.FinderClass ClientApplication.__init__(self) if url != None: self.gui.connectto.ShowURL(url) def Run(self): """\ Set the application running. """ self.gui.Show(self.gui.connectto) ClientApplication.Run(self) def ConfigDisplay(self): """\ Pop-up the configuration window. """ self.gui.ConfigDisplay() if __name__ == '__main__': try: if hasattr(sys,"frozen") and sys.frozen == "windows_exe": pwd=os.path.dirname(os.path.join(os.path.abspath(sys.executable))) else: pwd=os.path.dirname(os.path.join(os.path.abspath(__file__))) os.chdir(pwd) url = None if len(sys.argv) > 1: url = sys.argv[1] app = Application(url) app.Run() finally: utils.do_traceback() tpclient-pywx-0.3.1.1/utils.py0000644000175000017500000000250710773624641014375 0ustar timtim"""\ This file contains useful utilities for useage in the program. """ import pprint import sys import string import traceback import os import os.path try: import cPickle as pickle except ImportError: import pickle def do_traceback(): type, val, tb = sys.exc_info() if type is None or val is None or tb is None: return sys.stderr.write(string.join(traceback.format_exception(type, val, tb), '')) if hasattr(sys.stderr, "flush"): sys.stderr.flush() def warn(string): print "WARNING:", string class Blank: pass def configpath(): """\ Figures out where to save the preferences. """ dirs = [("APPDATA", "Thousand Parsec"), ("HOME", ".tp"), (".", "var")] for base, extra in dirs: if base in os.environ: base = os.environ[base] elif base != ".": continue rc = os.path.join(base, extra) if not os.path.exists(rc): os.mkdir(rc) return rc def load_data(file): """\ Loads preference data from a file. """ try: f = open(os.path.join(configpath(), file), "r") data = pickle.load(f) except IOError: return None return data def save_data(file, data): """\ Saves preference data to a file. """ f = open(os.path.join(configpath(), file), "w") pickle.dump(data, f) f.close() __all__ = [ 'Blank', 'save_data', 'load_data', 'configpath', # Config functions 'do_traceback', # Debugging functions ] tpclient-pywx-0.3.1.1/locale/0000755000175000017500000000000010773624641014116 5ustar timtimtpclient-pywx-0.3.1.1/locale/sl/0000755000175000017500000000000010773624641014534 5ustar timtimtpclient-pywx-0.3.1.1/locale/sl/tpclient-pywx.mo0000644000175000017500000006226110773624641017727 0ustar timtim0 *7_4D2y &9BJQW_ek p} ( 5~!!#!!!! !""" /",<"/i"."" """""2"-#/#8#<P#9# ####(#$(.$W$ r$ |$$X$T$T<%%%%!%%)& ,&!:&\&a&6&&&&&&& &&&'*'1'@'H' h''''''' ((((((DH(4( (((( (& )1)7)#;)!_)))) ) ) ))))*8*+U*:***** ++;+P+k+r+w+hz+j+N, h,t,,b-r--3-5-- ."+. N.X. h. r. }.%.!..... / "/0/ 4/ >/ I/T/Y/ s/ ////// // / / 0050+J0.v0000000 0 001 11 1#1(1 11 <1 H1T1g111"1'122 62 @2L2S20X222:2$233&3.3 43>3V3/\333 3%3334404'D4el4W4**5LU5.5:5o 6D|6;667C-7$q7s7R 8Q]8M8c8.a99999 9999%9:1:D:W: h:u:}:::"::O;U;%];5;;;;;0;T;mO<<<<<$>s>r:C+C+CDDD#D6DODhDDD DDD DDDD DD D DE E(E;E@E DEOEWE\E`EdE/F /G":G]GdGuG {G GGGG2G,G+HKHOHbHvH{HH9HH HHAH8+I dIoI wI I5II"II J )J 4Jp?JnJnKK KK+KK+L2LBL_LgL3LLLLLLLLM$MAMHM`M hM$MM M MMMN&N.N 4N>N2DNFwN:N&N O.O7O >O*IOtOyO&}O$OOOOOOP%P"DP(gPPP/P4P1QQQkQqQ Q"QQ"QQQQsQosRR RSYSYkS SS7S9T-LT*zT+TTT T T U)U#]<]"^7^FL^'^^DR_:_W_w*`-``+` aa$a?aEaKa"Oaraaaaa a a aa b2bbb,b7 cAc CcMc Oc9Yctcdddd2<$BC'ZtH&GOz}RV #k5,;\,0)N{|vQ-7j%L!4!0yE#w>leq)  '%sDUM-i* J gap$r_o.S 3.xA^F?PI@6`T 1"&hXW(Kb[ (]"c/++= f/ 8u:9Yd*m n~ Unknown Resource %i, S: %i, M: %i, I: %s

It appears that you do not own any objects. This may be for a number of reasons:

  • You have logged in as a guest user.

    On most servers guest users can only login and view the universe. They own no objects and can not issue orders. This is good to checkout what the Universe is like, but not if you actually want to play the game.

    Most servers allow you to create accounts right from this client! This can be done by clicking "Find" on the Login window to bring up the server browser. (Open server browser window.)


  • You have been defeated.

    If you have not logged in for a long time, all your objects may have been conquered or destroyed. Some servers may let you create a new account and start again.


  • There is a problem.

    There could be a bug in some of the software, if you are sure neither of the two cases above are correct please report it here.

The client is already set to autoconnect to %s. Would you instead like to autoconnect to %s. Would you like to continue adding these components? Would you like to continue adding this component? %i of %i%s %s inaccessible, %s %s minable, %s %s of %s inaccessible, %s %s of %s minable, %s %s of %s on surface, %s %s on surface, %s of %s&Cancel&Close&Copy&Delete&Find&Help&New&New Account&OK&Preferences&Refresh&Revert&Save(C) 2001-2008 Thousand Parsec Developers000010%100 of 10010kb/s43s50%80%
Subject: You are unloved!
You have recived no messages this turn!

Actually if you didn't recive any messages it most proberly means that your client couldn't load the results from the server. Try reload/restart the client.
A traceback of the error was printed to the console. AboutAbout the client you are running...AccountAccount CreatedAddAdd Account?Add ManyAfterAll fields are required.All filteredAny changes since last save have been lost. Argument type (ARG_PLAYER) not implimented yet.Argument type (ARG_RANGE) not implimented yet.At AutoconnectAutoconnect to?BeforeBoardsBoxBuilding two way tree of the universe for speed...CC&onnectC&onnect to Game Ctrl-OCancel the current update and go back to the connect screen.Cant paste because the orders arn't valid on this object.CategoriesCheckChoice 1Choice 2Choose a server to create an account on.Choose your password here.Cleaning up %s which have disappeared...Cleaning up any stray %s..ComponentComponentsConfigConfig-%s: Did not find a default position for your resolution (using 1024x768 defaults)Config-%s: Did not find a default show for your resolution (using 1024x768 defaults)Config-%s: Did not find a default size for your resolution (using 1024x768 defaults)Configure the ClientConnectConnect to Game Ctrl-OConnect to Thousand Parsec ServerConnect to a diffrent GameConnect to the currently selected server.Connecting...Continue to the main game window.CopyCopy the URL to the clipboard.Create a new account on the currently selected server.Create an AccountCurrent orders on %s.CutDDNSDebugDebug OutputDeleteDelete the currently selected order(s)DesignDesign WarningDesignsDo not show this message again.Don't have any messages to get..Don't have any orders to get..DoneDone!Download the &Universe Ctrl-UDownload the UniverseDownload the Universe Ctrl-UDuplicateEditEmail ExitFailed to get %s for %s (id: %s) (%s)...Failed to get order description with id, %i (last modified at %s)...Failed to get the %s which was previously called %s.Failed to get the %s with id %s.Fields RequiredFileFilterFinding %sFinished getting order descriptions...FirstFitForce a refresh of the server list.Found a Thousand Parsec Server...Found stray %s for %s..GGameGetting %sGetting %s..Getting %s...Getting order descriptions...Getting player objects...Getting your player object...Go to the online help page.Got %i %s for %s (id: %s)...Got %s %s (id: %i) (last modified at %s)...Got order description %s (ID: %i) (last modified at %s)...Got player %s (id: %i)...Got the supported features...GotoGotten all %s...Gotten all the %s..Gotten your player object...Have %i %s to get...Have to get %s for %i %s..HeightHelpIPIf the paste menu option is grayed out, the orders you are trying to paste are not valid on that object.If you hold down shift a number of buttons change to allow you to quickly jump to first or last of things.Important Information....InformationInsert new order.It appears you are using a different password for this account, would you like to update the saved information with the new password? It appears you havn't access this account before. Would you like to save this account's details? Known UniverseLastList of all the servers found on the local network.List of all the servers registered on the metaserver.ListAdd: No type selected.ListDel: No selection selected.ListSelect: No selection selected.LocationsLogged in okay!Login forLogin for Login for %sLooking for Thousand Parsec Server...Looking for supported features...MessagesMultiple orders selected.NameName goes hereName of object goes hereNetwork ErrorNewNew AfterNew BeforeNew DesignNextNo %s to get, skipping...No messagesNo objectNo object selected.No orders avaliableNot implimented.OObjectsObjects DescsObjects Without OrdersOnline HelpOrder DescsOrder InformationOrder queued for removal.Order type to createOrderSave: No order selected for save. (%s)OrderSave: No order selected for update. (%s))OrdersOtherPPasswordPassword fields do not match.PastePaste AfterPaste BeforePicturePlayersPlayingPortPreferencesPrevProgressPropertiesProperty 1:Property 2:Received all %s...Received all player objects...Received all the %s..Received your player object...Recieved all order descriptions...Removing %s %s as it has disappeared...Repeat the passwordRequest End of &Turn Ctrl-TResourcesResources: RevertSaveSave a copy of the message box window to a file.Save log as ...SelectObject: No such object.Send a message to the server requesting the turn end soon.Sending a request for all %s on %s..ServerServersShips: Show Show TipsShow seperate game box.Show?Skipping requesting %s on %s as there are none!Some Categories, Will Go, HereStarMapStatic textSuccessfully connected to the host...SystemTP: Connect to a ServerTP: Downloading UniverseTP: Server BrowserTP: Universe updateThe URL for the Thousand Parsec server.The client connected to the host but could not login because the username of password was incorrect. The client connected to the host but it did not appear to be a Thousand Parsec server. The client could not connect to the host. The client has many shortcuts, check out the help file for more information.The client was unable to connect to the host. The password for the account on the Thousand Parsec ServerThe system filter box uses standard matching pattern, you can use ? for a single character or * for any number.The turn has ended. Would you like to download all the new details? The username for the account on the Thousand Parsec server.The value of property 1The value of property 2The waypoint mode is a good way of setting up a large path quickly.There was an unknown network error. This Thousand Parsec client, written in python, is an easy way to join and start playing in a Thousand Parsec game.This could be because the server is down or the connection details are incorrect. This could be because the server is down or there is a problem with the network. This could be because the server is down or you mistyped the server address. This could be because you are connecting to the wrong server or mistyped the username or password. This server does not support account creation.Thousand ParsecThousand Parsec Server BrowserTitleTopTrying to Login to the server...TurnsTypeURLURL of the currently selected server.Universe DownloadUnknown (type: %s)Unknown Design id:Update Password?Update done!Update?UpdatingUsernameWarning - No Objects...Warning: Object %s does not exist!Welcome to tpclient-pywx. This client is written in python using wxPython and should allow to connect to any Thousand Parsec server.WidthWindowsWorking out the number of %s to get..Working out the number of order descriptions to get..XX PosYY PosYou can click on the star map to select objects!You can quickly issue a move order by right clicking where you want an object to go.You can right click on the orders windows to access a bunch of quick functions including cut, copy and paste!Zreceived all %s...wxPython ClientProject-Id-Version: tpclient-pywx Report-Msgid-Bugs-To: POT-Creation-Date: 2008-03-22 21:19+1030 PO-Revision-Date: 2008-03-22 22:00+0200 Last-Translator: Jure Repinc Language-Team: Slovenian MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Generator: KBabel 1.11.4 Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n%100==4 ? 3 : 0); Neznan vir %i, P: %i, I: %i, N: %s

Izgleda, da si ne lastite nobenega objekta. Možnih je več razlogov:

  • Prijavili ste se kot gost.

    Na večini strežnikov si gosti lahko le ogledujejo igro. Gosti si ne lastijo objektov in ne morejo izdajati ukazov. To je v redu, če si želite samo ogledati vesolje, ne pa dejansko igrati.

    Večina strežnikov vam omogoča ustvaritev računa kar iz tega odjemalca! To lahko storite s klikom na gumb »Najdi« v pogovornem oknu za prijavo. Pojavilo se bo okno za brskanje po strežnikih. (kliknite za odprtje tega okna)


  • Bili ste poraženi.

    Če se že dolgo niste prijavili na strežnik, so lahko drugi igralci zavzeli vse vaše objekte ali pa jih uničili. Nekateri strežniki vam omogočajo ustvaritev novega računa, s katerim lahko začnete znova.


  • Naleteli ste na napako.

    Mogoče je v programu napaka. Če ste prepričani, da ne gre za enega izmed gornjih dveh primer, poročajte o napaki na tej strani.

Odjemalec je že nastavljen za samodejno povezavo z %s. Želite zamenjati strežnik za samodejno povezavo z %s? Želite še naprej dodajati te komponente? Želite še naprej dodajati to komponento? %i od %i%s %s nedostopno, %s %s izkopljivo, %s %s od %s nedostopno, %s %s od %s izkopljivo, %s %s od %s na površju, %s %s na površju, %s od %s&Prekliči&Zapri&Kopiraj&Izbriši&Najdi&Pomoč&Nov&Nov račun&V redu&Nastavitve&Posodobi&Povrni&Shrani© 2001-2008, razvijalci Thousand Parsec000010%100 od 10010 kb/s43 s50%80%
Zadeva: Nihče vas nima rad!
Med to potezo niste dobili nobenega sporočila!

Če niste dobili nobenega sporočila, to najverjetneje pomeni, da vaš odjemalec ni pravilno prenesel rezultatov s strežnika. Poskusite ponovno zagnati odjemalca.
Povratna sled napake se je izpisala v konzoli. O programuO odjemalcu, ki ga uporabljate ...RačunRačun ustvarjenDodajDodam račun?Dodaj večZaVsa polja so obvezna.Vsa so filtriranaVse spremembe, ki niso shranjene, so se izgubile. Vrsta argumenta (ARG_PLAYER) še ni podprta.Vrsta argumenta (ARG_RANGE) še ni podprta.Na Samodejna povezavaSamodejna povezava?PredDeskeOkvirGrajenje dvosmernega drevesa vesolja, zaradi hitrosti ...CP&oveži seP&oveži se z igro Ctrl-OPrekliči trenutno posodobitev in se vrni na okno za povezovanje.Ni moč prilepiti, ker ukazi za ta objekt niso ustrezni.KategorijePreveriMožnost 1Možnost 2Izberite strežnik, na katerem se bo ustvaril račun.Sem vnesite svoje geslo.Čiščenje %s, ki so izginili ...Čiščenje izgubljenih %s ...KomponentaKomponenteNastavitveNastavitev-%s: Ni bilo moč najti privzetega položaja za vašo ločljivost (uporabljam privzetosti za 1024x768)Nastavitev-%s: Ni bilo moč najti privzetega prikaza za vašo ločljivost (uporabljam privzetosti za 1024x768)Nastavitev-%s: Ni bilo moč najti privzete velikosti za vašo ločljivost (uporabljam privzetosti za 1024x768)Nastavi programPoveži sePoveži se z igro Ctrl-OPoveži se s strežnikom za Thousand ParsecPoveži se z drugo igroPoveži se s trenutno izbranim strežnikom.Povezovanje ...Nadaljuj v glavno okno igre.KopirajKopiraj URL na odložišče.Ustvari nov račun na trenutno izbranem strežniku.Ustvari računTrenutni ukazi za %s.IzrežiIDNSRazhroščevanjeRazhroščevalni izhodIzbrišiIzbriši trenutno izbrana sporočilaNačrtOpozorilo glede načrtaNačrtiTega sporočila ne prikaži večZa pridobiti ni nobenega sporočila.Za pridobiti ni nobenega ukaza.ZaključenoZaključeno!Prenesi &vesolje Ctrl-VPrenesi vesoljePrenesi vesolje Ctrl-VPodvojiUrediE-pošta IzhodSpodletelo je pridobivanje %s za %s (ID: %s) (%s).Pridobivanje opisa ukaza z ID %i je spodletelo (zadnja sprememba: %s).Pridobivanje %s, ki se je prej imenoval %s, je spodletelo.Pridobivanje %s z ID %s je spodletelo.Obvezna poljaDatotekaFilterIskanje %sPridobivanje opisov ukazov je zaključeno.PrvoVseVsili posodobitev seznama strežnikov.Našel strežnik za Thousand Parsec.Našel izgubljenega %s za %s.IIgraPridobivanje %sPridobivanje %s...Pridobivanje %s ...Pridobivanje opisov ukazov ...Pridobivanje objektov igralcev ...Pridobivanje objekta vašega igralca ...Odpre spletno stran s pomočjo.Dobil %i %s za %s (ID: %s).Pridobil %s %s (ID: %i) (zadnja sprememba: %s).Dobil opis ukaza %s (ID: %i) (zadnja sprememba: %s).Pridobljen igralec %s (ID: %i).Dobil podprte zmožnosti.PojdiPridobil vse %s.Dobil vse %s.Objekt vašega igralca pridobljen.Za pridobiti je %i %s.Pridobiti je potrebno %s za %i %s.VišinaPomočIPČe je možnost za vstavljanje onemogočena, potem ukazi, ki jih želite vstaviti, za trenutni objekt niso mogoči.Če držite pritisnjeno tipko Shift, za nekatere bližnjice omogočite skok na prvo ali zadnjo stvar s seznama.Pomembni podatkiInformacijeVstavi nov ukaz.Izgleda, da uporabljate drugo geslo za ta račun. Želite zamenjati staro geslo z novim? Izgleda, da tega računa še niste uporabljali. Želite shraniti podatke o tem računu? Znano vesoljeZadnjeSeznam vseh strežnikov najdenih na krajevnem omrežju.Seznam vseh strežnikov registriranih pri metastrežniku.Dodajanje na seznam: Izbrane ni nobene vrste.Brisanje s seznama: Izbranega ni ničesar.Izbiranje s seznama: Izbranega ni ničesar.LokacijePrijava je uspela!Prijava zaPrijava za Prijava za %sIskanje strežnika za Thousand Parsec ...Preverjanje podprtih zmožnosti ...SporočilaIzbranih je več ukazov.ImeSem gre imeSem gre ime objektaNapaka glede omrežjaNovNov zaNov predNov načrtNasl.Nobenega %s za pridobiti, izpuščam ...Ni sporočilNi objektaIzbran ni noben objekt.Ni nobenega ukazaNi še narejeno.OObjektiOpisi objektovObjekti brez ukazovPomoč na internetuOpisi ukazovPodatku o ukazuUkaz je v vrsti za odstranitev.Vrsta novega ukazaShranjevanje ukazov: Za shranjevanje ni izbranega nobenega ukaza. (%s)Shranjevanje ukazov: Za posodabljanje ni izbranega nobenega ukaza. (%s)UkaziDrugoPGesloGesli se ne ujemata.PrilepiPrilepi zaPrilepi predSlikaIgralciIgranjeVrataNastavitvePred.NapredekLastnostiLastnost 1:Lastnost 2:Dobil vse %s ...Pridobljeni objekti vseh igralcev.Dobil vse %s ...Dobil objekt vašega igralca ...Pridobljeni opisi vseh ukazov.Odstranjevanje %s %s, ker je izginil ...Ponovite gesloZahtevaj konec &poteze Ctrl-TViriViri: PovrniShraniShrani kopijo okna s sporočilom v datoteko.Shrani dnevnik kot ...Izbiranje objektov: Tega objekta ni.Strežniku pošlje sporočilo z zahtevkom za konec poteze.Pošiljanje zahtevka za vse %s na %s ...StrežnikStrežnikiLadje: PrikažiPrikaži nasvetePrikaži ločeno okno za igro.Prikažem?Preskakujem zahtevo po %s na %s, ker ne obstaja!Sem, bodo šle, nekatere kategorijeZvezdna kartaStatično besediloUspešna povezava z gostiteljem.SistemTP: Poveži se s strežnikomTP: Prenašanje vesoljaTP: Brskalnik po strežnikihTP: posodobitev vesoljaURL strežnika za Thousand Parsec.Odjemalec se je povezal z gostiteljem, a se ni mogel prijaviti, ker je uporabniško ime ali pa geslo napačno. Odjemalec se je povezal z gostiteljem, a kot kaže ta ni strežnik za Thousand Parsec. Odjemalec se ni mogel povezati z gostiteljem. Odjemalec ima veliko bližnjic. Za podrobnosti si oglejte datoteko s pomočjo.Odjemalec se ni mogel povezati z gostiteljem. Geslo za račun na strežniku za Thousand ParsecVrstica za filtriranje objektov uporablja običajne vzorce za ujemanje. Za en znak lahko uporabite »?«, za katerokoli število zankov pa »*«.Poteza je zaključena. Ali želite prenesti vse nove podatke? Uporabniško ime za račun na strežniku za Thousand Parsec.Vrednost lastnosti 1Vrednost lastnosti 2Način »Točke poti« je zelo priročen za načrtovanje daljše poti.Prišlo je do neznane omrežne napake. Ta odjemalec za Thousand Parsec, ki je napisan v Pythonu, vam omogoča da se pridružite in igrate igre, ki tečejo na strežnikih za Thousand Parsec.Mogoče strežnik ne deluje, ali pa so podatki o povezavi napačne. Mogoče strežnik ne deluje, ali pa ime omrežje težave. Mogoče strežnik ne deluje, ali pa ste se zatipkali pri vnašanju naslova strežnika. Mogoče ste se povezali z napačnim strežnikom ali pa ste se zatipkali pri vpisovanju uporabniškega imena ali gesla. Ta strežnik ne podpira ustvarjanja računov.Thousand ParsecBrskalnik po strežnikih za Thousand ParsecNaslovNa vrhPoskušanje prijave na strežnik ...PotezVrstaURLURL trenutno izbranega strežnika.Prenašanje vesoljaNeznano (vrsta: %s)Neznan ID načrta:Zamenjam geslo?Posodobitev zaključena!Posodobim?PosodabljanjeUporabnikOpozorilo - ni objektovOpozorilo: objekt %s ne obstaja!Dobrodošli v tpclient-pywx. Ta odjemalec je napisan v Pythonu in uporablja wxPython. Omogoča vam povezavo na katerikoli strežnik za igre Thousand Parsec.ŠirinaOknaUgotavljanje števila %s za pridobivanje ...Ugotavljanje števila opisov ukazov za pridobivanje ...XVodoravnoYNavpičnoZa izbiro objektov lahko kliknite nanje na zvezdni karti!Za hitro izdajo ukaza premika lahko z desno kliknete na cilj, kamor želite poslati vesoljsko ladjo ali drug objekt.Za dostop do priročnih funkcij za izrez, kopiranje in vstavljanje ukazov lahko z desnim gumbom miške kliknete v oknu z ukazi.Zpridobljeni vsi %s.Odjemalec wxPythontpclient-pywx-0.3.1.1/locale/sl/tpclient-pywx.po0000644000175000017500000015305510773624641017734 0ustar timtim# translation of tpclient-pywx.po to Slovenian # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # Jure Repinc , 2007. #: windows/main/panelMessage.py:206 windows/winMain.py:289 #: windows/winMain.py:296 msgid "" msgstr "" "Project-Id-Version: tpclient-pywx\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-22 21:19+1030\n" "PO-Revision-Date: 2008-03-22 22:00+0200\n" "Last-Translator: Jure Repinc \n" "Language-Team: Slovenian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" "Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || " "n%100==4 ? 3 : 0);\n" #: windows/winAccount.py:30 windows/winAccount.py:31 windows/winAccount.py:33 msgid "Account" msgstr "Račun" #: windows/winAccount.py:174 windows/winAccount.py:175 #: windows/winAccount.py:182 windows/winAccount.py:184 msgid "This server does not support account creation." msgstr "Ta strežnik ne podpira ustvarjanja računov." #: windows/winAccount.py:178 windows/winAccount.py:179 #: windows/winAccount.py:189 msgid "Account Created" msgstr "Račun ustvarjen" #: windows/winAccount.py:182 windows/winBase.py:369 tpclient-pywx:264 #: tpclient-pywx:268 windows/winAccount.py:183 tpclient-pywx:362 #: windows/winAccount.py:196 tpclient-pywx:390 windows/winAccount.py:194 #: tpclient-pywx:389 msgid "Network Error" msgstr "Napaka glede omrežja" #: windows/winAccount.py:195 windows/winAccount.py:196 #: windows/winAccount.py:213 windows/winAccount.py:210 msgid "All fields are required." msgstr "Vsa polja so obvezna." #: windows/winAccount.py:195 windows/winAccount.py:199 #: windows/winAccount.py:196 windows/winAccount.py:200 #: windows/winAccount.py:213 windows/winAccount.py:217 #: windows/winAccount.py:210 windows/winAccount.py:214 msgid "Fields Required" msgstr "Obvezna polja" #: windows/winAccount.py:199 windows/winAccount.py:200 #: windows/winAccount.py:217 windows/winAccount.py:214 msgid "Password fields do not match." msgstr "Gesli se ne ujemata." #: windows/winBase.py:169 #, python-format msgid "" "Config-%s: Did not find a default show for your resolution (using 1024x768 " "defaults)" msgstr "" "Nastavitev-%s: Ni bilo moč najti privzetega prikaza za vašo ločljivost " "(uporabljam privzetosti za 1024x768)" #: windows/winBase.py:182 #, python-format msgid "" "Config-%s: Did not find a default position for your resolution (using " "1024x768 defaults)" msgstr "" "Nastavitev-%s: Ni bilo moč najti privzetega položaja za vašo ločljivost " "(uporabljam privzetosti za 1024x768)" #: windows/winBase.py:193 #, python-format msgid "" "Config-%s: Did not find a default size for your resolution (using 1024x768 " "defaults)" msgstr "" "Nastavitev-%s: Ni bilo moč najti privzete velikosti za vašo ločljivost " "(uporabljam privzetosti za 1024x768)" #: windows/winBase.py:237 msgid "Show?" msgstr "Prikažem?" #: windows/winBase.py:246 msgid "X Pos" msgstr "Vodoravno" #: windows/winBase.py:255 msgid "Y Pos" msgstr "Navpično" #: windows/winBase.py:264 msgid "Width" msgstr "Širina" #: windows/winBase.py:273 msgid "Height" msgstr "Višina" #: windows/winConfig.py:14 msgid "Config" msgstr "Nastavitve" #: windows/winConnect.py:141 windows/winConnect.py:137 #: windows/winConnect.py:140 #, python-format msgid "Login for %s" msgstr "Prijava za %s" #: windows/winConnect.py:166 windows/winConnect.py:162 #: windows/winConnect.py:165 msgid "Connect" msgstr "Poveži se" #: windows/winConnect.py:250 windows/winConnect.py:263 #: windows/winConnect.py:266 msgid "" "It appears you are using a different password for \n" "this account, would you like to update the saved \n" "information with the new password?\n" msgstr "" "Izgleda, da uporabljate drugo geslo za ta račun.\n" "Želite zamenjati staro geslo z novim?\n" #: windows/winConnect.py:255 windows/winConnect.py:269 #: windows/winConnect.py:272 msgid "Update Password?" msgstr "Zamenjam geslo?" #: windows/winConnect.py:264 windows/winConnect.py:246 #: windows/winConnect.py:249 msgid "" "It appears you havn't access this account before.\n" "\n" "Would you like to save this account's details?\n" msgstr "" "Izgleda, da tega računa še niste uporabljali.\n" "\n" "Želite shraniti podatke o tem računu?\n" #: windows/winConnect.py:269 windows/winConnect.py:251 #: windows/winConnect.py:254 msgid "Add Account?" msgstr "Dodam račun?" #: windows/winConnect.py:436 windows/winConnect.py:441 #: windows/winConnect.py:446 windows/winConnect.py:431 #: windows/winConnect.py:435 windows/winConnect.py:439 #: windows/winConnect.py:434 windows/winConnect.py:438 #: windows/winConnect.py:442 msgid "Login for " msgstr "Prijava za " #: windows/winConnect.py:453 windows/winConnect.py:446 #: windows/winConnect.py:449 #, python-format msgid "" "\n" "The client is already set to autoconnect to %s.\n" "\n" "Would you instead like to autoconnect to %s.\n" msgstr "" "\n" "Odjemalec je že nastavljen za samodejno povezavo z %s.\n" "\n" "Želite zamenjati strežnik za samodejno povezavo z %s?\n" #: windows/winConnect.py:458 windows/winConnect.py:451 #: windows/winConnect.py:454 msgid "Autoconnect to?" msgstr "Samodejna povezava?" #: windows/winDebug.py:8 msgid "Debug" msgstr "Razhroščevanje" #: windows/winDesign.py:43 windows/main/winDesign.py:43 #: windows/xrc/winDesign.py:96 windows/xrc/winDesign.py:99 msgid "Design" msgstr "Načrt" #: windows/winDesign.py:78 windows/winDesign.py:83 windows/xrc/winDesign.py:97 #: windows/xrc/winDesign.py:98 windows/xrc/winDesign.py:100 #: windows/xrc/winDesign.py:101 msgid "Title" msgstr "Naslov" #: windows/winDesign.py:106 windows/main/winDesign.py:75 msgid "Component" msgstr "Komponenta" #: windows/winDesign.py:129 windows/xrc/winDesign.py:105 #: windows/xrc/winDesign.py:108 msgid "Edit" msgstr "Uredi" #: windows/winDesign.py:134 windows/xrc/winDesign.py:106 #: windows/xrc/winDesign.py:109 msgid "Duplicate" msgstr "Podvoji" #: windows/winDesign.py:139 windows/winOrder.py:220 windows/winOrder.py:253 #: windows/xrc/panelMessage.py:76 windows/xrc/panelMessage.py:77 #: windows/xrc/winDesign.py:107 windows/xrc/panelMessage.py:80 #: windows/xrc/winDesign.py:110 windows/main/panelOrder.py:663 #: windows/main/panelOrder.py:696 msgid "Delete" msgstr "Izbriši" #: windows/winDesign.py:144 windows/xrc/winDesign.py:108 #: windows/xrc/winDesign.py:111 msgid "Revert" msgstr "Povrni" #: windows/winDesign.py:149 windows/xrc/winDesign.py:109 #: windows/xrc/winDesign.py:112 msgid "Save" msgstr "Shrani" #: windows/winDesign.py:165 windows/winOrder.py:766 #: windows/main/panelOrder.py:834 windows/xrc/winDesign.py:110 #: windows/main/panelOrder.py:831 windows/xrc/orderList.py:56 #: windows/xrc/winDesign.py:113 msgid "Add" msgstr "Dodaj" #: windows/winDesign.py:169 windows/xrc/winDesign.py:111 #: windows/xrc/winDesign.py:114 msgid "Add Many" msgstr "Dodaj več" #: windows/winDesign.py:237 windows/xrc/winUpdate.py:94 #: windows/main/winDesign.py:150 windows/xrc/winUpdate.py:95 #: windows/xrc/winUpdate.py:98 msgid "Designs" msgstr "Načrti" #: windows/winDesign.py:242 windows/main/winDesign.py:155 msgid "New Design" msgstr "Nov načrt" #: windows/winDesign.py:267 windows/xrc/winUpdate.py:95 #: windows/main/winDesign.py:191 windows/xrc/winUpdate.py:96 #: windows/xrc/winUpdate.py:99 msgid "Components" msgstr "Komponente" #: windows/winDesign.py:398 windows/main/winDesign.py:333 msgid "" "\n" "Would you like to continue adding these components?" msgstr "" "\n" "Želite še naprej dodajati te komponente?" #: windows/winDesign.py:400 windows/main/winDesign.py:335 msgid "" "\n" "Would you like to continue adding this component?" msgstr "" "\n" "Želite še naprej dodajati to komponento?" #: windows/winDesign.py:401 windows/main/winDesign.py:336 msgid "Design Warning" msgstr "Opozorilo glede načrta" #: windows/winInfo.py:57 windows/main/panelInfo.py:30 msgid "Information" msgstr "Informacije" #: windows/winMain.py:212 windows/winMain.py:108 windows/winMain.py:109 #: windows/winMain.py:115 msgid "Thousand Parsec" msgstr "Thousand Parsec" #: windows/winMain.py:332 msgid "Connect to Game\tCtrl-O" msgstr "Poveži se z igro\tCtrl-O" #: windows/winMain.py:332 windows/winMain.py:250 windows/winMain.py:253 #: windows/winMain.py:254 windows/winMain.py:260 msgid "Connect to a diffrent Game" msgstr "Poveži se z drugo igro" #: windows/winMain.py:333 msgid "Download the Universe\tCtrl-U" msgstr "Prenesi vesolje\tCtrl-V" #: windows/winMain.py:333 windows/winMain.py:251 windows/winMain.py:254 #: windows/winMain.py:255 windows/winMain.py:261 msgid "Download the Universe" msgstr "Prenesi vesolje" #: windows/winMain.py:335 msgid "Preferences" msgstr "Nastavitve" #: windows/winMain.py:335 windows/winMain.py:253 windows/winMain.py:256 #: windows/winMain.py:258 windows/winMain.py:264 msgid "Configure the Client" msgstr "Nastavi program" #: windows/winMain.py:337 windows/winMain.py:255 windows/winMain.py:258 #: windows/winMain.py:260 windows/winMain.py:266 msgid "Exit" msgstr "Izhod" #: windows/winMain.py:370 windows/winMain.py:278 windows/winMain.py:281 #: windows/winMain.py:283 windows/winMain.py:289 msgid "Show " msgstr "Prikaži" #: windows/winMain.py:377 windows/winMain.py:285 windows/winMain.py:288 #: windows/winMain.py:290 windows/winMain.py:296 msgid "Show Tips" msgstr "Prikaži nasvete" #: windows/winMain.py:378 windows/winMain.py:286 windows/main/winHelp.py:19 #: windows/xrc/winHelp.py:73 msgid "Help" msgstr "Pomoč" #: windows/winMain.py:382 windows/winMain.py:290 windows/winMain.py:293 #: windows/winMain.py:295 windows/winMain.py:302 msgid "File" msgstr "Datoteka" #: windows/winMain.py:384 windows/winMain.py:292 windows/winMain.py:295 #: windows/winMain.py:297 windows/winMain.py:304 msgid "Windows" msgstr "Okna" #: windows/winMain.py:385 windows/winMain.py:293 windows/winMain.py:305 msgid "&Help" msgstr "&Pomoč" #: windows/winMain.py:440 windows/winMain.py:348 windows/winMain.py:352 #: windows/winMain.py:375 windows/winMain.py:385 msgid "The turn has ended. Would you like to download all the new details?\n" msgstr "Poteza je zaključena. Ali želite prenesti vse nove podatke?\n" #: windows/winMain.py:443 windows/winMain.py:351 windows/winMain.py:355 #: windows/winMain.py:378 windows/winMain.py:388 msgid "Update?" msgstr "Posodobim?" #: windows/winMessage.py:93 windows/xrc/winUpdate.py:92 #: windows/main/panelMessage.py:26 windows/xrc/winUpdate.py:93 #: windows/xrc/winUpdate.py:96 msgid "Messages" msgstr "Sporočila" #: windows/winMessage.py:226 windows/main/panelMessage.py:206 #: windows/main/panelMessage.py:205 msgid "No messages" msgstr "Ni sporočil" #: windows/winMessage.py:235 msgid "All filtered" msgstr "Vsa so filtrirana" #: windows/winMessage.py:281 windows/main/panelMessage.py:240 #: windows/main/panelMessage.py:239 #, python-format msgid "%i of %i" msgstr "%i od %i" #: windows/winNewStarMap.py:51 windows/winStarMap.py:69 #: windows/main/panelStarMap.py:41 windows/main/panelStarMap.py:61 msgid "StarMap" msgstr "Zvezdna karta" #: windows/winOrder.py:38 windows/xrc/winUpdate.py:90 #: windows/main/panelOrder.py:43 windows/xrc/winUpdate.py:91 #: windows/xrc/winUpdate.py:94 msgid "Orders" msgstr "Ukazi" #: windows/winOrder.py:53 windows/main/panelOrder.py:56 msgid "Turns" msgstr "Potez" #: windows/winOrder.py:55 windows/main/panelOrder.py:58 msgid "Order Information" msgstr "Podatku o ukazu" #: windows/winOrder.py:203 windows/main/panelOrder.py:646 msgid "Top" msgstr "Na vrh" #: windows/winOrder.py:211 windows/winOrder.py:295 #: windows/main/panelOrder.py:654 windows/main/panelOrder.py:733 msgid "Before" msgstr "Pred" #: windows/winOrder.py:212 windows/main/panelOrder.py:655 msgid "New Before" msgstr "Nov pred" #: windows/winOrder.py:216 windows/winOrder.py:280 #: windows/main/panelOrder.py:659 windows/main/panelOrder.py:718 msgid "After" msgstr "Za" #: windows/winOrder.py:217 windows/main/panelOrder.py:660 msgid "New After" msgstr "Nov za" #: windows/winOrder.py:224 windows/winOrder.py:255 windows/winOrder.py:269 #: windows/main/panelOrder.py:667 windows/main/panelOrder.py:698 #: windows/main/panelOrder.py:707 msgid "Cut" msgstr "Izreži" #: windows/winOrder.py:225 windows/winOrder.py:255 #: windows/main/panelOrder.py:668 windows/main/panelOrder.py:698 msgid "Copy" msgstr "Kopiraj" #: windows/winOrder.py:228 windows/winOrder.py:229 #: windows/main/panelOrder.py:671 windows/main/panelOrder.py:672 msgid "Paste Before" msgstr "Prilepi pred" #: windows/winOrder.py:230 windows/winOrder.py:231 #: windows/main/panelOrder.py:673 windows/main/panelOrder.py:674 msgid "Paste After" msgstr "Prilepi za" #: windows/winOrder.py:234 windows/winOrder.py:235 #: windows/main/panelOrder.py:677 windows/main/panelOrder.py:678 msgid "New" msgstr "Nov" #: windows/winOrder.py:239 windows/winOrder.py:240 windows/winOrder.py:272 #: windows/main/panelOrder.py:682 windows/main/panelOrder.py:683 #: windows/main/panelOrder.py:710 msgid "Paste" msgstr "Prilepi" #: windows/winOrder.py:274 windows/main/panelOrder.py:712 msgid "Cant paste because the orders arn't valid on this object." msgstr "Ni moč prilepiti, ker ukazi za ta objekt niso ustrezni." #: windows/winOrder.py:315 #, python-format msgid "Warning: Object %s does not exist!" msgstr "Opozorilo: objekt %s ne obstaja!" #: windows/winOrder.py:335 windows/main/panelOrder.py:188 #: windows/main/panelOrder.py:189 #, python-format msgid "Current orders on %s." msgstr "Trenutni ukazi za %s." #: windows/winOrder.py:347 windows/main/panelOrder.py:197 #: windows/main/panelOrder.py:198 msgid "Order type to create" msgstr "Vrsta novega ukaza" #: windows/winOrder.py:413 windows/main/panelOrder.py:425 #: windows/main/panelOrder.py:424 windows/main/panelOrder.py:446 msgid "Multiple orders selected." msgstr "Izbranih je več ukazov." #: windows/winOrder.py:417 windows/main/panelOrder.py:434 #: windows/main/panelOrder.py:433 windows/main/panelOrder.py:455 msgid "No object selected." msgstr "Izbran ni noben objekt." #: windows/winOrder.py:486 #, python-format msgid "OrderSave: No order selected for save. (%s)" msgstr "Shranjevanje ukazov: Za shranjevanje ni izbranega nobenega ukaza. (%s)" #: windows/winOrder.py:528 #, python-format msgid "OrderSave: No order selected for update. (%s))" msgstr "" "Shranjevanje ukazov: Za posodabljanje ni izbranega nobenega ukaza. (%s)" #: windows/winOrder.py:651 msgid "Argument type (ARG_PLAYER) not implimented yet." msgstr "Vrsta argumenta (ARG_PLAYER) še ni podprta." #: windows/winOrder.py:653 msgid "Argument type (ARG_RANGE) not implimented yet." msgstr "Vrsta argumenta (ARG_RANGE) še ni podprta." #: windows/winOrder.py:676 windows/main/panelOrder.py:741 #: windows/main/panelOrder.py:738 msgid "Not implimented." msgstr "Ni še narejeno." #: windows/winOrder.py:709 windows/main/panelOrder.py:774 #: windows/main/panelOrder.py:771 msgid "No object" msgstr "Ni objekta" #: windows/winOrder.py:714 windows/main/panelOrder.py:779 #: windows/main/panelOrder.py:776 msgid "At " msgstr "Na " #: windows/winOrder.py:744 windows/winServerBrowser.py:26 #: windows/winServerBrowser.py:133 windows/winServerBrowser.py:28 #: windows/main/panelOrder.py:812 windows/winServerBrowser.py:138 #: windows/main/panelOrder.py:809 windows/main/panelOrder.py:855 msgid "Type" msgstr "Vrsta" #: windows/winOrder.py:769 windows/main/panelOrder.py:837 #: windows/main/panelOrder.py:834 windows/xrc/orderList.py:57 msgid "D" msgstr "I" #: windows/winOrder.py:791 windows/winOrder.py:835 msgid "ListAdd: No type selected." msgstr "Dodajanje na seznam: Izbrane ni nobene vrste." #: windows/winOrder.py:824 msgid "ListDel: No selection selected." msgstr "Brisanje s seznama: Izbranega ni ničesar." #: windows/winOrder.py:855 msgid "ListSelect: No selection selected." msgstr "Izbiranje s seznama: Izbranega ni ničesar." #: windows/winOrder.py:916 windows/main/panelOrder.py:980 #: windows/main/panelOrder.py:977 msgid "X" msgstr "X" #: windows/winOrder.py:924 windows/main/panelOrder.py:988 #: windows/main/panelOrder.py:985 msgid "Y" msgstr "Y" #: windows/winOrder.py:932 windows/main/panelOrder.py:996 #: windows/main/panelOrder.py:993 msgid "Z" msgstr "Z" #: windows/winOrder.py:940 windows/winServerBrowser.py:21 #: windows/winServerBrowser.py:76 windows/winServerBrowser.py:23 #: windows/main/panelOrder.py:1004 windows/winServerBrowser.py:81 #: windows/main/panelOrder.py:1001 windows/xrc/orderPosition.py:47 msgid "P" msgstr "P" #: windows/winPicture.py:60 windows/main/panelPicture.py:47 #: windows/main/panelPicture.py:49 msgid "Picture" msgstr "Slika" #: windows/winServerBrowser.py:19 windows/winUpdate.py:19 #: windows/winServerBrowser.py:21 windows/winUpdate.py:23 msgid "Updating" msgstr "Posodabljanje" #: windows/winServerBrowser.py:21 windows/winServerBrowser.py:52 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:57 msgid "Name" msgstr "Ime" #: windows/winServerBrowser.py:21 windows/winServerBrowser.py:57 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:62 msgid "Playing" msgstr "Igranje" #: windows/winServerBrowser.py:21 windows/winServerBrowser.py:60 #: windows/xrc/winAccount.py:75 windows/xrc/winConnect.py:76 #: windows/winServerBrowser.py:23 windows/xrc/winAccount.py:82 #: windows/xrc/winConnect.py:83 windows/winServerBrowser.py:65 #: windows/xrc/winAccount.py:85 windows/xrc/winConnect.py:86 msgid "Server" msgstr "Strežnik" #: windows/winServerBrowser.py:21 windows/winServerBrowser.py:68 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:73 msgid "C" msgstr "C" #: windows/winServerBrowser.py:21 windows/winServerBrowser.py:72 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:77 msgid "O" msgstr "O" #: windows/winServerBrowser.py:21 windows/winServerBrowser.py:80 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:85 msgid "Other" msgstr "Drugo" #: windows/winServerBrowser.py:26 windows/winServerBrowser.py:134 #: windows/winServerBrowser.py:28 windows/winServerBrowser.py:139 msgid "DNS" msgstr "DNS" #: windows/winServerBrowser.py:26 windows/winServerBrowser.py:135 #: windows/winServerBrowser.py:28 windows/winServerBrowser.py:140 msgid "IP" msgstr "IP" #: windows/winServerBrowser.py:26 windows/winServerBrowser.py:136 #: windows/winServerBrowser.py:28 windows/winServerBrowser.py:141 msgid "Port" msgstr "Vrata" #: windows/winSystem.py:23 windows/main/panelSystem.py:22 #: windows/xrc/panelStarMap.py:67 windows/main/panelSystem.py:23 #: windows/xrc/panelStarMap.py:70 msgid "System" msgstr "Sistem" #: windows/winSystem.py:126 windows/main/panelSystem.py:143 #: windows/main/panelSystem.py:152 windows/main/panelSystem.py:160 msgid "Known Universe" msgstr "Znano vesolje" #: windows/winUpdate.py:50 windows/winUpdate.py:55 windows/winUpdate.py:58 msgid "Save log as ..." msgstr "Shrani dnevnik kot ..." #: windows/winUpdate.py:171 windows/winUpdate.py:245 #: windows/xrc/winUpdate.py:84 windows/xrc/winUpdate.py:86 #: windows/xrc/winUpdate.py:85 windows/xrc/winUpdate.py:87 #: windows/winUpdate.py:177 windows/winUpdate.py:251 #: windows/xrc/winUpdate.py:88 windows/xrc/winUpdate.py:90 #: windows/winUpdate.py:182 windows/winUpdate.py:265 windows/winUpdate.py:193 #: windows/winUpdate.py:276 msgid "Done!" msgstr "Zaključeno!" #: windows/winUpdate.py:194 windows/winUpdate.py:200 windows/winUpdate.py:214 #: windows/winUpdate.py:225 #, python-format msgid "Getting %s" msgstr "Pridobivanje %s" #: windows/winUpdate.py:222 windows/winUpdate.py:233 windows/winUpdate.py:228 #: windows/winUpdate.py:239 windows/winUpdate.py:242 windows/winUpdate.py:253 #: windows/winUpdate.py:264 #, python-format msgid "%s of %s" msgstr "%s od %s" #: windows/xrc/configConnect.py:54 windows/xrc/configConnect.py:55 #: windows/xrc/configConnect.py:58 msgid "Login for" msgstr "Prijava za" #: windows/xrc/configConnect.py:55 windows/xrc/winAccount.py:79 #: windows/xrc/winConnect.py:78 windows/xrc/configConnect.py:56 #: windows/xrc/winAccount.py:86 windows/xrc/winConnect.py:86 #: windows/xrc/configConnect.py:59 windows/xrc/winAccount.py:89 #: windows/xrc/winConnect.py:89 msgid "Username" msgstr "Uporabnik" #: windows/xrc/configConnect.py:56 windows/xrc/winAccount.py:80 #: windows/xrc/winConnect.py:79 windows/xrc/configConnect.py:57 #: windows/xrc/winAccount.py:87 windows/xrc/winConnect.py:87 #: windows/xrc/configConnect.py:60 windows/xrc/winAccount.py:90 #: windows/xrc/winConnect.py:90 msgid "The username for the account on the Thousand Parsec server." msgstr "Uporabniško ime za račun na strežniku za Thousand Parsec." #: windows/xrc/configConnect.py:57 windows/xrc/winAccount.py:81 #: windows/xrc/winConnect.py:80 windows/xrc/configConnect.py:58 #: windows/xrc/winAccount.py:88 windows/xrc/winConnect.py:88 #: windows/xrc/configConnect.py:61 windows/xrc/winAccount.py:91 #: windows/xrc/winConnect.py:91 msgid "Show seperate game box." msgstr "Prikaži ločeno okno za igro." #: windows/xrc/configConnect.py:58 windows/xrc/winAccount.py:82 #: windows/xrc/winConnect.py:81 windows/xrc/configConnect.py:59 #: windows/xrc/winAccount.py:89 windows/xrc/winConnect.py:89 #: windows/xrc/configConnect.py:62 windows/xrc/winAccount.py:92 #: windows/xrc/winConnect.py:92 msgid "G" msgstr "I" #: windows/xrc/configConnect.py:59 windows/xrc/winAccount.py:83 #: windows/xrc/winConnect.py:82 windows/xrc/configConnect.py:60 #: windows/xrc/winAccount.py:90 windows/xrc/winConnect.py:90 #: windows/xrc/configConnect.py:63 windows/xrc/winAccount.py:93 #: windows/xrc/winConnect.py:93 msgid "Game" msgstr "Igra" #: windows/xrc/configConnect.py:60 windows/xrc/winAccount.py:84 #: windows/xrc/winConnect.py:83 windows/xrc/configConnect.py:61 #: windows/xrc/winAccount.py:91 windows/xrc/winConnect.py:91 #: windows/xrc/configConnect.py:64 windows/xrc/winAccount.py:94 #: windows/xrc/winConnect.py:94 msgid "Password" msgstr "Geslo" #: windows/xrc/configConnect.py:61 windows/xrc/configConnect.py:62 #: windows/xrc/configConnect.py:65 msgid "Autoconnect" msgstr "Samodejna povezava" #: windows/xrc/configConnect.py:62 windows/xrc/configConnect.py:63 #: windows/xrc/configConnect.py:66 msgid "Debug Output" msgstr "Razhroščevalni izhod" #: windows/xrc/panelInformation.py:38 windows/xrc/panelInformation.py:39 #: windows/xrc/panelInformation.py:42 msgid "Name of object goes here" msgstr "Sem gre ime objekta" #: windows/xrc/panelMessage.py:67 windows/xrc/panelMessage.py:68 #: windows/xrc/panelMessage.py:71 msgid "Filter" msgstr "Filter" #: windows/xrc/panelMessage.py:68 windows/xrc/panelMessage.py:69 #: windows/xrc/panelMessage.py:72 msgid "Static text" msgstr "Statično besedilo" #: windows/xrc/panelMessage.py:69 windows/xrc/panelMessage.py:70 #: windows/xrc/panelMessage.py:73 msgid "100 of 100" msgstr "100 od 100" #: windows/xrc/panelMessage.py:70 windows/xrc/panelMessage.py:71 #: windows/xrc/panelMessage.py:74 msgid "" "\n" "\n" "
\n" "\t\n" "\t\t\n" "\t\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\n" "\t
Subject: You are unloved!\n" "\t\t
\n" "\t\t\tYou have recived no messages this turn!

\n" "\t\t\tActually if you didn't recive any messages it most proberly\n" "\t\t\tmeans that your client couldn't load the results from the server.\n" "\t\t\tTry reload/restart the client.\n" "\t\t\t
\n" "
\n" "\n" "" msgstr "" "\n" "\n" "
\n" "\t\n" "\t\t\n" "\t\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\n" "\t
Zadeva: Nihče vas nima rad!\n" "\t\t
\n" "\t\t\tMed to potezo niste dobili nobenega sporočila!

\n" "\t\t\tČe niste dobili nobenega sporočila, to najverjetneje pomeni,\n" "\t\t\tda vaš odjemalec ni pravilno prenesel rezultatov s strežnika.\n" "\t\t\tPoskusite ponovno zagnati odjemalca.\n" "\t\t\t
\n" "
\n" "\n" "" #: windows/xrc/panelMessage.py:71 windows/xrc/panelMessage.py:72 #: windows/xrc/panelMessage.py:75 msgid "Prev" msgstr "Pred." #: windows/xrc/panelMessage.py:72 windows/xrc/panelMessage.py:73 #: windows/xrc/panelMessage.py:76 msgid "First" msgstr "Prvo" #: windows/xrc/panelMessage.py:73 windows/xrc/panelMessage.py:74 #: windows/xrc/panelMessage.py:77 msgid "Goto" msgstr "Pojdi" #: windows/xrc/panelMessage.py:74 windows/xrc/panelMessage.py:75 #: windows/xrc/panelMessage.py:78 msgid "Next" msgstr "Nasl." #: windows/xrc/panelMessage.py:75 windows/xrc/panelMessage.py:76 #: windows/xrc/panelMessage.py:79 msgid "Last" msgstr "Zadnje" #: windows/xrc/panelOrder.py:57 windows/xrc/panelOrder.py:64 #: windows/xrc/panelOrder.py:68 msgid "Insert new order." msgstr "Vstavi nov ukaz." #: windows/xrc/panelOrder.py:58 windows/xrc/panelOrder.py:65 #: windows/xrc/panelOrder.py:69 msgid "&New" msgstr "&Nov" #: windows/xrc/panelOrder.py:59 windows/xrc/winUpdate.py:102 #: windows/xrc/panelOrder.py:66 windows/xrc/winUpdate.py:103 #: windows/xrc/panelOrder.py:70 windows/xrc/winUpdate.py:106 msgid "&Save" msgstr "&Shrani" #: windows/xrc/panelOrder.py:60 windows/xrc/panelOrder.py:67 #: windows/xrc/panelOrder.py:71 msgid "&Revert" msgstr "&Povrni" #: windows/xrc/panelOrder.py:61 windows/xrc/panelOrder.py:68 #: windows/xrc/panelOrder.py:72 msgid "Delete the currently selected order(s)" msgstr "Izbriši trenutno izbrana sporočila" #: windows/xrc/panelOrder.py:62 windows/xrc/panelOrder.py:69 #: windows/xrc/panelOrder.py:73 msgid "&Delete" msgstr "&Izbriši" #: windows/xrc/panelPicture.py:43 windows/xrc/panelPicture.py:45 #: windows/xrc/panelPicture.py:48 msgid "Name goes here" msgstr "Sem gre ime" #: windows/xrc/panelPicture.py:44 windows/xrc/panelPicture.py:46 #: windows/xrc/panelPicture.py:49 msgid "10kb/s" msgstr "10 kb/s" #: windows/xrc/panelPicture.py:45 windows/xrc/panelPicture.py:47 #: windows/xrc/panelPicture.py:50 msgid "43s" msgstr "43 s" #: windows/xrc/winAccount.py:73 windows/xrc/winConnect.py:74 #: windows/xrc/winAccount.py:80 windows/xrc/winConnect.py:81 #: windows/xrc/winAccount.py:83 windows/xrc/winConnect.py:84 msgid "TP: Connect to a Server" msgstr "TP: Poveži se s strežnikom" #: windows/xrc/winAccount.py:74 windows/xrc/winAccount.py:81 #: windows/xrc/winAccount.py:84 msgid "Create an Account" msgstr "Ustvari račun" #: windows/xrc/winAccount.py:76 windows/xrc/winConnect.py:77 #: windows/xrc/winAccount.py:83 windows/xrc/winConnect.py:84 #: windows/xrc/winAccount.py:86 windows/xrc/winConnect.py:87 msgid "The URL for the Thousand Parsec server." msgstr "URL strežnika za Thousand Parsec." #: windows/xrc/winAccount.py:77 windows/xrc/winAccount.py:84 #: windows/xrc/winAccount.py:87 msgid "Choose a server to create an account on." msgstr "Izberite strežnik, na katerem se bo ustvaril račun." #: windows/xrc/winAccount.py:78 windows/xrc/winAccount.py:85 #: windows/xrc/winAccount.py:88 msgid "Check" msgstr "Preveri" #: windows/xrc/winAccount.py:85 windows/xrc/winAccount.py:92 #: windows/xrc/winAccount.py:95 msgid "Choose your password here." msgstr "Sem vnesite svoje geslo." #: windows/xrc/winAccount.py:86 windows/xrc/winAccount.py:93 #: windows/xrc/winAccount.py:96 msgid " " msgstr " " #: windows/xrc/winAccount.py:87 windows/xrc/winAccount.py:89 #: windows/xrc/winAccount.py:94 windows/xrc/winAccount.py:96 #: windows/xrc/winAccount.py:97 windows/xrc/winAccount.py:99 msgid "Repeat the password" msgstr "Ponovite geslo" #: windows/xrc/winAccount.py:88 windows/xrc/winAccount.py:95 #: windows/xrc/winAccount.py:98 msgid "Email " msgstr "E-pošta " #: windows/xrc/winAccount.py:90 windows/xrc/winConnect.py:85 #: windows/xrc/winUpdate.py:100 windows/xrc/winAccount.py:97 #: windows/xrc/winUpdate.py:101 windows/xrc/winConnect.py:93 #: windows/xrc/winAccount.py:100 windows/xrc/winUpdate.py:104 #: windows/xrc/winConnect.py:96 msgid "&OK" msgstr "&V redu" #: windows/xrc/winAccount.py:91 windows/xrc/winConnect.py:86 #: windows/xrc/winServerBrowser.py:88 windows/xrc/winUpdate.py:104 #: windows/xrc/winServerBrowser.py:89 windows/xrc/winAccount.py:98 #: windows/xrc/winUpdate.py:105 windows/xrc/winConnect.py:94 #: windows/xrc/winServerBrowser.py:92 windows/xrc/winAccount.py:101 #: windows/xrc/winUpdate.py:108 windows/xrc/winConnect.py:97 msgid "&Cancel" msgstr "&Prekliči" #: windows/xrc/winConnect.py:75 windows/xrc/winConnect.py:82 #: windows/xrc/winConnect.py:85 msgid "Connect to Thousand Parsec Server" msgstr "Poveži se s strežnikom za Thousand Parsec" #: windows/xrc/winConnect.py:84 windows/xrc/winConnect.py:92 #: windows/xrc/winConnect.py:95 msgid "The password for the account on the Thousand Parsec Server" msgstr "Geslo za račun na strežniku za Thousand Parsec" #: windows/xrc/winConnect.py:87 windows/xrc/winConnect.py:85 #: windows/xrc/winConnect.py:88 msgid "&Find" msgstr "&Najdi" #: windows/xrc/winConnect.py:88 windows/xrc/winConnect.py:95 #: windows/winMain.py:253 windows/xrc/winConnect.py:98 windows/winMain.py:256 #: windows/winMain.py:258 windows/winMain.py:264 msgid "&Preferences" msgstr "&Nastavitve" #: windows/xrc/winServerBrowser.py:72 windows/xrc/winServerBrowser.py:73 #: windows/xrc/winServerBrowser.py:76 msgid "TP: Server Browser" msgstr "TP: Brskalnik po strežnikih" #: windows/xrc/winServerBrowser.py:73 windows/xrc/winServerBrowser.py:74 #: windows/xrc/winServerBrowser.py:77 msgid "Thousand Parsec Server Browser" msgstr "Brskalnik po strežnikih za Thousand Parsec" #: windows/xrc/winServerBrowser.py:74 windows/xrc/winServerBrowser.py:75 #: windows/xrc/winServerBrowser.py:78 msgid "Servers" msgstr "Strežniki" #: windows/xrc/winServerBrowser.py:75 windows/xrc/winServerBrowser.py:76 #: windows/xrc/winServerBrowser.py:79 msgid "List of all the servers registered on the metaserver." msgstr "Seznam vseh strežnikov registriranih pri metastrežniku." #: windows/xrc/winServerBrowser.py:76 windows/xrc/winServerBrowser.py:77 #: windows/xrc/winServerBrowser.py:80 msgid "Locations" msgstr "Lokacije" #: windows/xrc/winServerBrowser.py:77 windows/xrc/winServerBrowser.py:78 #: windows/xrc/winServerBrowser.py:81 msgid "List of all the servers found on the local network." msgstr "Seznam vseh strežnikov najdenih na krajevnem omrežju." #: windows/xrc/winServerBrowser.py:78 windows/xrc/winServerBrowser.py:79 #: windows/xrc/winServerBrowser.py:82 msgid "URL" msgstr "URL" #: windows/xrc/winServerBrowser.py:79 windows/xrc/winServerBrowser.py:80 #: windows/xrc/winServerBrowser.py:83 msgid "URL of the currently selected server." msgstr "URL trenutno izbranega strežnika." #: windows/xrc/winServerBrowser.py:80 windows/xrc/winServerBrowser.py:81 #: windows/xrc/winServerBrowser.py:84 msgid "Copy the URL to the clipboard." msgstr "Kopiraj URL na odložišče." #: windows/xrc/winServerBrowser.py:81 windows/xrc/winServerBrowser.py:82 #: windows/xrc/winServerBrowser.py:85 msgid "&Copy" msgstr "&Kopiraj" #: windows/xrc/winServerBrowser.py:82 windows/xrc/winServerBrowser.py:83 #: windows/xrc/winServerBrowser.py:86 msgid "Force a refresh of the server list." msgstr "Vsili posodobitev seznama strežnikov." #: windows/xrc/winServerBrowser.py:83 windows/xrc/winServerBrowser.py:84 #: windows/xrc/winServerBrowser.py:87 msgid "&Refresh" msgstr "&Posodobi" #: windows/xrc/winServerBrowser.py:84 windows/xrc/winServerBrowser.py:85 #: windows/xrc/winServerBrowser.py:88 msgid "Create a new account on the currently selected server." msgstr "Ustvari nov račun na trenutno izbranem strežniku." #: windows/xrc/winServerBrowser.py:85 windows/xrc/winServerBrowser.py:86 #: windows/xrc/winServerBrowser.py:89 msgid "&New Account" msgstr "&Nov račun" #: windows/xrc/winServerBrowser.py:86 windows/xrc/winServerBrowser.py:87 #: windows/xrc/winServerBrowser.py:90 msgid "Connect to the currently selected server." msgstr "Poveži se s trenutno izbranim strežnikom." #: windows/xrc/winServerBrowser.py:87 windows/xrc/winServerBrowser.py:88 #: windows/xrc/winServerBrowser.py:91 msgid "C&onnect" msgstr "P&oveži se" #: windows/xrc/winUpdate.py:82 msgid "TP: Downloading Universe" msgstr "TP: Prenašanje vesolja" #: windows/xrc/winUpdate.py:83 windows/xrc/winUpdate.py:84 #: windows/xrc/winUpdate.py:87 msgid "Universe Download" msgstr "Prenašanje vesolja" #: windows/xrc/winUpdate.py:85 windows/xrc/winUpdate.py:86 #: windows/xrc/winUpdate.py:89 msgid "Progress" msgstr "Napredek" #: windows/xrc/winUpdate.py:87 windows/xrc/winUpdate.py:88 #: windows/xrc/winUpdate.py:91 msgid "Objects Descs" msgstr "Opisi objektov" #: windows/xrc/winUpdate.py:88 windows/xrc/winUpdate.py:89 #: windows/xrc/winUpdate.py:92 msgid "Order Descs" msgstr "Opisi ukazov" #: windows/xrc/winUpdate.py:89 windows/xrc/winUpdate.py:90 #: windows/xrc/winUpdate.py:93 msgid "Objects" msgstr "Objekti" #: windows/xrc/winUpdate.py:91 windows/xrc/winUpdate.py:92 #: windows/xrc/winUpdate.py:95 msgid "Boards" msgstr "Deske" #: windows/xrc/winUpdate.py:93 windows/xrc/winUpdate.py:94 #: windows/xrc/winUpdate.py:97 msgid "Categories" msgstr "Kategorije" #: windows/xrc/winUpdate.py:96 windows/xrc/winUpdate.py:97 #: windows/xrc/winUpdate.py:100 msgid "Properties" msgstr "Lastnosti" #: windows/xrc/winUpdate.py:97 windows/xrc/winUpdate.py:98 #: windows/xrc/winUpdate.py:101 msgid "Players" msgstr "Igralci" #: windows/xrc/winUpdate.py:98 windows/xrc/panelStarMap.py:68 #: windows/xrc/winUpdate.py:99 windows/xrc/panelStarMap.py:71 #: windows/xrc/winUpdate.py:102 msgid "Resources" msgstr "Viri" #: windows/xrc/winUpdate.py:99 windows/xrc/winUpdate.py:100 #: windows/xrc/winUpdate.py:103 msgid "Continue to the main game window." msgstr "Nadaljuj v glavno okno igre." #: windows/xrc/winUpdate.py:101 windows/xrc/winUpdate.py:102 #: windows/xrc/winUpdate.py:105 msgid "Save a copy of the message box window to a file." msgstr "Shrani kopijo okna s sporočilom v datoteko." #: windows/xrc/winUpdate.py:103 windows/xrc/winUpdate.py:104 #: windows/xrc/winUpdate.py:107 msgid "Cancel the current update and go back to the connect screen." msgstr "Prekliči trenutno posodobitev in se vrni na okno za povezovanje." #: windows/winInfo.py:83 msgid "SelectObject: No such object." msgstr "Izbiranje objektov: Tega objekta ni." #: windows/winInfo.py:96 windows/main/panelInfo.py:68 #: windows/main/panelInfo.py:75 msgid "Ships: " msgstr "Ladje: " #: windows/winInfo.py:103 windows/main/panelInfo.py:75 #: windows/main/panelInfo.py:82 msgid "Unknown Design id:" msgstr "Neznan ID načrta:" #: windows/winInfo.py:104 windows/main/panelInfo.py:76 #: windows/main/panelInfo.py:83 #, python-format msgid "Unknown (type: %s)" msgstr "Neznano (vrsta: %s)" #: tp/client/cache.py:348 tp/client/cache.py:438 tp/client/cache.py:443 msgid "Getting order descriptions..." msgstr "Pridobivanje opisov ukazov ..." #: tp/client/cache.py:349 tp/client/cache.py:439 tp/client/cache.py:444 msgid "Working out the number of order descriptions to get.." msgstr "Ugotavljanje števila opisov ukazov za pridobivanje ..." #: tp/client/cache.py:363 tp/client/cache.py:453 tp/client/cache.py:458 #, python-format msgid "Got order description %s (ID: %i) (last modified at %s)..." msgstr "Dobil opis ukaza %s (ID: %i) (zadnja sprememba: %s)." #: tp/client/cache.py:367 tp/client/cache.py:457 tp/client/cache.py:462 #, python-format msgid "Failed to get order description with id, %i (last modified at %s)..." msgstr "Pridobivanje opisa ukaza z ID %i je spodletelo (zadnja sprememba: %s)." #: tp/client/cache.py:368 tp/client/cache.py:458 msgid "Finished getting order descriptions..." msgstr "Pridobivanje opisov ukazov je zaključeno." #: tp/client/cache.py:387 tp/client/cache.py:477 msgid "Getting your player object..." msgstr "Pridobivanje objekta vašega igralca ..." #: tp/client/cache.py:389 msgid "Gotten your player object..." msgstr "Objekt vašega igralca pridobljen." #: tp/client/cache.py:411 tp/client/cache.py:501 tp/client/cache.py:534 #, python-format msgid "Getting %s..." msgstr "Pridobivanje %s ..." #: tp/client/cache.py:414 tp/client/cache.py:504 tp/client/cache.py:537 #, python-format msgid "Working out the number of %s to get.." msgstr "Ugotavljanje števila %s za pridobivanje ..." #: tp/client/cache.py:429 tp/client/cache.py:519 tp/client/cache.py:552 #, python-format msgid "Got %s %s (id: %i) (last modified at %s)..." msgstr "Pridobil %s %s (ID: %i) (zadnja sprememba: %s)." #: tp/client/cache.py:432 tp/client/cache.py:522 tp/client/cache.py:555 #, python-format msgid "No %s to get, skipping..." msgstr "Nobenega %s za pridobiti, izpuščam ..." #: tp/client/cache.py:437 tp/client/cache.py:527 tp/client/cache.py:560 #, python-format msgid "Have %i %s to get..." msgstr "Za pridobiti je %i %s." #: tp/client/cache.py:448 tp/client/cache.py:538 tp/client/cache.py:571 #, python-format msgid "Failed to get the %s which was previously called %s." msgstr "Pridobivanje %s, ki se je prej imenoval %s, je spodletelo." #: tp/client/cache.py:452 tp/client/cache.py:542 tp/client/cache.py:575 #, python-format msgid "Failed to get the %s with id %s." msgstr "Pridobivanje %s z ID %s je spodletelo." #: tp/client/cache.py:454 tp/client/cache.py:544 tp/client/cache.py:577 #, python-format msgid "Cleaning up %s which have disappeared..." msgstr "Čiščenje %s, ki so izginili ..." #: tp/client/cache.py:461 tp/client/cache.py:551 tp/client/cache.py:584 #, python-format msgid "Removing %s %s as it has disappeared..." msgstr "Odstranjevanje %s %s, ker je izginil ..." #: tp/client/cache.py:466 tp/client/cache.py:556 tp/client/cache.py:589 msgid "Building two way tree of the universe for speed..." msgstr "Grajenje dvosmernega drevesa vesolja, zaradi hitrosti ..." #: tp/client/cache.py:475 #, python-format msgid "Gotten all %s..." msgstr "Pridobil vse %s." #: tp/client/cache.py:493 tp/client/cache.py:583 tp/client/cache.py:616 #, python-format msgid "Getting %s.." msgstr "Pridobivanje %s..." #: tp/client/cache.py:494 tp/client/cache.py:584 tp/client/cache.py:617 #, python-format msgid "Have to get %s for %i %s.." msgstr "Pridobiti je potrebno %s za %i %s." #: tp/client/cache.py:504 tp/client/cache.py:594 tp/client/cache.py:627 #, python-format msgid "Sending a request for all %s on %s.." msgstr "Pošiljanje zahtevka za vse %s na %s ..." #: tp/client/cache.py:508 tp/client/cache.py:598 tp/client/cache.py:631 #, python-format msgid "Skipping requesting %s on %s as there are none!" msgstr "Preskakujem zahtevo po %s na %s, ker ne obstaja!" #: tp/client/cache.py:526 tp/client/cache.py:616 tp/client/cache.py:649 #, python-format msgid "Failed to get %s for %s (id: %s) (%s)..." msgstr "Spodletelo je pridobivanje %s za %s (ID: %s) (%s)." #: tp/client/cache.py:530 tp/client/cache.py:620 tp/client/cache.py:653 #, python-format msgid "Got %i %s for %s (id: %s)..." msgstr "Dobil %i %s za %s (ID: %s)." #: tp/client/cache.py:533 tp/client/cache.py:628 tp/client/cache.py:661 #, python-format msgid "Cleaning up any stray %s.." msgstr "Čiščenje izgubljenih %s ..." #: tp/client/cache.py:536 tp/client/cache.py:631 tp/client/cache.py:664 #, python-format msgid "Found stray %s for %s.." msgstr "Našel izgubljenega %s za %s." #: tp/client/cache.py:540 #, python-format msgid "Gotten all the %s.." msgstr "Dobil vse %s." #: tp/client/threads.py:286 tp/client/threads.py:550 tp/client/threads.py:321 #: tp/client/threads.py:616 tp/client/threads.py:323 tp/client/threads.py:529 #: tp/client/threads.py:545 msgid "There was an unknown network error.\n" msgstr "Prišlo je do neznane omrežne napake.\n" #: tp/client/threads.py:287 tp/client/threads.py:551 tp/client/threads.py:322 #: tp/client/threads.py:617 tp/client/threads.py:324 tp/client/threads.py:530 #: tp/client/threads.py:546 msgid "Any changes since last save have been lost.\n" msgstr "Vse spremembe, ki niso shranjene, so se izgubile.\n" #: tp/client/threads.py:289 tp/client/threads.py:324 tp/client/threads.py:326 msgid "A traceback of the error was printed to the console.\n" msgstr "Povratna sled napake se je izpisala v konzoli.\n" #: tp/client/threads.py:317 tp/client/threads.py:344 tp/client/threads.py:346 msgid "The client was unable to connect to the host.\n" msgstr "Odjemalec se ni mogel povezati z gostiteljem.\n" #: tp/client/threads.py:318 tp/client/threads.py:345 tp/client/threads.py:347 msgid "" "This could be because the server is down or there is a problem with the " "network.\n" msgstr "Mogoče strežnik ne deluje, ali pa ime omrežje težave.\n" #: tp/client/threads.py:322 tp/client/threads.py:349 tp/client/threads.py:351 msgid "The client could not connect to the host.\n" msgstr "Odjemalec se ni mogel povezati z gostiteljem.\n" #: tp/client/threads.py:323 tp/client/threads.py:350 tp/client/threads.py:352 msgid "" "This could be because the server is down or you mistyped the server " "address.\n" msgstr "" "Mogoče strežnik ne deluje, ali pa ste se zatipkali pri vnašanju naslova " "strežnika.\n" #: tp/client/threads.py:326 tp/client/threads.py:353 tp/client/threads.py:355 msgid "Successfully connected to the host..." msgstr "Uspešna povezava z gostiteljem." #: tp/client/threads.py:329 tp/client/threads.py:356 tp/client/threads.py:358 msgid "Looking for Thousand Parsec Server..." msgstr "Iskanje strežnika za Thousand Parsec ..." #: tp/client/threads.py:333 tp/client/threads.py:342 tp/client/threads.py:360 #: tp/client/threads.py:369 tp/client/threads.py:362 tp/client/threads.py:371 msgid "" "The client connected to the host but it did not appear to be a Thousand " "Parsec server.\n" msgstr "" "Odjemalec se je povezal z gostiteljem, a kot kaže ta ni strežnik za Thousand " "Parsec.\n" #: tp/client/threads.py:334 tp/client/threads.py:343 tp/client/threads.py:361 #: tp/client/threads.py:370 tp/client/threads.py:363 tp/client/threads.py:372 msgid "" "This could be because the server is down or the connection details are " "incorrect.\n" msgstr "Mogoče strežnik ne deluje, ali pa so podatki o povezavi napačne.\n" #: tp/client/threads.py:337 tp/client/threads.py:364 tp/client/threads.py:366 msgid "Found a Thousand Parsec Server..." msgstr "Našel strežnik za Thousand Parsec." #: tp/client/threads.py:339 tp/client/threads.py:366 tp/client/threads.py:368 msgid "Looking for supported features..." msgstr "Preverjanje podprtih zmožnosti ..." #: tp/client/threads.py:346 tp/client/threads.py:373 tp/client/threads.py:375 msgid "Got the supported features..." msgstr "Dobil podprte zmožnosti." #: tp/client/threads.py:355 tp/client/threads.py:382 tp/client/threads.py:384 msgid "Connecting..." msgstr "Povezovanje ..." #: tp/client/threads.py:361 tp/client/threads.py:388 tp/client/threads.py:390 msgid "Trying to Login to the server..." msgstr "Poskušanje prijave na strežnik ..." #: tp/client/threads.py:363 tp/client/threads.py:390 tp/client/threads.py:392 msgid "" "The client connected to the host but could not login because the username of " "password was incorrect.\n" msgstr "" "Odjemalec se je povezal z gostiteljem, a se ni mogel prijaviti, ker je " "uporabniško ime ali pa geslo napačno.\n" #: tp/client/threads.py:364 tp/client/threads.py:391 tp/client/threads.py:393 msgid "" "This could be because you are connecting to the wrong server or mistyped the " "username or password.\n" msgstr "" "Mogoče ste se povezali z napačnim strežnikom ali pa ste se zatipkali pri " "vpisovanju uporabniškega imena ali gesla.\n" #: tp/client/threads.py:367 tp/client/threads.py:394 tp/client/threads.py:396 msgid "Logged in okay!" msgstr "Prijava je uspela!" #: windows/main/panelSystem.py:145 windows/main/panelSystem.py:154 #: windows/main/panelSystem.py:162 #, python-format msgid "Finding %s" msgstr "Iskanje %s" #: windows/main/panelOrder.py:423 windows/main/panelOrder.py:422 #: windows/main/panelOrder.py:444 msgid "No orders avaliable" msgstr "Ni nobenega ukaza" #: windows/main/panelOrder.py:432 windows/main/panelOrder.py:431 #: windows/main/panelOrder.py:453 msgid "Order queued for removal." msgstr "Ukaz je v vrsti za odstranitev." #: windows/main/panelInfo.py:81 windows/main/panelInfo.py:88 msgid "Resources:\n" msgstr "Viri:\n" #: windows/main/panelInfo.py:90 windows/main/panelInfo.py:97 #, python-format msgid "%s %s of %s on surface, " msgstr "%s %s od %s na površju, " #: windows/main/panelInfo.py:94 windows/main/panelInfo.py:101 #, python-format msgid "%s %s on surface, " msgstr "%s %s na površju, " #: windows/main/panelInfo.py:98 windows/main/panelInfo.py:105 #, python-format msgid "%s %s of %s minable, " msgstr "%s %s od %s izkopljivo, " #: windows/main/panelInfo.py:102 windows/main/panelInfo.py:109 #, python-format msgid "%s %s minable, " msgstr "%s %s izkopljivo, " #: windows/main/panelInfo.py:106 windows/main/panelInfo.py:113 #, python-format msgid "%s %s of %s inaccessible, " msgstr "%s %s od %s nedostopno, " #: windows/main/panelInfo.py:110 windows/main/panelInfo.py:117 #, python-format msgid "%s %s inaccessible, " msgstr "%s %s nedostopno, " #: windows/main/panelInfo.py:114 windows/main/panelInfo.py:121 #, python-format msgid "\tUnknown Resource %i, S: %i, M: %i, I: %s\n" msgstr "\tNeznan vir %i, P: %i, I: %i, N: %s\n" #: windows/main/winIdleFinder.py:17 windows/xrc/winIdleFinder.py:51 #: windows/main/winIdleFinder.py:26 windows/xrc/winIdleFinder.py:54 msgid "Objects Without Orders" msgstr "Objekti brez ukazov" #: windows/xrc/panelStarMap.py:62 windows/xrc/panelStarMap.py:65 msgid "Fit" msgstr "Vse" #: windows/xrc/panelStarMap.py:63 windows/xrc/panelStarMap.py:66 msgid "80%" msgstr "80%" #: windows/xrc/panelStarMap.py:64 windows/xrc/panelStarMap.py:67 msgid "50%" msgstr "50%" #: windows/xrc/panelStarMap.py:65 windows/xrc/panelStarMap.py:68 msgid "10%" msgstr "10%" #: windows/xrc/panelStarMap.py:66 windows/xrc/panelStarMap.py:69 msgid "Box" msgstr "Okvir" #: windows/xrc/winDesign.py:99 windows/xrc/winDesign.py:102 msgid "0000" msgstr "0000" #: windows/xrc/winDesign.py:100 windows/xrc/winDesign.py:103 msgid "Some Categories, Will Go, Here" msgstr "Sem, bodo šle, nekatere kategorije" #: windows/xrc/winDesign.py:101 windows/xrc/winDesign.py:104 msgid "Property 1:" msgstr "Lastnost 1:" #: windows/xrc/winDesign.py:102 windows/xrc/winDesign.py:105 msgid "The value of property 1" msgstr "Vrednost lastnosti 1" #: windows/xrc/winDesign.py:103 windows/xrc/winDesign.py:106 msgid "Property 2:" msgstr "Lastnost 2:" #: windows/xrc/winDesign.py:104 windows/xrc/winDesign.py:107 msgid "The value of property 2" msgstr "Vrednost lastnosti 2" #: windows/xrc/winUpdate.py:83 windows/xrc/winUpdate.py:86 msgid "TP: Universe update" msgstr "TP: posodobitev vesolja" #: windows/winMain.py:250 windows/winMain.py:253 windows/winMain.py:254 #: windows/winMain.py:260 msgid "C&onnect to Game\tCtrl-O" msgstr "P&oveži se z igro\tCtrl-O" #: windows/winMain.py:251 windows/winMain.py:254 windows/winMain.py:255 #: windows/winMain.py:261 msgid "Download the &Universe\tCtrl-U" msgstr "Prenesi &vesolje\tCtrl-V" #: tp/client/cache.py:479 msgid "Received your player object..." msgstr "Dobil objekt vašega igralca ..." #: tp/client/cache.py:565 #, python-format msgid "Received all %s..." msgstr "Dobil vse %s ..." #: tp/client/cache.py:635 tp/client/cache.py:668 #, python-format msgid "Received all the %s.." msgstr "Dobil vse %s ..." #: windows/xrc/orderList.py:54 msgid "Choice 1" msgstr "Možnost 1" #: windows/xrc/orderList.py:55 msgid "Choice 2" msgstr "Možnost 2" #: windows/xrc/winResourceSelect.py:58 windows/xrc/winResourceSelect.py:67 msgid "Done" msgstr "Zaključeno" #: windows/winUpdate.py:192 windows/winUpdate.py:203 msgid "Update done!" msgstr "Posodobitev zaključena!" #: tp/client/cache.py:464 msgid "Recieved all order descriptions..." msgstr "Pridobljeni opisi vseh ukazov." #: tp/client/cache.py:473 msgid "Don't have any orders to get.." msgstr "Za pridobiti ni nobenega ukaza." #: tp/client/cache.py:479 msgid "Don't have any messages to get.." msgstr "Za pridobiti ni nobenega sporočila." #: tp/client/cache.py:488 msgid "Getting player objects..." msgstr "Pridobivanje objektov igralcev ..." #: tp/client/cache.py:506 #, python-format msgid "Got player %s (id: %i)..." msgstr "Pridobljen igralec %s (ID: %i)." #: tp/client/cache.py:510 msgid "Received all player objects..." msgstr "Pridobljeni objekti vseh igralcev." #: tp/client/cache.py:598 #, python-format msgid "received all %s..." msgstr "pridobljeni vsi %s." #: doc/tips.txt:1 msgid "" "Welcome to tpclient-pywx. This client is written in python using wxPython " "and should allow to connect to any Thousand Parsec server." msgstr "" "Dobrodošli v tpclient-pywx. Ta odjemalec je napisan v Pythonu in uporablja " "wxPython. Omogoča vam povezavo na katerikoli strežnik za igre Thousand Parsec." #: doc/tips.txt:2 msgid "You can click on the star map to select objects!" msgstr "Za izbiro objektov lahko kliknite nanje na zvezdni karti!" #: doc/tips.txt:3 msgid "" "The client has many shortcuts, check out the help file for more information." msgstr "" "Odjemalec ima veliko bližnjic. Za podrobnosti si oglejte datoteko s pomočjo." #: doc/tips.txt:4 msgid "" "You can quickly issue a move order by right clicking where you want an " "object to go." msgstr "" "Za hitro izdajo ukaza premika lahko z desno kliknete na cilj, kamor želite " "poslati vesoljsko ladjo ali drug objekt." #: doc/tips.txt:5 msgid "The waypoint mode is a good way of setting up a large path quickly." msgstr "Način »Točke poti« je zelo priročen za načrtovanje daljše poti." #: doc/tips.txt:6 msgid "" "You can right click on the orders windows to access a bunch of quick " "functions including cut, copy and paste!" msgstr "" "Za dostop do priročnih funkcij za izrez, kopiranje in vstavljanje ukazov " "lahko z desnim gumbom miške kliknete v oknu z ukazi." #: doc/tips.txt:7 msgid "" "If the paste menu option is grayed out, the orders you are trying to paste " "are not valid on that object." msgstr "" "Če je možnost za vstavljanje onemogočena, potem ukazi, ki jih želite " "vstaviti, za trenutni objekt niso mogoči." #: doc/tips.txt:8 msgid "" "If you hold down shift a number of buttons change to allow you to quickly " "jump to first or last of things." msgstr "" "Če držite pritisnjeno tipko Shift, za nekatere bližnjice omogočite " "skok na prvo ali zadnjo stvar s seznama." #: doc/tips.txt:9 msgid "" "The system filter box uses standard matching pattern, you can use ? for a " "single character or * for any number." msgstr "" "Vrstica za filtriranje objektov uporablja običajne vzorce za ujemanje. " "Za en znak lahko uporabite »?«, za katerokoli število zankov pa »*«." #: windows/main/winHelp.py:54 msgid "Warning - No Objects..." msgstr "Opozorilo - ni objektov" #: windows/main/winHelp.py:55 msgid "" "\n" "

\n" "It appears that you do not own any objects. This may be for a number of\n" "reasons:\n" "

\n" "
    \n" "\t
  • You have logged in as a guest user.\n" "\t

    \n" "\t\tOn most servers guest users can only login and view the universe. They\n" "own no objects and can not issue orders. This is good to checkout what the\n" "Universe is like, but not if you actually want to play the game.\n" "\t

    \n" "\t\tMost servers allow you to create accounts right from this client! This\n" "can be done by clicking \"Find\" on the Login window to bring up the \n" "server browser. (Open server browser " "window.)\n" "\t


  • \n" "\t
  • You have been defeated.\n" "\t

    \n" "\t\tIf you have not logged in for a long time, all your objects may have\n" "been conquered or destroyed. Some servers may let you create a new account " "and\n" "start again.\n" "\t


  • \n" "\t
  • There is a problem.\n" "\t

    \n" "\t\tThere could be a bug in some of the software, if you are sure neither\n" "of the two cases above are correct please report it \n" "here.\n" "\t

  • \n" "
\n" msgstr "" "\n" "

\n" "Izgleda, da si ne lastite nobenega objekta. Možnih je več razlogov:\n" "

\n" "
    \n" "\t
  • Prijavili ste se kot gost.\n" "\t

    \n" "\t\tNa večini strežnikov si gosti lahko le ogledujejo igro. Gosti \n" "si ne lastijo objektov in ne morejo izdajati ukazov. To je v redu, \n" "če si želite samo ogledati vesolje, ne pa dejansko igrati.\n" "\t

    \n" "\t\tVečina strežnikov vam omogoča ustvaritev računa kar iz tega odjemalca!\n" "To lahko storite s klikom na gumb »Najdi« v pogovornem oknu za prijavo. \n" "Pojavilo se bo okno za brskanje po strežnikih. (" "kliknite za odprtje tega okna)\n" "\t


  • \n" "\t
  • Bili ste poraženi.\n" "\t

    \n" "\t\tČe se že dolgo niste prijavili na strežnik, so lahko drugi igralci\n" "zavzeli vse vaše objekte ali pa jih uničili. Nekateri strežniki vam omogočajo\n" "ustvaritev novega računa, s katerim lahko začnete znova." "\t


  • \n" "\t
  • Naleteli ste na napako.\n" "\t

    \n" "\t\tMogoče je v programu napaka. Če ste prepričani, da ne gre za enega izmed\n" "gornjih dveh primer, poročajte o napaki " "na tej strani.\n" "\t

  • \n" "
\n" #: windows/xrc/winHelp.py:70 msgid "Important Information...." msgstr "Pomembni podatki" #: windows/xrc/winHelp.py:71 msgid "Do not show this message again." msgstr "Tega sporočila ne prikaži več" #: windows/xrc/winHelp.py:72 msgid "&Close" msgstr "&Zapri" #: windows/winMain.py:256 windows/winMain.py:262 msgid "Request End of &Turn\tCtrl-T" msgstr "Zahtevaj konec &poteze\tCtrl-T" #: windows/winMain.py:256 windows/winMain.py:262 msgid "Send a message to the server requesting the turn end soon." msgstr "Strežniku pošlje sporočilo z zahtevkom za konec poteze." #: windows/winMain.py:299 msgid "Online Help" msgstr "Pomoč na internetu" #: windows/winMain.py:299 msgid "Go to the online help page." msgstr "Odpre spletno stran s pomočjo." #: windows/winMain.py:300 msgid "About" msgstr "O programu" #: windows/winMain.py:300 msgid "About the client you are running..." msgstr "O odjemalcu, ki ga uporabljate ..." #: windows/winMain.py:403 msgid "wxPython Client" msgstr "Odjemalec wxPython" #: windows/winMain.py:405 msgid "(C) 2001-2008 Thousand Parsec Developers" msgstr "© 2001-2008, razvijalci Thousand Parsec" #: windows/winMain.py:406 msgid "" "This Thousand Parsec client, written in python, is an easy way to join and " "start playing in a Thousand Parsec game." msgstr "" "Ta odjemalec za Thousand Parsec, ki je napisan v Pythonu, vam omogoča da se " "pridružite in igrate igre, ki tečejo na strežnikih za Thousand Parsec."tpclient-pywx-0.3.1.1/locale/tpclient-pywx.pot0000644000175000017500000015223610773624641017502 0ustar timtim# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #: windows/main/panelMessage.py:206 windows/winMain.py:289 #: windows/winMain.py:296 #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-03-22 21:19+1030\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: windows/winAccount.py:30 windows/winAccount.py:31 windows/winAccount.py:33 #: windows/winAccount.py:33 msgid "Account" msgstr "" #: windows/winAccount.py:174 windows/winAccount.py:175 #: windows/winAccount.py:182 windows/winAccount.py:184 #: windows/winAccount.py:184 msgid "This server does not support account creation." msgstr "" #: windows/winAccount.py:178 windows/winAccount.py:179 #: windows/winAccount.py:189 windows/winAccount.py:189 msgid "Account Created" msgstr "" #: windows/winAccount.py:182 windows/winBase.py:369 tpclient-pywx:264 #: tpclient-pywx:268 windows/winAccount.py:183 tpclient-pywx:362 #: windows/winAccount.py:196 tpclient-pywx:390 windows/winAccount.py:194 #: tpclient-pywx:389 windows/winAccount.py:194 msgid "Network Error" msgstr "" #: windows/winAccount.py:195 windows/winAccount.py:196 #: windows/winAccount.py:213 windows/winAccount.py:210 #: windows/winAccount.py:210 msgid "All fields are required." msgstr "" #: windows/winAccount.py:195 windows/winAccount.py:199 #: windows/winAccount.py:196 windows/winAccount.py:200 #: windows/winAccount.py:213 windows/winAccount.py:217 #: windows/winAccount.py:210 windows/winAccount.py:214 #: windows/winAccount.py:210 windows/winAccount.py:214 msgid "Fields Required" msgstr "" #: windows/winAccount.py:199 windows/winAccount.py:200 #: windows/winAccount.py:217 windows/winAccount.py:214 #: windows/winAccount.py:214 msgid "Password fields do not match." msgstr "" #: windows/winBase.py:169 #, python-format msgid "" "Config-%s: Did not find a default show for your resolution (using 1024x768 " "defaults)" msgstr "" #: windows/winBase.py:182 #, python-format msgid "" "Config-%s: Did not find a default position for your resolution (using " "1024x768 defaults)" msgstr "" #: windows/winBase.py:193 #, python-format msgid "" "Config-%s: Did not find a default size for your resolution (using 1024x768 " "defaults)" msgstr "" #: windows/winBase.py:237 msgid "Show?" msgstr "" #: windows/winBase.py:246 msgid "X Pos" msgstr "" #: windows/winBase.py:255 msgid "Y Pos" msgstr "" #: windows/winBase.py:264 msgid "Width" msgstr "" #: windows/winBase.py:273 msgid "Height" msgstr "" #: windows/winConfig.py:14 windows/winConfig.py:14 msgid "Config" msgstr "" #: windows/winConnect.py:141 windows/winConnect.py:137 #: windows/winConnect.py:140 windows/winConnect.py:140 #, python-format msgid "Login for %s" msgstr "" #: windows/winConnect.py:166 windows/winConnect.py:162 #: windows/winConnect.py:165 windows/winConnect.py:165 msgid "Connect" msgstr "" #: windows/winConnect.py:250 windows/winConnect.py:263 #: windows/winConnect.py:266 windows/winConnect.py:266 msgid "" "It appears you are using a different password for \n" "this account, would you like to update the saved \n" "information with the new password?\n" msgstr "" #: windows/winConnect.py:255 windows/winConnect.py:269 #: windows/winConnect.py:272 windows/winConnect.py:272 msgid "Update Password?" msgstr "" #: windows/winConnect.py:264 windows/winConnect.py:246 #: windows/winConnect.py:249 windows/winConnect.py:249 msgid "" "It appears you havn't access this account before.\n" "\n" "Would you like to save this account's details?\n" msgstr "" #: windows/winConnect.py:269 windows/winConnect.py:251 #: windows/winConnect.py:254 windows/winConnect.py:254 msgid "Add Account?" msgstr "" #: windows/winConnect.py:436 windows/winConnect.py:441 #: windows/winConnect.py:446 windows/winConnect.py:431 #: windows/winConnect.py:435 windows/winConnect.py:439 #: windows/winConnect.py:434 windows/winConnect.py:438 #: windows/winConnect.py:442 windows/winConnect.py:434 #: windows/winConnect.py:438 windows/winConnect.py:442 msgid "Login for " msgstr "" #: windows/winConnect.py:453 windows/winConnect.py:446 #: windows/winConnect.py:449 windows/winConnect.py:449 #, python-format msgid "" "\n" "The client is already set to autoconnect to %s.\n" "\n" "Would you instead like to autoconnect to %s.\n" msgstr "" #: windows/winConnect.py:458 windows/winConnect.py:451 #: windows/winConnect.py:454 windows/winConnect.py:454 msgid "Autoconnect to?" msgstr "" #: windows/winDebug.py:8 msgid "Debug" msgstr "" #: windows/winDesign.py:43 windows/main/winDesign.py:43 #: windows/xrc/winDesign.py:96 windows/xrc/winDesign.py:99 #: windows/main/winDesign.py:43 windows/xrc/winDesign.py:99 msgid "Design" msgstr "" #: windows/winDesign.py:78 windows/winDesign.py:83 windows/xrc/winDesign.py:97 #: windows/xrc/winDesign.py:98 windows/xrc/winDesign.py:100 #: windows/xrc/winDesign.py:101 windows/xrc/winDesign.py:100 #: windows/xrc/winDesign.py:101 msgid "Title" msgstr "" #: windows/winDesign.py:106 windows/main/winDesign.py:75 #: windows/main/winDesign.py:75 msgid "Component" msgstr "" #: windows/winDesign.py:129 windows/xrc/winDesign.py:105 #: windows/xrc/winDesign.py:108 windows/xrc/winDesign.py:108 msgid "Edit" msgstr "" #: windows/winDesign.py:134 windows/xrc/winDesign.py:106 #: windows/xrc/winDesign.py:109 windows/xrc/winDesign.py:109 msgid "Duplicate" msgstr "" #: windows/winDesign.py:139 windows/winOrder.py:220 windows/winOrder.py:253 #: windows/xrc/panelMessage.py:76 windows/xrc/panelMessage.py:77 #: windows/xrc/winDesign.py:107 windows/xrc/panelMessage.py:80 #: windows/xrc/winDesign.py:110 windows/main/panelOrder.py:663 #: windows/main/panelOrder.py:696 windows/main/panelOrder.py:663 #: windows/main/panelOrder.py:696 windows/xrc/panelMessage.py:80 #: windows/xrc/winDesign.py:110 msgid "Delete" msgstr "" #: windows/winDesign.py:144 windows/xrc/winDesign.py:108 #: windows/xrc/winDesign.py:111 windows/xrc/winDesign.py:111 msgid "Revert" msgstr "" #: windows/winDesign.py:149 windows/xrc/winDesign.py:109 #: windows/xrc/winDesign.py:112 windows/xrc/winDesign.py:112 msgid "Save" msgstr "" #: windows/winDesign.py:165 windows/winOrder.py:766 #: windows/main/panelOrder.py:834 windows/xrc/winDesign.py:110 #: windows/main/panelOrder.py:831 windows/xrc/orderList.py:56 #: windows/xrc/winDesign.py:113 windows/xrc/orderList.py:56 #: windows/xrc/winDesign.py:113 msgid "Add" msgstr "" #: windows/winDesign.py:169 windows/xrc/winDesign.py:111 #: windows/xrc/winDesign.py:114 windows/xrc/winDesign.py:114 msgid "Add Many" msgstr "" #: windows/winDesign.py:237 windows/xrc/winUpdate.py:94 #: windows/main/winDesign.py:150 windows/xrc/winUpdate.py:95 #: windows/xrc/winUpdate.py:98 windows/main/winDesign.py:150 #: windows/xrc/winUpdate.py:98 msgid "Designs" msgstr "" #: windows/winDesign.py:242 windows/main/winDesign.py:155 #: windows/main/winDesign.py:155 msgid "New Design" msgstr "" #: windows/winDesign.py:267 windows/xrc/winUpdate.py:95 #: windows/main/winDesign.py:191 windows/xrc/winUpdate.py:96 #: windows/xrc/winUpdate.py:99 windows/main/winDesign.py:191 #: windows/xrc/winUpdate.py:99 msgid "Components" msgstr "" #: windows/winDesign.py:398 windows/main/winDesign.py:333 #: windows/main/winDesign.py:333 msgid "" "\n" "Would you like to continue adding these components?" msgstr "" #: windows/winDesign.py:400 windows/main/winDesign.py:335 #: windows/main/winDesign.py:335 msgid "" "\n" "Would you like to continue adding this component?" msgstr "" #: windows/winDesign.py:401 windows/main/winDesign.py:336 #: windows/main/winDesign.py:336 msgid "Design Warning" msgstr "" #: windows/winInfo.py:57 windows/main/panelInfo.py:30 #: windows/main/panelInfo.py:30 msgid "Information" msgstr "" #: windows/winMain.py:212 windows/winMain.py:108 windows/winMain.py:109 #: windows/winMain.py:115 msgid "Thousand Parsec" msgstr "" #: windows/winMain.py:332 msgid "Connect to Game\tCtrl-O" msgstr "" #: windows/winMain.py:332 windows/winMain.py:250 windows/winMain.py:253 #: windows/winMain.py:254 windows/winMain.py:260 msgid "Connect to a diffrent Game" msgstr "" #: windows/winMain.py:333 msgid "Download the Universe\tCtrl-U" msgstr "" #: windows/winMain.py:333 windows/winMain.py:251 windows/winMain.py:254 #: windows/winMain.py:255 windows/winMain.py:261 msgid "Download the Universe" msgstr "" #: windows/winMain.py:335 msgid "Preferences" msgstr "" #: windows/winMain.py:335 windows/winMain.py:253 windows/winMain.py:256 #: windows/winMain.py:258 windows/winMain.py:264 msgid "Configure the Client" msgstr "" #: windows/winMain.py:337 windows/winMain.py:255 windows/winMain.py:258 #: windows/winMain.py:260 windows/winMain.py:266 msgid "Exit" msgstr "" #: windows/winMain.py:370 windows/winMain.py:278 windows/winMain.py:281 #: windows/winMain.py:283 windows/winMain.py:289 msgid "Show " msgstr "" #: windows/winMain.py:377 windows/winMain.py:285 windows/winMain.py:288 #: windows/winMain.py:290 windows/winMain.py:296 msgid "Show Tips" msgstr "" #: windows/winMain.py:378 windows/winMain.py:286 windows/main/winHelp.py:19 #: windows/xrc/winHelp.py:73 windows/main/winHelp.py:19 #: windows/xrc/winHelp.py:73 msgid "Help" msgstr "" #: windows/winMain.py:382 windows/winMain.py:290 windows/winMain.py:293 #: windows/winMain.py:295 windows/winMain.py:302 msgid "File" msgstr "" #: windows/winMain.py:384 windows/winMain.py:292 windows/winMain.py:295 #: windows/winMain.py:297 windows/winMain.py:304 msgid "Windows" msgstr "" #: windows/winMain.py:385 windows/winMain.py:293 windows/winMain.py:305 msgid "&Help" msgstr "" #: windows/winMain.py:440 windows/winMain.py:348 windows/winMain.py:352 #: windows/winMain.py:375 windows/winMain.py:385 msgid "The turn has ended. Would you like to download all the new details?\n" msgstr "" #: windows/winMain.py:443 windows/winMain.py:351 windows/winMain.py:355 #: windows/winMain.py:378 windows/winMain.py:388 msgid "Update?" msgstr "" #: windows/winMessage.py:93 windows/xrc/winUpdate.py:92 #: windows/main/panelMessage.py:26 windows/xrc/winUpdate.py:93 #: windows/xrc/winUpdate.py:96 windows/main/panelMessage.py:26 #: windows/xrc/winUpdate.py:96 msgid "Messages" msgstr "" #: windows/winMessage.py:226 windows/main/panelMessage.py:206 #: windows/main/panelMessage.py:205 windows/main/panelMessage.py:205 msgid "No messages" msgstr "" #: windows/winMessage.py:235 msgid "All filtered" msgstr "" #: windows/winMessage.py:281 windows/main/panelMessage.py:240 #: windows/main/panelMessage.py:239 windows/main/panelMessage.py:239 #, python-format msgid "%i of %i" msgstr "" #: windows/winNewStarMap.py:51 windows/winStarMap.py:69 #: windows/main/panelStarMap.py:41 windows/main/panelStarMap.py:61 #: windows/main/panelStarMap.py:61 msgid "StarMap" msgstr "" #: windows/winOrder.py:38 windows/xrc/winUpdate.py:90 #: windows/main/panelOrder.py:43 windows/xrc/winUpdate.py:91 #: windows/xrc/winUpdate.py:94 windows/main/panelOrder.py:43 #: windows/xrc/winUpdate.py:94 msgid "Orders" msgstr "" #: windows/winOrder.py:53 windows/main/panelOrder.py:56 #: windows/main/panelOrder.py:56 msgid "Turns" msgstr "" #: windows/winOrder.py:55 windows/main/panelOrder.py:58 #: windows/main/panelOrder.py:58 msgid "Order Information" msgstr "" #: windows/winOrder.py:203 windows/main/panelOrder.py:646 #: windows/main/panelOrder.py:646 msgid "Top" msgstr "" #: windows/winOrder.py:211 windows/winOrder.py:295 #: windows/main/panelOrder.py:654 windows/main/panelOrder.py:733 #: windows/main/panelOrder.py:654 windows/main/panelOrder.py:733 msgid "Before" msgstr "" #: windows/winOrder.py:212 windows/main/panelOrder.py:655 #: windows/main/panelOrder.py:655 msgid "New Before" msgstr "" #: windows/winOrder.py:216 windows/winOrder.py:280 #: windows/main/panelOrder.py:659 windows/main/panelOrder.py:718 #: windows/main/panelOrder.py:659 windows/main/panelOrder.py:718 msgid "After" msgstr "" #: windows/winOrder.py:217 windows/main/panelOrder.py:660 #: windows/main/panelOrder.py:660 msgid "New After" msgstr "" #: windows/winOrder.py:224 windows/winOrder.py:255 windows/winOrder.py:269 #: windows/main/panelOrder.py:667 windows/main/panelOrder.py:698 #: windows/main/panelOrder.py:707 windows/main/panelOrder.py:667 #: windows/main/panelOrder.py:698 windows/main/panelOrder.py:707 msgid "Cut" msgstr "" #: windows/winOrder.py:225 windows/winOrder.py:255 #: windows/main/panelOrder.py:668 windows/main/panelOrder.py:698 #: windows/main/panelOrder.py:668 windows/main/panelOrder.py:698 msgid "Copy" msgstr "" #: windows/winOrder.py:228 windows/winOrder.py:229 #: windows/main/panelOrder.py:671 windows/main/panelOrder.py:672 #: windows/main/panelOrder.py:671 windows/main/panelOrder.py:672 msgid "Paste Before" msgstr "" #: windows/winOrder.py:230 windows/winOrder.py:231 #: windows/main/panelOrder.py:673 windows/main/panelOrder.py:674 #: windows/main/panelOrder.py:673 windows/main/panelOrder.py:674 msgid "Paste After" msgstr "" #: windows/winOrder.py:234 windows/winOrder.py:235 #: windows/main/panelOrder.py:677 windows/main/panelOrder.py:678 #: windows/main/panelOrder.py:677 windows/main/panelOrder.py:678 msgid "New" msgstr "" #: windows/winOrder.py:239 windows/winOrder.py:240 windows/winOrder.py:272 #: windows/main/panelOrder.py:682 windows/main/panelOrder.py:683 #: windows/main/panelOrder.py:710 windows/main/panelOrder.py:682 #: windows/main/panelOrder.py:683 windows/main/panelOrder.py:710 msgid "Paste" msgstr "" #: windows/winOrder.py:274 windows/main/panelOrder.py:712 #: windows/main/panelOrder.py:712 msgid "Cant paste because the orders arn't valid on this object." msgstr "" #: windows/winOrder.py:315 #, python-format msgid "Warning: Object %s does not exist!" msgstr "" #: windows/winOrder.py:335 windows/main/panelOrder.py:188 #: windows/main/panelOrder.py:189 windows/main/panelOrder.py:189 #, python-format msgid "Current orders on %s." msgstr "" #: windows/winOrder.py:347 windows/main/panelOrder.py:197 #: windows/main/panelOrder.py:198 windows/main/panelOrder.py:198 msgid "Order type to create" msgstr "" #: windows/winOrder.py:413 windows/main/panelOrder.py:425 #: windows/main/panelOrder.py:424 windows/main/panelOrder.py:446 #: windows/main/panelOrder.py:446 msgid "Multiple orders selected." msgstr "" #: windows/winOrder.py:417 windows/main/panelOrder.py:434 #: windows/main/panelOrder.py:433 windows/main/panelOrder.py:455 #: windows/main/panelOrder.py:455 msgid "No object selected." msgstr "" #: windows/winOrder.py:486 #, python-format msgid "OrderSave: No order selected for save. (%s)" msgstr "" #: windows/winOrder.py:528 #, python-format msgid "OrderSave: No order selected for update. (%s))" msgstr "" #: windows/winOrder.py:651 msgid "Argument type (ARG_PLAYER) not implimented yet." msgstr "" #: windows/winOrder.py:653 msgid "Argument type (ARG_RANGE) not implimented yet." msgstr "" #: windows/winOrder.py:676 windows/main/panelOrder.py:741 #: windows/main/panelOrder.py:738 msgid "Not implimented." msgstr "" #: windows/winOrder.py:709 windows/main/panelOrder.py:774 #: windows/main/panelOrder.py:771 windows/main/panelOrder.py:774 msgid "No object" msgstr "" #: windows/winOrder.py:714 windows/main/panelOrder.py:779 #: windows/main/panelOrder.py:776 msgid "At " msgstr "" #: windows/winOrder.py:744 windows/winServerBrowser.py:26 #: windows/winServerBrowser.py:133 windows/winServerBrowser.py:28 #: windows/main/panelOrder.py:812 windows/winServerBrowser.py:138 #: windows/main/panelOrder.py:809 windows/main/panelOrder.py:855 #: windows/winServerBrowser.py:28 windows/winServerBrowser.py:138 #: windows/main/panelOrder.py:855 msgid "Type" msgstr "" # Short for "Delete" #: windows/winOrder.py:769 windows/main/panelOrder.py:837 #: windows/main/panelOrder.py:834 windows/xrc/orderList.py:57 #: windows/xrc/orderList.py:57 msgid "D" msgstr "" #: windows/winOrder.py:791 windows/winOrder.py:835 msgid "ListAdd: No type selected." msgstr "" #: windows/winOrder.py:824 msgid "ListDel: No selection selected." msgstr "" #: windows/winOrder.py:855 msgid "ListSelect: No selection selected." msgstr "" # The "X" coordinate #: windows/winOrder.py:916 windows/main/panelOrder.py:980 #: windows/main/panelOrder.py:977 msgid "X" msgstr "" # The "Y" coordinate #: windows/winOrder.py:924 windows/main/panelOrder.py:988 #: windows/main/panelOrder.py:985 msgid "Y" msgstr "" # The "Z" coordinate #: windows/winOrder.py:932 windows/main/panelOrder.py:996 #: windows/main/panelOrder.py:993 msgid "Z" msgstr "" #: windows/winOrder.py:940 windows/winServerBrowser.py:21 #: windows/winServerBrowser.py:76 windows/winServerBrowser.py:23 #: windows/main/panelOrder.py:1004 windows/winServerBrowser.py:81 #: windows/main/panelOrder.py:1001 windows/xrc/orderPosition.py:47 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:81 #: windows/xrc/orderPosition.py:47 msgid "P" msgstr "" #: windows/winPicture.py:60 windows/main/panelPicture.py:47 #: windows/main/panelPicture.py:49 windows/main/panelPicture.py:49 msgid "Picture" msgstr "" #: windows/winServerBrowser.py:19 windows/winUpdate.py:19 #: windows/winServerBrowser.py:21 windows/winUpdate.py:23 #: windows/winServerBrowser.py:21 windows/winUpdate.py:23 msgid "Updating" msgstr "" #: windows/winServerBrowser.py:21 windows/winServerBrowser.py:52 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:57 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:57 msgid "Name" msgstr "" #: windows/winServerBrowser.py:21 windows/winServerBrowser.py:57 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:62 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:62 msgid "Playing" msgstr "" #: windows/winServerBrowser.py:21 windows/winServerBrowser.py:60 #: windows/xrc/winAccount.py:75 windows/xrc/winConnect.py:76 #: windows/winServerBrowser.py:23 windows/xrc/winAccount.py:82 #: windows/xrc/winConnect.py:83 windows/winServerBrowser.py:65 #: windows/xrc/winAccount.py:85 windows/xrc/winConnect.py:86 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:65 #: windows/xrc/winAccount.py:85 windows/xrc/winConnect.py:86 msgid "Server" msgstr "" # Number of "Connected Players" #: windows/winServerBrowser.py:21 windows/winServerBrowser.py:68 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:73 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:73 msgid "C" msgstr "" # Number of "Visible Objects" #: windows/winServerBrowser.py:21 windows/winServerBrowser.py:72 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:77 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:77 msgid "O" msgstr "" #: windows/winServerBrowser.py:21 windows/winServerBrowser.py:80 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:85 #: windows/winServerBrowser.py:23 windows/winServerBrowser.py:85 msgid "Other" msgstr "" #: windows/winServerBrowser.py:26 windows/winServerBrowser.py:134 #: windows/winServerBrowser.py:28 windows/winServerBrowser.py:139 #: windows/winServerBrowser.py:28 windows/winServerBrowser.py:139 msgid "DNS" msgstr "" #: windows/winServerBrowser.py:26 windows/winServerBrowser.py:135 #: windows/winServerBrowser.py:28 windows/winServerBrowser.py:140 #: windows/winServerBrowser.py:28 windows/winServerBrowser.py:140 msgid "IP" msgstr "" #: windows/winServerBrowser.py:26 windows/winServerBrowser.py:136 #: windows/winServerBrowser.py:28 windows/winServerBrowser.py:141 #: windows/winServerBrowser.py:28 windows/winServerBrowser.py:141 msgid "Port" msgstr "" #: windows/winSystem.py:23 windows/main/panelSystem.py:22 #: windows/xrc/panelStarMap.py:67 windows/main/panelSystem.py:23 #: windows/xrc/panelStarMap.py:70 windows/main/panelSystem.py:23 #: windows/xrc/panelStarMap.py:70 msgid "System" msgstr "" #: windows/winSystem.py:126 windows/main/panelSystem.py:143 #: windows/main/panelSystem.py:152 windows/main/panelSystem.py:160 #: windows/main/panelSystem.py:160 msgid "Known Universe" msgstr "" #: windows/winUpdate.py:50 windows/winUpdate.py:55 windows/winUpdate.py:58 #: windows/winUpdate.py:58 msgid "Save log as ..." msgstr "" #: windows/winUpdate.py:171 windows/winUpdate.py:245 #: windows/xrc/winUpdate.py:84 windows/xrc/winUpdate.py:86 #: windows/xrc/winUpdate.py:85 windows/xrc/winUpdate.py:87 #: windows/winUpdate.py:177 windows/winUpdate.py:251 #: windows/xrc/winUpdate.py:88 windows/xrc/winUpdate.py:90 #: windows/winUpdate.py:182 windows/winUpdate.py:265 windows/winUpdate.py:193 #: windows/winUpdate.py:276 windows/xrc/winUpdate.py:88 #: windows/xrc/winUpdate.py:90 windows/winUpdate.py:193 #: windows/winUpdate.py:276 msgid "Done!" msgstr "" #: windows/winUpdate.py:194 windows/winUpdate.py:200 windows/winUpdate.py:214 #: windows/winUpdate.py:225 windows/winUpdate.py:225 #, python-format msgid "Getting %s" msgstr "" #: windows/winUpdate.py:222 windows/winUpdate.py:233 windows/winUpdate.py:228 #: windows/winUpdate.py:239 windows/winUpdate.py:242 windows/winUpdate.py:253 #: windows/winUpdate.py:264 windows/winUpdate.py:253 windows/winUpdate.py:264 #, python-format msgid "%s of %s" msgstr "" #: windows/xrc/configConnect.py:54 windows/xrc/configConnect.py:55 #: windows/xrc/configConnect.py:58 windows/xrc/configConnect.py:58 msgid "Login for" msgstr "" #: windows/xrc/configConnect.py:55 windows/xrc/winAccount.py:79 #: windows/xrc/winConnect.py:78 windows/xrc/configConnect.py:56 #: windows/xrc/winAccount.py:86 windows/xrc/winConnect.py:86 #: windows/xrc/configConnect.py:59 windows/xrc/winAccount.py:89 #: windows/xrc/winConnect.py:89 windows/xrc/configConnect.py:59 #: windows/xrc/winAccount.py:89 windows/xrc/winConnect.py:89 msgid "Username" msgstr "" #: windows/xrc/configConnect.py:56 windows/xrc/winAccount.py:80 #: windows/xrc/winConnect.py:79 windows/xrc/configConnect.py:57 #: windows/xrc/winAccount.py:87 windows/xrc/winConnect.py:87 #: windows/xrc/configConnect.py:60 windows/xrc/winAccount.py:90 #: windows/xrc/winConnect.py:90 windows/xrc/configConnect.py:60 #: windows/xrc/winAccount.py:90 windows/xrc/winConnect.py:90 msgid "The username for the account on the Thousand Parsec server." msgstr "" #: windows/xrc/configConnect.py:57 windows/xrc/winAccount.py:81 #: windows/xrc/winConnect.py:80 windows/xrc/configConnect.py:58 #: windows/xrc/winAccount.py:88 windows/xrc/winConnect.py:88 #: windows/xrc/configConnect.py:61 windows/xrc/winAccount.py:91 #: windows/xrc/winConnect.py:91 windows/xrc/configConnect.py:61 #: windows/xrc/winAccount.py:91 windows/xrc/winConnect.py:91 msgid "Show seperate game box." msgstr "" # This "G" indicates the "Game" menu fly out. #: windows/xrc/configConnect.py:58 windows/xrc/winAccount.py:82 #: windows/xrc/winConnect.py:81 windows/xrc/configConnect.py:59 #: windows/xrc/winAccount.py:89 windows/xrc/winConnect.py:89 #: windows/xrc/configConnect.py:62 windows/xrc/winAccount.py:92 #: windows/xrc/winConnect.py:92 windows/xrc/configConnect.py:62 #: windows/xrc/winAccount.py:92 windows/xrc/winConnect.py:92 msgid "G" msgstr "" #: windows/xrc/configConnect.py:59 windows/xrc/winAccount.py:83 #: windows/xrc/winConnect.py:82 windows/xrc/configConnect.py:60 #: windows/xrc/winAccount.py:90 windows/xrc/winConnect.py:90 #: windows/xrc/configConnect.py:63 windows/xrc/winAccount.py:93 #: windows/xrc/winConnect.py:93 windows/xrc/configConnect.py:63 #: windows/xrc/winAccount.py:93 windows/xrc/winConnect.py:93 msgid "Game" msgstr "" #: windows/xrc/configConnect.py:60 windows/xrc/winAccount.py:84 #: windows/xrc/winConnect.py:83 windows/xrc/configConnect.py:61 #: windows/xrc/winAccount.py:91 windows/xrc/winConnect.py:91 #: windows/xrc/configConnect.py:64 windows/xrc/winAccount.py:94 #: windows/xrc/winConnect.py:94 windows/xrc/configConnect.py:64 #: windows/xrc/winAccount.py:94 windows/xrc/winConnect.py:94 msgid "Password" msgstr "" #: windows/xrc/configConnect.py:61 windows/xrc/configConnect.py:62 #: windows/xrc/configConnect.py:65 windows/xrc/configConnect.py:65 msgid "Autoconnect" msgstr "" #: windows/xrc/configConnect.py:62 windows/xrc/configConnect.py:63 #: windows/xrc/configConnect.py:66 windows/xrc/configConnect.py:66 msgid "Debug Output" msgstr "" #: windows/xrc/panelInformation.py:38 windows/xrc/panelInformation.py:39 #: windows/xrc/panelInformation.py:42 windows/xrc/panelInformation.py:42 msgid "Name of object goes here" msgstr "" #: windows/xrc/panelMessage.py:67 windows/xrc/panelMessage.py:68 #: windows/xrc/panelMessage.py:71 windows/xrc/panelMessage.py:71 msgid "Filter" msgstr "" #: windows/xrc/panelMessage.py:68 windows/xrc/panelMessage.py:69 #: windows/xrc/panelMessage.py:72 windows/xrc/panelMessage.py:72 msgid "Static text" msgstr "" #: windows/xrc/panelMessage.py:69 windows/xrc/panelMessage.py:70 #: windows/xrc/panelMessage.py:73 windows/xrc/panelMessage.py:73 msgid "100 of 100" msgstr "" #: windows/xrc/panelMessage.py:70 windows/xrc/panelMessage.py:71 #: windows/xrc/panelMessage.py:74 windows/xrc/panelMessage.py:74 msgid "" "\n" "\n" "
\n" "\t\n" "\t\t\n" "\t\t\t\n" "\t\t\n" "\t\t\t\n" "\t\t\n" "\t
Subject: You are unloved!\n" "\t\t
\n" "\t\t\tYou have recived no messages this turn!

\n" "\t\t\tActually if you didn't recive any messages it most proberly\n" "\t\t\tmeans that your client couldn't load the results from the server.\n" "\t\t\tTry reload/restart the client.\n" "\t\t\t
\n" "
\n" "\n" "" msgstr "" #: windows/xrc/panelMessage.py:71 windows/xrc/panelMessage.py:72 #: windows/xrc/panelMessage.py:75 windows/xrc/panelMessage.py:75 msgid "Prev" msgstr "" #: windows/xrc/panelMessage.py:72 windows/xrc/panelMessage.py:73 #: windows/xrc/panelMessage.py:76 windows/xrc/panelMessage.py:76 msgid "First" msgstr "" #: windows/xrc/panelMessage.py:73 windows/xrc/panelMessage.py:74 #: windows/xrc/panelMessage.py:77 windows/xrc/panelMessage.py:77 msgid "Goto" msgstr "" #: windows/xrc/panelMessage.py:74 windows/xrc/panelMessage.py:75 #: windows/xrc/panelMessage.py:78 windows/xrc/panelMessage.py:78 msgid "Next" msgstr "" #: windows/xrc/panelMessage.py:75 windows/xrc/panelMessage.py:76 #: windows/xrc/panelMessage.py:79 windows/xrc/panelMessage.py:79 msgid "Last" msgstr "" #: windows/xrc/panelOrder.py:57 windows/xrc/panelOrder.py:64 #: windows/xrc/panelOrder.py:68 windows/xrc/panelOrder.py:68 msgid "Insert new order." msgstr "" #: windows/xrc/panelOrder.py:58 windows/xrc/panelOrder.py:65 #: windows/xrc/panelOrder.py:69 windows/xrc/panelOrder.py:69 msgid "&New" msgstr "" #: windows/xrc/panelOrder.py:59 windows/xrc/winUpdate.py:102 #: windows/xrc/panelOrder.py:66 windows/xrc/winUpdate.py:103 #: windows/xrc/panelOrder.py:70 windows/xrc/winUpdate.py:106 #: windows/xrc/panelOrder.py:70 windows/xrc/winUpdate.py:106 msgid "&Save" msgstr "" #: windows/xrc/panelOrder.py:60 windows/xrc/panelOrder.py:67 #: windows/xrc/panelOrder.py:71 windows/xrc/panelOrder.py:71 msgid "&Revert" msgstr "" #: windows/xrc/panelOrder.py:61 windows/xrc/panelOrder.py:68 #: windows/xrc/panelOrder.py:72 windows/xrc/panelOrder.py:72 msgid "Delete the currently selected order(s)" msgstr "" #: windows/xrc/panelOrder.py:62 windows/xrc/panelOrder.py:69 #: windows/xrc/panelOrder.py:73 windows/xrc/panelOrder.py:73 msgid "&Delete" msgstr "" #: windows/xrc/panelPicture.py:43 windows/xrc/panelPicture.py:45 #: windows/xrc/panelPicture.py:48 windows/xrc/panelPicture.py:48 msgid "Name goes here" msgstr "" #: windows/xrc/panelPicture.py:44 windows/xrc/panelPicture.py:46 #: windows/xrc/panelPicture.py:49 windows/xrc/panelPicture.py:49 msgid "10kb/s" msgstr "" #: windows/xrc/panelPicture.py:45 windows/xrc/panelPicture.py:47 #: windows/xrc/panelPicture.py:50 windows/xrc/panelPicture.py:50 msgid "43s" msgstr "" #: windows/xrc/winAccount.py:73 windows/xrc/winConnect.py:74 #: windows/xrc/winAccount.py:80 windows/xrc/winConnect.py:81 #: windows/xrc/winAccount.py:83 windows/xrc/winConnect.py:84 #: windows/xrc/winAccount.py:83 windows/xrc/winConnect.py:84 msgid "TP: Connect to a Server" msgstr "" #: windows/xrc/winAccount.py:74 windows/xrc/winAccount.py:81 #: windows/xrc/winAccount.py:84 windows/xrc/winAccount.py:84 msgid "Create an Account" msgstr "" #: windows/xrc/winAccount.py:76 windows/xrc/winConnect.py:77 #: windows/xrc/winAccount.py:83 windows/xrc/winConnect.py:84 #: windows/xrc/winAccount.py:86 windows/xrc/winConnect.py:87 #: windows/xrc/winAccount.py:86 windows/xrc/winConnect.py:87 msgid "The URL for the Thousand Parsec server." msgstr "" #: windows/xrc/winAccount.py:77 windows/xrc/winAccount.py:84 #: windows/xrc/winAccount.py:87 windows/xrc/winAccount.py:87 msgid "Choose a server to create an account on." msgstr "" #: windows/xrc/winAccount.py:78 windows/xrc/winAccount.py:85 #: windows/xrc/winAccount.py:88 windows/xrc/winAccount.py:88 msgid "Check" msgstr "" #: windows/xrc/winAccount.py:85 windows/xrc/winAccount.py:92 #: windows/xrc/winAccount.py:95 windows/xrc/winAccount.py:95 msgid "Choose your password here." msgstr "" #: windows/xrc/winAccount.py:86 windows/xrc/winAccount.py:93 #: windows/xrc/winAccount.py:96 windows/xrc/winAccount.py:96 msgid " " msgstr "" #: windows/xrc/winAccount.py:87 windows/xrc/winAccount.py:89 #: windows/xrc/winAccount.py:94 windows/xrc/winAccount.py:96 #: windows/xrc/winAccount.py:97 windows/xrc/winAccount.py:99 #: windows/xrc/winAccount.py:97 windows/xrc/winAccount.py:99 msgid "Repeat the password" msgstr "" #: windows/xrc/winAccount.py:88 windows/xrc/winAccount.py:95 #: windows/xrc/winAccount.py:98 windows/xrc/winAccount.py:98 msgid "Email " msgstr "" #: windows/xrc/winAccount.py:90 windows/xrc/winConnect.py:85 #: windows/xrc/winUpdate.py:100 windows/xrc/winAccount.py:97 #: windows/xrc/winUpdate.py:101 windows/xrc/winConnect.py:93 #: windows/xrc/winAccount.py:100 windows/xrc/winUpdate.py:104 #: windows/xrc/winConnect.py:96 windows/xrc/winAccount.py:100 #: windows/xrc/winUpdate.py:104 windows/xrc/winConnect.py:96 msgid "&OK" msgstr "" #: windows/xrc/winAccount.py:91 windows/xrc/winConnect.py:86 #: windows/xrc/winServerBrowser.py:88 windows/xrc/winUpdate.py:104 #: windows/xrc/winServerBrowser.py:89 windows/xrc/winAccount.py:98 #: windows/xrc/winUpdate.py:105 windows/xrc/winConnect.py:94 #: windows/xrc/winServerBrowser.py:92 windows/xrc/winAccount.py:101 #: windows/xrc/winUpdate.py:108 windows/xrc/winConnect.py:97 #: windows/xrc/winServerBrowser.py:92 windows/xrc/winAccount.py:101 #: windows/xrc/winUpdate.py:108 windows/xrc/winConnect.py:97 msgid "&Cancel" msgstr "" #: windows/xrc/winConnect.py:75 windows/xrc/winConnect.py:82 #: windows/xrc/winConnect.py:85 windows/xrc/winConnect.py:85 msgid "Connect to Thousand Parsec Server" msgstr "" #: windows/xrc/winConnect.py:84 windows/xrc/winConnect.py:92 #: windows/xrc/winConnect.py:95 windows/xrc/winConnect.py:95 msgid "The password for the account on the Thousand Parsec Server" msgstr "" #: windows/xrc/winConnect.py:87 windows/xrc/winConnect.py:85 #: windows/xrc/winConnect.py:88 windows/xrc/winConnect.py:88 msgid "&Find" msgstr "" #: windows/xrc/winConnect.py:88 windows/xrc/winConnect.py:95 #: windows/winMain.py:253 windows/xrc/winConnect.py:98 windows/winMain.py:256 #: windows/winMain.py:258 windows/xrc/winConnect.py:98 windows/winMain.py:264 msgid "&Preferences" msgstr "" #: windows/xrc/winServerBrowser.py:72 windows/xrc/winServerBrowser.py:73 #: windows/xrc/winServerBrowser.py:76 windows/xrc/winServerBrowser.py:76 msgid "TP: Server Browser" msgstr "" #: windows/xrc/winServerBrowser.py:73 windows/xrc/winServerBrowser.py:74 #: windows/xrc/winServerBrowser.py:77 windows/xrc/winServerBrowser.py:77 msgid "Thousand Parsec Server Browser" msgstr "" #: windows/xrc/winServerBrowser.py:74 windows/xrc/winServerBrowser.py:75 #: windows/xrc/winServerBrowser.py:78 windows/xrc/winServerBrowser.py:78 msgid "Servers" msgstr "" #: windows/xrc/winServerBrowser.py:75 windows/xrc/winServerBrowser.py:76 #: windows/xrc/winServerBrowser.py:79 windows/xrc/winServerBrowser.py:79 msgid "List of all the servers registered on the metaserver." msgstr "" #: windows/xrc/winServerBrowser.py:76 windows/xrc/winServerBrowser.py:77 #: windows/xrc/winServerBrowser.py:80 windows/xrc/winServerBrowser.py:80 msgid "Locations" msgstr "" #: windows/xrc/winServerBrowser.py:77 windows/xrc/winServerBrowser.py:78 #: windows/xrc/winServerBrowser.py:81 windows/xrc/winServerBrowser.py:81 msgid "List of all the servers found on the local network." msgstr "" #: windows/xrc/winServerBrowser.py:78 windows/xrc/winServerBrowser.py:79 #: windows/xrc/winServerBrowser.py:82 windows/xrc/winServerBrowser.py:82 msgid "URL" msgstr "" #: windows/xrc/winServerBrowser.py:79 windows/xrc/winServerBrowser.py:80 #: windows/xrc/winServerBrowser.py:83 windows/xrc/winServerBrowser.py:83 msgid "URL of the currently selected server." msgstr "" #: windows/xrc/winServerBrowser.py:80 windows/xrc/winServerBrowser.py:81 #: windows/xrc/winServerBrowser.py:84 windows/xrc/winServerBrowser.py:84 msgid "Copy the URL to the clipboard." msgstr "" #: windows/xrc/winServerBrowser.py:81 windows/xrc/winServerBrowser.py:82 #: windows/xrc/winServerBrowser.py:85 windows/xrc/winServerBrowser.py:85 msgid "&Copy" msgstr "" #: windows/xrc/winServerBrowser.py:82 windows/xrc/winServerBrowser.py:83 #: windows/xrc/winServerBrowser.py:86 windows/xrc/winServerBrowser.py:86 msgid "Force a refresh of the server list." msgstr "" #: windows/xrc/winServerBrowser.py:83 windows/xrc/winServerBrowser.py:84 #: windows/xrc/winServerBrowser.py:87 windows/xrc/winServerBrowser.py:87 msgid "&Refresh" msgstr "" #: windows/xrc/winServerBrowser.py:84 windows/xrc/winServerBrowser.py:85 #: windows/xrc/winServerBrowser.py:88 windows/xrc/winServerBrowser.py:88 msgid "Create a new account on the currently selected server." msgstr "" #: windows/xrc/winServerBrowser.py:85 windows/xrc/winServerBrowser.py:86 #: windows/xrc/winServerBrowser.py:89 windows/xrc/winServerBrowser.py:89 msgid "&New Account" msgstr "" #: windows/xrc/winServerBrowser.py:86 windows/xrc/winServerBrowser.py:87 #: windows/xrc/winServerBrowser.py:90 windows/xrc/winServerBrowser.py:90 msgid "Connect to the currently selected server." msgstr "" #: windows/xrc/winServerBrowser.py:87 windows/xrc/winServerBrowser.py:88 #: windows/xrc/winServerBrowser.py:91 windows/xrc/winServerBrowser.py:91 msgid "C&onnect" msgstr "" #: windows/xrc/winUpdate.py:82 msgid "TP: Downloading Universe" msgstr "" #: windows/xrc/winUpdate.py:83 windows/xrc/winUpdate.py:84 #: windows/xrc/winUpdate.py:87 windows/xrc/winUpdate.py:87 msgid "Universe Download" msgstr "" #: windows/xrc/winUpdate.py:85 windows/xrc/winUpdate.py:86 #: windows/xrc/winUpdate.py:89 windows/xrc/winUpdate.py:89 msgid "Progress" msgstr "" #: windows/xrc/winUpdate.py:87 windows/xrc/winUpdate.py:88 #: windows/xrc/winUpdate.py:91 windows/xrc/winUpdate.py:91 msgid "Objects Descs" msgstr "" #: windows/xrc/winUpdate.py:88 windows/xrc/winUpdate.py:89 #: windows/xrc/winUpdate.py:92 windows/xrc/winUpdate.py:92 msgid "Order Descs" msgstr "" #: windows/xrc/winUpdate.py:89 windows/xrc/winUpdate.py:90 #: windows/xrc/winUpdate.py:93 windows/xrc/winUpdate.py:93 msgid "Objects" msgstr "" #: windows/xrc/winUpdate.py:91 windows/xrc/winUpdate.py:92 #: windows/xrc/winUpdate.py:95 windows/xrc/winUpdate.py:95 msgid "Boards" msgstr "" #: windows/xrc/winUpdate.py:93 windows/xrc/winUpdate.py:94 #: windows/xrc/winUpdate.py:97 windows/xrc/winUpdate.py:97 msgid "Categories" msgstr "" #: windows/xrc/winUpdate.py:96 windows/xrc/winUpdate.py:97 #: windows/xrc/winUpdate.py:100 windows/xrc/winUpdate.py:100 msgid "Properties" msgstr "" #: windows/xrc/winUpdate.py:97 windows/xrc/winUpdate.py:98 #: windows/xrc/winUpdate.py:101 windows/xrc/winUpdate.py:101 msgid "Players" msgstr "" #: windows/xrc/winUpdate.py:98 windows/xrc/panelStarMap.py:68 #: windows/xrc/winUpdate.py:99 windows/xrc/panelStarMap.py:71 #: windows/xrc/winUpdate.py:102 windows/xrc/panelStarMap.py:71 #: windows/xrc/winUpdate.py:102 msgid "Resources" msgstr "" #: windows/xrc/winUpdate.py:99 windows/xrc/winUpdate.py:100 #: windows/xrc/winUpdate.py:103 windows/xrc/winUpdate.py:103 msgid "Continue to the main game window." msgstr "" #: windows/xrc/winUpdate.py:101 windows/xrc/winUpdate.py:102 #: windows/xrc/winUpdate.py:105 windows/xrc/winUpdate.py:105 msgid "Save a copy of the message box window to a file." msgstr "" #: windows/xrc/winUpdate.py:103 windows/xrc/winUpdate.py:104 #: windows/xrc/winUpdate.py:107 windows/xrc/winUpdate.py:107 msgid "Cancel the current update and go back to the connect screen." msgstr "" #: windows/winInfo.py:83 msgid "SelectObject: No such object." msgstr "" #: windows/winInfo.py:96 windows/main/panelInfo.py:68 #: windows/main/panelInfo.py:75 windows/main/panelInfo.py:75 msgid "Ships: " msgstr "" #: windows/winInfo.py:103 windows/main/panelInfo.py:75 #: windows/main/panelInfo.py:82 windows/main/panelInfo.py:82 msgid "Unknown Design id:" msgstr "" #: windows/winInfo.py:104 windows/main/panelInfo.py:76 #: windows/main/panelInfo.py:83 windows/main/panelInfo.py:83 #, python-format msgid "Unknown (type: %s)" msgstr "" #: tp/client/cache.py:348 tp/client/cache.py:438 tp/client/cache.py:443 #: tp/client/cache.py:443 msgid "Getting order descriptions..." msgstr "" #: tp/client/cache.py:349 tp/client/cache.py:439 tp/client/cache.py:444 #: tp/client/cache.py:444 msgid "Working out the number of order descriptions to get.." msgstr "" #: tp/client/cache.py:363 tp/client/cache.py:453 tp/client/cache.py:458 #: tp/client/cache.py:458 #, python-format msgid "Got order description %s (ID: %i) (last modified at %s)..." msgstr "" #: tp/client/cache.py:367 tp/client/cache.py:457 tp/client/cache.py:462 #: tp/client/cache.py:462 #, python-format msgid "Failed to get order description with id, %i (last modified at %s)..." msgstr "" #: tp/client/cache.py:368 tp/client/cache.py:458 msgid "Finished getting order descriptions..." msgstr "" #: tp/client/cache.py:387 tp/client/cache.py:477 msgid "Getting your player object..." msgstr "" #: tp/client/cache.py:389 msgid "Gotten your player object..." msgstr "" #: tp/client/cache.py:411 tp/client/cache.py:501 tp/client/cache.py:534 #: tp/client/cache.py:534 #, python-format msgid "Getting %s..." msgstr "" #: tp/client/cache.py:414 tp/client/cache.py:504 tp/client/cache.py:537 #: tp/client/cache.py:537 #, python-format msgid "Working out the number of %s to get.." msgstr "" #: tp/client/cache.py:429 tp/client/cache.py:519 tp/client/cache.py:552 #: tp/client/cache.py:552 #, python-format msgid "Got %s %s (id: %i) (last modified at %s)..." msgstr "" #: tp/client/cache.py:432 tp/client/cache.py:522 tp/client/cache.py:555 #: tp/client/cache.py:555 #, python-format msgid "No %s to get, skipping..." msgstr "" #: tp/client/cache.py:437 tp/client/cache.py:527 tp/client/cache.py:560 #: tp/client/cache.py:560 #, python-format msgid "Have %i %s to get..." msgstr "" #: tp/client/cache.py:448 tp/client/cache.py:538 tp/client/cache.py:571 #: tp/client/cache.py:571 #, python-format msgid "Failed to get the %s which was previously called %s." msgstr "" #: tp/client/cache.py:452 tp/client/cache.py:542 tp/client/cache.py:575 #: tp/client/cache.py:575 #, python-format msgid "Failed to get the %s with id %s." msgstr "" #: tp/client/cache.py:454 tp/client/cache.py:544 tp/client/cache.py:577 #: tp/client/cache.py:577 #, python-format msgid "Cleaning up %s which have disappeared..." msgstr "" #: tp/client/cache.py:461 tp/client/cache.py:551 tp/client/cache.py:584 #: tp/client/cache.py:584 #, python-format msgid "Removing %s %s as it has disappeared..." msgstr "" #: tp/client/cache.py:466 tp/client/cache.py:556 tp/client/cache.py:589 #: tp/client/cache.py:589 msgid "Building two way tree of the universe for speed..." msgstr "" #: tp/client/cache.py:475 #, python-format msgid "Gotten all %s..." msgstr "" #: tp/client/cache.py:493 tp/client/cache.py:583 tp/client/cache.py:616 #: tp/client/cache.py:616 #, python-format msgid "Getting %s.." msgstr "" #: tp/client/cache.py:494 tp/client/cache.py:584 tp/client/cache.py:617 #: tp/client/cache.py:617 #, python-format msgid "Have to get %s for %i %s.." msgstr "" #: tp/client/cache.py:504 tp/client/cache.py:594 tp/client/cache.py:627 #: tp/client/cache.py:627 #, python-format msgid "Sending a request for all %s on %s.." msgstr "" #: tp/client/cache.py:508 tp/client/cache.py:598 tp/client/cache.py:631 #: tp/client/cache.py:631 #, python-format msgid "Skipping requesting %s on %s as there are none!" msgstr "" #: tp/client/cache.py:526 tp/client/cache.py:616 tp/client/cache.py:649 #: tp/client/cache.py:649 #, python-format msgid "Failed to get %s for %s (id: %s) (%s)..." msgstr "" #: tp/client/cache.py:530 tp/client/cache.py:620 tp/client/cache.py:653 #: tp/client/cache.py:653 #, python-format msgid "Got %i %s for %s (id: %s)..." msgstr "" #: tp/client/cache.py:533 tp/client/cache.py:628 tp/client/cache.py:661 #: tp/client/cache.py:661 #, python-format msgid "Cleaning up any stray %s.." msgstr "" #: tp/client/cache.py:536 tp/client/cache.py:631 tp/client/cache.py:664 #: tp/client/cache.py:664 #, python-format msgid "Found stray %s for %s.." msgstr "" #: tp/client/cache.py:540 #, python-format msgid "Gotten all the %s.." msgstr "" #: tp/client/threads.py:286 tp/client/threads.py:550 tp/client/threads.py:321 #: tp/client/threads.py:616 tp/client/threads.py:323 tp/client/threads.py:529 #: tp/client/threads.py:545 tp/client/threads.py:323 tp/client/threads.py:545 msgid "There was an unknown network error.\n" msgstr "" #: tp/client/threads.py:287 tp/client/threads.py:551 tp/client/threads.py:322 #: tp/client/threads.py:617 tp/client/threads.py:324 tp/client/threads.py:530 #: tp/client/threads.py:546 tp/client/threads.py:324 tp/client/threads.py:546 msgid "Any changes since last save have been lost.\n" msgstr "" #: tp/client/threads.py:289 tp/client/threads.py:324 tp/client/threads.py:326 #: tp/client/threads.py:326 msgid "A traceback of the error was printed to the console.\n" msgstr "" #: tp/client/threads.py:317 tp/client/threads.py:344 tp/client/threads.py:346 #: tp/client/threads.py:346 msgid "The client was unable to connect to the host.\n" msgstr "" #: tp/client/threads.py:318 tp/client/threads.py:345 tp/client/threads.py:347 #: tp/client/threads.py:347 msgid "" "This could be because the server is down or there is a problem with the " "network.\n" msgstr "" #: tp/client/threads.py:322 tp/client/threads.py:349 tp/client/threads.py:351 #: tp/client/threads.py:351 msgid "The client could not connect to the host.\n" msgstr "" #: tp/client/threads.py:323 tp/client/threads.py:350 tp/client/threads.py:352 #: tp/client/threads.py:352 msgid "" "This could be because the server is down or you mistyped the server " "address.\n" msgstr "" #: tp/client/threads.py:326 tp/client/threads.py:353 tp/client/threads.py:355 #: tp/client/threads.py:355 msgid "Successfully connected to the host..." msgstr "" #: tp/client/threads.py:329 tp/client/threads.py:356 tp/client/threads.py:358 #: tp/client/threads.py:358 msgid "Looking for Thousand Parsec Server..." msgstr "" #: tp/client/threads.py:333 tp/client/threads.py:342 tp/client/threads.py:360 #: tp/client/threads.py:369 tp/client/threads.py:362 tp/client/threads.py:371 #: tp/client/threads.py:362 tp/client/threads.py:371 msgid "" "The client connected to the host but it did not appear to be a Thousand " "Parsec server.\n" msgstr "" #: tp/client/threads.py:334 tp/client/threads.py:343 tp/client/threads.py:361 #: tp/client/threads.py:370 tp/client/threads.py:363 tp/client/threads.py:372 #: tp/client/threads.py:363 tp/client/threads.py:372 msgid "" "This could be because the server is down or the connection details are " "incorrect.\n" msgstr "" #: tp/client/threads.py:337 tp/client/threads.py:364 tp/client/threads.py:366 #: tp/client/threads.py:366 msgid "Found a Thousand Parsec Server..." msgstr "" #: tp/client/threads.py:339 tp/client/threads.py:366 tp/client/threads.py:368 #: tp/client/threads.py:368 msgid "Looking for supported features..." msgstr "" #: tp/client/threads.py:346 tp/client/threads.py:373 tp/client/threads.py:375 #: tp/client/threads.py:375 msgid "Got the supported features..." msgstr "" #: tp/client/threads.py:355 tp/client/threads.py:382 tp/client/threads.py:384 #: tp/client/threads.py:384 msgid "Connecting..." msgstr "" #: tp/client/threads.py:361 tp/client/threads.py:388 tp/client/threads.py:390 #: tp/client/threads.py:390 msgid "Trying to Login to the server..." msgstr "" #: tp/client/threads.py:363 tp/client/threads.py:390 tp/client/threads.py:392 #: tp/client/threads.py:392 msgid "" "The client connected to the host but could not login because the username of " "password was incorrect.\n" msgstr "" #: tp/client/threads.py:364 tp/client/threads.py:391 tp/client/threads.py:393 #: tp/client/threads.py:393 msgid "" "This could be because you are connecting to the wrong server or mistyped the " "username or password.\n" msgstr "" #: tp/client/threads.py:367 tp/client/threads.py:394 tp/client/threads.py:396 #: tp/client/threads.py:396 msgid "Logged in okay!" msgstr "" #: windows/main/panelSystem.py:145 windows/main/panelSystem.py:154 #: windows/main/panelSystem.py:162 windows/main/panelSystem.py:162 #, python-format msgid "Finding %s" msgstr "" #: windows/main/panelOrder.py:423 windows/main/panelOrder.py:422 #: windows/main/panelOrder.py:444 windows/main/panelOrder.py:444 msgid "No orders avaliable" msgstr "" #: windows/main/panelOrder.py:432 windows/main/panelOrder.py:431 #: windows/main/panelOrder.py:453 windows/main/panelOrder.py:453 msgid "Order queued for removal." msgstr "" #: windows/main/panelInfo.py:81 windows/main/panelInfo.py:88 #: windows/main/panelInfo.py:88 msgid "Resources:\n" msgstr "" #: windows/main/panelInfo.py:90 windows/main/panelInfo.py:97 #: windows/main/panelInfo.py:97 #, python-format msgid "%s %s of %s on surface, " msgstr "" #: windows/main/panelInfo.py:94 windows/main/panelInfo.py:101 #: windows/main/panelInfo.py:101 #, python-format msgid "%s %s on surface, " msgstr "" #: windows/main/panelInfo.py:98 windows/main/panelInfo.py:105 #: windows/main/panelInfo.py:105 #, python-format msgid "%s %s of %s minable, " msgstr "" #: windows/main/panelInfo.py:102 windows/main/panelInfo.py:109 #: windows/main/panelInfo.py:109 #, python-format msgid "%s %s minable, " msgstr "" #: windows/main/panelInfo.py:106 windows/main/panelInfo.py:113 #: windows/main/panelInfo.py:113 #, python-format msgid "%s %s of %s inaccessible, " msgstr "" #: windows/main/panelInfo.py:110 windows/main/panelInfo.py:117 #: windows/main/panelInfo.py:117 #, python-format msgid "%s %s inaccessible, " msgstr "" #: windows/main/panelInfo.py:114 windows/main/panelInfo.py:121 #: windows/main/panelInfo.py:121 #, python-format msgid "\tUnknown Resource %i, S: %i, M: %i, I: %s\n" msgstr "" #: windows/main/winIdleFinder.py:17 windows/xrc/winIdleFinder.py:51 #: windows/main/winIdleFinder.py:26 windows/xrc/winIdleFinder.py:54 #: windows/main/winIdleFinder.py:26 windows/xrc/winIdleFinder.py:54 msgid "Objects Without Orders" msgstr "" #: windows/xrc/panelStarMap.py:62 windows/xrc/panelStarMap.py:65 #: windows/xrc/panelStarMap.py:65 msgid "Fit" msgstr "" #: windows/xrc/panelStarMap.py:63 windows/xrc/panelStarMap.py:66 #: windows/xrc/panelStarMap.py:66 msgid "80%" msgstr "" #: windows/xrc/panelStarMap.py:64 windows/xrc/panelStarMap.py:67 #: windows/xrc/panelStarMap.py:67 msgid "50%" msgstr "" #: windows/xrc/panelStarMap.py:65 windows/xrc/panelStarMap.py:68 #: windows/xrc/panelStarMap.py:68 msgid "10%" msgstr "" #: windows/xrc/panelStarMap.py:66 windows/xrc/panelStarMap.py:69 #: windows/xrc/panelStarMap.py:69 msgid "Box" msgstr "" #: windows/xrc/winDesign.py:99 windows/xrc/winDesign.py:102 #: windows/xrc/winDesign.py:102 msgid "0000" msgstr "" #: windows/xrc/winDesign.py:100 windows/xrc/winDesign.py:103 #: windows/xrc/winDesign.py:103 msgid "Some Categories, Will Go, Here" msgstr "" #: windows/xrc/winDesign.py:101 windows/xrc/winDesign.py:104 #: windows/xrc/winDesign.py:104 msgid "Property 1:" msgstr "" #: windows/xrc/winDesign.py:102 windows/xrc/winDesign.py:105 #: windows/xrc/winDesign.py:105 msgid "The value of property 1" msgstr "" #: windows/xrc/winDesign.py:103 windows/xrc/winDesign.py:106 #: windows/xrc/winDesign.py:106 msgid "Property 2:" msgstr "" #: windows/xrc/winDesign.py:104 windows/xrc/winDesign.py:107 #: windows/xrc/winDesign.py:107 msgid "The value of property 2" msgstr "" #: windows/xrc/winUpdate.py:83 windows/xrc/winUpdate.py:86 #: windows/xrc/winUpdate.py:86 msgid "TP: Universe update" msgstr "" #: windows/winMain.py:250 windows/winMain.py:253 windows/winMain.py:254 #: windows/winMain.py:260 msgid "C&onnect to Game\tCtrl-O" msgstr "" #: windows/winMain.py:251 windows/winMain.py:254 windows/winMain.py:255 #: windows/winMain.py:261 msgid "Download the &Universe\tCtrl-U" msgstr "" #: tp/client/cache.py:479 msgid "Received your player object..." msgstr "" #: tp/client/cache.py:565 #, python-format msgid "Received all %s..." msgstr "" #: tp/client/cache.py:635 tp/client/cache.py:668 tp/client/cache.py:668 #, python-format msgid "Received all the %s.." msgstr "" #: windows/xrc/orderList.py:54 windows/xrc/orderList.py:54 msgid "Choice 1" msgstr "" #: windows/xrc/orderList.py:55 windows/xrc/orderList.py:55 msgid "Choice 2" msgstr "" #: windows/xrc/winResourceSelect.py:58 windows/xrc/winResourceSelect.py:67 #: windows/xrc/winResourceSelect.py:67 msgid "Done" msgstr "" #: windows/winUpdate.py:192 windows/winUpdate.py:203 windows/winUpdate.py:203 msgid "Update done!" msgstr "" #: tp/client/cache.py:464 tp/client/cache.py:464 msgid "Recieved all order descriptions..." msgstr "" #: tp/client/cache.py:473 tp/client/cache.py:473 msgid "Don't have any orders to get.." msgstr "" #: tp/client/cache.py:479 tp/client/cache.py:479 msgid "Don't have any messages to get.." msgstr "" #: tp/client/cache.py:488 tp/client/cache.py:488 msgid "Getting player objects..." msgstr "" #: tp/client/cache.py:506 tp/client/cache.py:506 #, python-format msgid "Got player %s (id: %i)..." msgstr "" #: tp/client/cache.py:510 tp/client/cache.py:510 msgid "Received all player objects..." msgstr "" #: tp/client/cache.py:598 tp/client/cache.py:598 #, python-format msgid "received all %s..." msgstr "" #: doc/tips.txt:1 doc/tips.txt:1 msgid "" "Welcome to tpclient-pywx. This client is written in python using wxPython " "and should allow to connect to any Thousand Parsec server." msgstr "" #: doc/tips.txt:2 doc/tips.txt:2 msgid "You can click on the star map to select objects!" msgstr "" #: doc/tips.txt:3 doc/tips.txt:3 msgid "" "The client has many shortcuts, check out the help file for more information." msgstr "" #: doc/tips.txt:4 doc/tips.txt:4 msgid "" "You can quickly issue a move order by right clicking where you want an " "object to go." msgstr "" #: doc/tips.txt:5 doc/tips.txt:5 msgid "The waypoint mode is a good way of setting up a large path quickly." msgstr "" #: doc/tips.txt:6 doc/tips.txt:6 msgid "" "You can right click on the orders windows to access a bunch of quick " "functions including cut, copy and paste!" msgstr "" #: doc/tips.txt:7 doc/tips.txt:7 msgid "" "If the paste menu option is grayed out, the orders you are trying to paste " "are not valid on that object." msgstr "" #: doc/tips.txt:8 doc/tips.txt:8 msgid "" "If you hold down shift a number of buttons change to allow you to quickly " "jump to first or last of things." msgstr "" #: doc/tips.txt:9 doc/tips.txt:9 msgid "" "The system filter box uses standard matching pattern, you can use ? for a " "single character or * for any number." msgstr "" #: windows/main/winHelp.py:54 windows/main/winHelp.py:54 msgid "Warning - No Objects..." msgstr "" #: windows/main/winHelp.py:55 windows/main/winHelp.py:55 msgid "" "\n" "

\n" "It appears that you do not own any objects. This may be for a number of\n" "reasons:\n" "

\n" "
    \n" "\t
  • You have logged in as a guest user.\n" "\t

    \n" "\t\tOn most servers guest users can only login and view the universe. They\n" "own no objects and can not issue orders. This is good to checkout what the\n" "Universe is like, but not if you actually want to play the game.\n" "\t

    \n" "\t\tMost servers allow you to create accounts right from this client! This\n" "can be done by clicking \"Find\" on the Login window to bring up the \n" "server browser. (Open server browser " "window.)\n" "\t


  • \n" "\t
  • You have been defeated.\n" "\t

    \n" "\t\tIf you have not logged in for a long time, all your objects may have\n" "been conquered or destroyed. Some servers may let you create a new account " "and\n" "start again.\n" "\t


  • \n" "\t
  • There is a problem.\n" "\t

    \n" "\t\tThere could be a bug in some of the software, if you are sure neither\n" "of the two cases above are correct please report it \n" "here.\n" "\t

  • \n" "
\n" msgstr "" #: windows/xrc/winHelp.py:70 windows/xrc/winHelp.py:70 msgid "Important Information...." msgstr "" #: windows/xrc/winHelp.py:71 windows/xrc/winHelp.py:71 msgid "Do not show this message again." msgstr "" #: windows/xrc/winHelp.py:72 windows/xrc/winHelp.py:72 msgid "&Close" msgstr "" #: windows/winMain.py:256 windows/winMain.py:262 msgid "Request End of &Turn\tCtrl-T" msgstr "" #: windows/winMain.py:256 windows/winMain.py:262 msgid "Send a message to the server requesting the turn end soon." msgstr "" #: windows/winMain.py:299 msgid "Online Help" msgstr "" #: windows/winMain.py:299 msgid "Go to the online help page." msgstr "" #: windows/winMain.py:300 msgid "About" msgstr "" #: windows/winMain.py:300 msgid "About the client you are running..." msgstr "" #: windows/winMain.py:403 msgid "wxPython Client" msgstr "" #: windows/winMain.py:405 msgid "(C) 2001-2008 Thousand Parsec Developers" msgstr "" #: windows/winMain.py:406 msgid "" "This Thousand Parsec client, written in python, is an easy way to join and " "start playing in a Thousand Parsec game." msgstr "" tpclient-pywx-0.3.1.1/locale/generate.sh0000755000175000017500000000025010773624641016244 0ustar timtim#! /bin/sh cd .. xgettext -j -L python --from-code utf-8 -o ./locale/tpclient-pywx.pot `find -name \*.py` tpclient-pywx `find ./tp/client/ -name \*.py` ./doc/tips.txt tpclient-pywx-0.3.1.1/build-deb.sh0000755000175000017500000000053310773624641015046 0ustar timtim#! /bin/sh # Reset the tree to the checkout cg-reset cg-clean -d -x #cg-restore -f ./tp/netlib/version.py # Update to the latest version cg-update # Update the debian changelog cd debian; ./update-debian-changelog; cd .. # Build the deb package dpkg-buildpackage -us -uc -b -rfakeroot # Reset the tree to the checkout cg-reset cg-clean -d -x tpclient-pywx-0.3.1.1/TODO0000644000175000017500000000114710773624641013352 0ustar timtim TODO ======================================================= See also - https://sourceforge.net/tracker/?group_id=132078&atid=829724 Short Term * Remove all the print states - make debug output go to the debug window * Put up screenshots on www.thousandparsec.net * Better default positioning of windows * Allow starting tips to be disabled in the config * Stop annoying flicker on save * Fixup and cleanup the Config dialog Longer Term * Make data in the info panel good looking * Let the fonts be selected * Fix the default fonts Longest Term * Check what it looks like under windows / MacOSX tpclient-pywx-0.3.1.1/requirements.py0000755000175000017500000002463710773624641015773 0ustar timtim#! /usr/bin/env python # This file checks you have installed the requirements for tpclient-pywx # It can be run as standalone but is also run by the client at startup # Preference the local directory first... import sys sys.path.insert(0, '.') import time import os.path notfound = [] recommended = [] class FileOutput(object): def __init__(self, stdout=None): self.o = stdout from utils import configpath self.f = open(os.path.join(configpath(), "tpclient-pywx.log"), "wb") if not self.o is None: self.o.write("Output going to %s\n" % self.f.name) def write(self, s): if isinstance(s, unicode): s = s.encode('utf-8') if not self.o is None: self.o.write(s) self.f.write(s) def __del__(self): if not self.o is None: import os os.unlink(self.f.name) if hasattr(sys, "frozen"): sys.stdout = FileOutput() sys.stderr = sys.stdout system = "unknown" else: sys.stdout = FileOutput(sys.stdout) sys.stderr = sys.stdout # Try and figure out what type of system this computer is running. import os result = os.system('apt-get --version > /dev/null 2>&1') if result == 0: system = "debian-based" else: system = "unknown" def location(): if hasattr(sys, "frozen") and sys.frozen == "windows_exe": return os.path.dirname(unicode(sys.executable, sys.getfilesystemencoding( ))) elif hasattr(sys, "frozen") and sys.platform == "darwin": return unicode('/'+'/'.join(__file__.split('/')[:-4]), sys.getfilesystemencoding( )) else: return os.path.dirname(unicode(__file__, sys.getfilesystemencoding( ))) from types import StringTypes import re def cmp(ver1, ver2): if type(ver2) in StringTypes: ver2 = [int(x) for x in ver2.split('.')] ver2 = list(ver2) for i,x in enumerate(ver2): try: ver2[i] = int(x) except ValueError: # This means there could be a "pre" or "rc" something in the version # We will treat this version as the one before. ver2[i] = int(re.search('(\d+)', x).group())-1 for a, b in zip(ver1, ver2): if a < b: break if a == b: continue return False return True def tostr(ver1): s = "" for a in ver1: s += "."+str(a) return s[1:] print "My information:" print "---------------------------------------------------------------" import version try: print "My version", version.version_str+'+'+version.version_target_str, "(git %s)" % version.version_git except AttributeError: print "My version", version.version_str print "Running from ", os.path.dirname(os.path.join(os.path.abspath(__file__))) print print "Checking requirements:" print "---------------------------------------------------------------" try: import numpy except ImportError: if system == "debian-based": notfound.append("python-numpy") notfound.append("python-numpy-ext") else: notfound.append("NumPy or SciPy") if not hasattr(sys, "frozen"): wx_version = (2, 8, 0, 0) wx_version_str = '.'.join([str(x) for x in wx_version[0:2]]) try: import wxversion if os.path.exists("wxversion"): wxversion.select(open("wxversion").read()) else: wxversion.ensureMinimal(wx_version_str) except ImportError, e: pass try: import wx if not cmp(wx_version, wx.__version__.split('.')): raise ImportError("wxPython was too old") print "wxPython version is", wx.__version__ except (ImportError, KeyError), e: print e if system == "debian-based": notfound.append("python-wxgtk2.8") else: notfound.append("wxPython > " + wx_version_str) import __builtin__ try: import gettext __builtin__._ = gettext.gettext if sys.platform == "linux2": import os import wx import gettext basepath = os.path.abspath(os.path.dirname(__file__)) localedir = os.path.join(basepath, "locale") langid = wx.LANGUAGE_DEFAULT # use OS default; or use LANGUAGE_JAPANESE, etc. domain = "tpclient-pywx" # the translation file is tpclient-pywx.mo # Set locale for wxWidgets mylocale = wx.Locale(langid) mylocale.AddCatalogLookupPathPrefix(localedir) mylocale.AddCatalog(domain) # Set up Python's gettext mytranslation = gettext.translation(domain, localedir, [mylocale.GetCanonicalName()], fallback=True) mytranslation.install() import __builtin__ __builtin__.__dict__['_'] = wx.GetTranslation except ImportError, e: print e def _(s): return s __builtin__._ = _ reason = "Without gettext support localisation will be disabled." if system == "debian-based": recommended.append(("Python gettext should come with Python, please check your python install", reason)) else: recommended.append(("Python with gettext enabled", reason)) try: import psyco except ImportError, e: reason = "Installing pysco can give a 10-20% speed increase in starmap calculations. (Pysco is x86 only.)" if system == "debian-based": recommended.append(("python-psyco", reason)) else: recommended.append(("Pysco JIT compiler", reason)) try: try: import pyOpenSSL except ImportError, e: # Maybe it's using a different name import OpenSSL as pyOpenSSL except ImportError, e: print e reason = "Installing pyOpenSSL allows the client to check if the host you are connecting to has a valid certificate." if system == "debian-based": recommended.append(("python-pyopenssl", reason)) else: recommended.append(("pyOpenSSL", reason)) try: import Image except ImportError, e: print e reason = "Installing the PIL library will increase speed of displaying graphics." if system == "debian-based": recommended.append(("python-imaging", reason)) else: recommended.append(("Python Imaging library", reason)) try: import pygame except ImportError, e: print e reason = "Installing the Pygame library will allow you to see the intro movie and hear sounds." if system == "debian-based": recommended.append(("python-pygame", reason)) else: recommended.append(("Pygame library", reason)) netlib_version = (0, 2, 4) try: import tp.netlib print "Thousand Parsec Protocol Library Version", tp.netlib.__version__ try: print " (installed at %s)" % tp.netlib.__installpath__ except AttributeError: print " (version to old to work out install path)" try: from tp.netlib.version import version_git print " (git %s)" % version_git except ImportError: print if not cmp(netlib_version, tp.netlib.__version__): raise ImportError("Thousand Parsec Network Library (libtpproto-py) is to old") except (ImportError, KeyError, AttributeError), e: print e notfound.append("tp.netlib > " + tostr(netlib_version)) client_version = (0, 3, 1) try: import tp.client print "Thousand Parsec Client Library Version", tp.client.__version__ try: print " (installed at %s)" % tp.client.__installpath__ except AttributeError: print " (version to old to work out install path)" try: from tp.client.version import version_git print " (git %s)" % version_git except ImportError: print if not cmp(client_version, tp.client.__version__): raise ImportError("Thousand Parsec Client Library (libtpclient-py) is to old") except (ImportError, KeyError, AttributeError), e: print e notfound.append("tp.client > " + tostr(client_version)) if len(notfound) == 0: import sys if sys.platform == 'linux2': import os.path, stat linux_location = os.path.join(os.path.dirname(os.path.join(os.path.abspath(__file__))), "tpclient-pywx") if not os.path.exists(linux_location): print "Hrm, unable to find tpclient-pywx are you running outside a tpclient-pywx tree?" else: #print location # Check the file is executable try: os.chmod(linux_location, stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR|stat.S_IRGRP|stat.S_IXGRP|stat.S_IROTH|stat.S_IXOTH) except Exception, e: pass # Register the URL Handlers try: import gconf for prefix in ['tp', 'tps', 'tphttp', 'tphttps', 'tp+http', 'tp+https']: prefix = gconf.escape_key(prefix, len(prefix)) gconf.client_get_default().set_string('/desktop/gnome/url-handlers/%s/command' % prefix, linux_location) gconf.client_get_default().set_bool('/desktop/gnome/url-handlers/%s/enabled' % prefix, True) except ImportError, e: print e reason = "It is recommended that under gnome you have the Python Gconf module installed so I can register URL handlers." if system == "debian-based": recommended.append(("python-gconf", reason)) else: recommended.append(("Recent version of pyGTK", reason)) print print "Checking locations:" print "---------------------------------------------------------------" import os try: graphicsdir = os.environ["TPCLIENT_GRAPHICS"] except KeyError: graphicsdir = 'graphics' print "Graphics are in %s" % graphicsdir if not os.path.exists(os.path.join(graphicsdir, 'blank.png')): print "Can not find graphics required by this client." sys.exit() try: docdir = os.environ["TPCLIENT_DOC"] except KeyError: docdir = 'doc' print "Documents are in %s" % docdir if not os.path.exists(os.path.join(docdir, 'tips.txt')): print "Can not find help documentation required by this client." sys.exit() if len(notfound) > 0 or len(recommended) > 0: print print "Possible problems found:" print "---------------------------------------------------------------" if len(notfound) > 0: print "The following requirements where not met:" for module in notfound: print ' ', module print import os, pprint try: COLS = int(os.environ["COLUMNS"]) except (KeyError, ValueError): try: import struct, fcntl, sys, termios COLS = struct.unpack('hh', fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ, '1234'))[1] except: COLS = 80 ALIGN = 25 if len(recommended) > 0: print "The following recommended modules where not found:" for module, reason in recommended: lines = [""] lines[-1] += ' %s, ' % module lines[-1] += ' ' * (ALIGN-len(lines[-1])) for word in reason.split(" "): if (len(lines[-1]) + len(word) + 2) > COLS: lines.append(' '*ALIGN) lines[-1] += word + " " print print "\n".join(lines) # Check for an apt-get based system, if system == "debian-based": notfound_debian = [] for module in notfound: if module.find(' ') == -1: notfound_debian.append(module) if len(notfound_debian) > 0: print """ You may be able to install some of the requirements by running the following command as root: apt-get install %s """ % " ".join(notfound_debian) if len(recommended) > 0: print """ To install the modules recommended for full functionality, run the following command as root: apt-get install %s """ % " ".join(zip(*recommended)[0]) if len(notfound) > 0: import sys sys.exit(1) ## FIXME: This is here to extra is imported very early on. #import extra tpclient-pywx-0.3.1.1/windows/0000755000175000017500000000000010773624641014351 5ustar timtimtpclient-pywx-0.3.1.1/windows/__init__.py0000644000175000017500000000043410773624641016463 0ustar timtim from winSplash import winSplash from winMain import winMain from winConnect import winConnect from winAccount import winAccount from winUpdate import winUpdate from winConfig import winConfig __all__ = ['winSplash', 'winMain', 'winConnect', 'winAccount', 'winUpdate', 'winConfig'] tpclient-pywx-0.3.1.1/windows/winServerBrowser.py0000644000175000017500000001705710773624641020265 0ustar timtim # Python imports import string import os, os.path import time # wxPython Imports import wx # Local Imports from winBase import winBaseXRC from xrc.winServerBrowser import winServerBrowserBase from requirements import graphicsdir throbber = os.path.join(graphicsdir, "downloading.gif") okay = os.path.join(graphicsdir, "finished.gif") notokay = os.path.join(graphicsdir, "waiting.gif") class winServerBrowser(winServerBrowserBase, winBaseXRC): title = _("Updating") ServersColumns = [_("Name"), _("Playing"), _("Server"), _("P"), _("C"), _("O"), _("Other")] ServersColumns_Sizes = [ wx.LIST_AUTOSIZE, wx.LIST_AUTOSIZE, 100, wx.LIST_AUTOSIZE, wx.LIST_AUTOSIZE, wx.LIST_AUTOSIZE, -1] LocationsColumns = [_("Type"), _("DNS"), _("IP"), _("Port")] LocationsColumns_Sizes = [ wx.LIST_AUTOSIZE, wx.LIST_AUTOSIZE, wx.LIST_AUTOSIZE, wx.LIST_AUTOSIZE] def __init__(self, application): winServerBrowserBase.__init__(self, None) winBaseXRC.__init__(self, application) self.Servers.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnServerSelect) self.Locations.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnLocationSelect) self.LocationsBox.Bind(wx.EVT_LEFT_DOWN, self.OnToggleLocation) self.LocationsPanel.Bind(wx.EVT_LEFT_DOWN, self.OnToggleLocation) self.OnToggleLocation(False) self.application.gui.Binder(self.application.FinderClass.FoundLocalGameEvent, self.OnFoundLocalGame, self.IsShown) self.application.gui.Binder(self.application.FinderClass.FoundRemoteGameEvent, self.OnFoundRemoteGame, self.IsShown) # self.application.gui.Binder(self.application.FinderClass.LostLocalGameEvent, self.OnCacheUpdate) # self.application.gui.Binder(self.application.FinderClass.LostRemoteGameEvent, self.OnCacheUpdate) def AddGame(self, game=None, resize=True): ctrl = self.Servers Columns, Columns_Sizes = self.ServersColumns, self.ServersColumns_Sizes if not game is None: i = ctrl.GetItemCount() ctrl.InsertStringItem(i, "") ctrl.SetItemPyData(i, game) ctrl.SetStringItem(i, Columns.index(_("Name")), game.name) if game.where == "local": ctrl.SetItemTextColour(i, wx.Color(0,0,255)) try: ctrl.SetStringItem(i, Columns.index(_("Playing")), "%s (%s)" % (game.rule, game.rulever)) except AttributeError: pass try: ctrl.SetStringItem(i, Columns.index(_("Server")), "%s (%s)" % (game.sertype, game.server)) except AttributeError: pass # try: # ctrl.SetToolTipItem(i, game.cmt) # except AttributeError: pass try: ctrl.SetStringItem(i, Columns.index(_("C")), unicode(game.cons)) except AttributeError: pass try: ctrl.SetStringItem(i, Columns.index(_("O")), unicode(game.objs)) except AttributeError: pass try: ctrl.SetStringItem(i, Columns.index(_("P")), unicode(game.plys)) except AttributeError: pass try: ctrl.SetStringItem(i, Columns.index(_("Other")), game.cmt) except AttributeError: pass if resize: for i, name in enumerate(Columns): ctrl.SetColumnWidth(i, Columns_Sizes[i]) def Setup(self): ctrl = self.Servers Columns, Columns_Sizes = self.ServersColumns, self.ServersColumns_Sizes ctrl.ClearAll() for i, name in enumerate(Columns): ctrl.InsertColumn(i, name) local, remote = self.application.finder.Games() for games in (local, remote): for game in games.values(): if game.name in local: game.where = "local" else: game.where = "remote" self.AddGame(game, False) self.AddGame(None, True) def OnFoundLocalGame(self, evt): game = evt.game game.where = "local" self.AddGame(game) def OnFoundRemoteGame(self, evt): game = evt.game game.where = "remote" self.AddGame(game) def OnServerSelect(self, evt): ctrl = self.Locations shown = ctrl.IsShown() Columns, Columns_Sizes = self.LocationsColumns, self.LocationsColumns_Sizes game = self.Servers.GetItemPyData(evt.GetIndex()) ctrl.ClearAll() # Add the columns for i, name in enumerate(Columns): ctrl.InsertColumn(i, name) # Populate the columns with data for type, addrs in game.locations.items(): for dns, ip, port in addrs: i = ctrl.GetItemCount() ctrl.InsertStringItem(i, "") ctrl.SetStringItem(i, Columns.index(_("Type")), type) ctrl.SetStringItem(i, Columns.index(_("DNS")), dns) ctrl.SetStringItem(i, Columns.index(_("IP")), ip) ctrl.SetStringItem(i, Columns.index(_("Port")), unicode(port)) ctrl.SetItemPyData(i, (game, (type, dns, ip, port))) # Set the column widths for i, name in enumerate(Columns): ctrl.SetColumnWidth(i, Columns_Sizes[i]) ctrl.Show() # Set best location item selected and focused type, addr = game.bestLocation() slot = ctrl.FindItemByPyData((game, (type, addr[0], addr[1], addr[2]))) t = wx.LIST_STATE_FOCUSED|wx.LIST_STATE_SELECTED ctrl.SetItemState(slot, t, t) self.OnLocationSelect(slot) self.OnToggleLocation(shown) def OnToggleLocation(self, evt): if not isinstance(evt, bool): toggle = not self.Locations.IsShown() else: toggle = evt if toggle: self.Locations.Show() self.LocationsBox.SetClientSize(self.Locations.GetBestSize()) else: self.Locations.Hide() self.LocationsBox.SetSize((-1, 1)) self.LocationsBox.Layout() self.LocationsPanel.Layout() if wx.Platform == "__WXMAC__": self.Servers.SetSize((-1, 10)) self.Panel.Layout() def OnLocationSelect(self, evt): if isinstance(evt, int): slot = evt else: slot = evt.GetIndex() game, (type, dns, ip, port) = self.Locations.GetItemPyData(slot) # We use the IP address for local games as mDNS's might not be resolvable to everyone if game.where == "local": dns = ip # Set the copy box to the URL self.URL.SetValue("%s://%s:%s/%s" % (type, dns, port, game.name)) def OnNewAccount(self, evt): self.application.gui.Show(self.application.gui.account) def OnConnectTo(self, evt): pass def Show(self, show=True): if not show: return self.Hide() # Setup the ListCtrl try: self.Setup() except Exception, e: import traceback traceback.print_exc() print e # Hide the Location Control self.OnToggleLocation(False) self.CenterOnScreen(wx.BOTH) return winBaseXRC.Show(self) def OnCancel(self, evt): self.application.gui.Show(self.application.gui.connectto) def OnRefresh(self, evt=None): self.Progress.LoadFile(throbber) self.Progress.Play() self.application.finder.Call(self.application.finder.refresh) # Disable the refresh button until the finder is done... self.Refresh.Disable() def OnRefreshFinished(self, worked, message=""): # Renable the refresh button self.Refresh.Enable() if worked: self.Progress.LoadFile(okay) else: self.Progress.LoadFile(notokay) self.Progress.Play() self.Progress.SetToolTip(message) def OnFinderError(self, evt): self.RefreshFinished(False, unicode(evt)) def OnFinderFinished(self, evt): self.RefreshFinished(True) # Config Functions ----------------------------------------------------------------------------- def ConfigDefault(self, config=None): """\ Fill out the config with defaults (if the options are not valid or nonexistant). """ return {} def ConfigSave(self): """\ Returns the configuration of the Window (and it's children). """ return {} def ConfigLoad(self, config={}): """\ Loads the configuration of the Window (and it's children). """ pass def ConfigUpdate(self): """\ Updates the config details using external sources. """ pass def ConfigDisplay(self, panel, sizer): """\ Display a config panel with all the config options. """ pass def ConfigDisplayUpdate(self, evt): """\ Update the Display because it's changed externally. """ pass tpclient-pywx-0.3.1.1/windows/main/0000755000175000017500000000000010773624641015275 5ustar timtimtpclient-pywx-0.3.1.1/windows/main/panelSystem.py0000644000175000017500000001573210773624641020163 0ustar timtim"""\ This module contains the System window. The System window displays all objects at this current location and "quick" details about them. """ # Python imports import random import os.path import sys # wxPython imports import wx import wx.gizmos # Local imports from requirements import graphicsdir NAME = 0 DESC = 1 from extra.StateTracker import TrackerObject from windows.xrc.panelSystem import panelSystemBase class panelSystem(panelSystemBase, TrackerObject): title = _("System") def __init__(self, application, parent): panelSystemBase.__init__(self, parent) # Setup to recieve game events self.application = application self.SelectIgnore = False self.SelectedPrevious = None self.icons = {} self.icons['Blank'] = wx.Image(os.path.join(graphicsdir, "blank-icon.png")).ConvertToBitmap() self.icons['Root'] = wx.Image(os.path.join(graphicsdir, "tp-icon.png")).ConvertToBitmap() self.icons['Container'] = wx.Image(os.path.join(graphicsdir, "link-icon.png")).ConvertToBitmap() self.icons['StarSystem'] = wx.Image(os.path.join(graphicsdir, "system-icon.png")).ConvertToBitmap() self.icons['Fleet'] = wx.Image(os.path.join(graphicsdir, "ship-icon.png")).ConvertToBitmap() self.icons['Planet'] = wx.Image(os.path.join(graphicsdir, "planet-icon.png")).ConvertToBitmap() self.icons['Unknown'] = wx.Image(os.path.join(graphicsdir, "starbase-icon.png")).ConvertToBitmap() self.il = wx.ImageList(16, 16) self.il.Add(wx.Image(os.path.join(graphicsdir, "blank.png")).ConvertToBitmap()) for i in self.icons.keys(): self.icons[i] = self.il.Add(self.icons[i]) self.Tree.SetImageList(self.il) self.Tree.SetFont(wx.local.normalFont) self.Tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelectItem) self.NextObject.Bind(wx.EVT_BUTTON, self.OnNextObject) self.PrevObject.Bind(wx.EVT_BUTTON, self.OnPrevObject) self.StepInto.Bind(wx.EVT_BUTTON, self.OnStepInto) self.Search.Bind(wx.EVT_TEXT, self.Rebuild) self.Search.Bind(wx.EVT_TEXT_ENTER, self.Rebuild) self.Search.Bind(wx.EVT_SEARCHCTRL_SEARCH_BTN, self.Rebuild) self.Search.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, self.OnSearchCancel) self.application.gui.Binder(self.application.CacheClass.CacheUpdateEvent, self.OnCacheUpdate) self.application.gui.Binder(self.application.gui.SelectObjectEvent, self.OnSelectObject) self.Bind(wx.EVT_SIZE, self.OnResize) self.Layout() TrackerObject.__init__(self) def OnResize(self, evt): if sys.platform == "darwin": self.Tree.SetMinSize((-1,self.GetSize()[1]-self.Search.GetBestSize()[1]-self.StepInto.GetBestSize()[1]-10)) else: self.Tree.SetMinSize((-1,self.GetSize()[1]-self.Search.GetBestSize()[1]-self.StepInto.GetBestSize()[1])) self.Layout() evt.Skip() def OnSearchCancel(self, evt): self.Search.SetValue("") self.Rebuild() def GetPaneInfo(self): info = wx.aui.AuiPaneInfo() info.MinSize(wx.Size(200,-1)) info.Right() info.Layer(1) info.PinButton(True) return info def ObjectTurnSummary(self, object): """\ Builds a brief string, identifying the number of turns remaining on the given object's current order, and the total number of turns allocated to all future scheduled orders. """ orders = self.application.cache.orders[object.id] if len(orders) == 0: return "#" elif len(orders) == 1: return unicode(orders.first.CurrentOrder.turns) else: turns = 0 for node in orders[1:]: turns += node.CurrentOrder.turns return unicode(orders.first.CurrentOrder.turns) + ", " + unicode(turns) def Rebuild(self, evt=None): """\ Rebuilds the list of objects. """ self.SelectIgnore = True selected = self.Tree.GetPyData(self.Tree.GetSelection()) if selected != None: self.SelectedPrevious = selected else: selected = self.SelectedPrevious self.Tree.Freeze() # Remove all the current items self.Tree.DeleteAllItems() self.Add(None, self.application.cache.objects[0], selected) # Sort the tree self.Tree.SortChildren(self.Tree.GetRootItem()) if self.Filter != '*': self.Tree.ExpandAll() # Reselect the previously selected item.. selecteditem = self.Tree.GetSelection() if self.Tree.GetPyData(selecteditem) != None: self.Tree.EnsureVisible(selecteditem) self.Tree.Thaw() self.SelectIgnore = False def Filter(self): filter = self.Search.GetValue() if len(filter) == 0: return "*" elif not '*' in filter: return filter.lower()+'*' else: return filter Filter = property(Filter) def Add(self, parent, object, selected=None): # Figure out the caption for this text... caption = object.name if object != None and hasattr(object, "order_types") and len(object.order_types) > 0: caption += " [" + self.ObjectTurnSummary(object) + "]" # Add the item if parent is None: if self.Filter == '*': item = self.Tree.AddRoot(_("Known Universe"), self.icons['Root']) else: item = self.Tree.AddRoot(_("Finding %s") % self.Filter, self.icons['Root']) else: # Filter the list.. from fnmatch import fnmatch as match if match(caption.lower(), self.Filter.lower()): try: icon = self.icons[object.__class__.__name__] except KeyError: icon = self.icons['Unknown'] item = self.Tree.AppendItem(parent, caption, icon) self.Tree.SetPyData(item, object.id) if selected == object.id: self.Tree.SelectItem(item) else: item = parent if selected != object.id: self.Tree.UnselectItem(item) if hasattr(object, "contains"): for id in object.contains: self.Add(item, self.application.cache.objects[id], selected) def OnSelectItem(self, evt): """\ When somebody selects an item on the list. """ if self.SelectIgnore: return if not evt.GetItem().IsOk(): return # Figure out which item it is id = self.Tree.GetPyData(evt.GetItem()) if id != None: # Okay we need to post an event now self.oid = id self.application.Post(self.application.gui.SelectObjectEvent(id), source=self) self.Refresh() def OnNextObject(self, evt): """\ When someone clicks the "Next Object" button. """ self.SelectNextObject() def OnPrevObject(self, evt): """\ When someone clicks the "Prev Object" button. """ self.SelectPreviousObject() def OnStepInto(self, evt): """\ When someone clicks the "Step Into" button. """ self.SelectNextChild() #################################################### # Remote Event Handlers #################################################### def OnCacheUpdate(self, evt): self.Rebuild() def OnSelectObject(self, evt): """\ When somebody selects an object. """ TrackerObject.OnSelectObject(self, evt) id = self.Tree.GetPyData(self.Tree.GetSelection()) if id == evt.id: return item = self.Tree.FindItemByData(evt.id) if item: self.SelectIgnore = True #self.Tree.CollapseAll() # Collapse all the other stuff self.Tree.SelectItem(item) # Select Item if not self.Tree.IsVisible(item): self.Tree.EnsureVisible(item) self.Tree.Expand(item) # Expand the Item self.SelectIgnore = False self.Refresh() tpclient-pywx-0.3.1.1/windows/main/__init__.py0000644000175000017500000000000010773624641017374 0ustar timtimtpclient-pywx-0.3.1.1/windows/main/panelStarMap.py0000644000175000017500000003112610773624641020241 0ustar timtim"""\ This module contains the StarMap window. This window displays a view of the universe. """ # Python imports import copy import os from math import * import sys import numpy as N from requirements import graphicsdir # wxPython imports import wx from extra.StateTracker import TrackerObjectOrder from extra.wxFloatCanvas import FloatCanvas from overlays.Resource import Resource from overlays.Systems import Systems from overlays.Path import Paths from windows.xrc.panelStarMap import panelStarMapBase from tp.netlib.objects import OrderDescs import extra.wxFloatCanvas.GUIMode as GUIMode class GUIWaypoint(GUIMode.GUIMouse): def __init__(self, *args, **kw): GUIMode.GUIMouse.__init__(self, *args, **kw) self.Overlay = None self.CallNext = None def OnLeftUp(self, event): print "OnLeftUp", event EventType = FloatCanvas.EVT_FC_LEFT_UP if not self.parent.HitTest(event, EventType): if hasattr(self.Overlay, "OnLeftUpMiss"): self.Overlay.OnLeftUpMiss(event) if not self.CallNext is None: CallNext = self.CallNext self.CallNext = None wx.CallAfter(CallNext) def SetOverlay(self, Overlay): self.Overlay = Overlay def SetCallNext(self, tocall): assert callable(tocall) self.CallNext = tocall class GUIWaypointEdit(GUIWaypoint): pass class panelStarMap(panelStarMapBase, TrackerObjectOrder): title = _("StarMap") Overlays = [(Paths, Systems), (Paths, Resource)] def __init__(self, application, parent): panelStarMapBase.__init__(self, parent) self.parent = parent self.application = application self.Canvas = FloatCanvas.FloatCanvas(self.FloatCanvas, Debug=1, BackgroundColor="black") self.Find.Hide() # Create the mouse-mode popup self.MouseModePopup = wx.PopupWindow(self) p = wx.Panel(self.MouseModePopup) s = wx.BoxSizer(wx.VERTICAL) for button in [ wx.Button(p, -1, 'Mouse'), wx.Button(p, -1, 'Move'), wx.Button(p, -1, 'Zoom In'), wx.Button(p, -1, 'Zoom Out')]: button.Bind(wx.EVT_BUTTON, self.OnMouseModeButton) s.Add(button, proportion=1, flag=wx.EXPAND) self.WaypointButton = wx.Button(p, -1, 'Waypoint') self.WaypointButton.Bind(wx.EVT_BUTTON, self.OnMouseModeButton) s.Add(self.WaypointButton, proportion=1, flag=wx.EXPAND) p.SetSizer(s) p.Layout() p.SetSize(p.GetBestSize()) self.MouseModePopup.SetSize(p.GetBestSize()) self.ZoomLevel.SetValidator(wx.SimpleValidator(wx.DIGIT_ONLY)) self.ZoomLevel.Bind(wx.EVT_SET_FOCUS, self.OnZoomLevelFocus) self.ZoomLevel.SetWindowStyleFlag(self.ZoomLevel.GetWindowStyleFlag()|wx.TE_PROCESS_ENTER) # Create the find popup self.FindPopup = wx.PopupWindow(self) pf = wx.Panel(self.FindPopup) sf = wx.BoxSizer(wx.HORIZONTAL) findtext = wx.TextCtrl(pf, -1, "Enter Text") findbutton = wx.Button(pf, -1, 'Go') #findtext.Bind(wx.EVT_COMMAND_TEXT_ENTER, self.OnFindButton) findbutton.Bind(wx.EVT_BUTTON, self.OnFindButton) sf.Add(findtext, proportion=1, flag=wx.EXPAND) sf.Add(findbutton, proportion=0, flag=wx.EXPAND) pf.SetSizer(sf) pf.Layout() pf.SetSize(pf.GetBestSize()) self.FindPopup.SetSize(pf.GetBestSize()) self.Bind(wx.EVT_SIZE, self.OnSize) self.Home.Bind(wx.EVT_BUTTON, self.OnHome) self.Find.Bind(wx.EVT_BUTTON, self.OnFind) # Populate the overlay chooser self.Overlay = None for overlay in self.Overlays: self.DisplayMode.Append(overlay[-1].name, overlay) self.DisplayMode.SetSelection(0) self.GUISelect = GUIMode.GUIMouseAndMove(self.Canvas) self.GUIMove = GUIMode.GUIMove(self.Canvas) self.GUIZoomIn = GUIMode.GUIZoomIn(self.Canvas) self.GUIZoomOut = GUIMode.GUIZoomOut(self.Canvas) self.GUIWaypoint = GUIWaypoint(self.Canvas) self.GUIWaypointEdit = GUIWaypointEdit(self.Canvas) # Initialize mouse-mode bitmaps if sys.platform == "darwin" or sys.platform == "win32": self.GUISelect.Icon = wx.Bitmap(os.path.join(graphicsdir, "mousemode-icon16.png")) self.GUIMove.Icon = wx.Bitmap(os.path.join(graphicsdir, "mousemove-icon16.png")) self.GUIZoomIn.Icon = wx.Bitmap(os.path.join(graphicsdir, "mousezoomin-icon16.png")) self.GUIZoomOut.Icon = wx.Bitmap(os.path.join(graphicsdir, "mousezoomout-icon16.png")) self.GUIWaypoint.Icon = wx.Bitmap(os.path.join(graphicsdir, "mousewaypoint-icon16.png")) self.GUIWaypointEdit.Icon = wx.Bitmap(os.path.join(graphicsdir, "mousewaypoint-icon16.png")) else: self.GUISelect.Icon = wx.Bitmap(os.path.join(graphicsdir, "mousemode-icon24.png")) self.GUIMove.Icon = wx.Bitmap(os.path.join(graphicsdir, "mousemove-icon24.png")) self.GUIZoomIn.Icon = wx.Bitmap(os.path.join(graphicsdir, "mousezoomin-icon24.png")) self.GUIZoomOut.Icon = wx.Bitmap(os.path.join(graphicsdir, "mousezoomout-icon24.png")) self.GUIWaypoint.Icon = wx.Bitmap(os.path.join(graphicsdir, "mousewaypoint-icon24.png")) self.GUIWaypointEdit.Icon = wx.Bitmap(os.path.join(graphicsdir, "mousewaypoint-icon16.png")) self.SetMode(self.GUISelect) self.Canvas.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnter) self.Canvas.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave) self.Bind(wx.EVT_KEY_UP, self.OnKeyUp) TrackerObjectOrder.__init__(self) def Show(self, show=True): self.SetFocusIgnoringChildren() def OnMouseEnter(self, evt): print "OnMouseEnter!", evt # FIXME: Should make sure we gain the keyboard focus self.SetFocusIgnoringChildren() def OnMouseLeave(self, evt): # print "OnMouseLeave!", evt # FIXME: Put the keyboard focus back where it was pass def OnMouseMode(self, evt): """ Occurs when a person clicks on the MouseMode button. Pops-up a menu which lets them select which MouseMode to change too. """ if self.MouseModePopup.IsShown(): self.MouseModePopup.Hide() else: size = (0, self.MouseMode.GetSize()[1]) self.MouseModePopup.Position(self.MouseMode.GetScreenPosition(), size) self.MouseModePopup.Show() def OnMouseModeButton(self, evt): """ Occurs when a person clicks on an option on the MouseMode popup. Changes the current GUIMode to the selected option. """ self.MouseModePopup.Hide() mode = evt.GetEventObject().GetLabel() mode = mode.replace(' ', '') GUIMode = getattr(self, 'GUI%s' % mode, self.GUISelect) self.SetMode(GUIMode) def SetMode(self, mode): """ Set the current mode of the canvas to a given type. """ if not self.Overlay is None: for overlay in self.Overlay: if hasattr(overlay, "ModeChange"): overlay.ModeChange(self.mode, mode) self.MouseMode.SetBitmapLabel(mode.Icon) self.Canvas.SetMode(mode) self.mode = mode def OnDisplayMode(self, evt): """ Called when the DisplayMode choice box is changed. Causes the overlay being displayed on the starmap to be changed. """ cls = self.DisplayMode.GetClientData(self.DisplayMode.GetSelection()) oid = -1 # Clear any overlay which is currently around if self.Overlay != None: oid = self.Overlay[-1].Focus()[0] for Overlay in self.Overlay: Overlay.CleanUp() Overlay = None # Remove the panel from the sizer self.DisplayModeExtra.GetSizer().Remove(self.DisplayModePanel) # Destroy the panel and all it's children self.DisplayModePanel.Destroy() # Destory our reference to the panel del self.DisplayModePanel # Create a new panel self.DisplayModePanel = wx.Panel(self.DisplayModeExtra) #self.DisplayModePanel.SetBackgroundColour(wx.BLUE) # Only needed for debugging where the panel is covering # Add the panel to the sizer self.DisplayModeExtra.GetSizer().Add(self.DisplayModePanel, proportion=1, flag=wx.EXPAND) # Create the new overlay self.Overlay = [] for Overlay in cls: self.Overlay.append(Overlay(self, self.Canvas, self.DisplayModePanel, self.application.cache)) try: self.Overlay[-1].UpdateAll() except Exception, e: import traceback traceback.print_exc() self.GUIWaypoint.SetOverlay(self.Overlay[-1]) if oid != -1: for Overlay in self.Overlay: try: Overlay.SelectObject(oid) except NotImplementedError: pass # Force the panel to layout self.DisplayModeExtra.Layout() self.Canvas.Draw() def GetPaneInfo(self): """ wx.aui method for getting the initial position and settings of this panel. """ info = wx.aui.AuiPaneInfo() info.Center() info.PinButton(True) info.MaximizeButton(True) return info def OnSize(self, evt): self.Layout() self.FloatCanvas.Layout() self.Canvas.SetSize(self.FloatCanvas.GetClientSize()) def OnZoomLevelFocus(self, evt): self.ZoomLevel.SetMark(-1, -1) evt.Skip() def OnZoomLevel(self, evt): """ Called when the ZoomLevel box is changed. """ # FIXME: When the ZoomLevel is changed in any there way, we should get called too... if isinstance(evt, wx.Event): to = evt.GetString().lower() evt.Skip() else: to = unicode(evt).lower() if self.Canvas.GUIMode == self.GUIZoomIn: self.SetMode(self.GUISelect) if to == 'fit': self.Canvas.ZoomToBB() self.ScaleMax = self.Canvas.Scale elif to == 'box': self.SetMode(self.GUIZoomIn) else: if to[-1] == '%': to = to[:-1] else: self.ZoomLevel.SetValue(unicode(to+"%")) try: to = float(to) self.Canvas.Scale = self.ScaleMax*(100/to) self.Canvas.Zoom(1, self.Overlay[-1].Focus()[1], 'World') except ValueError: # FIXME: This should pop-up some type of error. print "Can not zoom to that level" self.ZoomLevel.SetMark(0, len(self.ZoomLevel.GetValue())) def OnCacheUpdate(self, evt): """\ Called when the cache has been updated. """ if evt.what == None: # FIXME: These shouldn't really be here if self.Overlay is not None: for Overlay in self.Overlay: Overlay.UpdateAll() else: self.OnDisplayMode(None) self.ZoomLevel.SetValue("Fit") self.OnZoomLevel('fit') self.OnHome(None) self.Canvas.Draw() def ObjectSelect(self, id): """\ Called when an object is selected. """ self.SetMode(self.GUISelect) # Check if this object can move so we can enable waypoint mode canmove = False for orderid in self.application.cache.objects[id].order_types: order = OrderDescs()[orderid] # FIXME: Needs to be a better way to do this... if order._name in ("Move", "Move To", "Intercept"): canmove = True break if canmove: self.WaypointButton.Enable() else: self.WaypointButton.Disable() def OnHome(self, evt): """\ Called when home button is pressed. """ # Figure out the homeworld resource homeresource = None for number, resource in self.application.cache.resources.items(): if resource.name != "Home Planet": continue homeresource = number # Figure out the homeworld foundhomeworld = 0 if not homeresource is None: for oid in self.application.cache.objects.keys(): # Is this object ownable? if not hasattr(self.application.cache.objects[oid], "owner"): continue # Does the player own this object if self.application.cache.objects[oid].owner != self.application.cache.players[0].id: continue # Does this object have any resources? if not (hasattr(self.application.cache.objects[oid], "resources")): continue for resources in self.application.cache.objects[oid].resources: if not resources[0] == homeresource: continue if reduce(int.__add__, resources[1:]) == 0: continue foundhomeworld = oid break if foundhomeworld != 0: break # Select the object self.SelectObject(foundhomeworld) self.Canvas.Zoom(1, self.application.cache.objects[foundhomeworld].pos[:2]) self.Canvas.Draw() def OnFind(self, evt): """\ Called when find button is pressed. """ if self.FindPopup.IsShown(): self.FindPopup.Hide() else: size = (0, self.Find.GetSize()[1]) self.FindPopup.Position(self.Find.GetScreenPosition(), size) self.FindPopup.Show() def OnFindButton(self, evt): """\ Called when the enter key is pressed in the find text box or the find button next to the text box is pressed. """ # TODO: Either pop up a list of possible choices matching the selection, # or just select the object that matches most closely. pass def OnKeyUp(self, evt): if evt.GetKeyCode() in (77,): if self.oid is None: return # FIXME: Duplicate code!!!! canmove = False for orderid in self.application.cache.objects[self.oid].order_types: order = OrderDescs()[orderid] # FIXME: Needs to be a better way to do this... if order._name in ("Move", "Move To", "Intercept"): canmove = True break if canmove: if evt.ShiftDown(): def n(mode=self.mode): self.SetMode(mode) self.GUIWaypoint.SetCallNext(n) self.SetMode(self.GUIWaypoint) else: TrackerObjectOrder.OnKeyUp(self, evt) if sys.platform == "win32": self.Canvas.ProcessEvent(evt) tpclient-pywx-0.3.1.1/windows/main/panelPicture.py0000644000175000017500000001443710773624641020313 0ustar timtim"""\ This module contains the Picture window. The Picture window displays all objects information. """ # Python Imports import os import os.path from types import * import time import pprint # wxPython imports import wx try: from extra.GIFAnimationCtrl import GIFAnimationCtrl except ImportError: from wx.animate import GIFAnimationCtrl from extra.decorators import freeze_wrapper # Network imports from tp.netlib.objects.ObjectExtra.Universe import Universe from tp.netlib.objects.ObjectExtra.Galaxy import Galaxy from tp.netlib.objects.ObjectExtra.StarSystem import StarSystem from tp.netlib.objects.ObjectExtra.Planet import Planet from tp.netlib.objects.ObjectExtra.Fleet import Fleet # Config imports from requirements import graphicsdir def splitall(start): bits = [] while True: start, end = os.path.split(start) if end is '': break bits.append(end) bits.reverse() return bits WAITING = os.path.join(graphicsdir, "loading.gif") from windows.xrc.panelPicture import panelPictureBase class panelPicture(panelPictureBase): title = _("Picture") def __init__(self, application, parent): panelPictureBase.__init__(self, parent) self.application = application self.current = -1 self.Animation.Hide() self.Static.Hide() # Find the images self.images = {'nebula':{'still':[]}, 'star':{'still':[]}, 'planet':{'still':[]}} self.progress = [] self.averages = [] self.Download.Hide() self.Static.Show() self.Animation.Hide() self.Layout() self.Update() self.application.gui.Binder(self.application.MediaClass.MediaUpdateEvent, self.OnMediaUpdate) self.application.gui.Binder(self.application.MediaClass.MediaDownloadProgressEvent, self.OnMediaDownloadProgress) self.application.gui.Binder(self.application.MediaClass.MediaDownloadDoneEvent, self.OnMediaDownloadDone) self.application.gui.Binder(self.application.gui.SelectObjectEvent, self.OnSelectObject) def GetPaneInfo(self): info = wx.aui.AuiPaneInfo() info.MinSize(wx.Size(128,150)) info.MaxSize(wx.Size(128,150)) info.FloatingSize(wx.Size(128,150)) info.Fixed() info.Left() info.Layer(2) return info def OnMediaUpdate(self, evt): files = {} for file in evt.files: bits = splitall(file) if bits[-2] in ['animation', 'still']: type = bits[-2] del bits[-2] else: type = 'still' if not bits[-2].endswith("-small"): continue else: key = bits[-2][:-6] if not files.has_key(key): files[key] = {} if not files[key].has_key(type): files[key][type] = [] files[key][type].append(file) self.images = files def OnMediaDownloadProgress(self, evt): self.Download.Show() self.Layout() self.Update() #print "winPicture.MediaDownloadProgress", evt.file self.progress.append((time.time(), evt.progress)) # Trim off the oldest samples while len(self.progress) > 200: self.progress.pop(0) if len(self.progress) < 2: return average = [] time1, progress1 = self.progress[0] for time2, progress2 in self.progress[1:]: average.append((progress2-progress1)/(time2-time1)) time1, progress1 = time2, progress2 # Calculate an average average = sum(average)/len(average) self.Progress.SetRange(evt.size) self.Progress.SetValue(evt.progress) if average < 10e3: self.Speed.SetLabel("%.2f kb/s" % (average/1e3)) elif average < 1e6: self.Speed.SetLabel("%.0f kb/s" % (average/1e3)) else: self.Speed.SetLabel("%.2f mb/s" % (average/1e6)) self.averages.append(average) aaverage = (self.progress[-1][1]-self.progress[0][1])/(self.progress[-1][0]-self.progress[0][0]) eta = (evt.size - evt.progress)/aaverage if eta > 60: eta = (int(eta)//60, eta-int(eta)//60*60) self.ETA.SetLabel("%im %is" % eta) else: self.ETA.SetLabel("%is" % eta) self.Download.Layout() self.Download.Update() def OnMediaDownloadDone(self, evt): self.Progress.SetRange(0) self.Progress.SetValue(0) self.Speed.SetLabel('') self.ETA.SetLabel('') self.Download.Hide() self.Layout() self.Update() if evt is None: return print "winInfo.MediaDownloadDone - Finished D", evt.file, evt.localfile print "winInfo.MediaDownloadDone - Waiting On", self.image_waiting if evt.file == self.image_waiting: # FIXME: Should load the image now... self.DisplayImage(evt.localfile) @freeze_wrapper def DisplayImage(self, file, background=wx.BLACK): print "Setting background color to ", background self.Background.SetBackgroundColour(background) self.Static.SetBackgroundColour(background) self.Animation.SetBackgroundColour(background) print "Displaying", file if file.endswith(".gif"): print "Animated image!" self.Static.Hide() print "Showing the Image" self.Animation.Show() print "Loading Image" self.Animation.LoadFile(file) print "Playing the Image" self.Animation.Play() else: print "Still image!" self.Static.Show() self.Animation.Stop() self.Animation.Hide() if file != "": bitmap = wx.BitmapFromImage(wx.Image(file)) else: bitmap = wx.BitmapFromImage(wx.EmptyImage(128, 128)) self.Static.SetBitmap(bitmap) self.Layout() def OnSelectObject(self, evt): if evt.id == self.current: return self.current = evt.id try: object = self.application.cache.objects[evt.id] except: do_traceback() debug(DEBUG_WINDOWS, "SelectObject: No such object.") return self.Title.SetLabel(object.name) # Figure out the right graphic try: if isinstance(object, (Universe, Galaxy)): images = self.images['nebula'] elif isinstance(object, StarSystem): images = self.images['star'] elif isinstance(object, Planet): images = self.images['planet'] elif isinstance(object, Fleet): images = self.images['ship'] else: images = {'still': []} except KeyError, e: print e images = {'still': []} if images.has_key("animation"): images = images["animation"] else: images = images["still"] try: image = images[object.id % len(images)] print "Choose:", image file = self.application.media.GetFile(image) except ZeroDivisionError, e: file = os.path.join(graphicsdir, "unknown.png") except Exception, e: print e file = None if file is None: self.image_waiting = image self.DisplayImage(os.path.join(graphicsdir, "loading.png"), wx.NullColour) else: self.image_waiting = None self.DisplayImage(file) tpclient-pywx-0.3.1.1/windows/main/panelOrder.py0000644000175000017500000006622210773624641017752 0ustar timtim"""\ The order window. """ # Python Imports import time import copy import sys from extra.decorators import * # wxPython Imports import wx # Protocol Imports from tp.netlib import objects from tp.netlib.objects import constants from tp.client.ChangeList import ChangeNode, ChangeHead TURNS_COL = 0 ORDERS_COL = 1 buttonSize = (wx.local.buttonSize[0], wx.local.buttonSize[1]+2) CREATING = wx.Color(0, 0, 150) UPDATING = wx.Color(150, 150, 0) REMOVING = wx.Color(150, 0, 0) # FIXME: This is quite annoying.. defaults = { constants.ARG_ABS_COORD: [0,0,0], constants.ARG_TIME: [0, 0], constants.ARG_OBJECT: [0], constants.ARG_PLAYER: [0,0], constants.ARG_STRING: [0, ""], constants.ARG_LIST: [[], []], constants.ARG_RANGE: [-1, -1, -1, -1], } from extra.StateTracker import TrackerObjectOrder from windows.xrc.panelOrder import panelOrderBase class panelOrder(panelOrderBase, TrackerObjectOrder): title = _("Orders") def __init__(self, application, parent): panelOrderBase.__init__(self, parent) self.application = application self.parent = parent TrackerObjectOrder.__init__(self) self.clipboard = None self.ignore = False self.Orders.InsertColumn(TURNS_COL, _("Turns")) self.Orders.SetColumnWidth(TURNS_COL, 40) self.Orders.InsertColumn(ORDERS_COL, _("Order Information")) self.Orders.SetColumnWidth(ORDERS_COL, 140) self.Orders.SetFont(wx.local.normalFont) self.DetailsSizer = self.DetailsPanel.GetSizer() self.Orders.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnOrderSelect) self.Orders.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnOrderDeselect) self.Orders.Bind(wx.EVT_RIGHT_UP, self.OnRightClick) self.Bind(wx.EVT_KEY_UP, self.OnKeyUp) ########################################################################## # AUI interface bits ########################################################################## def GetPaneInfo(self): info = wx.aui.AuiPaneInfo() info.MinSize((self.GetBestSize()[0]*1.5,self.GetBestSize()[1])) info.Left() info.Layer(2) return info def DockBestSize(self): return wx.Size(*self.GetBestSize()) min_size = property(DockBestSize) ########################################################################## # Update the various bits in the order list ########################################################################## def ColourListItem(self, listpos, color): """\ Makes a listpos show that the item is pending changes. """ item = self.Orders.GetItem(listpos) item.SetTextColour(color) self.Orders.SetItem(item) def ColourOrderPanel(self): if len(self.nodes) != 1: self.DetailsBorderPanel.SetBackgroundColour(wx.NullColour) else: node = self.nodes[0] # Colour the background of the argument panel depending on the current state of the node if node.LastState == "idle": self.DetailsBorderPanel.SetBackgroundColour(wx.NullColour) if node.LastState == "creating": self.DetailsBorderPanel.SetBackgroundColour(CREATING) if node.LastState == "removing": self.DetailsBorderPanel.SetBackgroundColour(REMOVING) if node.LastState == "updating": self.DetailsBorderPanel.SetBackgroundColour(UPDATING) def InsertListItem(self, listpos, node): """\ Inserts an order a certain position in the list. """ assert listpos <= self.Orders.GetItemCount() assert not isinstance(node, ChangeHead) assert isinstance(node, ChangeNode) newlistpos = self.Orders.InsertStringItem(listpos, "") assert newlistpos == listpos, "%s == %s" % (newlistpos, listpos) self.Orders.SetItemPyData(listpos, node) self.UpdateListItem(listpos) def UpdateListItem(self, listpos): """\ Updates an node at a certain position in the list. """ node = self.Orders.GetItemPyData(listpos) if node.CurrentState is "idle": self.Orders.SetStringItem(listpos, TURNS_COL, unicode(node.CurrentOrder.turns)) else: self.Orders.SetStringItem(listpos, TURNS_COL, 'U') self.Orders.SetStringItem(listpos, ORDERS_COL, node.CurrentOrder._name) # FIXME: Hack self.ColourOrderPanel() if node.LastState == "idle": self.ColourListItem(listpos, wx.BLACK) if node.LastState == "creating": self.ColourListItem(listpos, CREATING) if node.LastState == "removing": self.ColourListItem(listpos, REMOVING) if node.LastState == "updating": self.ColourListItem(listpos, UPDATING) def RemoveListItem(self, listpos): """\ Removes an order from a position in the list. """ # FIXME: Hack self.ColourOrderPanel() self.Orders.DeleteItem(listpos) ########################################################################## # Methods called when state changes with an object ########################################################################## @freeze_wrapper def ObjectSelect(self, id): """\ Called when an object is selected. """ # Hide the order panel when no object is selected if id is None: self.Master.Hide() return # Check the object exists object = self.application.cache.objects[self.oid] # Do the clean up first self.Orders.DeleteAllItems() self.Possible.Clear() if object.order_number == 0 and len(object.order_types) == 0: # No orders and no possible orders on this object! self.Master.Hide() else: self.Master.Show() self.Master.Layout() self.Master.Update() self.Orders.SetToolTipDefault(_("Current orders on %s.") % object.name) orders = self.application.cache.orders[self.oid] # Add all the orders to the list for listpos, node in enumerate(orders): self.InsertListItem(listpos, node) # Set which order types can be added to this object self.Possible.SetToolTipDefault(_("Order type to create")) for type in object.order_types: if not objects.OrderDescs().has_key(type): print "WARNING: Unknown order type with id %s" % type continue od = objects.OrderDescs()[type] self.Possible.Append(od._name, type) if hasattr(od, "doc"): desc = od.doc else: desc = od.__doc__ desc = desc.strip() self.Possible.SetToolTipItem(self.Possible.GetCount()-1, desc) # Set the order types to the first selection if len(object.order_types) > 0: self.Possible.Enable() self.Possible.SetSelection(0) else: self.Possible.Disable() ########################################################################## # Methods called when state changes with the order ########################################################################## @freeze_wrapper def OrdersSelect(self, nodes): # Orders Select is only valid when an object is selected assert self.oid != None d = self.application.cache.orders[self.oid] listpos = [] for node in nodes: assert node in d listpos.append(d.index(node)) assert listpos[-1] < self.Orders.GetItemCount() self.Orders.SetSelected(listpos) self.BuildPanel() # Enable the delete button if we have orders to delete if len(nodes) > 0: self.Delete.Enable() else: self.Delete.Disable() # Ensure we can see the items if len(listpos) > 0: self.Orders.EnsureVisible(listpos[-1]) @freeze_wrapper def OrderInsertAfter(self, afterme, toinsert): """\ Inserts the order into a slot. """ assert self.oid != None d = self.application.cache.orders[self.oid] assert afterme in d assert toinsert in d # Inserting into an empty list listpos = d.index(afterme) + 1 # Update the list box self.InsertListItem(listpos, toinsert) @freeze_wrapper def OrderInsertBefore(self, beforeme, toinsert): """\ Inserts the order into a slot. """ assert self.oid != None d = self.application.cache.orders[self.oid] assert beforeme in d assert toinsert in d # Inserting into an empty list listpos = d.index(beforeme)-1 # Update the list box self.InsertListItem(listpos, toinsert) @freeze_wrapper def OrderRefresh(self, node): """\ """ assert self.oid != None d = self.application.cache.orders[self.oid] assert node in d assert self.Orders.GetItemPyData(d.index(node)) is node self.UpdateListItem(d.index(node)) if node in self.nodes: self.BuildPanel() @freeze_wrapper def OrdersRemove(self, nodes, override=False): """\ Deletes the order from a slot. """ assert self.oid != None d = self.application.cache.orders[self.oid] listposes = [] for i in range(0, self.Orders.GetItemCount()): node = self.Orders.GetItemPyData(i) if node in nodes: listposes.append((i, node)) listposes.sort(reverse=True) if override: for listpos, node in listposes: self.UpdateListItem(listpos) if node in self.nodes: self.BuildPanel() else: for listpos, node in listposes: self.RemoveListItem(listpos) #################################################### # Local Event Handlers #################################################### def OnOrderDeselect(self, evt): wx.CallAfter(self.OnOrderSelect, evt) @freeze_wrapper def OnOrderSelect(self, evt): """\ Called when somebody selects an order. """ if self.Orders.ignore > 0: self.Orders.ignore -= 1 return nodes = [] for listpos in self.Orders.GetSelected(): nodes.append(self.Orders.GetItemPyData(listpos)) if self.nodes == nodes: return self.SelectOrders(nodes) @freeze_wrapper def OnOrderNew(self, evt, after=True): """\ Called to add a new order. """ assert self.oid != None # Figure out what type of new order we are creating type = self.Possible.GetSelection() if type == wx.NOT_FOUND: return type = self.Possible.GetClientData(type) # Build the argument list orderdesc = objects.OrderDescs()[type] # sequence, id, slot, type, turns, resources args = [0, self.oid, -1, type, 0, []] for name, type in orderdesc.names: args += defaults[type] # Create the new order new = objects.Order(*args) new._dirty = True # Insert the new order (after the currently selected) if after: node = self.InsertAfterOrder(new) else: node = self.InsertBeforeOrder(new) self.SelectOrders([node]) @freeze_wrapper def OnOrderDelete(self, evt): """\ Called to delete the selected orders. """ self.RemoveOrders() @freeze_wrapper def OnOrderSave(self, evt): """\ Called to save the current selected orders. """ if len(self.nodes) != 1: return # Update the order order = self.FromPanel(self.nodes[0].CurrentOrder) self.ChangeOrder(order) OnNew = OnOrderNew OnSave = OnOrderSave OnDelete = OnOrderDelete @freeze_wrapper def OnRevert(self, evt): self.BuildPanel() @freeze_wrapper def OnOrderDirty(self, evt): """\ Called when an order is updated but not yet saved. """ # Ignore programatic changes if self.ignore: return assert len(self.nodes) == 1 # Update the order order = self.FromPanel(self.nodes[0].CurrentOrder) # Tell the gui about the change self.DirtyOrder(order) #################################################### # Panel Functions #################################################### @freeze_wrapper def BuildPanel(self): """\ Builds a panel for the entering of orders arguments. """ try: object = self.application.cache.objects[self.oid] nodes = self.nodes if object.order_number == 0 and len(object.order_types) == 0: node = _("No orders avaliable") elif len(nodes) > 1: node = _("Multiple orders selected.") elif len(nodes) < 1: node = None else: node = nodes[0] if node.LastState in ("removing", "removed"): node = _("Order queued for removal.") except KeyError: node = _("No object selected.") self.ColourOrderPanel() # Remove the previous panel and stuff if hasattr(self, "ArgumentsPanel"): self.ArgumentsPanel.Hide() self.DetailsSizer.Remove(self.ArgumentsPanel) self.ArgumentsPanel.Destroy() del self.ArgumentsPanel # Show the details panel DetailsPanelShow = True self.DetailsPanel.Hide() self.ArgumentLine.Hide() self.Message.SetLabel("") self.Message.Hide() if isinstance(node, ChangeNode): order = node.CurrentOrder assert not order is None # Create a new panel self.ArgumentsPanel = wx.Panel(self.DetailsPanel, -1) self.ArgumentsPanel.SetAutoLayout( True ) self.ArgumentsSizer = wx.FlexGridSizer( 0, 1, 0, 0) self.ArgumentsPanel.SetSizer(self.ArgumentsSizer) self.ArgumentsSizer.AddGrowableCol( 0 ) orderdesc = objects.OrderDescs()[order.subtype] # List for the argument subpanels self.ArgumentsChildren = [] for name, subtype in orderdesc.names: # Add there name.. name_text = wx.StaticText( self.ArgumentsPanel, -1, name.title().replace("_","") ) name_text.SetFont(wx.local.tinyFont) # Add the arguments bit namepos = wx.LEFT if subtype == constants.ARG_ABS_COORD: subpanel = PositionArgumentPanel(self.ArgumentsPanel) subpanel.application = self.application subpanel.set_value(list(getattr(order, name))) elif subtype == constants.ARG_LIST: subpanel = ListArgumentPanel(self.ArgumentsPanel) subpanel.set_value(list(getattr(order, name))) elif subtype == constants.ARG_STRING: subpanel = TextArgumentPanel(self.ArgumentsPanel) subpanel.set_value([getattr(order, name)]) elif subtype == constants.ARG_TIME: subpanel = TimeArgumentPanel(self.ArgumentsPanel) subpanel.set_value([getattr(order,name)]) elif subtype == constants.ARG_OBJECT: subpanel = ObjectArgumentPanel(self.ArgumentsPanel) subpanel.application(self.application) subpanel.set_value([getattr(order,name)]) else: return subpanel.SetToolTip(wx.ToolTip(getattr(orderdesc, name+'__doc__'))) subpanel.SetFont(wx.local.normalFont) self.ArgumentsChildren.append( subpanel ) if subpanel.namepos == wx.TOP: self.ArgumentsSizer.Add( name_text, 0, wx.ALIGN_CENTER|wx.RIGHT|wx.LEFT, border=4) self.ArgumentsSizer.Add( subpanel, 1, wx.GROW|wx.EXPAND|wx.ALIGN_CENTER) elif subpanel.namepos == wx.LEFT: ArgumentSubSizer = wx.BoxSizer(wx.HORIZONTAL) ArgumentSubSizer.Add( name_text, 0, wx.ALIGN_CENTER|wx.RIGHT, 4 ) ArgumentSubSizer.Add( subpanel, 1, wx.GROW|wx.EXPAND|wx.ALIGN_CENTER) self.ArgumentsSizer.Add(ArgumentSubSizer, 1, wx.GROW|wx.EXPAND|wx.ALIGN_CENTER) else: raise TypeError('WTF?') self.ArgumentsPanel.Layout() if len(orderdesc.names) == 0: name_text = wx.StaticText( self.ArgumentsPanel, -1, "No arguments" ) name_text.SetFont(wx.local.normalFont) self.ArgumentsSizer.Add( name_text, 0, wx.ALIGN_CENTER|wx.CENTER, 4 ) # self.DetailsPanel.SetClientSize(wx.Size(self.GetBestSize()[0], -1)) self.DetailsSizer.Add( self.ArgumentsPanel, flag=wx.GROW|wx.EXPAND|wx.ALIGN_CENTER|wx.ALL) # Show the Save/Revert/Delete buttons self.Message.Show() self.Save.Show() self.Revert.Show() self.Delete.Show() elif isinstance(node, (unicode, str)): self.Message.SetLabel(node) self.Message.Show() # Hide the Save/Revert buttons self.Save.Hide() self.Revert.Hide() # Delete button should still be valid self.Delete.Show() else: DetailsPanelShow = False self.ArgumentLine.Hide() # Hide the Save/Revert/Delete buttons self.Save.Hide() self.Revert.Hide() self.Delete.Hide() if DetailsPanelShow: self.DetailsPanel.Show() self.ArgumentLine.Show() self.Orders.SetSize((-1,0)) self.Master.Layout() self.DetailsPanel.Layout() self.Layout() self.Orders._doResize() def FromPanel(self, order): orderdesc = objects.OrderDescs()[order.subtype] args = [order.sequence, order.id, -1, order.subtype, 0, []] subpanels = copy.copy(self.ArgumentsChildren) for name, type in orderdesc.names: panel = subpanels.pop(0) args += panel.get_value() return apply(objects.Order, args) ########################################################################## # Clipboard functionality ########################################################################## def BuildMenu(self, menu): """\ Build a menu containing the order types which could be inserted. """ object = self.application.cache.objects[self.oid] for type in object.order_types: if not objects.OrderDescs().has_key(type): continue od = objects.OrderDescs()[type] if hasattr(od, "doc"): desc = od.doc else: desc = od.__doc__ desc = desc.strip() menu.Append(-1, od._name, desc) def CheckClipBoard(self): """\ Check if the items in the clipboard could be pasted on the currently selected object. """ if self.clipboard != None: for order in self.clipboard: if not objects.OrderDescs().has_key(order.subtype): return False slot = self.Possible.FindString(objects.OrderDescs()[order.subtype]._name) if slot == wx.NOT_FOUND: return False return True return False #################################################### # Window Event Handlers #################################################### def OnRightClick(self, evt): """\ Pop-up a menu when a person right clicks on the order list. """ slot = self.Orders.HitTest(evt.GetPosition())[0] if slot != wx.NOT_FOUND: if not evt.ControlDown() and not evt.ShiftDown(): # Check if shift or ctrl is being held down... self.Orders.SetSelected([slot]) else: self.Orders.AddSelected(slot) id = wx.NewId() menu = wx.Menu() menu.SetTitle(_("Top")) # Check to see if we can paste the stuff here... nopaste = self.CheckClipBoard() slots = self.Orders.GetSelected() if len(slots) > 0: before = wx.Menu() before.SetTitle(_("Before")) menu.AppendMenu(-1, _("New Before"), before) self.BuildMenu(before) after = wx.Menu() after.SetTitle(_("After")) menu.AppendMenu(-1, _("New After"), after) self.BuildMenu(after) menu.Append(-1, _("Delete")) menu.AppendSeparator() menu.Append(-1, _("Cut")) menu.Append(-1, _("Copy")) if self.clipboard != None: menu.Append(-1, _("Paste Before")) menu.Enable(menu.FindItem(_("Paste Before")), nopaste) menu.Append(-1, _("Paste After")) menu.Enable(menu.FindItem(_("Paste After")), nopaste) else: new = wx.Menu() new.SetTitle(_("New")) menu.AppendMenu(-1, _("New"), new) self.BuildMenu(new) if self.clipboard != None: menu.Append(-1, _("Paste")) menu.Enable(menu.FindItem(_("Paste")), nopaste) self.Bind(wx.EVT_MENU, self.OnOrderMenu) self.PopupMenu(menu) def OnOrderMenu(self, evt): """\ An action from the right click menu. """ menu = evt.GetEventObject() item = menu.FindItemById(evt.GetId()) t = item.GetText() if t == _("Delete"): self.OnOrderDelete(None) elif t in (_("Copy"), _("Cut")): if len(self.nodes) < 1: return self.clipboard = [] for node in self.nodes: self.clipboard.append(node.CurrentOrder) if t == _("Cut"): self.OnOrderDelete(None) elif t.startswith(_("Paste")): if self.CheckClipBoard() == False: print _("Cant paste because the orders arn't valid on this object.") return # Figure out whats out new position order = copy.deepcopy(self.clipboard[0]) if t.endswith(_("After")): node = self.InsertAfterOrder(order) else: node = self.InsertBeforeOrder(order) for order in self.clipboard[1:]: node = self.InsertAfterOrder(order, node) else: slot = self.Possible.FindString(t) if slot == wx.NOT_FOUND: return self.Possible.SetSelection(slot) if menu.GetTitle() == _("Before"): self.OnOrderNew(None, after=False) else: self.OnOrderNew(None) class ArgumentPanel(object): """\ Base class for all other Argument panels. """ # The position to place the name argument namepos = wx.LEFT pass from windows.xrc.orderText import orderTextBase class TextArgumentPanel(ArgumentPanel, orderTextBase): def set_value(self, list): print "TextArgumentPanel", list self.__max, self.__text = list.pop(0) self.Value.SetValue(self.__text) def get_value(self): return [self.__max, unicode(self.Value.GetValue())] from windows.xrc.orderObject import orderObjectBase class ObjectArgumentPanel(ArgumentPanel, orderObjectBase): def __init__(self, parent, *args, **kw): ArgumentPanel.__init__(self) orderObjectBase.__init__(self, parent, *args, **kw) self.Value.SetFont(wx.local.tinyFont) # FIXME: This is broken def application(self, value): combobox = self.Value combobox.Freeze() combobox.Append(_("No object"), -1) # Sort the objects by name objects = value.cache.objects.values() def objcmp(obja, objb): return cmp(obja.name, objb.name) objects.sort(objcmp) for object in objects: combobox.Append(object.name + " (%s)" % object.id, object.id) #if hasattr(object, "parent"): # combobox.SetToolTipItem(combobox.GetCount()-1, _("At ") + cache.objects[object.parent].name) combobox.Thaw() def set_value(self, list): print "ObjectArgumentPanel", list self.__oid = list.pop(0) combobox = self.Value combobox.SetSelection(0) for slot in xrange(0, combobox.GetCount()): if combobox.GetClientData(slot) == self.__oid: combobox.SetSelection(slot) break def get_value(self): self.__oid = long(self.Value.GetClientData(self.Value.GetSelection())) return [self.__oid] from windows.xrc.orderRange import orderRangeBase class TimeArgumentPanel(ArgumentPanel, orderRangeBase): def set_value(self, list): print "RangeArgumentPanel", list self.__text, self.__max = list.pop(0) self.Value.SetValue(self.__text) def get_value(self): return [long(self.Value.GetValue()), self.__max] from windows.xrc.orderPosition import orderPositionBase class PositionArgumentPanel(ArgumentPanel, orderPositionBase): def OnSelectPosition(self, evt): self.X.SetValue(unicode(evt[0])) self.Y.SetValue(unicode(evt[1])) self.Z.SetValue(unicode(evt[2])) def OnLocate(self, evt): self.application.gui.main.panels[panelOrder.title].OnSelectPosition = self.OnSelectPosition from windows.main.panelStarMap import panelStarMap starmap = self.application.gui.main.panels[panelStarMap.title] starmap.SetMode(starmap.GUIWaypointEdit) def set_value(self, list): print "PositionArgumentPanel", list self.X.SetValue(unicode(list.pop(0))) self.Y.SetValue(unicode(list.pop(0))) self.Z.SetValue(unicode(list.pop(0))) def get_value(self): return [long(self.X.GetValue()), long(self.Y.GetValue()), long(self.Z.GetValue())] from windows.xrc.orderList import orderListBase class ListArgumentPanel(ArgumentPanel, orderListBase): namepos = wx.TOP NAME = 0 MAX = 1 def __init__(self, parent, *args, **kw): ArgumentPanel.__init__(self) orderListBase.__init__(self, parent, *args, **kw) self.__options = {} self.__selections = {} self.__choices = [None] self.Choices.InsertColumn(0, "#") self.Choices.SetColumnWidth(0, 25) self.Choices.InsertColumn(1, _("Type")) self.Choices.SetColumnWidth(1, 100) self.Choices.Layout() self.Type.SetMaxSize((-1, self.Number.GetSize()[1])) self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.OnChoicesSelect) self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.OnChoicesDeselect) self.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.OnChoicesEditStart) self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnChoicesEditEnd) self.OnChoicesDeselect(None) self.OnType(None) def set_value(self, list): print "ListArgumentPanel", list options_list = list.pop(0) selection_list = list.pop(0) # Convert the options into a dictionary options = {} for type, name, max in options_list: options[type] = (name, max) # Convert the selection into a dictionary selections = {} for type, number in selection_list: selections[type] = number if self.__options != options: self.__options = options # FIXME: Should sort by the name self.Type.Clear() for type, (name, max) in options.items(): self.Type.Append(name, type) if self.__selections != selections: self.__selections = selections self.Choices.DeleteAllItems() for slot, (type, number) in enumerate(selections.items()): self.Choices.InsertStringItem(slot, "") self.Choices.SetStringItem(slot, 0, unicode(number)) self.Choices.SetStringItem(slot, 1, options[type][self.NAME]) self.Choices.SetItemPyData(slot, type) self.Choices.Layout() def get_value(self): options = [] for type, (name, max) in self.__options.items(): options.append((type, name, max)) selections = [] for type, number in self.__selections.items(): selections.append((type, number)) return [options, selections] def OnChoicesEditStart(self, evt): pass def OnChoicesEditEnd(self, evt): try: value = long(evt.GetLabel()) # Make sure the value is positive if value < 0: evt.Veto() return type = self.Choices.GetItemPyData(evt.GetIndex()) # Make sure that the value is not bigger then the maximum value = min(value, self.__options[type][self.MAX]) slot = self.Choices.FindItemByPyData(type) if value > 0: # Set the value self.__selections[type] = value self.Choices.SetStringItem(slot, 0, unicode(value)) self.UpdateNumber(type) else: del self.__selections[type] self.Choices.DeleteItem(slot) self.UpdateNumber(type) except ValueError: pass evt.Veto() def OnAdd(self, evt): amount = self.Number.GetValue() if amount == 0: return type = self.Type.GetSelection() if type == wx.NOT_FOUND: return type = self.Type.GetClientData(type) s = self.__selections if not s.has_key(type): s[type] = 0 slot = self.Choices.GetItemCount() self.Choices.InsertStringItem(slot, "") self.Choices.SetStringItem(slot, 0, unicode(amount)) self.Choices.SetStringItem(slot, 1, self.__options[type][self.NAME]) self.Choices.SetItemPyData(slot, type) s[type] += amount s[type] = max(min(s[type], self.__options[type][self.MAX]), 0) slot = self.Choices.FindItemByPyData(type) if s[type] == 0: del s[type] self.Choices.DeleteItem(slot) else: self.Choices.SetStringItem(slot, 0, unicode(s[type])) self.UpdateNumber(type) def OnDelete(self, evt): selected = self.Choices.GetSelected() for selection in selected: type = self.Choices.GetItemPyData(selection) del self.__selections[type] self.Choices.DeleteItem(selection) def UpdateNumber(self, type): s = self.__selections if s.has_key(type): self.Number.SetRange(-1*self.__selections[type], self.__options[type][self.MAX]-self.__selections[type]) else: self.Number.SetRange(1, self.__options[type][self.MAX]) if self.Number.GetValue() == 0: self.Number.SetValue(1) def OnType(self, evt): type = self.Type.GetSelection() if type == wx.NOT_FOUND: self.Add.Disable() self.Number.Disable() return type = self.Type.GetClientData(type) self.Add.Enable() self.Number.Enable() self.UpdateNumber(type) # Select the linst related to this type slot = self.Choices.FindItemByPyData(type) if slot == wx.NOT_FOUND: self.Choices.SetSelected([]) else: self.Choices.SetSelected([slot]) self.Choices.EnsureVisible(slot) def OnChoicesDeselect(self, evt): wx.CallAfter(self.OnChoicesSelect, evt) def OnChoicesSelect(self, evt): choices = self.Choices.GetSelected() if self.__choices == choices: return else: self.__choices = choices if len(choices) > 1: self.Type.SetSelection(wx.NOT_FOUND) self.Add.Disable() self.Number.Disable() self.Type.Disable() else: self.Type.Enable() if len(choices) > 0: self.Delete.Enable() type = self.Choices.GetItemPyData(choices[0]) for slot in range(0, self.Type.GetCount()): if self.Type.GetClientData(slot) == type: self.Type.SetSelection(slot) self.OnType(None) break else: self.Delete.Disable() tpclient-pywx-0.3.1.1/windows/main/panelMessage.py0000644000175000017500000001542210773624641020257 0ustar timtim"""\ This module contains the message window, it displays all the ingame messages and lets the player filter out unimportant messages. Messages are displayed using basic HTML. """ # Python Imports from sets import Set # wxPython Imports import wx import wx.html # Config information from requirements import graphicsdir # Local Imports from windows.winBase import ShiftMixIn # Protocol Imports from tp.netlib import GenericRS from windows.xrc.panelMessage import panelMessageBase class panelMessage(panelMessageBase, ShiftMixIn): title = _("Messages") def __init__(self, application, parent): panelMessageBase.__init__(self, parent) ShiftMixIn.__init__(self) self.application = application self.Message.Bind(wx.html.EVT_HTML_LINK_CLICKED, self.OnLinkEvent) # The current message slot self.node = None self.application.gui.Binder(self.application.CacheClass.CacheUpdateEvent, self.OnCacheUpdate) def OnLinkEvent(self, evt): link = evt.GetLinkInfo().GetHref() from extra.Opener import open open(link) html_filtered = """\
Subject: %(subject)s
%(body)s
""".replace("%GRAPHICS", graphicsdir) html_message = """\
Subject: %(subject)s
%(body)s
""".replace("%GRAPHICS", graphicsdir) html_nomessage = """\
Subject: You are unloved!
You have received no messages this turn!

Actually if you didn't receive any messages it most probably means that your client couldn't load the results from the server. Try reload/restart the client.
""" html_allfiltered = """\
Subject: All messages filtered
All messages you have received this turn have been filtered.
""".replace("%GRAPHICS", graphicsdir) def GetPaneInfo(self): info = wx.aui.AuiPaneInfo() info.MinSize(self.GetBestSize()) info.Bottom() info.Layer(1) return info def Show(self, show=True): if show: self.ShiftStart() panelMessageBase.Show(self) else: self.Hide() def Hide(self, hide=True): if hide: self.ShiftStop() panelMessageBase.Hide(self) else: self.Show() def OnShiftDown(self, evt): self.ShowFL() def OnShiftUp(self, evt): self.ShowPN() def ShowPN(self): self.First.Hide() self.Last.Hide() self.Prev.Show() self.Next.Show() self.Layout() def ShowFL(self): self.Prev.Hide() self.Next.Hide() self.First.Show() self.Last.Show() self.Layout() def OnCacheUpdate(self, evt=None): """\ Called when the cache is updated. """ # If it's a full cache update if evt.what == None: self.BoardSet(0) return # Only intrested in an order has been updated and we are currently looking at that if evt.what != "messages" or evt.id != self.bid: return self.BoardSet(0, evt.node) @property def message(self): """\ Returns the currently displayed message. """ return self.node.CurrentOrder @property def messages(self): """\ Returns all the messages for the current board. """ if self.application.cache.messages.has_key(self.bid): return self.application.cache.messages[self.bid] else: return [] def BoardSet(self, id, node=None): """\ Set the currently displayed board to id. """ self.bid = id if not self.messages.first is None: self.MessageSet(node=self.messages.first) def MessageSet(self, direction=None, node=None): """\ Set the currently displayed message to the given node. """ # Are there any messages? if len(self.messages) == 0: message_subject = _("No messages") message_counter = _("") message_body = self.html_nomessage message_filter = False message_buttons = [False, False, False, False] else: if not direction is None: if direction > 0 and not self.node.right is None: self.node = self.node.right elif direction < 0 and not self.node.left.left is None: self.node = self.node.left else: raise SystemError("Need to give a direction or node") elif not node is None: assert node in self.messages self.node = node else: raise SystemError("Need to give a direction or node") message_subject = self.message.subject message_body = self.html_message % self.message.__dict__ message_filter = False message_buttons = [ not self.node.left.left is None, GenericRS.Types["Object"] in self.message.references.types, not self.node.right is None, True ] message_counter = _("%i of %i") % (self.messages.index(self.node)+1, len(self.messages)) self.Title.SetLabel(message_subject) self.Counter.SetLabel(message_counter) self.Message.SetPage(message_body) self.Prev.Enable(message_buttons[0]) self.First.Enable(message_buttons[0]) self.Goto.Enable(message_buttons[1]) self.Last.Enable(message_buttons[2]) self.Next.Enable(message_buttons[2]) self.Delete.Enable(message_buttons[3]) def OnFirst(self, evt=None): self.MessageSet(node=self.messages.first) def OnNext(self, evt=None): self.MessageSet(1) def OnLast(self, evt=None): self.MessageSet(node=self.messages.last) def OnPrev(self, evt=None): self.MessageSet(-1) def OnDelete(self, evt=None): # Tell everyone about the change self.application.Post(self.application.cache.apply("messages", "remove", self.bid, self.node, None), source=self) def OnGoto(self, slot): # Select the object this message references ids = [] for reference, id in self.message.references: if reference == GenericRS.Types["Object"]: try: obj = self.application.cache.objects[id] ids.append(id) except KeyError: pass if len(ids) > 1: menu = wx.Menu() for id in ids: try: obj = self.application.cache.objects[id] menu.Append(-1, "%s (%s)" % (obj.name, obj.id)) except KeyError: pass self.Bind(wx.EVT_MENU, self.MessageGotoMenu) x, y = self.Goto.GetPosition() self.PopupMenu(menu, (x,y+self.Goto.GetSize()[1])) elif len(ids) == 1: self.application.Post(self.application.gui.SelectObjectEvent(ids[0]), source=self) def MessageGotoMenu(self, evt): menu = evt.GetEventObject() item = menu.FindItemById(evt.GetId()) id = int(item.GetLabel().split('(')[-1][:-1]) self.application.Post(self.application.gui.SelectObjectEvent(id), source=self) def MessageNew(self, evt=None): pass def MessageFilter(self): pass tpclient-pywx-0.3.1.1/windows/main/overlays/0000755000175000017500000000000010773624641017141 5ustar timtimtpclient-pywx-0.3.1.1/windows/main/overlays/__init__.py0000644000175000017500000000000010773624641021240 0ustar timtimtpclient-pywx-0.3.1.1/windows/main/overlays/Value.py0000644000175000017500000000143510773624641020572 0ustar timtim"""\ *Internal* This overlay is a base for things which draw proportional circles to some value. """ from Overlay import Overlay class Value(Overlay): """\ Draws circles defined by a value. """ scale = 1 def __init__(self, canvas, cache): Overlay.__init__(self, canvas, cache) def value(self, oid): """\ The absolute size of this object (non-proportional). """ return 1 def updateall(self): """\ """ # Remove all the objects. self.cleanup() for oid in self.cache.objects.keys(): self.updateone(oid) def updateone(self, oid): """\ """ # Create the new object. value = self.value(oid) if value is None: return self[oid] = FloatCanvas.Circle(self.cache.objects[oid].pos[0:2], self.value(oid)*self.scale, FillColor="White", LineColor="Red") tpclient-pywx-0.3.1.1/windows/main/overlays/Overlay.py0000644000175000017500000002723410773624641021144 0ustar timtim"""\ This module contains the base classes used to build a new overlays for the Starmap. """ import sys from tp.netlib.objects import Object class Overlay(dict): """\ A layer which displays something on the StarMap. """ layer = None def name(): raise NotImplementedError("This overlay has not specified a name! - This is bad!") name = property(staticmethod(name)) def __init__(self, parent, canvas, panel, cache): """ Create a new Overlay object. parent is the application which can be used to post events. canvas is the wx.FloatCanvas to draw onto. panel is the toolbar panel which the overlay can add it's own icons/widgets too. cache is the libtpclient-py cache containing the universe data. """ self.parent = parent self.application = self.parent.application if canvas is None: raise TypeError("Canvas can not be none!") self.canvas = canvas if cache is None: raise TypeError("Cache can not be none!") self.cache = cache self.panel = panel def CleanUp(self): """\ Remove this overlay from the Canvas. """ for oid in self.keys(): # Remove the old object del self[oid] def __setitem__(self, key, value): """\ Adds Drawable (or list of Drawables) for key and updates the Canvas. """ if self.has_key(key): del self[key] if type(value) in (list, tuple): for v in value: if not self.layer is None: v.DrawOrder = self.layer self.canvas.AddObject(v) else: if not self.layer is None: value.DrawOrder = self.layer self.canvas.AddObject(value) dict.__setitem__(self, key, value) def __delitem__(self, oid): """\ Removes Drawable (or list of Drawables) for key and updates the Canvas. """ value = self[oid] if type(value) in (list, tuple): for v in value: v.UnBindAll() self.canvas.RemoveObject(v) else: value.UnBindAll() self.canvas.RemoveObject(value) dict.__delitem__(self, oid) def __del__(self): self.CleanUp() def __str__(self): return "" % (self.__class__.__name__, hex(id(self))) __repr__ = __str__ def Update(self, oid=None): """\ Update the FloatCanvas objects for this oid. Called when an object changes. """ if oid is None: self.UpdateAll() else: # Remove the old object. if self.has_key(oid): del self[oid] # If the oid is no longer in the cache we shouldn't continue. if not c.objects.has_key(oid): return # Otherwise Update the object. self.UpdateOne(oid) def UpdateAll(self): """\ Updates all objects on the Canvas. """ # Remove all the objects. self.CleanUp() # Sort the objects by name oids = self.cache.objects.keys() def objcmp(oida, oidb): return cmp(self.cache.objects[oida].name, self.cache.objects[oidb].name) oids.sort(objcmp) for oid in oids: self.UpdateOne(oid) def UpdateOne(self, oid): """\ Updates an object on the Canvas. """ pass def Focus(self): """\ Returns a tuple of, Selected object id (-1 for no object) The coordinates that the current overlay is focused at. This should probably be the selected object (but something else could be focused on other overlays). """ return -1, (0,0) def ObjectSelect(self, oid): """ Select an object using an external event. Simulates this as a mouse click. """ raise NotImplementedError("Select Object method has not been implemented!") class Holder(list): """ A holder is an entity which contains a "primary" object and a bunch of "children". It also maintains a pointer to the "current" object which can be advanced by the Loop methods. """ def primary(self): """ The primary object. """ return self[0] primary = property(primary) def children(self): """ The rest of the objects. """ return self[1:] children = property(children) def current(self): """ The currently 'selected' object. """ if self.__current == -1: return None return self[self.__current] current = property(current) def __init__(self, primary, children=[]): if not isinstance(primary, Object): raise TypeError("Parent must be an Object not %r" % primary) for i, child in enumerate(children): if not isinstance(child, Object): raise TypeError("Child %i must be an Object not %r" % (i, child)) # Sort the children by name def childcmp(childa, childb): return cmp(childa.name, childb.name) children.sort(childcmp) self.extend([primary] + children) self.ResetLoop() def __eq__(self, value): if isinstance(value, Holder): return self.primary.id == value.primary.id return list.__eq__(self, value) def __str__(self): return "<%s %s>" % (self.__current, dict.__str__(self)) def copy(self): return self.__class__(self.primary, self.children) def ResetLoop(self): """ Make the loop go back to the beginning. """ self.__current = -1 def NextLoop(self): """ Get the next object from the holder, this will loop around. """ self.__current = (self.__current + 1) % len(self) return self.__current, self.current def SetLoop(self, v): """ Set the loop's position to a given object. """ if not v in self: raise TypeError("That object %r doesn't exist in the Holder!" % v) self.__current = self.index(v) return self.__current from extra.StateTracker import TrackerObject from tp.netlib.objects.ObjectExtra.Universe import Universe from tp.netlib.objects.ObjectExtra.Galaxy import Galaxy class SystemLevelOverlay(Overlay, TrackerObject): """ A SystemLevelOverlay groups objects together at the Systems level. """ TopLevel = Galaxy, Universe HoverTimeOutFirst = 2000 HoverTimeOut = 2000 def __init__(self, *args, **kw): Overlay.__init__(self, *args, **kw) self.Selected = None self.Hovering = None self.Timer = wx.Timer() self.Timer.Bind(wx.EVT_TIMER, self.SystemHovering) self.Popup = ObjectPopup(self.canvas, wx.SIMPLE_BORDER) TrackerObject.__init__(self) def CleanUp(self): if self.Hovering != None: self.SystemLeave(self.Hovering) Overlay.CleanUp(self) def UpdateOne(self, oid): """\ """ obj = self.cache.objects[oid] # Only draw top level objects if isinstance(obj, self.TopLevel) or not hasattr(obj, 'parent'): return # Don't draw objects which parent's are not top level objects parent = self.cache.objects[obj.parent] if not isinstance(parent, self.TopLevel): return icon = self.Icon(obj) self[oid] = icon from extra.wxFloatCanvas.FloatCanvas import EVT_FC_ENTER_OBJECT, EVT_FC_LEAVE_OBJECT from extra.wxFloatCanvas.FloatCanvas import EVT_FC_LEFT_UP, EVT_FC_RIGHT_UP from extra.wxFloatCanvas.FloatCanvas import EVT_FC_LEFT_DOWN, EVT_FC_RIGHT_DOWN # These pop-up the name of the object icon.Bind(EVT_FC_ENTER_OBJECT, self.SystemEnter) icon.Bind(EVT_FC_LEAVE_OBJECT, self.SystemLeave) # This is needed to the hit test doesn't fall through icon.Bind(EVT_FC_LEFT_DOWN, lambda x: True) icon.Bind(EVT_FC_LEFT_UP, self.SystemLeftClick) icon.Bind(EVT_FC_RIGHT_DOWN, lambda x: True) icon.Bind(EVT_FC_RIGHT_UP, self.SystemRightClick) def Focus(self): """\ Returns the coordinates of the currently selected object or the center of the universe. """ try: return self.Selected.primary.id, self.Selected.XY except Exception, e: return 0, (0,0) def ObjectSelect(self, oid): """ Select an object using an external event. Simulates this as a mouse click. """ if oid == None: return # Figure out which Icon this object is under parentid = oid while not self.has_key(parentid): try: parentid = self.cache.objects[parentid].parent except AttributeError: return system = self.cache.objects[parentid] real = self.cache.objects[oid] icon = self[system.id].copy() icon.SetLoop(real) self.Selected = icon self.ObjectLeftClick(icon, real) #self.SystemEnter(self.Selected) def SystemRightClick(self, icon): # Leave the currently hovered system HoveredOn = self.SystemLeave(self.Hovering) self.ObjectRightClick(icon, HoveredOn.current) def SystemLeftClick(self, icon): # Leave the currently hovered system HoveredOn = self.SystemLeave(self.Hovering) # Are we clicking on the same object? SameSystem = (self.Selected == icon) if self.Selected == icon: # Cycle throught the children on each click self.Selected.NextLoop() # Select the same icon we are previewing elif HoveredOn == icon: self.Selected = HoveredOn # Clicking on a new object else: self.Selected = icon.copy() self.Selected.ResetLoop() if self.Selected.current == None: self.Selected.NextLoop() if self.ObjectLeftClick(self.Selected, self.Selected.current, SameSystem): # Post a selected event self.SelectObject(self.Selected.current.id) self.SystemEnter(self.Selected) def SystemEnter(self, icon): pos = self.canvas.ClientToScreen(self.canvas.WorldToPixel(icon.XY)) # Did someone forget to unhover? if self.Hovering != icon: self.SystemLeave(self.Hovering) # Set the new hover object self.Hovering = icon.copy() self.Hovering.ResetLoop() # Start hovering this icon self.ObjectHoverEnter(icon, pos) if self.Hovering != self.Selected: # Start the "preview" mode self.Timer.Start(self.HoverTimeOutFirst) def SystemHovering(self, event): # Reset the timer self.Timer.Stop() self.Timer.Start(self.HoverTimeOut) # Go to the next object i, object = self.Hovering.NextLoop() if self.ObjectHovering(self.Hovering, object): # Post a preview event self.PreviewObject(object.id) def ObjectPreview(self, id): pass def SystemLeave(self, icon): if icon == None: return # Stop the timer self.Timer.Stop() self.ObjectHoverLeave(icon) # Return back the originally selected object if self.Hovering != None and self.Selected != None: self.SelectObject(self.Selected.current.id, True) t = self.Hovering # Clear the currently hovering object self.Hovering = None return t ########################################################################## ########################################################################## def ObjectLeftClick(self, icon, subobject, samesystem=False): """ Called when a person clicks on a system icon. The first click with give the system object, each subsquent click with give a new subobject. Return True if you want a Selection event to be posted. """ return True def ObjectHoverEnter(self, icon, pos): """ Called when a person mouses over a system icon. Gets the icon and the position of the enter. """ text = self.ObjectPopupText(icon) if text != None: if sys.platform == "win32": pos = self.canvas.ScreenToClient(pos) self.Popup.Position(pos, icon.GetSize()) self.Popup.SetText(text) self.Popup.Show() self.canvas.SetFocus() def ObjectHovering(self, icon, object): """ Called as a person continues to hover over a system icon. Return True if you want a Preview event to be posted. """ pass def ObjectHoverLeave(self, icon): """ Called when a person mouses over a system icon. """ self.Popup.Hide() def ObjectPopupText(self, icon): """ FancyText to put in the pop-up box. Return None to prevent the popup. """ pass import wx from wx.lib.fancytext import StaticFancyText class ObjectPopup(wx.PopupWindow): Padding = 2 def __init__(self, parent, style): wx.PopupWindow.__init__(self, parent, style) self.parent = parent self.SetBackgroundColour("#202020") self.Bind(wx.EVT_MOTION, parent.MotionEvent) def SetText(self, text): try: self.st.Unbind(wx.EVT_MOTION) self.st.Destroy() except AttributeError: pass self.st = StaticFancyText(self.Window, -1, text.encode('UTF-8'), pos=(self.Padding, self.Padding)) sz = self.st.GetSize() self.SetSize( (sz.width+2*self.Padding, sz.height+2*self.Padding) ) self.st.Bind(wx.EVT_MOTION, self.parent.MotionEvent) tpclient-pywx-0.3.1.1/windows/main/overlays/Proportional.py0000644000175000017500000001100710773624641022202 0ustar timtim"""\ *Internal* This overlay is the base for overlays which use proportional circles. """ import operator # wxPython imports from extra.wxFloatCanvas import FloatCanvas from extra.wxFloatCanvas import PieChart from extra.wxFloatCanvas.FloatCanvas import Point, Group, Line from tp.netlib.objects.ObjectExtra.StarSystem import StarSystem from tp.netlib.objects import Object from Overlay import SystemLevelOverlay, Holder def FindChildren(cache, obj): """ Figure out all the children of this object. """ if not isinstance(obj, Object): raise TypeError("Object must be an object not %r" % obj) kids = set() for cid in obj.contains: child = cache.objects[cid] kids.update(FindChildren(cache, child)) kids.add(child) return list(kids) class IconMixIn: """ """ PrimarySize = 3 ChildSize = 3 def __init__(self, cache): self.cache = cache # FIXME: Should probably just monkey patch this onto Group? def XY(self): return self.ObjectList[0].XY XY = property(XY) def GetSize(self): return (self.PrimarySize*2, self.PrimarySize*2) def ChildOffset(self, i): num = len(self.children) angle = ((2.0*pi)/num)*(i-0.125) return (int(cos(angle)*6), int(sin(angle)*6)) class SystemIcon(Group, Holder, IconMixIn): """ Display a round dot which is sized proportionally. """ def copy(self): # FIXME: Very expensive return SystemIcon(self.cache, self.primary, self.proportion, self.scale) def __init__(self, cache, system, proportion, scale): self.cache = cache self.proportion = proportion self.scale = scale Holder.__init__(self, system, FindChildren(cache, system)) # Create a list of the objects ObjectList = [] # The center point ObjectList.append(FloatCanvas.Point(system.pos[0:2], 'White', self.proportion*self.scale)) Group.__init__(self, ObjectList, False) def Amount(self, oid): """\ The absolute size of this object (non-proportional). """ return 1 class Proportional(SystemLevelOverlay): """\ Draws proportional circles defined by amount. """ scale = 60L #scale = 150L #def __init__(self, *args, **kw): # SystemLevelOverlay.__init__(self, *args, **kw) def __init__(self, parent, canvas, panel, cache, *args, **kw): SystemLevelOverlay.__init__(self, parent, canvas, panel, cache, *args, **kw) self.cache = cache self.max = 0 self.min = 0 self.fco = {} def UpdateAll(self): """\ """ c = self.cache # Remove all the objects. self.CleanUp() # Calculate all the values so we can figure min/max. values = {} for oid in c.objects.keys(): #print oid, self.Amount(oid) # Disregard the Universe and the Galaxy if (c.objects[oid].subtype > 1): values[oid] = self.Amount(oid) import pprint #pprint.pprint(values) # Get min/max values. v = values.values() self.min = min(v) self.max = max(v) for oid, value in sorted(values.items(), key=operator.itemgetter(1), reverse=True): self.UpdateOne(oid, value) def UpdateOne(self, oid, value=None): """\ """ if isinstance(self.cache.objects[oid], StarSystem): SystemLevelOverlay.UpdateOne(self, oid) def Proportion(self, oid, value=None): c = self.cache # Disregard the Universe and the Galaxy if (c.objects[oid].subtype > 1): if value is None: # Get the new value. value = self.Amount(oid) # If the min/max value has changed we need to redraw everything. #if value < self.min or value > self.max: #self.UpdateAll() #return # New proportional value. if not (self.max-self.min) is 0: proportional = value/float(self.max-self.min) else : proportional = .01 if (proportional*self.scale) < 10 and proportional > 0: proportional = 10.0 / self.scale #if (proportional*self.scale) > 30: #proportional = 30.0 / self.scale # Create the new object. #print proportional #'LineColor':'Red', 'FillColor':'Red' # 'LineColor':'White', 'FillColor':'White' return proportional def Icon(self, obj): if isinstance(obj, StarSystem): return SystemIcon(self.cache, obj, self.Proportion(obj.id), self.scale) def ObjectHoverEnter(self, icon, pos): """ The pop-up contains details about what is in the system. Also draws the path of each object in the system. """ SystemLevelOverlay.ObjectHoverEnter(self, icon, pos) def ObjectHovering(self, icon, object): SystemLevelOverlay.ObjectHovering(self, icon, object) return True def ObjectHoverLeave(self, icon): SystemLevelOverlay.ObjectHoverLeave(self, icon) def ObjectPopupText(self, icon): return ""tpclient-pywx-0.3.1.1/windows/main/overlays/Systems.py0000644000175000017500000003006510773624641021166 0ustar timtim"""\ This overlay draws Star Systems on the Starmap. """ # Python imports from math import * import copy import numpy as N # wxPython imports import wx from extra.wxFloatCanvas.FloatCanvas import Point, Group, Line from extra.wxFloatCanvas.RelativePoint import RelativePoint, RelativePointSet from extra.wxFloatCanvas.PolygonStatic import PolygonArrow, PolygonShip # tp imports from tp.netlib.objects import constants from tp.netlib.objects import Object, OrderDescs from tp.netlib.objects.ObjectExtra.Universe import Universe from tp.netlib.objects.ObjectExtra.Galaxy import Galaxy from tp.netlib.objects.ObjectExtra.StarSystem import StarSystem from tp.netlib.objects.ObjectExtra.Planet import Planet from tp.netlib.objects.ObjectExtra.Fleet import Fleet from Overlay import SystemLevelOverlay, Holder from Colorizer import * def FindChildren(cache, obj): """ Figure out all the children of this object. """ if not isinstance(obj, Object): raise TypeError("Object must be an object not %r" % obj) kids = set() for cid in obj.contains: child = cache.objects[cid] kids.update(FindChildren(cache, child)) kids.add(child) return list(kids) def FindOwners(cache, obj): """ Figure out the owners of this oidect (and it's children). """ if not isinstance(obj, Object): raise TypeError("Object must be an object not %r" % obj) owners = set() for child in [obj]+FindChildren(cache, obj): if not hasattr(child, 'owner'): continue if child.owner in (0, -1): continue owners.add(child.owner) return list(owners) class IconMixIn: """ """ PrimarySize = 3 ChildSize = 3 def __init__(self, cache, colorizer): self.cache = cache self.SetColorizer(colorizer) # FIXME: Should probably just monkey patch this onto Group? def XY(self): return self.ObjectList[0].XY XY = property(XY) def GetSize(self): return (self.PrimarySize*2, self.PrimarySize*2) def ChildOffset(self, i): num = len(self.children) angle = ((2.0*pi)/num)*(i-0.125) return (int(cos(angle)*6), int(sin(angle)*6)) def SetColorizer(self, colorizer): if not isinstance(colorizer, Colorizer): raise TypeError('Colorizer must be of Colorizer type!') self.Colorizer = colorizer def GetColors(self): parentcolor = self.Colorizer(FindOwners(self.cache, self.primary)) childrencolors = [] for child in self.children: childrencolors.append(self.Colorizer(FindOwners(self.cache, child))) return parentcolor, childrencolors class SystemIcon(Group, Holder, IconMixIn): """ Display a round dot with a dot for each child. """ def copy(self): # FIXME: Very expensive return SystemIcon(self.cache, self.primary, self.Colorizer) def __init__(self, cache, system, colorizer=None): if not isinstance(system, StarSystem): raise TypeError('SystemIcon must be given a StarSystem, %r' % system) Holder.__init__(self, system, FindChildren(cache, system)) # Get the colors of the object IconMixIn.__init__(self, cache, colorizer) type, childtype = self.GetColors() # Create a list of the objects ObjectList = [] # The center point ObjectList.append(Point(system.pos[0:2], type, self.PrimarySize, False)) if len(self.children) > 0: # The orbit bits ObjectList.insert(0, Point(system.pos[0:2], "Black", 8, InForeground=True)) ObjectList.insert(0, Point(system.pos[0:2], "Grey", 9, InForeground=True)) # The orbiting children for i, childtype in enumerate(childtype): ObjectList.append( RelativePoint(system.pos[0:2], childtype, self.ChildSize, True, self.ChildOffset(i)) ) Group.__init__(self, ObjectList, False) class FleetIcon(Group, Holder, IconMixIn): """ Display a little arrow shape thing. """ def copy(self): # FIXME: Very expensive return FleetIcon(self.cache, self.primary, self.Colorizer) def __init__(self, cache, fleet, colorizer=None): if not isinstance(fleet, Fleet): raise TypeError('FleetIcon must be given a Fleet, %r' % system) if len(FindChildren(cache, fleet)) > 0: raise TypeError('The fleet has children! WTF?') Holder.__init__(self, fleet, []) # Get the colors of the object IconMixIn.__init__(self, cache, colorizer) type, childtype = self.GetColors() # Create a list of the objects ObjectList = [] # The little ship icon ObjectList.append(Point(fleet.pos[0:2], None, 12)) ObjectList.append(PolygonShip(fleet.pos[0:2], type)) Group.__init__(self, ObjectList, False) from extra.StateTracker import TrackerObjectOrder class Systems(SystemLevelOverlay, TrackerObjectOrder): name = "Systems" toplevel = Galaxy, Universe Colorizers = [ColorVerses, ColorEach] def __init__(self, parent, canvas, panel, cache, *args, **kw): SystemLevelOverlay.__init__(self, parent, canvas, panel, cache, *args, **kw) self.canvas.SetCursor(wx.StockCursor(wx.CURSOR_RIGHT_ARROW)) # Create a drop-down on the panel for colorizer self.ColorizeMode = wx.Choice(panel) self.ColorizeMode.Bind(wx.EVT_CHOICE, self.OnColorizeMode) # Populate the colorizer dropdown with information for colorizer in self.Colorizers: self.ColorizeMode.Append(colorizer.name, colorizer) self.ColorizeMode.SetSelection(0) self.Colorizer = None self.OnColorizeMode(None) sizer = wx.FlexGridSizer(10) sizer.AddGrowableRow(0) sizer.Add(self.ColorizeMode, proportion=1, flag=wx.EXPAND) panel.SetSizer(sizer) self.menumap = None TrackerObjectOrder.__init__(self) def OnColorizeMode(self, evt): cls = self.ColorizeMode.GetClientData(self.ColorizeMode.GetSelection()) if not isinstance(self.Colorizer, cls): # Change the colorizer self.Colorizer = cls(self.cache.players[0].id) if not evt is None: self.CleanUp() self.UpdateAll() self.canvas.Draw() def UpdateAll(self): SystemLevelOverlay.UpdateAll(self) self['preview-arrow'] = PolygonArrow((0,0), "#555555", True) self['preview-arrow'].Hide() self['selected-arrow'] = PolygonArrow((0,0), "Red", True) def Icon(self, obj): if isinstance(obj, Fleet): return FleetIcon(self.cache, obj, self.Colorizer) else: return SystemIcon(self.cache, obj, self.Colorizer) def ArrowTo(self, arrow, icon, object): arrow.SetPoint(icon.primary.pos[0:2]) arrow.SetOffset((0,0)) i = icon.index(object) if i > 0: arrow.SetOffset(icon.ChildOffset(i-1)) def ObjectLeftClick(self, icon, obj, samesystem=False): """ Move the red arrow to the current object. """ # FIXME: This really is a horrible hack :( if self.parent.mode is self.parent.GUISelect: self.ArrowTo(self['selected-arrow'], icon, obj) self.canvas.Draw() return True elif self.parent.mode is self.parent.GUIWaypointEdit: # FIXME: Hack from windows.main.panelOrder import panelOrder order = self.parent.application.gui.main.panels[panelOrder.title] if hasattr(order, "OnSelectPosition"): order.OnSelectPosition(self.Selected.current.pos) return False elif self.parent.mode is self.parent.GUIWaypoint: orderdesc = None for orderdesc in OrderDescs().values(): if orderdesc._name in ("Move",) : break assert not orderdesc is None if samesystem: assert len(self.nodes) > 0 # Modify the last move order updatedorder = orderdesc(0, self.oid, -1, orderdesc.subtype, 0, [], self.Selected.current.pos) self.ChangeOrder(updatedorder,self.nodes[-1]) self.ObjectHoverEnter(self.Selected, self.canvas.WorldToPixel(self.Selected.XY)) else: # Insert new move order neworder = orderdesc(0, self.oid, -1, orderdesc.subtype, 0, [], self.Selected.current.pos) self.InsertAfterOrder(neworder) return False def SelectObject(self, id, forceother=False): if self.parent.mode in (self.parent.GUIWaypoint, self.parent.GUIWaypointEdit) : return TrackerObjectOrder.SelectObject(self, id, forceother) def OrderInsertAfter(self, afterme, what): if self.parent.mode in (self.parent.GUIWaypoint, self.parent.GUIWaypointEdit): self.SelectOrders([what]) OrderInsertBefore = OrderInsertAfter def SystemHovering(self, event): if self.parent.mode in (self.parent.GUIWaypoint, self.parent.GUIWaypointEdit): return SystemLevelOverlay.SystemHovering(self, event) def ModeChange(self, oldmode, newmode): print "ModeChange", oldmode, newmode if newmode in (self.parent.GUIWaypoint, self.parent.GUIWaypointEdit): self.RealSelected = copy.copy(self.Selected) if oldmode in (self.parent.GUIWaypoint, self.parent.GUIWaypointEdit): self.Selected = self.RealSelected self.RealSelected = None def ObjectRightClick(self, icon, hover): """ Popup a selection menu. """ self.menumap = {} orders = [] if not self.oid is None: obj = self.cache.objects[self.oid] for id in obj.order_types: orderdesc = OrderDescs()[id] if len(orderdesc.names) != 1: continue argument_name, subtype = orderdesc.names[0] if subtype == constants.ARG_ABS_COORD: def s(to, what=obj, how=orderdesc): print "order what: %r to: %r (%r) how: %r" % (what, to, to.pos, how) neworder = how(0, what.id, -1, how.subtype, 0, [], to.pos) neworder._dirty = True self.InsertAfterOrder(neworder) moveorder = s elif subtype == constants.ARG_OBJECT: def s(to, what=obj, how=orderdesc): print "order what: %r to: %r how: %r" % (what, to, how) neworder = how(0, what.id, -1, how.subtype, 0, [], to.id) neworder._dirty = True self.InsertAfterOrder(neworder) moveorder = s else: continue orders.append((orderdesc._name, moveorder)) menu = wx.Menu() for obj in icon: id = wx.NewId() def s(evt, obj=obj): self.SelectObject(obj.id) self.menumap[id] = s if obj == hover: menu.AppendCheckItem(id, obj.name) menu.Check(id, True) else: menu.Append(id, obj.name) if len(orders) > 0: for name, order in orders: submenu = wx.Menu() for obj in icon: id = wx.NewId() def s(evt, obj=obj, order=order): order(obj) self.menumap[id] = s submenu.Append(id, "to %s" % obj.name) menu.AppendSeparator() menu.AppendMenu(wx.NewId(), "%s %s" % (name ,self.Selected.current.name), submenu) self.parent.Bind(wx.EVT_MENU, self.OnContextMenu) self.parent.Bind(wx.EVT_MENU_CLOSE, self.OnContextMenuClose) #pos = self.canvas.WorldToPixel(icon.XY) self.parent.PopupMenu(menu) self.menumap = None def OnContextMenu(self, evt): self.menumap[evt.GetId()](evt) def OnContextMenuClose(self, evt): pass def ObjectHoverEnter(self, icon, pos): """ The pop-up contains details about what is in the system. Also draws the path of each object in the system. """ SystemLevelOverlay.ObjectHoverEnter(self, icon, pos) # Draw the path of the object paths = [] ## for i, cobj in enumerate(icon): ## path = FindPath(self.cache, cobj) ## if path: ## pr = path[0] ## for p in path[1:]: ## paths.append(Line([pr[0:2], p[0:2]], LineColor='Blue', InForeground=True)) ## pr = p if len(paths) > 0: self['paths'] = paths self.canvas.Draw() def ObjectHovering(self, icon, object): if not self.menumap is None: return False SystemLevelOverlay.ObjectHovering(self, icon, object) self['preview-arrow'].Show() self.ArrowTo(self['preview-arrow'], icon, object) self.canvas.Draw() return True def ObjectHoverLeave(self, icon): SystemLevelOverlay.ObjectHoverLeave(self, icon) # Hide any paths which are showing if self.has_key('paths'): del self['paths'] self['preview-arrow'].Hide() self.canvas.Draw() def ObjectPopupText(self, icon): # Build the string s = "" % wx.local.normalFont.GetPointSize() for i, cobj in enumerate(icon): # Italics the currently selected object style = 'normal' if self.Selected != None and self.Selected.current == cobj: style = 'italic' color = icon.Colorizer(FindOwners(self.cache, cobj)) s += "%s" % (style, color, cobj.name) if isinstance(cobj, Fleet): for shipid, amount in cobj.ships: try: s+= "\n %s %ss" % (amount, self.cache.designs[shipid].name) except KeyError: s+= "\n %s %ss" % (amount, "Unknown Ship") s += "\n" s = s[:-1]+"" return s def ObjectRefreshAll(self): self.UpdateAll() tpclient-pywx-0.3.1.1/windows/main/overlays/Colorizer.py0000644000175000017500000000601610773624641021466 0ustar timtim class Colorizer(object): """ These classes deal with figuring out the color of an object. """ def name(self): raise NotImplementedError("The name attribute has not been implemented.") name = property(staticmethod(name)) def __init__(self, playerid): """ Create a new colorizer, takes a player id. """ pass def __call__(self, owners): """ This function takes a list of the owners of this object. """ raise NotImplementedError("This function has not been implimented!") class ColorVerses(Colorizer): """ This colorizer shows you in green and all the enemies in red. """ name = "Verses" Friendly = "Green" Enemy = "Red" Unowned = "White" Contested = "Yellow" def __init__(self, pid): self.pid = pid def __call__(self, owners): type = (ColorVerses.Unowned, ColorVerses.Enemy)[len(owners)>0] if self.pid in owners: type = (ColorVerses.Friendly, ColorVerses.Contested)[len(owners)>1] return type class ColorEach(Colorizer): """ This colorizer gives each player it's own color. Alot of the code is based on stuff at http://mg.pov.lt/irclog2html/svn/irclog2html.py """ name = "Individual" def __init__(self, pid, rgbmin=240, rgbmax=125, rgb=None, a=0.95, b=0.5): """Define a range of colors available for choosing. `rgbmin` and `rgbmax` define the outmost range of color depth (note that it is allowed to have rgbmin > rgbmax). `rgb`, if specified, is a list of (r,g,b) values where each component is between 0 and 1.0. If `rgb` is not specified, then it is constructed as [(a,b,b), (b,a,b), (b,b,a), (a,a,b), (a,b,a), (b,a,a)] You can tune `a` and `b` for the starting and ending concentrations of RGB. """ assert 0 <= rgbmin < 256 assert 0 <= rgbmax < 256 self.rgbmin = rgbmin self.rgbmax = rgbmax if not rgb: assert 0 <= a <= 1.0 assert 0 <= b <= 1.0 rgb = [(a,b,b), (b,a,b), (b,b,a), (a,a,b), (a,b,a), (b,a,a)] else: for r, g, b in rgb: assert 0 <= r <= 1.0 assert 0 <= g <= 1.0 assert 0 <= b <= 1.0 self.rgb = rgb # Preserve the mapping self.playercount = 0 self.playersmax = 10 self.playercolor = {} def choose(self, i, n): """Choose a color. `n` specifies how many different colors you want in total. `i` identifies a particular color in a set of `n` distinguishable colors. Returns a string '#rrggbb'. """ if n == 0: n = 1 r, g, b = self.rgb[i % len(self.rgb)] m = self.rgbmin + (self.rgbmax - self.rgbmin) * float(n - i) / n r, g, b = map(int, (r * m, g * m, b * m)) assert 0 <= r < 256 assert 0 <= g < 256 assert 0 <= b < 256 return '#%x%x%x' % (r, g, b) def __getitem__(self, playername): color = self.playercolor.get(playername) if not color: self.playercount += 1 if self.playercount >= self.playersmax: self.playersmax *= 2 color = self.choose(self.playercount, self.playersmax) self.playercolor[playername] = color return color def __call__(self, owners): if len(owners) > 1: return "Red" elif len(owners) == 0: return "White" else: return self[owners[0]] tpclient-pywx-0.3.1.1/windows/main/overlays/Size.py0000644000175000017500000000101410773624641020421 0ustar timtim"""\ Draws circles proportional to the actual size of the object. """ # wxPython imports from Value import Value # Network imports from tp.netlib.objects.ObjectExtra.StarSystem import StarSystem from tp.netlib.objects.ObjectExtra.Planet import Planet class Size(Value): """\ Draws proportional circles for the relative to size of object. """ def value(self, oid): """\ The amount of this resource on this object. """ obj = self.cache.objects[oid] if isinstance(obj, (Planet, StarSystem)): return obj.size tpclient-pywx-0.3.1.1/windows/main/overlays/Velocity.py0000644000175000017500000000061710773624641021315 0ustar timtim"""\ This overlay displays a line showing where objects may end up based on their current velocity. """ # Python imports import os from math import * import numpy as N # wxPython imports import wx from extra.wxFloatCanvas import FloatCanvas from extra.wxFloatCanvas.RelativePoint import RelativePoint from extra.wxFloatCanvas.Icon import Icon from extra.wxFloatCanvas.NavCanvas import NavCanvas tpclient-pywx-0.3.1.1/windows/main/overlays/Path.py0000644000175000017500000001620510773624641020413 0ustar timtim"""\ An Overlay which provides a line showing where objects have orders to go. """ # Python imports import os from math import * # wxPython imports import wx from extra.wxFloatCanvas import FloatCanvas from extra.wxFloatCanvas.FloatCanvas import Point, Group, Line from extra.StateTracker import TrackerObjectOrder # tp imports from tp.netlib.objects import constants from tp.netlib.objects import Object, OrderDescs from tp.netlib.objects import Order from tp.netlib.objects.ObjectExtra.Universe import Universe from tp.netlib.objects.ObjectExtra.Galaxy import Galaxy from Overlay import Overlay def FindPath(cache, obj): """ Figure out the path this object will take. Returns a list of tuples (node, order destination) """ if not isinstance(obj, Object): raise TypeError("Object must be an object not %r" % obj) locations = [(-1, obj.pos)] for listpos, node in enumerate(cache.orders[obj.id]): order = node.CurrentOrder # FIXME: Needs to be a better way to do this... orderdesc = OrderDescs()[order._subtype] if len(orderdesc.names) != 1: continue argument_name, subtype = orderdesc.names[0] if subtype == constants.ARG_ABS_COORD: locations.append((node, getattr(order, argument_name))) elif subtype == constants.ARG_OBJECT: locations.append((node, cache.objects[getattr(order, argument_name)].pos)) if len(locations) == 1: return None return locations class PathSegment(Group): """ This represents a segment on a path to somewhere. It has a reference to which order this path comes from. It has a "previous segment" reference which can be an object or another path segment. It has a endingat destination """ BackgroundColor = None # The color of paths when just shown InactiveColor = "Grey" # The color of path of the currently selected object ActiveColor = "Blue" # The color of the currently active segment of the path SelectedColor = "Red" # The color of the "split" handles SplitHandleColor = "Yellow" class States: Inactive = "Inactive" Active = "Active" Selected = "Selected" transisions = [ (Inactive, Active), (Active, Selected), (Selected, Active), (Active, Inactive), (Selected, Inactive), ] def XY(self): return self.ObjectList[0].XY XY = property(XY) def __init__(self, what, endingat, previous): # Check the ending at parameter # Must be a set of corrdinates or an object self.State = self.States.Inactive self.what = what self.endat = endingat self.previous = previous self.next = None if isinstance(previous, PathSegment): # Link this with the previous segment self.previous.SetNext(self) start = self.previous.endat elif isinstance(previous, Object): start = self.previous.pos[0:2] else: raise TypeError("The previous item must either be an Object or another PathSegment") end = self.endat ObjectList = [] # Draw the line # A wider version of the path to make it easier to click on the line ObjectList.append(Line([start[0:2], end[0:2]], LineColor=self.BackgroundColor, LineWidth = 10)) # The visible version of the path ObjectList.append(Line([start[0:2], end[0:2]], LineColor=self.InactiveColor)) # Draw the "ticks" which indicate how far the object will reach each turn Group.__init__(self, ObjectList, False) def SetNext(self, segment): """ Insert the given segment as the next segment. IE a -> b a.SetNext(c) a -> c -> b """ if not isinstance(segment, PathSegment): raise TypeError("The next object must be a Path Segment!") if self.next is None: self.next = segment else: if not segment.next is None: raise TypeError("This given segment has stuff after is!") segment.SetNext(self.next) self.next = segment def SetState(self, state): if self.State == state: return if not (self.State, state) in self.States.transisions: raise TypeError("Can not change from %s to %s" % (self.State, state)) self.State = state # Change the color of this segment color = getattr(self, unicode(state) + 'Color') self.ObjectList[-1].SetColor(color) def Select(self, yes): if yes: self.SetState(self.States.Selected) else: self.SetState(self.States.Active) def Active(self, yes): if yes: self.SetState(self.States.Active) else: self.SetState(self.States.Inactive) # FIXME: The hitpath and the actual path should be seperated for speed reasons.. class Paths(Overlay, TrackerObjectOrder): """\ Draws a path of ships and similar objects. """ name = "Paths" toplevel = Galaxy, Universe layer = -1 def __init__(self, parent, canvas, panel, cache, *args, **kw): Overlay.__init__(self, parent, canvas, panel, cache, *args, **kw) self.active = [] TrackerObjectOrder.__init__(self) def UpdateOne(self, oid, overrides={}): # Remove all the previous segments for nid, nodeid in self.keys(): if oid == nid: del self[(oid, nodeid)] if oid == self.oid: self.active = [] # Create the new path path = FindPath(self.cache, self.cache.objects[oid]) if not path is None: previous = self.cache.objects[oid] for node, end in path[1:]: segment = PathSegment((oid, node), end, previous) # Make sure the selected bits are still selected.. if oid == self.oid: segment.Active(True) if node in self.nodes: segment.Select(True) self.active.append(segment) self[(oid, node.id)] = segment from extra.wxFloatCanvas.FloatCanvas import EVT_FC_ENTER_OBJECT, EVT_FC_LEAVE_OBJECT from extra.wxFloatCanvas.FloatCanvas import EVT_FC_LEFT_UP, EVT_FC_RIGHT_UP from extra.wxFloatCanvas.FloatCanvas import EVT_FC_LEFT_DOWN, EVT_FC_RIGHT_DOWN # These pop-up the name of the object segment.Bind(EVT_FC_ENTER_OBJECT, self.Empty) segment.Bind(EVT_FC_LEAVE_OBJECT, self.Empty) # This is needed to the hit test doesn't fall through segment.Bind(EVT_FC_LEFT_DOWN, lambda x: True) segment.Bind(EVT_FC_LEFT_UP, self.OnClickSegment) previous = segment def ClearActive(self): for active in self.active: active.Select(False) self.active = [] def ObjectSelect(self, oid): """ Select an object using an external event. Simulates this as a mouse click. """ self.ClearActive() # FIXME: This is kind of suckily slow! for nid, nodeid in self.keys(): if oid == nid: self[(nid, nodeid)].Active(True) else: self[(nid, nodeid)].Active(False) self.canvas.Draw(True) def OrdersSelect(self, nodes): self.ClearActive() for node in nodes: try: self.active.append(self[(self.oid, node.id)]) except KeyError: pass for active in self.active: active.Select(True) self.canvas.Draw(True) def OrderInsertAfter(self, node, override=None): self.UpdateOne(self.oid) self.canvas.Draw() OrderInsertBefore = OrderInsertAfter OrderRefresh = OrderInsertAfter def OrdersRemove(self, nodes, override=False): self.UpdateOne(self.oid) self.canvas.Draw() def ObjectRefresh(self, oid): if oid is None: return self.UpdateOne(self.oid) def ObjectRefreshAll(self): self.UpdateAll() def OnClickSegment(self, evt): self.SelectObject(evt.what[0]) self.SelectOrders([evt.what[1]]) def Empty(self, evt): pass tpclient-pywx-0.3.1.1/windows/main/overlays/Resource.py0000644000175000017500000002033010773624641021300 0ustar timtim"""\ This overlay shows circles which are proportional to the amount of a certain resource found in that object. """ # Python imports import os from math import * import numpy as N # wxPython imports import wx from extra.wxFloatCanvas import FloatCanvas from extra.wxFloatCanvas import PieChart from extra.wxFloatCanvas.RelativePoint import RelativePoint from extra.wxFloatCanvas.FloatCanvas import Point, Group, Line import operator from extra.wxFloatCanvas.NavCanvas import NavCanvas from Proportional import SystemIcon, FindChildren from Overlay import SystemLevelOverlay, Holder from windows.xrc.winResourceSelect import ResourceSelectBase class ResourceSelect(ResourceSelectBase, wx.Frame): def __init__(self, parent, cache): ResourceSelectBase.__init__(self, parent) self.parent = parent self.ResourceTypeList = {} for number, resource in cache.resources.items(): self.ResourceTypeList[resource.name] = number self.ResourceList.InsertItems(self.ResourceTypeList.keys(), 0) self.Bind(wx.EVT_ACTIVATE, self.OnActivate) self.Hide() def OnActivate(self, evt): if evt.GetActive() == False: self.OnDone(evt) def Show(self, show=True): self.Panel.Layout() size = self.ResourceList.GetBestSize() self.ResourceList.SetMinSize(size) self.SetMinSize(size) self.SetSize(size) self.SetMaxSize(size) wx.Frame.Show(self) def OnDone(self, evt): self.parent.PopDown() class RsrcSelectorControl(wx.Button): def __init__(self, resourceview, cache, parent, id): wx.Button.__init__(self, parent, id, "Resource Types") self.Bind(wx.EVT_BUTTON, self.OnClick) self.cache = cache self.resourceview = resourceview self.selected = [] self.win = ResourceSelect(self, cache) def OnClick(self, evt): if not self.win.IsShown(): self.win.Move(self.GetScreenRect().GetBottomLeft()) self.win.Show() else: self.PopDown() def PopDown(self): self.selected=[] self.win.Hide() for i in range(0, self.win.ResourceList.GetCount()): if self.win.ResourceList.IsChecked(i): self.selected.append(self.win.ResourceTypeList[self.win.ResourceList.GetString(i)]) self.resourceview.CleanUp() self.resourceview.UpdateAll() self.resourceview.canvas.Draw() class RsrcSelectorPanel(wx.Panel): def __init__(self, resourceview, parent, cache): wx.Panel.__init__(self, parent, -1) self.selector = RsrcSelectorControl(resourceview, cache, self, -1) class PieChartIcon(SystemIcon): def copy(self): return PieChartIcon(self.cache, self.primary, self.proportional, self.scale, self.valuesforchart) def __init__(self, cache, system, proportional, scale, valuesforchart): self.cache = cache self.proportional = proportional self.scale = scale self.valuesforchart = valuesforchart Holder.__init__(self, system, FindChildren(cache, system)) # Create a list of the objects ObjectList = [] # The center point if (self.proportional*self.scale != 0 and self.valuesforchart != ()): ObjectList.append(PieChart.PieChart(system.pos[0:2], self.proportional*self.scale, self.valuesforchart, Scaled=False, LineColor="Black")) else: ObjectList.append(PieChart.PieChart(system.pos[0:2], .0001, (1,1), Scaled=False, LineColor="Black")) Group.__init__(self, ObjectList, False) from Proportional import Proportional class Resource(Proportional): """\ Draws proportional circles for the relative number of resources. """ name = "Resources" TOTAL = -1 SURFACE = 1 MINABLE = 2 INACCESSABLE = 3 def __init__(self, parent, canvas, panel, cache, resource=None, type=-1): Proportional.__init__(self, parent, canvas, panel, cache) self.ResourceTypeList = {"All":Resource.TOTAL} for number, resource in cache.resources.items(): self.ResourceTypeList[resource.name] = number self.resource = resource self.type = type # Create a drop-down on the panel for resource selection sizer = wx.FlexGridSizer(len(self.ResourceTypeList)) self.selectpanel = RsrcSelectorPanel(self, panel, cache) sizer.Add(self.selectpanel, proportion=1, flag=wx.EXPAND) sizer.AddGrowableRow(0) panel.SetSizer(sizer) self.UpdateAll() self.canvas.Draw() def OnResourceSelected(self, evt): self.type = self.ResourceSelector.GetClientData(self.ResourceSelector.GetSelection()) if not evt is None: self.CleanUp() self.UpdateAll() self.canvas.Draw() def UpdateAll(self): Proportional.UpdateAll(self) def UpdateOne(self, oid, value=None): #print self.type proportional = Proportional.UpdateOne(self, oid, value) def Icon(self, obj): proportional = Proportional.Proportion(self, obj.id) c = self.cache o = obj self.valuesforchart = () self.valuesresources = {} if (o.subtype == 2): if hasattr(o, "contains"): for child in o.contains: if hasattr(c.objects[child], "resources"): for resource in c.objects[child].resources: if sum(resource[1:]) != 0: if len(self.selectpanel.selector.selected) == 0 or resource[0] in self.selectpanel.selector.selected: if self.valuesresources.has_key(resource[0]): self.valuesresources[resource[0]] += sum(resource[1:]) else: self.valuesresources[resource[0]] = sum(resource[1:]) for resource, amount in self.valuesresources.items(): if amount < (self.Amount(obj.id) * .10): if self.valuesresources.has_key(100000): self.valuesresources[100000] += amount else: self.valuesresources[100000] = amount del self.valuesresources[resource] for resource, amount in sorted(self.valuesresources.iteritems(), key=operator.itemgetter(1), reverse=True): if (resource != 100000): self.valuesforchart += (amount,) if (self.valuesresources.has_key(100000)): self.valuesforchart += (self.valuesresources[100000],) if proportional*self.scale > 0: pass return PieChartIcon(self.cache, obj, proportional, self.scale, self.valuesforchart) else: pass return PieChartIcon(self.cache, obj, 0.001, 1, (1,1)) else: pass return PieChartIcon(self.cache, obj, 0.001, 1, (1,1)) def Amount(self, oid): """\ The amount of this resource on this object. """ c = self.cache o = c.objects[oid] amount = 0 if hasattr(o, "contains"): for child in o.contains: amount += self.Amount(child) if hasattr(o, "resources"): if self.type == Resource.TOTAL: for resource in o.resources: amount += sum(resource[1:]) else: for resource in o.resources: if resource[0] == self.type: amount += sum(resource[1:]) return amount def ObjectPopupText(self, icon): returnstring = "" % wx.local.normalFont.GetPointSize() system = icon.primary returnstring += system.name returnstring += ":\nTotal (for all resources) In System: " temptype = self.type self.type = Resource.TOTAL returnstring += "%s" % self.Amount(system.id) self.type = temptype valuesresources = {} thisresourcetotal = 0 for c in system.contains: child = self.cache.objects[c] if len(self.selectpanel.selector.selected) != 0: returnstring += "\n " + child.name + ":" if hasattr(child, "resources"): for resource in child.resources: if sum(resource[1:]) > 0: if len(self.selectpanel.selector.selected) == 0: if valuesresources.has_key(resource[0]): valuesresources[resource[0]] += sum(resource[1:]) else: valuesresources[resource[0]] = sum(resource[1:]) else: if resource[0] in self.selectpanel.selector.selected: thisresourcetotal += sum(resource[1:]) returnstring += "\n " + self.cache.resources[resource[0]].name \ + ": %s " % sum(resource[1:]) \ + [self.cache.resources[resource[0]].unit_singular, self.cache.resources[resource[0]].unit_plural] \ [sum(resource[1:]) > 1] if not self.type == Resource.TOTAL: returnstring += "\n\nTotal " + self.cache.resources[self.type].name + " in system: %s" % thisresourcetotal else : for resource, amount in sorted(valuesresources.iteritems(), key=operator.itemgetter(1), reverse=True): returnstring += "\n " + self.cache.resources[resource].name + \ ": %s " % amount + \ [self.cache.resources[resource].unit_singular, self.cache.resources[resource].unit_plural][amount > 1] return returnstring + "" tpclient-pywx-0.3.1.1/windows/main/winHelp.py0000644000175000017500000000451610773624641017263 0ustar timtim"""\ This module contains the System window. The System window displays all objects at this current location and "quick" details about them. """ # Python imports from types import TupleType from copy import deepcopy # wxPython imports import wx # Local imports from windows.winBase import winReportXRC, ShiftMixIn from windows.xrc.winHelp import winHelpBase # Show the universe class winHelp(winReportXRC, winHelpBase): title = _("Help") def __init__(self, application, parent): winHelpBase.__init__(self, parent) winReportXRC.__init__(self, application, parent) self.Message.Bind(wx.html.EVT_HTML_LINK_CLICKED, self.OnLinkEvent) def OnLinkEvent(self, evt): link = evt.GetLinkInfo().GetHref() from extra.Opener import open protocol, url = link.split('://') if protocol == "local": if url == "serverbrowser": self.application.gui.Show(self.application.gui.servers) else: open(link) self.OnClose(None) def Show(self, show=True): if show: self.CenterOnParent() winReportXRC.Show(self) else: self.Hide() def OnClose(self, evt): self.Hide() def SetMessage(self, subject, body): self.Subject.SetLabel(_(subject)) self.Message.SetPage(_(body)) message_NoObjects_Subject = _("Warning - No Objects...") message_NoObjects_Body = _("""

It appears that you do not own any objects. This may be for a number of reasons:

  • You have logged in as a guest user.

    On most servers guest users can only login and view the universe. They own no objects and can not issue orders. This is good to checkout what the Universe is like, but not if you actually want to play the game.

    Most servers allow you to create accounts right from this client! This can be done by clicking "Find" on the Login window to bring up the server browser. (Open server browser window.)


  • You have been defeated.

    If you have not logged in for a long time, all your objects may have been conquered or destroyed. Some servers may let you create a new account and start again.


  • There is a problem.

    There could be a bug in some of the software, if you are sure neither of the two cases above are correct please report it here.

""") tpclient-pywx-0.3.1.1/windows/main/winDesign.py0000644000175000017500000004066710773624641017613 0ustar timtim"""\ This module contains the System window. The System window displays all objects at this current location and "quick" details about them. """ # Python imports from types import TupleType from copy import deepcopy # wxPython imports import wx import wx.gizmos # Local imports from windows.winBase import winReportXRC, ShiftMixIn from windows.xrc.winDesign import winDesignBase from tp.client.parser import DesignCalculator from tp.netlib.objects import Design, Component, Category NAME = 0 DESC = 1 COL_SIZE=150 wx.ArtProvider() Art = wx.ArtProvider_GetBitmap wx.ArtSize = (16, 16) def comparetoid(a, b): if not b is None and a[0] == type(b) and a[1] == b.id: return True return False def comparebyid(a, b): if not b is None and type(a) == type(b) and a.id == b.id: return True return False # Show the universe class winDesign(winReportXRC, winDesignBase, ShiftMixIn): title = _("Design") def __init__(self, application, parent): winDesignBase.__init__(self, parent) winReportXRC.__init__(self, application, parent) ShiftMixIn.__init__(self) self.selected = None # Currently selected design self.updating = [] # Designs which are been saved to the server #Panel = wx.Panel(self, -1) self.icons = wx.ImageList(*wx.ArtSize) self.icons.Add(Art(wx.ART_FOLDER, wx.ART_OTHER, wx.ArtSize)) self.icons.Add(Art(wx.ART_FILE_OPEN, wx.ART_OTHER, wx.ArtSize)) self.icons.Add(Art(wx.ART_NORMAL_FILE, wx.ART_OTHER, wx.ArtSize)) self.grid = self.Panel.GetSizer() self.DesignsTree.SetImageList(self.icons) # The labels ################################################################ self.top = self.TitlePanel.GetSizer() self.middle = self.DesignPanel.GetSizer() self.designsizer = self.DesignInfoPanel.GetSizer() self.compssizer = self.ComponentsPanel.GetSizer() self.addsizer = self.ComponentsButtonPanel.GetSizer() self.design_ps = wx.BoxSizer(wx.HORIZONTAL) self.PartsList.InsertColumn(0, "#", format=wx.LIST_FORMAT_RIGHT, width=20) self.PartsList.InsertColumn(1, _("Component")) self.ComponentsTree.SetImageList(self.icons) self.Panel.SetAutoLayout( True ) self.Bind(wx.EVT_BUTTON, self.OnEdit, self.Edit) self.Bind(wx.EVT_BUTTON, self.OnSelect, self.Revert) self.Bind(wx.EVT_BUTTON, self.OnSave, self.Save) self.Bind(wx.EVT_BUTTON, self.OnAdd, self.ComponentsAdd) self.Bind(wx.EVT_BUTTON, self.OnAddMany, self.ComponentsAddMany) self.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelectObject, self.DesignsTree) self.DesignsSearch.Bind(wx.EVT_TEXT, self.BuildDesignList) self.DesignsSearch.Bind(wx.EVT_TEXT_ENTER, self.BuildDesignList) self.DesignsSearch.Bind(wx.EVT_SEARCHCTRL_SEARCH_BTN, self.BuildDesignList) self.DesignsSearch.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, self.OnDesignsSearchCancel) self.ComponentsSearch.Bind(wx.EVT_TEXT, self.BuildCompList) self.ComponentsSearch.Bind(wx.EVT_TEXT_ENTER, self.BuildCompList) self.ComponentsSearch.Bind(wx.EVT_SEARCHCTRL_SEARCH_BTN, self.BuildCompList) self.ComponentsSearch.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN, self.OnComponentsSearchCancel) self.application.gui.Binder(self.application.CacheClass.CacheUpdateEvent, self.OnCacheUpdate) self.application.gui.Binder(self.application.gui.SelectObjectEvent, self.OnSelectObject) #self.Panel = Panel self.OnSelect() # Functions to manipulate the Tree controls.... # FIXME: These should be part of the tree controls themselves... ################################################################################# def TreeAddCategory(self, tree, category): child = tree.AppendItem(tree.GetRootItem(), category.name) tree.SetPyData(child, category) tree.SetItemImage(child, 0, wx.TreeItemIcon_Normal) tree.SetItemImage(child, 1, wx.TreeItemIcon_Expanded) return child def TreeAddItem(self, tree, category, object): child = tree.AppendItem(category, object.name) tree.SetPyData(child, object) tree.SetItemImage(child, 2, wx.TreeItemIcon_Normal) def TreeColourItem(self, tree, item, mode): if mode == "normal": tree.SetItemTextColour(item, wx.Color(0, 0, 0)) elif mode == "updating": tree.SetItemTextColour(item, wx.Color(0, 0, 255)) elif mode == "removing": tree.SetItemTextColour(item, wx.Color(255, 0, 0)) def TreeSelectedData(self, tree, criteria): selected = [] for tid in tree.GetSelections(): object = self.ComponentsTree.GetPyData(tid) if isinstance(object, criteria): selected.append(object) return selected # Functions to build PartsList of the interface ################################################################################# def DesignsFilter(self): filter = self.DesignsSearch.GetValue() if len(filter) == 0: return "*" if filter[-1] != '*': return '*'+filter.lower()+'*' DesignsFilter = property(DesignsFilter) def BuildDesignList(self, evt=None): self.DesignsTree.DeleteAllItems() root = self.DesignsTree.AddRoot(_("Designs")) self.DesignsTree.SetPyData(root, None) self.DesignsTree.SetItemImage(root, 0, wx.TreeItemIcon_Normal) self.DesignsTree.SetItemImage(root, 1, wx.TreeItemIcon_Expanded) blank = Design(-1, -1, -1, [1], _("New Design"), "", -1, -1, [], "", []) self.TreeAddItem(self.DesignsTree, root, blank) # FIXME: Designs which have no Categories are not shown. cache = self.application.cache for category in cache.categories.values(): categoryitem = self.TreeAddCategory(self.DesignsTree, category) for design in cache.designs.values(): if category.id in design.categories: # Filter the list.. from fnmatch import fnmatch as match if match(design.name.lower(), self.DesignsFilter.lower()): self.TreeAddItem(self.DesignsTree, categoryitem, design) if not self.DesignsTree.ItemHasChildren(categoryitem): self.DesignsTree.Delete(categoryitem) self.DesignsTree.SortChildren(self.DesignsTree.GetRootItem()) self.DesignsTree.ExpandAll() def ComponentsFilter(self): filter = self.ComponentsSearch.GetValue() if len(filter) == 0: return "*" if filter[-1] != '*': return '*'+filter.lower()+'*' ComponentsFilter = property(ComponentsFilter) def BuildCompList(self, evt=None): #FIXME: This is broken as it does not take into account the change of position of items #selected = self.ComponentsTree.GetSelection() self.ComponentsTree.DeleteAllItems() root = self.ComponentsTree.AddRoot(_("Components")) self.ComponentsTree.SetPyData(root, None) self.ComponentsTree.SetItemImage(root, 0, wx.TreeItemIcon_Normal) self.ComponentsTree.SetItemImage(root, 1, wx.TreeItemIcon_Expanded) cache = self.application.cache for category in cache.categories.values(): categoryitem = self.TreeAddCategory(self.ComponentsTree, category) for component in cache.components.values(): if category.id in component.categories: # Filter the list.. from fnmatch import fnmatch as match if match(component.name.lower(), self.ComponentsFilter.lower()): self.TreeAddItem(self.ComponentsTree, categoryitem, component) if not self.ComponentsTree.ItemHasChildren(categoryitem): self.ComponentsTree.Delete(categoryitem) self.ComponentsTree.SortChildren(self.ComponentsTree.GetRootItem()) self.ComponentsTree.ExpandAll() # FIXME: This is broken as it does not take into account the change of position of items # if selected: # self.ComponentsTree.SelectItem(selected) # self.ComponentsTree.EnsureVisible(selected) def BuildHeaderPanel(self, design): # Set the title self.TitleStatic.SetLabel(design.name) self.TitleEditable.SetValue(design.name) # Set the Used self.Used.SetLabel(unicode(design.used)) if design.used == -1: self.Used.SetForegroundColour(wx.Color(255, 0, 0)) elif design.used == 0: self.Used.SetForegroundColour(wx.Color(0, 255, 0)) else: self.Used.SetForegroundColour(wx.Color(0, 0, 0)) # Set the Categories c = "" for cid in design.categories: c += self.application.cache.categories[cid].name + ", " c = c[:-2] self.Categories.SetLabel(c) def BuildPropertiesPanel(self, design): SIZER_FLAGS = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL cache = self.application.cache # Remove the previous Panel and stuff if hasattr(self, 'properties'): self.properties.Hide() self.design_ps.Remove(self.properties) self.properties.Destroy() del self.properties if hasattr(self, 'DesignPropertyGroup1'): self.DesignProperties.Hide() self.designsizer.Remove(self.DesignPropertyGroup1) self.DesignPropertyGroup1.Destroy() del self.DesignPropertyGroup1 # Create a new Panel Panel = wx.Panel(self.DesignProperties, -1) sizer = wx.BoxSizer(wx.VERTICAL) Panel.SetSizer(sizer) Panel.SetSize((250, 390)) # Sort the properties into category groups properties = {} for pid, pstring in design.properties: property = cache.properties[pid] for cid in property.categories: if not properties.has_key(cid): properties[cid] = [] properties[cid].append((property, pstring)) for cid in properties.keys(): category = cache.categories[cid] # The box around the properties in the category box = wx.StaticBox(Panel, -1, category.name) box.SetFont(wx.local.normalFont) box_sizer = wx.StaticBoxSizer(box, wx.VERTICAL) sizer.Add(box_sizer, 1, SIZER_FLAGS, 5) # The properties prop_sizer = wx.FlexGridSizer( 0, 2, 0, 0 ) box_sizer.Add(prop_sizer, 1, SIZER_FLAGS, 5) for property, pstring in properties[cid]: # Property name name = wx.StaticText(Panel, -1, property.display_name) name.SetFont(wx.local.normalFont) prop_sizer.Add(name, 0, SIZER_FLAGS|wx.ALIGN_RIGHT, 5) # Property value value = wx.StaticText(Panel, -1, pstring) value.SetFont(wx.local.normalFont) prop_sizer.Add(value, 1, SIZER_FLAGS|wx.ALIGN_RIGHT, 5) self.design_ps.Layout() Panel.Layout() self.DesignProperties.Show() self.design_ps.Show(Panel) self.properties = Panel def BuildPartsPanel(self, design): # Populate the PartsList list self.PartsList.DeleteAllItems() for cid, number in design.components: component = self.application.cache.components[cid] self.PartsList.InsertStringItem(0, unicode(number)) self.PartsList.SetStringItem(0, 1, component.name) # Functions to update the component lists ################################################################################# def OnAddMany(self, evt): """\ Pops up a selection box to ask for how many to ComponentsAdd. """ self.OnAdd(evt, amount) def OnAdd(self, evt, amount=1): """\ Adds components to the current design. """ # Figure out if a component is selected components = self.TreeSelectedData(self.ComponentsTree, Component) dc = DesignCalculator(self.application.cache, self.selected) for component in components: dc.change(component, amount) dc.update() if self.selected.Used == -1: if amount > 1 or len(components) > 1: reason = self.selected.feedback + _("\nWould you like to continue adding these components?") else: reason = self.selected.feedback + _("\nWould you like to continue adding this component?") dlg = wx.MessageDialog(self, reason, _('Design Warning'), wx.YES_NO|wx.NO_DEFAULT|wx.ICON_ERROR) if dlg.ShowModal() == wx.ID_NO: for component in components: dc.change(component, -amount) dc.update() dlg.Destroy() # Redisplay the panels self.BuildPartsPanel(self.selected) self.BuildPropertiesPanel(self.selected) # Functions to change the mode of the dialog ################################################################################# def OnEdit(self, evt=None): # FIXME: Check if we can modify this Design. # Disable the select side self.DesignsTree.Disable() # Show the component bar self.grid.Show(self.ComponentsPanel) self.grid.Show(self.ComponentsSearch) self.ComponentsPanel.SetSize((0, 0)) self.ComponentsSearch.SetSize((0, 0)) self.ComponentsPanel.Layout() # Make the title and description editable self.top.Show(self.TitleEditable) self.top.Hide(self.TitleStatic) self.top.Layout() # Disable Edit, Duplicate, Delete self.Edit.Disable() self.Duplicate.Disable() self.Delete.Disable() # Enable the Save, Revert self.Revert.Enable() self.Revert.SetDefault() self.Save.Enable() # Re-layout everything self.grid.Layout() # Start the timer so that Add -> Add Many self.ShiftStart() def OnSave(self, evt): design = self.selected # Is this a new design? if design.id == -1: self.application.Post(self.application.cache.CacheDirtyEvent("DesignsTree", "create", -1, design), source=self) self.selected = None else: # Add the design to ones which are being updated self.updating.append(design.id) # Change the colour on the side for item in self.DesignsTree.FindAllByData(design, comparebyid): self.TreeColourItem(self.DesignsTree, item, "updating") # Tell the world about the change self.application.Post(self.application.cache.CacheDirtyEvent("DesignsTree", "change", design.id, design), source=self) self.OnSelect(None) def OnRemove(self, evt): design = self.selected # Add the design to ones which are being updated self.updating.append(design.id) # Change the colour on the side for item in self.DesignsTree.FindAllByData(design, comparebyid): self.TreeColourItem(self.DesignsTree, item, "removing") self.application.Post(self.application.cache.CacheDirtyEvent("DesignsTree", "remove", design.id, design), source=self) def OnSelect(self, evt=None): # Stop any running Shift timers self.ShiftStop() # Enable the selection side self.DesignsTree.Enable() # Hide the component bar self.grid.Hide(self.ComponentsPanel) self.grid.Hide(self.ComponentsSearch) self.ComponentsPanel.SetSize((0,0)) self.ComponentsSearch.SetSize((0,0)) self.ComponentsPanel.Layout() # Make the title and description uneditable self.top.Hide(self.TitleEditable) self.top.Show(self.TitleStatic) self.top.Layout() # Disable Save, Revert self.Revert.Disable() self.Save.Disable() # Re-layout everything self.grid.Layout() self.OnSelectObject() def OnSelectObject(self, evt=None): selected = self.TreeSelectedData(self.DesignsTree, Design) if len(selected) != 1: self.selected = None else: if selected[0].id in self.updating: self.selected = None else: self.selected = deepcopy(selected[0]) if self.selected == None: # Clear the title self.TitleStatic.SetLabel("") # Hide the design self.grid.Hide(self.DesignPanel) self.grid.Layout() # Disable the buttons self.Edit.Disable() self.Duplicate.Disable() self.Delete.Disable() return # # Recalculate all the properties if they are empty # if len(self.selected.properties) == 0: # self.Recalculate() # Build the Header Panel self.BuildHeaderPanel(self.selected) # Show the PartsList list self.grid.Show(self.DesignPanel) self.grid.Layout() # Populate the PartsList list self.BuildPartsPanel(self.selected) # Populate the properties self.BuildPropertiesPanel(self.selected) # Set if Edit can work if self.selected.used <= 0: self.Edit.Enable() self.Edit.SetDefault() self.Duplicate.Enable() self.Delete.Enable() else: self.Edit.Disable() self.Delete.Disable() self.Duplicate.Enable() self.Duplicate.SetDefault() # Re-layout everything self.grid.Layout() def OnCacheUpdate(self, evt=None): # Full cache update, rebuild everything if evt.what is None: self.BuildDesignList() self.BuildCompList() if evt.what is "DesignsTree": design = evt.change if evt.action in ("change", "remove"): for item in self.DesignsTree.FindAllByData(design, comparebyid): categoryitem = self.DesignsTree.GetItemParent(item) self.DesignsTree.Delete(item) # Remove the category if it will be empty if self.DesignsTree.ItemHasChildren(categoryitem): self.DesignsTree.Delete(categoryitem) if evt.action in ("change", "create"): for categoryid in design.Categories: # Check the category exists parent = self.DesignsTree.FindItemByData((Category, categoryid), comparetoid) if parent is None: parent = self.TreeAddCategory(self.DesignsTree, self.application.cache.Categories[categoryid]) # Add the new design under this category self.TreeAddItem(self.DesignsTree, parent, design) if design.id in self.updating: self.updating.remove(design.id) self.DesignsTree.SortChildren(self.DesignsTree.GetRootItem()) def OnDesignsSearchCancel(self, evt): self.DesignsSearch.SetValue("") self.BuildDesignList() def OnComponentsSearchCancel(self, evt): self.ComponentsSearch.SetValue("") self.BuildCompList() tpclient-pywx-0.3.1.1/windows/main/panelInfo.py0000644000175000017500000000764510773624641017576 0ustar timtim"""\ This module contains the Information window. The Information window displays all objects information. """ # Python Imports import os import os.path from types import * import pprint # wxPython imports import wx try: from extra.GIFAnimationCtrl import GIFAnimationCtrl except ImportError: from wx.animate import GIFAnimationCtrl # Network imports from tp.netlib.objects.ObjectExtra.Universe import Universe from tp.netlib.objects.ObjectExtra.Galaxy import Galaxy from tp.netlib.objects.ObjectExtra.StarSystem import StarSystem from tp.netlib.objects.ObjectExtra.Planet import Planet from tp.netlib.objects.ObjectExtra.Fleet import Fleet from windows.xrc.panelInformation import panelInformationBase class panelInformation(panelInformationBase): title = _("Information") def __init__(self, application, parent): panelInformationBase.__init__(self, parent) self.application = application self.current = -1 self.application.gui.Binder(self.application.gui.SelectObjectEvent, self.OnSelectObject) def GetPaneInfo(self): info = wx.aui.AuiPaneInfo() info.MinSize(self.GetBestSize()) info.Bottom() info.Layer(1) return info def OnSelectObject(self, evt): if evt.id == self.current: return self.current = evt.id try: object = self.application.cache.objects[evt.id] except: do_traceback() return self.Title.SetLabel(object.name) # Add the object type specific information s = "" for key, value in object.__dict__.items(): if key.startswith("_") or key in \ ('protocol', 'sequence', 'otype', 'length', 'order_types', 'order_number', 'contains'): continue if key == "owner": if self.application.cache.players.has_key(value): s += "Owner: %s (%s)\n" % (self.application.cache.players[value].name, value) else: s += "Owner: Unknown (%s)\n" % (value,) continue if key == "ships": s += _("Ships: ") # FIXME: This is a hack :/ for t, number in value: if self.application.cache.designs.has_key(t): design = self.application.cache.designs[t] s += "%s %s, " % (number, design.name) else: print _("Unknown Design id:"), t s += "%s %s, " % (number, _("Unknown (type: %s)") % t) s = s[:-2] + "\n" continue if key == "resources": s += _("Resources:\n") for t, surface, minable, inaccess in value: if surface+minable+inaccess == 0: continue if self.application.cache.resources.has_key(t): res = self.application.cache.resources[t] s+="\t" if surface > 0: if len(res.unit_singular) > 0: s+=_("%s %s of %s on surface, ") % (surface, \ [res.unit_singular, res.unit_plural][surface > 1], [res.name_singular, res.name_plural][surface > 1]) else: s+=_("%s %s on surface, ") % (surface, [res.name_singular, res.name_plural][surface > 1]) if minable > 0: if len(res.unit_singular) > 0: s+=_("%s %s of %s minable, ") % (minable, \ [res.unit_singular, res.unit_plural][minable > 1], [res.name_singular, res.name_plural][minable > 1]) else: s+=_("%s %s minable, ") % (minable, [res.name_singular, res.name_plural][minable > 1]) if inaccess > 0: if len(res.unit_singular) > 0: s+=_("%s %s of %s inaccessible, ") % (inaccess, \ [res.unit_singular, res.unit_plural][inaccess > 1], [res.name_singular, res.name_plural][inaccess > 1]) else: s+=_("%s %s inaccessible, ") % (inaccess, [res.name_singular, res.name_plural][inaccess > 1]) s = s[:-2]+"\n" else: s+= _("\tUnknown Resource %i, S: %i, M: %i, I: %s\n") % (t, surface, minable, inaccess) continue key = key.title() if type(value) == StringType: s += "%s: %s\n" % (key, value) elif type(value) in (ListType, TupleType): s += "%s: " % (key,) for i in value: s += "%s, " % (i,) s = s[:-2] + "\n" else: s += "%s: %s\n" % (key, value) self.Details.SetValue(s) tpclient-pywx-0.3.1.1/windows/main/winIdleFinder.py0000644000175000017500000001153410773624641020376 0ustar timtim"""\ This module contains the idle objects finder display. """ # wxPython imports import wx import wx.gizmos #from wx import * import wx.lib.anchors # Local imports from windows.winBase import winReportXRC, ShiftMixIn from windows.xrc.winIdleFinder import IdleFinderBase # Shows messages from the game system to the player. from extra.StateTracker import TrackerObject # tp imports from tp.netlib.objects import Object, OrderDescs from tp.netlib.objects.ObjectExtra.Universe import Universe from tp.netlib.objects.ObjectExtra.Galaxy import Galaxy from tp.netlib.objects.ObjectExtra.StarSystem import StarSystem from tp.netlib.objects.ObjectExtra.Planet import Planet from tp.netlib.objects.ObjectExtra.Fleet import Fleet class winIdleFinder(winReportXRC, IdleFinderBase, TrackerObject): title = _("Objects Without Orders") def __init__(self, application, parent): IdleFinderBase.__init__(self, parent) winReportXRC.__init__(self, application, parent) self.application = application self.oid = -1 # Create a panel for the current window. self.idlelist.InsertColumn(0, "Item ID", width = 100) self.idlelist.InsertColumn(1, "Item Name", width = 200) self.idlelist.InsertColumn(2, "Item Type", width = 100) self.ascending = 1 self.Bind(wx.EVT_SHOW, self.OnShow) self.Bind(wx.EVT_ACTIVATE, self.OnShow) self.idlelist.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.SelectObject) self.idlelist.Bind(wx.EVT_LIST_COL_CLICK, self.OnColClick) def OnShow(self, evt): """\ Runs when the window is shown. """ self.idlelist.DeleteAllItems() numinlist = 0 universe = self.application.cache.objects.keys() for object in universe: numorders = 0 # The object must have an owner to have orders if not hasattr(self.application.cache.objects[object], "owner"): continue # Only show objects owned by this player if self.application.cache.objects[object].owner != self.application.cache.players[0].id: continue if object in self.application.cache.orders.keys(): # Find any orders for this object for listpos, node in enumerate(self.application.cache.orders[object]): numorders = numorders + 1 # If the object has no orders, add it to the list if numorders == 0: self.idlelist.InsertStringItem(numinlist, "%d" % object) self.idlelist.SetStringItem(numinlist, 1, self.application.cache.objects[object].name) self.idlelist.SetItemData(numinlist, object) # Determine object's type if isinstance(self.application.cache.objects[object], Universe): self.idlelist.SetStringItem(numinlist, 2, "Universe") elif isinstance(self.application.cache.objects[object], Galaxy): self.idlelist.SetStringItem(numinlist, 2, "Galaxy") elif isinstance(self.application.cache.objects[object], StarSystem): self.idlelist.SetStringItem(numinlist, 2, "System") elif isinstance(self.application.cache.objects[object], Planet): self.idlelist.SetStringItem(numinlist, 2, "Planet") elif isinstance(self.application.cache.objects[object], Fleet): self.idlelist.SetStringItem(numinlist, 2, "Fleet") else: self.idlelist.SetStringItem(numinlist, 2, "Unknown") numinlist = numinlist + 1 def Sort(self, d1, d2): data1 = self.GetColData(d1, self.col) data2 = self.GetColData(d2, self.col) if data1 == data2: return 0 elif data1 > data2: return self.ascending*1 else: return self.ascending*-1 def GetColData(self, obj, col): if col == 0: return obj elif col == 1: return self.application.cache.objects[obj].name.lower() elif col == 2: return self.application.cache.objects[obj].subtype def OnColClick(self, event): # Reverse sort order, then re-sort, when list column heading is clicked. self.col = event.GetColumn() self.ascending *= -1 self.idlelist.SortItems(self.Sort) def OnClose(self, evt): """\ Runs when the window is closed. """ self.Hide() # Config Functions (required by winBase.py) ----------------------------------------------------------------------------- def ConfigDefault(self, config=None): """\ Fill out the config with defaults (if the options are not valid or nonexistant). """ return {} def ConfigSave(self): """\ Returns the configuration of the Window (and it's children). """ return {} def ConfigLoad(self, config={}): """\ Loads the configuration of the Window (and it's children). """ pass def ConfigUpdate(self): """\ Updates the config details using external sources. """ pass def ConfigDisplay(self, panel, sizer): """\ Display a config panel with all the config options. """ pass def ConfigDisplayUpdate(self, evt): """\ Update the Display because it's changed externally. """ pass def SelectObject(self, id): """ Called to select an object. """ TrackerObject.SelectObject(self, int(id.GetText())) tpclient-pywx-0.3.1.1/windows/winConfig.py0000644000175000017500000000556610773624641016662 0ustar timtim"""\ This module contains the config window. """ # wxPython Imports import wx import wx.lib.anchors # Local Imports from winBase import winBase # Shows messages from the game system to the player. class winConfig(winBase): title = _("Config") def __init__(self, application, windows): winBase.__init__(self, application) self.application = application # The first panel is the current window, we then go through all the other windows. main = wx.Panel(self, -1) base = wx.BoxSizer(wx.VERTICAL) notebook = wx.Notebook(main, -1) base.Add(notebook, 1, wx.EXPAND) # Now add each window which can be configured for window in windows: panel = wx.Panel(notebook, -1) sizer = wx.BoxSizer(wx.HORIZONTAL) window.ConfigDisplay(panel, sizer) panel.SetAutoLayout(True) panel.SetSizer(sizer) if len(sizer.GetChildren()) == 0: continue notebook.AddPage(panel, window.title) # FIXME: This is only temporary till they fix this on mac! if wx.Platform != "__WXMAC__": butt = wx.StdDialogButtonSizer() else: butt = wx.BoxSizer(wx.HORIZONTAL) base.Add(butt, 0, wx.ALIGN_RIGHT) # Buttons for saving/reverting save = wx.Button(main, wx.ID_SAVE) self.Bind(wx.EVT_BUTTON, self.OnConfigSave, save) revert = wx.Button(main, wx.ID_REVERT_TO_SAVED) self.Bind(wx.EVT_BUTTON, self.OnConfigRevert, revert) revert.SetDefault() if wx.Platform != "__WXMAC__": butt.AddButton(save), butt.SetCancelButton(revert) butt.Realize() else: butt.Add(save, 0, wx.ALIGN_RIGHT) butt.Add(revert, 0, wx.ALIGN_RIGHT) main.SetAutoLayout(True) main.SetSizer(base) base.SetSizeHints(self) self.notebook = notebook self.Bind(wx.EVT_SHOW, self.OnShow) def OnShow(self, evt): for page in xrange(self.notebook.GetPageCount()): if self.notebook.GetPageText(page) == self.application.gui.current.title: self.notebook.SetSelection(page) break def OnConfigSave(self, evt): self.application.ConfigSave() self.Hide() def OnConfigRevert(self, evt): self.application.ConfigLoad() self.Hide() def OnClose(self, evt): self.OnConfigRevert(evt) # Config Functions ----------------------------------------------------------------------------- def ConfigDefault(self, config=None): """\ Fill out the config with defaults (if the options are not valid or nonexistant). """ return {} def ConfigSave(self): """\ Returns the configuration of the Window (and it's children). """ return {} def ConfigLoad(self, config={}): """\ Loads the configuration of the Window (and it's children). """ pass def ConfigUpdate(self): """\ Updates the config details using external sources. """ pass def ConfigDisplay(self, panel, sizer): """\ Display a config panel with all the config options. """ pass def ConfigDisplayUpdate(self, evt): """\ Update the Display because it's changed externally. """ pass tpclient-pywx-0.3.1.1/windows/xrc/0000755000175000017500000000000010773624641015145 5ustar timtimtpclient-pywx-0.3.1.1/windows/xrc/panelSystem.py0000644000175000017500000000303610773624641020025 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class panelSystemBase(wx.Panel): xrc = os.path.join(location(), "windows", "xrc", 'panelSystem.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.PrePanel() res.LoadOnPanel(pre, parent, "panelSystem") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Tree = XRCCTRL(self, "Tree") self.PrevObject = XRCCTRL(self, "PrevObject") if hasattr(self, "OnPrevObject"): self.Bind(wx.EVT_BUTTON, self.OnPrevObject, self.PrevObject) self.NextObject = XRCCTRL(self, "NextObject") if hasattr(self, "OnNextObject"): self.Bind(wx.EVT_BUTTON, self.OnNextObject, self.NextObject) self.StepInto = XRCCTRL(self, "StepInto") if hasattr(self, "OnStepInto"): self.Bind(wx.EVT_BUTTON, self.OnStepInto, self.StepInto) self.Search = XRCCTRL(self, "Search") def strings(): pass tpclient-pywx-0.3.1.1/windows/xrc/orderText.xrc0000644000175000017500000000123010773624641017637 0ustar timtim 8 normal 0 swiss Sans wxEXPAND|wxGROW 1 1 0 tpclient-pywx-0.3.1.1/windows/xrc/__init__.py0000644000175000017500000000000010773624641017244 0ustar timtimtpclient-pywx-0.3.1.1/windows/xrc/orderRange.xrc0000644000175000017500000000152510773624641017756 0ustar timtim 8 normal 0 swiss Sans wxEXPAND|wxGROW 1 1 0 8 normal 0 swiss Sans tpclient-pywx-0.3.1.1/windows/xrc/panelStarMap.py0000644000175000017500000000405510773624641020112 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class panelStarMapBase(wx.Panel): xrc = os.path.join(location(), "windows", "xrc", 'panelStarMap.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.PrePanel() res.LoadOnPanel(pre, parent, "panelStarMap") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.MouseMode = XRCCTRL(self, "MouseMode") if hasattr(self, "OnMouseMode"): self.Bind(wx.EVT_BUTTON, self.OnMouseMode, self.MouseMode) self.ZoomLevel = XRCCTRL(self, "ZoomLevel") if hasattr(self, "OnZoomLevel"): self.Bind(wx.EVT_COMBOBOX, self.OnZoomLevel, self.ZoomLevel) self.Bind(wx.EVT_TEXT_ENTER, self.OnZoomLevel, self.ZoomLevel) if hasattr(self, "OnDirtyZoomLevel"): self.Bind(wx.EVT_TEXT, self.OnZoomLevel, self.ZoomLevel) self.Home = XRCCTRL(self, "Home") if hasattr(self, "OnHome"): self.Bind(wx.EVT_BUTTON, self.OnHome, self.Home) self.Find = XRCCTRL(self, "Find") if hasattr(self, "OnFind"): self.Bind(wx.EVT_BUTTON, self.OnFind, self.Find) self.DisplayMode = XRCCTRL(self, "DisplayMode") if hasattr(self, "OnDisplayMode"): self.DisplayMode.Bind(wx.EVT_CHOICE, self.OnDisplayMode) self.DisplayModeExtra = XRCCTRL(self, "DisplayModeExtra") self.FloatCanvas = XRCCTRL(self, "FloatCanvas") def strings(): pass _("Fit"); _("80%"); _("50%"); _("10%"); _("Box"); _("System"); _("Resources"); tpclient-pywx-0.3.1.1/windows/xrc/panelMessage.xrc0000644000175000017500000002507610773624641020301 0ustar timtim 400,170 1 2 0 0 0 1 wxGROW|wxALIGN_CENTER_VERTICAL|wxALL 1 wxHORIZONTAL wxALIGN_CENTER_VERTICAL|wxALL 1 8 swiss Sans wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 0 wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 0 8 swiss Sans wxGROW|wxGROW|wxALL 2 2 2 0 0 0 0 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxRIGHT 2 <html> <body> <center> <table cols=1 width="100%"> <tr> <td><b>Subject:</b> You are unloved! </tr> <tr> <td> You have recived no messages this turn!<br><br> Actually if you didn't recive any messages it most proberly means that your client couldn't load the results from the server. Try reload/restart the client. </td> </tr> </table> </center> </body> </html> wxGROW|wxGROW|wxLEFT|wxTOP|wxBOTTOM 0 1 2 0 0 wxGROW|wxALIGN_CENTER_VERTICAL|wxALL 0 wxHORIZONTAL wxALIGN_CENTER_VERTICAL|wxALL 0 45,22 8 swiss Sans wxALIGN_CENTER_VERTICAL|wxALL 0 45,-1 8 swiss Sans 1 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 0 45,22 8 swiss Sans wxGROW|wxALIGN_CENTER_VERTICAL|wxALL 0 wxHORIZONTAL wxALIGN_CENTER_VERTICAL|wxALL 0 45,22 8 swiss Sans wxALIGN_CENTER_VERTICAL|wxALL 0 45,-1 8 swiss Sans 1 wxALIGN_CENTER_HORIZONTAL|wxALIGN_TOP|wxALL 2 20,-1 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 0 45,22 8 swiss Sans tpclient-pywx-0.3.1.1/windows/xrc/configConnect.py0000644000175000017500000000364610773624641020307 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class configConnectBase(wx.Panel): xrc = os.path.join(location(), "windows", "xrc", 'configConnect.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.PrePanel() res.LoadOnPanel(pre, parent, "configConnect") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Servers = XRCCTRL(self, "Servers") self.ServerDetails = XRCCTRL(self, "ServerDetails") self.Username = XRCCTRL(self, "Username") self.GameShow = XRCCTRL(self, "GameShow") if hasattr(self, "OnGameShow"): self.Bind(wx.EVT_TOGGLEBUTTON, self.OnGameShow, self.GameShow) self.GameTitle = XRCCTRL(self, "GameTitle") self.Game = XRCCTRL(self, "Game") self.Password = XRCCTRL(self, "Password") self.AutoConnect = XRCCTRL(self, "AutoConnect") if hasattr(self, "OnAutoConnect"): self.Bind(wx.EVT_CHECKBOX, self.OnAutoConnect, self.AutoConnect) self.Debug = XRCCTRL(self, "Debug") if hasattr(self, "OnDebug"): self.Bind(wx.EVT_CHECKBOX, self.OnDebug, self.Debug) def strings(): pass _("Login for"); _("Username"); _("The username for the account on the Thousand Parsec server."); _("Show seperate game box."); _("G"); _("Game"); _("Password"); _("Autoconnect"); _("Debug Output"); tpclient-pywx-0.3.1.1/windows/xrc/winServerBrowser.py0000644000175000017500000000544710773624641021061 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class winServerBrowserBase: xrc = os.path.join(location(), "windows", "xrc", 'winServerBrowser.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Figure out what Frame class (MDI, MiniFrame, etc) is actually our base... bases = set() def findbases(klass, set): for base in klass.__bases__: set.add(base) findbases(base, set) findbases(self.__class__, bases) for base in bases: if base.__name__.endswith("Frame"): break # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = getattr(wx, "Pre%s" % base.__name__)() res.LoadOnFrame(pre, parent, "winServerBrowser") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Panel = XRCCTRL(self, "Panel") self.Progress = XRCCTRL(self, "Progress") self.Servers = XRCCTRL(self, "Servers") self.LocationsPanel = XRCCTRL(self, "LocationsPanel") self.LocationsBox = XRCCTRL(self, "LocationsBox") self.Locations = XRCCTRL(self, "Locations") self.URLTitle = XRCCTRL(self, "URLTitle") self.URL = XRCCTRL(self, "URL") self.Refresh = XRCCTRL(self, "wxID_REFRESH") if hasattr(self, "OnRefresh"): self.Bind(wx.EVT_BUTTON, self.OnRefresh, self.Refresh) self.NewAccount = XRCCTRL(self, "NewAccount") if hasattr(self, "OnNewAccount"): self.Bind(wx.EVT_BUTTON, self.OnNewAccount, self.NewAccount) self.ConnectTo = XRCCTRL(self, "ConnectTo") if hasattr(self, "OnConnectTo"): self.Bind(wx.EVT_BUTTON, self.OnConnectTo, self.ConnectTo) self.Cancel = XRCCTRL(self, "wxID_CANCEL") if hasattr(self, "OnCancel"): self.Bind(wx.EVT_BUTTON, self.OnCancel, self.Cancel) def strings(): pass _("TP: Server Browser"); _("Thousand Parsec Server Browser"); _("Servers"); _("List of all the servers registered on the metaserver."); _("Locations"); _("List of all the servers found on the local network."); _("URL"); _("URL of the currently selected server."); _("Copy the URL to the clipboard."); _("&Copy"); _("Force a refresh of the server list."); _("&Refresh"); _("Create a new account on the currently selected server."); _("&New Account"); _("Connect to the currently selected server."); _("C&onnect"); _("&Cancel"); tpclient-pywx-0.3.1.1/windows/xrc/configConnect.xrc0000644000175000017500000002162310773624641020446 0ustar timtim 400,300 2 2 0 0 0 0 wxGROW|wxGROW|wxALL 5 200,100 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 1 2 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 wxHORIZONTAL wxALIGN_CENTER_VERTICAL|wxALL 5 2 2 0 0 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 0 2 2 0 0 0 wxGROW|wxGROW|wxALL 1 The username for the account on the Thousand Parsec server. 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 0 25,25 Show seperate game box. 0 0 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxADJUST_MINSIZE 5 1 wxGROW|wxGROW|wxALL 0 1 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 0 200,-1 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 5,5 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 5,5 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 1 2 0 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 1 tpclient-pywx-0.3.1.1/windows/xrc/panelPicture.py0000644000175000017500000000263210773624641020155 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class panelPictureBase(wx.Panel): xrc = os.path.join(location(), "windows", "xrc", 'panelPicture.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.PrePanel() res.LoadOnPanel(pre, parent, "panelPicture") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Title = XRCCTRL(self, "Title") self.Background = XRCCTRL(self, "Background") self.Static = XRCCTRL(self, "Static") self.Animation = XRCCTRL(self, "Animation") self.Download = XRCCTRL(self, "Download") self.Progress = XRCCTRL(self, "Progress") self.Speed = XRCCTRL(self, "Speed") self.ETA = XRCCTRL(self, "ETA") def strings(): pass _("Name goes here"); _("10kb/s"); _("43s"); tpclient-pywx-0.3.1.1/windows/xrc/panelOrder.py0000644000175000017500000000423510773624641017616 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class panelOrderBase(wx.Panel): xrc = os.path.join(location(), "windows", "xrc", 'panelOrder.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.PrePanel() res.LoadOnPanel(pre, parent, "panelOrder") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Master = XRCCTRL(self, "Master") self.Orders = XRCCTRL(self, "Orders") self.Possible = XRCCTRL(self, "Possible") if hasattr(self, "OnPossible"): self.Possible.Bind(wx.EVT_CHOICE, self.OnPossible) self.New = XRCCTRL(self, "New") if hasattr(self, "OnNew"): self.Bind(wx.EVT_BUTTON, self.OnNew, self.New) self.DetailsParentPanel = XRCCTRL(self, "DetailsParentPanel") self.ArgumentLine = XRCCTRL(self, "ArgumentLine") self.DetailsBorderPanel = XRCCTRL(self, "DetailsBorderPanel") self.DetailsPanel = XRCCTRL(self, "DetailsPanel") self.ButtonsPanel = XRCCTRL(self, "ButtonsPanel") self.Message = XRCCTRL(self, "Message") self.Save = XRCCTRL(self, "Save") if hasattr(self, "OnSave"): self.Bind(wx.EVT_BUTTON, self.OnSave, self.Save) self.Revert = XRCCTRL(self, "Revert") if hasattr(self, "OnRevert"): self.Bind(wx.EVT_BUTTON, self.OnRevert, self.Revert) self.Delete = XRCCTRL(self, "Delete") if hasattr(self, "OnDelete"): self.Bind(wx.EVT_BUTTON, self.OnDelete, self.Delete) def strings(): pass _("Insert new order."); _("&New"); _("&Save"); _("&Revert"); _("Delete the currently selected order(s)"); _("&Delete"); tpclient-pywx-0.3.1.1/windows/xrc/orderList.py0000644000175000017500000000300010773624641017457 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class orderListBase(wx.Panel): xrc = os.path.join(location(), "windows", "xrc", 'orderList.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.PrePanel() res.LoadOnPanel(pre, parent, "orderList") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Choices = XRCCTRL(self, "Choices") self.Type = XRCCTRL(self, "Type") if hasattr(self, "OnType"): self.Type.Bind(wx.EVT_CHOICE, self.OnType) self.Number = XRCCTRL(self, "Number") self.Add = XRCCTRL(self, "Add") if hasattr(self, "OnAdd"): self.Bind(wx.EVT_BUTTON, self.OnAdd, self.Add) self.Delete = XRCCTRL(self, "Delete") if hasattr(self, "OnDelete"): self.Bind(wx.EVT_BUTTON, self.OnDelete, self.Delete) def strings(): pass _("Choice 1"); _("Choice 2"); _("Add"); _("D"); tpclient-pywx-0.3.1.1/windows/xrc/orderList.xrc0000644000175000017500000001041410773624641017632 0ustar timtim 1 2 8 normal 0 swiss Sans wxEXPAND|wxGROW -1,100 4 1 1 3 0,0 wxEXPAND|wxGROW Choice 1 Choice 2 8 swiss normal 0 Sans wxEXPAND|wxGROW 0,0 wxEXPAND|wxGROW 0 0 2 wxEXPAND|wxGROW 40,-1 8 normal 0 swiss Sans Number of things to add or remove. wxEXPAND|wxGROW|wxALIGN_CENTRE_VERTICAL 0 8 normal 0 swiss Sans Add items. wxALIGN_CENTRE_VERTICAL 0 8 normal 0 swiss Sans Delete selected. wxALIGN_CENTRE_VERTICAL 0 0 wxEXPAND|wxGROW 0 0 tpclient-pywx-0.3.1.1/windows/xrc/GameSetupWizard.xrc0000644000175000017500000003417610773624641020751 0ustar timtim wxWIZARD_EX_HELPBUTTON Game Setup Wizard wizard.png 0 8 0 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 12 swiss bold Sans wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 200,150 10 swiss Sans <p> This wizard will walk you through setting up a temporary Thousand Parsec server on your local machine. </p><p> If you would like people to access the game while you are not running this client you CAN NOT use this wizard. Instead follow the instructions found at <a href="http://www.thousandparsec.net/tp/gettingstarted.php#server">here</a>. </p><p> You can load an old game or start a new game. </p> wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 5,5 wxGROW|wxALIGN_CENTER_VERTICAL|wxALL 5 0 0 &Start New Game &Load Existing Game 1 6 0 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 12 swiss bold Sans wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 wxGROW|wxGROW|wxALL|wxADJUST_MINSIZE 5 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 5,5 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 0 0 &Test Game 1 &Test Game 2 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL 5 1 6 0 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 12 swiss bold Sans wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 wxGROW|wxGROW|wxALL|wxADJUST_MINSIZE 5 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 5,5 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 0 0 &Test Ruleset 1 &Test Ruleset 2 1 6 0 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 12 swiss bold Sans wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 wxGROW|wxGROW|wxALL|wxADJUST_MINSIZE 5 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 5,5 wxGROW|wxGROW|wxALL 5 2 0 0 0 1 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 5,5 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL 5 wxHORIZONTAL wxALIGN_CENTER_VERTICAL|wxALL 5 Connect to the newly created server. wxALIGN_CENTER_VERTICAL|wxALL 5 Create a new account on the newly created server. tpclient-pywx-0.3.1.1/windows/xrc/winConnect.xrc0000644000175000017500000001614210773624641017776 0ustar timtim TP: Connect to a Server 1 3 0 0 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 14 swiss bold Sans wxGROW|wxGROW|wxALL 5 2 2 0 0 1 0,1,2 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 The URL for the Thousand Parsec server. 300,-1 wxEXPAND wxBOTTOM|wxEXPAND|wxGROW|wxALIGN_CENTRE_VERTICAL|wxALIGN_CENTRE_HORIZONTAL 2 1 0 wxEXPAND|wxGROW wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 0 2 2 0 0 0 wxGROW|wxGROW|wxALL 1 The username for the account on the Thousand Parsec server. wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 0 25,25 Show seperate game box. 0 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 1 wxGROW|wxALIGN_CENTER_VERTICAL|wxALL 1 1 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxALIGN_CENTER_VERTICAL|wxALL 1 The password for the account on the Thousand Parsec Server wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 0 5 2 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxLEFT|wxBOTTOM 5 1 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxBOTTOM 5 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 5,5 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxBOTTOM 5 tpclient-pywx-0.3.1.1/windows/xrc/winServerBrowser.xrc0000644000175000017500000001741410773624641021222 0ustar timtim 800,450 TP: Server Browser 1 2 0 0 0 1 wxGROW|wxGROW|wxALL 0 2 2 0 0 0 wxALIGN_LEFT|wxALIGN_BOTTOM|wxALL|wxADJUST_MINSIZE 5 14 swiss bold Sans wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL 0 32,32 1 wxGROW|wxGROW|wxALL 5 1 2 0 0 0 0 wxGROW|wxGROW|wxLEFT|wxRIGHT|wxBOTTOM 5 wxVERTICAL 10 swiss bold Sans wxGROW|wxALL 5 100,100 List of all the servers registered on the metaserver. wxGROW|wxALIGN_CENTER_VERTICAL|wxALL 5 100,-1 wxVERTICAL 10 swiss bold Sans wxGROW|wxALL 5 100,100 List of all the servers found on the local network. wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT 5 3 2 0 0 1 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 5 URL of the currently selected server. wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 0 Copy the URL to the clipboard. wxGROW|wxGROW|wxALL 5 5 1 0 0 1 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 0 1 Force a refresh of the server list. 1 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 5,5 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 0 Create a new account on the currently selected server. 1 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 0 Connect to the currently selected server. wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 0 tpclient-pywx-0.3.1.1/windows/xrc/orderRange.py0000644000175000017500000000210010773624641017600 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class orderRangeBase(wx.Panel): xrc = os.path.join(location(), "windows", "xrc", 'orderRange.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.PrePanel() res.LoadOnPanel(pre, parent, "orderRange") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Value = XRCCTRL(self, "Value") def strings(): pass tpclient-pywx-0.3.1.1/windows/xrc/orderPosition.py0000644000175000017500000000240610773624641020361 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class orderPositionBase(wx.Panel): xrc = os.path.join(location(), "windows", "xrc", 'orderPosition.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.PrePanel() res.LoadOnPanel(pre, parent, "orderPosition") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.X = XRCCTRL(self, "X") self.Y = XRCCTRL(self, "Y") self.Z = XRCCTRL(self, "Z") self.Locate = XRCCTRL(self, "Locate") if hasattr(self, "OnLocate"): self.Bind(wx.EVT_BUTTON, self.OnLocate, self.Locate) def strings(): pass _("P"); tpclient-pywx-0.3.1.1/windows/xrc/winUpdate.xrc0000644000175000017500000005517110773624641017634 0ustar timtim 600,600 TP: Universe update 1 2 0 0 0 1 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 14 swiss bold Sans wxGROW|wxGROW|wxALL 5 100,100 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 3 2 0 0 0,1 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 1 100 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 32,32 wxGROW|wxGROW|wxALL 5 2 2 0 0 1 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 1 100 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 32,32 wxGROW|wxGROW|wxALL 5 5,5 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 5 2 0 0 wxGROW|wxGROW|wxALL 5 wxVERTICAL wxALIGN_CENTER_HORIZONTAL|wxALL 5 32,32 wxALIGN_CENTER_HORIZONTAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 5 wxVERTICAL wxALIGN_CENTER_HORIZONTAL|wxALL 5 32,32 wxALIGN_CENTER_HORIZONTAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 5 wxVERTICAL wxALIGN_CENTER_HORIZONTAL|wxALL 5 32,32 wxALIGN_CENTER_HORIZONTAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 5 wxVERTICAL wxALIGN_CENTER_HORIZONTAL|wxALL 5 32,32 wxALIGN_CENTER_HORIZONTAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 5 wxVERTICAL wxALIGN_CENTER_HORIZONTAL|wxALL 5 32,32 wxALIGN_CENTER_HORIZONTAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 5 wxVERTICAL wxALIGN_CENTER_HORIZONTAL|wxALL 5 32,32 wxALIGN_CENTER_HORIZONTAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 5 wxVERTICAL wxALIGN_CENTER_HORIZONTAL|wxALL 5 32,32 wxALIGN_CENTER_HORIZONTAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 5 wxVERTICAL wxALIGN_CENTER_HORIZONTAL|wxALL 5 32,32 wxALIGN_CENTER_HORIZONTAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 5 wxVERTICAL wxALIGN_CENTER_HORIZONTAL|wxALL 5 32,32 wxALIGN_CENTER_HORIZONTAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 5 wxVERTICAL wxALIGN_CENTER_HORIZONTAL|wxALL 5 32,32 wxALIGN_CENTER_HORIZONTAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 5 wxVERTICAL wxALIGN_CENTER_HORIZONTAL|wxALL 5 32,32 wxALIGN_CENTER_HORIZONTAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 5 wxVERTICAL wxALIGN_CENTER_HORIZONTAL|wxALL 5 32,32 wxALIGN_CENTER_HORIZONTAL|wxALL|wxADJUST_MINSIZE 5 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL 5 wxHORIZONTAL wxALIGN_CENTER_VERTICAL|wxALL 5 Continue to the main game window. 1 wxALIGN_CENTER_VERTICAL|wxALL 5 Save a copy of the message box window to a file. wxALIGN_CENTER_VERTICAL|wxALL 5 Cancel the current update and go back to the connect screen. tpclient-pywx-0.3.1.1/windows/xrc/panelMessage.py0000644000175000017500000000506410773624641020130 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class panelMessageBase(wx.Panel): xrc = os.path.join(location(), "windows", "xrc", 'panelMessage.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.PrePanel() res.LoadOnPanel(pre, parent, "panelMessage") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Filter = XRCCTRL(self, "Filter") if hasattr(self, "OnFilter"): self.Bind(wx.EVT_BUTTON, self.OnFilter, self.Filter) self.Title = XRCCTRL(self, "Title") self.Counter = XRCCTRL(self, "Counter") self.Message = XRCCTRL(self, "Message") self.Prev = XRCCTRL(self, "Prev") if hasattr(self, "OnPrev"): self.Bind(wx.EVT_BUTTON, self.OnPrev, self.Prev) self.First = XRCCTRL(self, "First") if hasattr(self, "OnFirst"): self.Bind(wx.EVT_BUTTON, self.OnFirst, self.First) self.Goto = XRCCTRL(self, "Goto") if hasattr(self, "OnGoto"): self.Bind(wx.EVT_BUTTON, self.OnGoto, self.Goto) self.Next = XRCCTRL(self, "Next") if hasattr(self, "OnNext"): self.Bind(wx.EVT_BUTTON, self.OnNext, self.Next) self.Last = XRCCTRL(self, "Last") if hasattr(self, "OnLast"): self.Bind(wx.EVT_BUTTON, self.OnLast, self.Last) self.Delete = XRCCTRL(self, "Delete") if hasattr(self, "OnDelete"): self.Bind(wx.EVT_BUTTON, self.OnDelete, self.Delete) def strings(): pass _("Filter"); _("Static text"); _("100 of 100"); _("\n\n
\n\t\n\t\t\n\t\t\t\n\t\t\n\t\t\t\n\t\t\n\t
Subject: You are unloved!\n\t\t
\n\t\t\tYou have recived no messages this turn!

\n\t\t\tActually if you didn't recive any messages it most proberly\n\t\t\tmeans that your client couldn't load the results from the server.\n\t\t\tTry reload/restart the client.\n\t\t\t
\n
\n\n"); _("Prev"); _("First"); _("Goto"); _("Next"); _("Last"); _("Delete"); tpclient-pywx-0.3.1.1/windows/xrc/ServerBrowser.xrc0000644000175000017500000001156310773624641020503 0ustar timtim wxWS_EX_BLOCK_EVENTS 400,300 Thousand Parsec Server Browser 1 1 2 0 0 wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 12 swiss bold Sans wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 wxGROW|wxGROW|wxALL 5 1 2 0 0 0 wxGROW|wxGROW|wxALL 5 wxVERTICAL wxGROW|wxALL 5 100,100 List of all the servers registered on the metaserver. wxGROW|wxGROW|wxALL 5 wxVERTICAL wxGROW|wxALL 5 100,100 List of all the servers found on the local network. wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 wxHORIZONTAL wxALIGN_CENTER_VERTICAL|wxALL 5 Create a new account on the currently selected server. wxALIGN_CENTER_VERTICAL|wxALL 5 Connect to the currently selected server. tpclient-pywx-0.3.1.1/windows/xrc/orderObject.xrc0000644000175000017500000000123210773624641020123 0ustar timtim 8 normal 0 swiss Sans wxEXPAND|wxGROW 1 1 0 tpclient-pywx-0.3.1.1/windows/xrc/generate.sh0000755000175000017500000000007710773624641017302 0ustar timtim#! /bin/sh for xrc in *.xrc; do python generate.py $xrc done tpclient-pywx-0.3.1.1/windows/xrc/winAccount.py0000644000175000017500000000564610773624641017644 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class winAccountBase: xrc = os.path.join(location(), "windows", "xrc", 'winAccount.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Figure out what Frame class (MDI, MiniFrame, etc) is actually our base... bases = set() def findbases(klass, set): for base in klass.__bases__: set.add(base) findbases(base, set) findbases(self.__class__, bases) for base in bases: if base.__name__.endswith("Frame"): break # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = getattr(wx, "Pre%s" % base.__name__)() res.LoadOnFrame(pre, parent, "winAccount") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Panel = XRCCTRL(self, "Panel") self.Server = XRCCTRL(self, "Server") if hasattr(self, "OnServer"): self.Bind(wx.EVT_COMBOBOX, self.OnServer, self.Server) self.Bind(wx.EVT_TEXT_ENTER, self.OnServer, self.Server) if hasattr(self, "OnDirtyServer"): self.Bind(wx.EVT_TEXT, self.OnServer, self.Server) self.Checking = XRCCTRL(self, "Checking") self.Check = XRCCTRL(self, "Check") if hasattr(self, "OnCheck"): self.Bind(wx.EVT_BUTTON, self.OnCheck, self.Check) self.Username = XRCCTRL(self, "Username") self.GameShow = XRCCTRL(self, "GameShow") if hasattr(self, "OnGameShow"): self.Bind(wx.EVT_TOGGLEBUTTON, self.OnGameShow, self.GameShow) self.GameTitle = XRCCTRL(self, "GameTitle") self.Game = XRCCTRL(self, "Game") self.Password1 = XRCCTRL(self, "Password1") self.Password2 = XRCCTRL(self, "Password2") self.Email = XRCCTRL(self, "Email") self.Okay = XRCCTRL(self, "wxID_OK") if hasattr(self, "OnOkay"): self.Bind(wx.EVT_BUTTON, self.OnOkay, self.Okay) self.Cancel = XRCCTRL(self, "wxID_CANCEL") if hasattr(self, "OnCancel"): self.Bind(wx.EVT_BUTTON, self.OnCancel, self.Cancel) def strings(): pass _("TP: Connect to a Server"); _("Create an Account"); _("Server"); _("The URL for the Thousand Parsec server."); _("Choose a server to create an account on."); _("Check"); _("Username"); _("The username for the account on the Thousand Parsec server."); _("Show seperate game box."); _("G"); _("Game"); _("Password"); _("Choose your password here."); _(" "); _("Repeat the password"); _("Email "); _("Repeat the password"); _("&OK"); _("&Cancel"); tpclient-pywx-0.3.1.1/windows/xrc/winResourceSelect.xrc0000644000175000017500000000261710773624641021336 0ustar timtim wxVERTICAL wxALL|wxEXPAND|wxALIGN_CENTRE 150,200 wxALL|wxEXPAND|wxALIGN_CENTRE 0 20,20 1 2 0 0 1 wxALL|wxEXPAND|wxALIGN_CENTRE tpclient-pywx-0.3.1.1/windows/xrc/panelPicture.xrc0000644000175000017500000000656110773624641020326 0ustar timtim wxWS_EX_BLOCK_EVENTS 400,300 1 2 0 0 0 1 wxGROW|wxGROW|wxALL|wxADJUST_MINSIZE 0 wxGROW|wxGROW|wxALL 0 128,128 wxVERTICAL wxALIGN_CENTER_HORIZONTAL|wxALL 0 128,128 wxALIGN_LEFT|wxALL 0 128,128 3 2 0 0 0 wxALL|wxEXPAND|wxGROW 0 10,10 1 100 wxGROW|wxGROW|wxLEFT|wxRIGHT|wxADJUST_MINSIZE 3 -1,10 8 swiss Sans wxALIGN_RIGHT|wxGROW|wxLEFT|wxRIGHT|wxADJUST_MINSIZE 3 -1,10 8 swiss Sans wxEXPAND|wxGROW 3 tpclient-pywx-0.3.1.1/windows/xrc/winHelp.py0000644000175000017500000000405210773624641017126 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class winHelpBase: """\ Unlike a normal XRC generated class, this is a not a full class but a MixIn. Any class which uses this as a base must also inherit from a proper wx object such as the wx.Frame class. This is so that a the same XRC can be used for both MDI and non-MDI frames. """ xrc = os.path.join(location(), "windows", "xrc", 'winHelp.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Figure out what Frame class (MDI, MiniFrame, etc) is actually our base... bases = set() def findbases(klass, set): for base in klass.__bases__: set.add(base) findbases(base, set) findbases(self.__class__, bases) for base in bases: if base.__name__.endswith("Frame"): break # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = getattr(wx, "Pre%s" % base.__name__)() res.LoadOnFrame(pre, parent, "winHelp") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Subject = XRCCTRL(self, "Subject") self.Message = XRCCTRL(self, "Message") self.ShowAgain = XRCCTRL(self, "ShowAgain") if hasattr(self, "OnShowAgain"): self.Bind(wx.EVT_CHECKBOX, self.OnShowAgain, self.ShowAgain) self.Close = XRCCTRL(self, "wxID_CLOSE") if hasattr(self, "OnClose"): self.Bind(wx.EVT_BUTTON, self.OnClose, self.Close) def strings(): pass _("Important Information...."); _("Do not show this message again."); _("&Close"); _("Help"); tpclient-pywx-0.3.1.1/windows/xrc/tp.xrc0000644000175000017500000006052210773624641016313 0ustar timtim wxWIZARD_EX_HELPBUTTON Game Setup Wizard wizard.png 0 8 0 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 12 swiss bold Sans wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 200,150 10 swiss Sans <p> This wizard will walk you through setting up a temporary Thousand Parsec server on your local machine. </p><p> If you would like people to access the game while you are not running this client you CAN NOT use this wizard. Instead follow the instructions found at <a href="http://www.thousandparsec.net/tp/gettingstarted.php#server">here</a>. </p><p> You can load an old game or start a new game. </p> wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 5,5 wxGROW|wxALIGN_CENTER_VERTICAL|wxALL 5 0 0 &Start New Game &Load Existing Game 1 6 0 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 12 swiss bold Sans wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 wxGROW|wxGROW|wxALL|wxADJUST_MINSIZE 5 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 5,5 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 0 0 &Test Game 1 &Test Game 2 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL 5 1 6 0 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 12 swiss bold Sans wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 wxGROW|wxGROW|wxALL|wxADJUST_MINSIZE 5 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 5,5 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 0 0 &Test Ruleset 1 &Test Ruleset 2 1 6 0 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 12 swiss bold Sans wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 wxGROW|wxGROW|wxALL|wxADJUST_MINSIZE 5 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 5,5 wxGROW|wxGROW|wxALL 5 2 0 0 0 1 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 5,5 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL 5 wxHORIZONTAL wxALIGN_CENTER_VERTICAL|wxALL 5 Connect to the newly created server. wxALIGN_CENTER_VERTICAL|wxALL 5 Create a new account on the newly created server. wxWS_EX_BLOCK_EVENTS 400,300 Thousand Parsec Server Browser 1 1 2 0 0 wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 12 swiss bold Sans wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 wxGROW|wxGROW|wxALL 5 1 2 0 0 0 wxGROW|wxGROW|wxALL 5 wxVERTICAL wxGROW|wxALL 5 100,100 List of all the servers registered on the metaserver. wxGROW|wxGROW|wxALL 5 wxVERTICAL wxGROW|wxALL 5 100,100 List of all the servers found on the local network. wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 wxHORIZONTAL wxALIGN_CENTER_VERTICAL|wxALL 5 Create a new account on the currently selected server. wxALIGN_CENTER_VERTICAL|wxALL 5 Connect to the currently selected server. wxWS_EX_BLOCK_EVENTS 400,300 Dialog 1 2 2 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 2 1 0 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL 0 20,-1 Filter messages using this message as a template. wxGROW|wxALIGN_CENTER_VERTICAL|wxALL 5 100,100 Boards avaliable on the server. wxGROW|wxGROW|wxALL 5 1 2 0 0 wxGROW|wxGROW|wxALL 5 200,150 <html> <body> <center> <table cols=1 width="100%" background=""> <tr> <td><b>Subject:</b> Subject goes here!</td> </tr> <tr> <td>A really cool message body should go here.</td> </tr> </table> </center> </body> </html> wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 wxHORIZONTAL wxALIGN_CENTER_VERTICAL|wxALL 5 Create a new message on the current board. wxALIGN_CENTER_VERTICAL|wxALL 5 Goto objects referenced by this message. wxALIGN_CENTER_VERTICAL|wxALL 5 Delete this message. tpclient-pywx-0.3.1.1/windows/xrc/panelInformation.py0000644000175000017500000000223310773624641021024 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class panelInformationBase(wx.Panel): xrc = os.path.join(location(), "windows", "xrc", 'panelInformation.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.PrePanel() res.LoadOnPanel(pre, parent, "panelInformation") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Title = XRCCTRL(self, "Title") self.Details = XRCCTRL(self, "Details") def strings(): pass _("Name of object goes here"); tpclient-pywx-0.3.1.1/windows/xrc/winDesign.xrc0000644000175000017500000002776010773624641017626 0ustar timtim Design 3 2 wxALL|wxEXPAND|wxGROW wxALL|wxEXPAND|wxGROW|wxALIGN_CENTRE 1 Title wxALL|wxEXPAND|wxGROW|wxALIGN_CENTRE 1 wxALL|wxEXPAND|wxGROW|wxALIGN_RIGHT 1 wxHORIZONTAL wxALL|wxEXPAND|wxGROW|wxALIGN_CENTRE 1 wxALL|wxEXPAND|wxGROW wxALL|wxEXPAND|wxGROW|wxALIGN_CENTRE 1 1 1 0 0 wxALL|wxEXPAND|wxGROW|wxALIGN_CENTRE 1 200, 0 wxALL|wxEXPAND|wxGROW|wxALIGN_CENTRE 0 wxALL|wxEXPAND|wxGROW wxVERTICAL wxVERTICAL 2 2 5 1 wxALL|wxEXPAND|wxGROW wxALL|wxGROW|wxALIGN_CENTRE 1 250, 300 2 1 0 0 1 wxALL|wxEXPAND|wxGROW|wxALIGN_CENTRE 0,0 wxALL|wxEXPAND|wxGROW|wxALIGN_CENTRE 1 wxALL|wxEXPAND|wxGROW|wxALIGN_CENTRE 1 wxALL|wxEXPAND|wxGROW|wxALIGN_CENTRE 1 wxALL|wxEXPAND|wxGROW|wxALIGN_CENTRE 1 wxALL|wxEXPAND|wxGROW|wxALIGN_CENTRE 1 6 1 wxALL|wxEXPAND|wxGROW 1 0 1 wxALL|wxEXPAND|wxGROW|wxALIGN_LEFT 1 500, 0 wxALL|wxGROW|wxALIGN_RIGHT 1 200, 400 wxALL|wxEXPAND|wxGROW|wxALIGN_RIGHT 1 wxALL|wxEXPAND|wxGROW|wxALIGN_RIGHT 1 2 1 wxALL|wxEXPAND|wxGROW 1 4 0 0 wxALL|wxEXPAND|wxGROW|wxALIGN_CENTRE 1 1 900, 500 tpclient-pywx-0.3.1.1/windows/xrc/orderText.py0000644000175000017500000000207510773624641017503 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class orderTextBase(wx.Panel): xrc = os.path.join(location(), "windows", "xrc", 'orderText.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.PrePanel() res.LoadOnPanel(pre, parent, "orderText") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Value = XRCCTRL(self, "Value") def strings(): pass tpclient-pywx-0.3.1.1/windows/xrc/winDesign.py0000644000175000017500000000711610773624641017453 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class winDesignBase: xrc = os.path.join(location(), "windows", "xrc", 'winDesign.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Figure out what Frame class (MDI, MiniFrame, etc) is actually our base... bases = set() def findbases(klass, set): for base in klass.__bases__: set.add(base) findbases(base, set) findbases(self.__class__, bases) for base in bases: if base.__name__.endswith("Frame"): break # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = getattr(wx, "Pre%s" % base.__name__)() res.LoadOnFrame(pre, parent, "winDesign") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Panel = XRCCTRL(self, "Panel") self.DesignsSearch = XRCCTRL(self, "DesignsSearch") self.TitlePanel = XRCCTRL(self, "TitlePanel") self.TitleStatic = XRCCTRL(self, "TitleStatic") self.TitleEditable = XRCCTRL(self, "TitleEditable") self.Used = XRCCTRL(self, "Used") self.ComponentsSearch = XRCCTRL(self, "ComponentsSearch") self.DesignsPanel = XRCCTRL(self, "DesignsPanel") self.DesignsTree = XRCCTRL(self, "DesignsTree") self.DesignPanel = XRCCTRL(self, "DesignPanel") self.Categories = XRCCTRL(self, "Categories") self.DesignInfoPanel = XRCCTRL(self, "DesignInfoPanel") self.PartsList = XRCCTRL(self, "PartsList") self.DesignProperties = XRCCTRL(self, "DesignProperties") self.DesignPropertyGroup1 = XRCCTRL(self, "DesignPropertyGroup1") self.DesignButtonsPanel = XRCCTRL(self, "DesignButtonsPanel") self.Edit = XRCCTRL(self, "Edit") if hasattr(self, "OnEdit"): self.Bind(wx.EVT_BUTTON, self.OnEdit, self.Edit) self.Duplicate = XRCCTRL(self, "Duplicate") if hasattr(self, "OnDuplicate"): self.Bind(wx.EVT_BUTTON, self.OnDuplicate, self.Duplicate) self.Delete = XRCCTRL(self, "Delete") if hasattr(self, "OnDelete"): self.Bind(wx.EVT_BUTTON, self.OnDelete, self.Delete) self.Revert = XRCCTRL(self, "Revert") if hasattr(self, "OnRevert"): self.Bind(wx.EVT_BUTTON, self.OnRevert, self.Revert) self.Save = XRCCTRL(self, "Save") if hasattr(self, "OnSave"): self.Bind(wx.EVT_BUTTON, self.OnSave, self.Save) self.ComponentsPanel = XRCCTRL(self, "ComponentsPanel") self.ComponentsTree = XRCCTRL(self, "ComponentsTree") self.ComponentsButtonPanel = XRCCTRL(self, "ComponentsButtonPanel") self.ComponentsAdd = XRCCTRL(self, "ComponentsAdd") if hasattr(self, "OnComponentsAdd"): self.Bind(wx.EVT_BUTTON, self.OnComponentsAdd, self.ComponentsAdd) self.ComponentsAddMany = XRCCTRL(self, "ComponentsAddMany") if hasattr(self, "OnComponentsAddMany"): self.Bind(wx.EVT_BUTTON, self.OnComponentsAddMany, self.ComponentsAddMany) def strings(): pass _("Design"); _("Title"); _("Title"); _("0000"); _("Some Categories, Will Go, Here"); _("Property 1:"); _("The value of property 1"); _("Property 2:"); _("The value of property 2"); _("Edit"); _("Duplicate"); _("Delete"); _("Revert"); _("Save"); _("Add"); _("Add Many"); tpclient-pywx-0.3.1.1/windows/xrc/winAccount.xrc0000644000175000017500000002562210773624641020004 0ustar timtim 400,240 TP: Connect to a Server 1 3 0 0 0 wxGROW|wxGROW|wxALL|wxADJUST_MINSIZE 5 14 swiss bold Sans wxGROW|wxGROW|wxALL 5 2 2 0 0 1 0,1,2 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 0 wxHORIZONTAL wxGROW|wxALL 0 The URL for the Thousand Parsec server. wxALIGN_CENTER_VERTICAL|wxALL 0 32,32 Choose a server to create an account on. 1 wxALIGN_CENTER_VERTICAL|wxALL 0 50,32 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxGROW|wxALL 0 2 2 0 0 0 wxGROW|wxGROW|wxALL 1 The username for the account on the Thousand Parsec server. 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 0 25,25 Show seperate game box. 0 0 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 1 wxGROW|wxALIGN_CENTER_VERTICAL|wxALL 1 1 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxALIGN_CENTER_VERTICAL|wxALL 1 Choose your password here. 0 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxALIGN_CENTER_VERTICAL|wxALL 1 Repeat the password 0 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxGROW|wxALIGN_CENTER_VERTICAL|wxALL 1 280,-1 Repeat the password 0 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL 3 wxALIGN_CENTER_HORIZONTAL|wxLEFT|wxBOTTOM 5 0 1 wxALIGN_RIGHT|wxBOTTOM 5 tpclient-pywx-0.3.1.1/windows/xrc/winResourceSelect.py0000644000175000017500000000362010773624641021165 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class ResourceSelectBase: """\ Unlike a normal XRC generated class, this is a not a full class but a MixIn. Any class which uses this as a base must also inherit from a proper wx object such as the wx.Frame class. This is so that a the same XRC can be used for both MDI and non-MDI frames. """ xrc = os.path.join(location(), "windows", "xrc", 'winResourceSelect.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Figure out what Frame class (MDI, MiniFrame, etc) is actually our base... bases = set() def findbases(klass, set): for base in klass.__bases__: set.add(base) findbases(base, set) findbases(self.__class__, bases) for base in bases: if base.__name__.endswith("Frame"): break # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = getattr(wx, "Pre%s" % base.__name__)() res.LoadOnFrame(pre, parent, "ResourceSelect") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.RsrcSelectPanel = XRCCTRL(self, "RsrcSelectPanel") self.Panel = XRCCTRL(self, "Panel") self.ResourceList = XRCCTRL(self, "ResourceList") self.Done = XRCCTRL(self, "Done") if hasattr(self, "OnDone"): self.Bind(wx.EVT_BUTTON, self.OnDone, self.Done) def strings(): pass _("Done"); tpclient-pywx-0.3.1.1/windows/xrc/orderObject.py0000644000175000017500000000222310773624641017760 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class orderObjectBase(wx.Panel): xrc = os.path.join(location(), "windows", "xrc", 'orderObject.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.PrePanel() res.LoadOnPanel(pre, parent, "orderObject") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Value = XRCCTRL(self, "Value") if hasattr(self, "OnValue"): self.Value.Bind(wx.EVT_CHOICE, self.OnValue) def strings(): pass tpclient-pywx-0.3.1.1/windows/xrc/generate.py0000644000175000017500000002176110773624641017320 0ustar timtim# This script generates boilerplate classes out of an XRC resource file. # For each top-level windows (Panel, Frame or Dialog) a class is generated # and all the controls become attributes of the class. import sys import re import os from xml.dom import minidom # --------------------------- Template definitions -------------------------- fileHeaderTemplate = """\ # This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location """ frameTemplate = """\ class %(windowName)sBase: \"\"\"\\ Unlike a normal XRC generated class, this is a not a full class but a MixIn. Any class which uses this as a base must also inherit from a proper wx object such as the wx.Frame class. This is so that a the same XRC can be used for both MDI and non-MDI frames. \"\"\" xrc = os.path.join(location(), "windows", "xrc", '%(fileName)s') def PreCreate(self, pre): \"\"\" This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().\"\"\" pass def __init__(self, parent, *args, **kw): \"\"\" Pass an initialized wx.xrc.XmlResource into res \"\"\" f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Figure out what Frame class (MDI, MiniFrame, etc) is actually our base... bases = set() def findbases(klass, set): for base in klass.__bases__: set.add(base) findbases(base, set) findbases(self.__class__, bases) for base in bases: if base.__name__.endswith("Frame"): break # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = getattr(wx, "Pre%%s" %% base.__name__)() res.LoadOnFrame(pre, parent, "%(windowName)s") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls""" panelTemplate = """\ class %(windowName)sBase(wx.Panel): xrc = os.path.join(location(), "windows", "xrc", '%(fileName)s') def PreCreate(self, pre): \"\"\" This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().\"\"\" pass def __init__(self, parent, *args, **kw): \"\"\" Pass an initialized wx.xrc.XmlResource into res \"\"\" f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.PrePanel() res.LoadOnPanel(pre, parent, "%(windowName)s") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls""" IDmap = { "wxID_CANCEL": "Cancel", "wxID_CLOSE": "Close", "wxID_SAVE": "Save", "wxID_SAVEAS": "SaveAs", "wxID_NEW": "New", "wxID_OK": "Okay", "wxID_FIND": "Find", "wxID_REFRESH": "Refresh", "wxID_PREFERENCES": "Config", } Template_Default = """\ self.%(controlName)s = XRCCTRL(self, "%(controlID)s")""" Template_Button = """\ self.%(controlName)s = XRCCTRL(self, "%(controlID)s") if hasattr(self, "On%(controlName)s"): self.Bind(wx.EVT_BUTTON, self.On%(controlName)s, self.%(controlName)s) """ Template_CheckBox = """\ self.%(controlName)s = XRCCTRL(self, "%(controlID)s") if hasattr(self, "On%(controlName)s"): self.Bind(wx.EVT_CHECKBOX, self.On%(controlName)s, self.%(controlName)s) """ Template_ToggleButton = """\ self.%(controlName)s = XRCCTRL(self, "%(controlID)s") if hasattr(self, "On%(controlName)s"): self.Bind(wx.EVT_TOGGLEBUTTON, self.On%(controlName)s, self.%(controlName)s) """ Template_BitmapButton = Template_Button Template_ComboBox = """\ self.%(controlName)s = XRCCTRL(self, "%(controlID)s") if hasattr(self, "On%(controlName)s"): self.Bind(wx.EVT_COMBOBOX, self.On%(controlName)s, self.%(controlName)s) self.Bind(wx.EVT_TEXT_ENTER, self.On%(controlName)s, self.%(controlName)s) if hasattr(self, "OnDirty%(controlName)s"): self.Bind(wx.EVT_TEXT, self.On%(controlName)s, self.%(controlName)s) """ Template_Choice = """\ self.%(controlName)s = XRCCTRL(self, "%(controlID)s") if hasattr(self, "On%(controlName)s"): self.%(controlName)s.Bind(wx.EVT_CHOICE, self.On%(controlName)s) """ def Generate_wxFrame(xrcFile, topWindow, outFile): fileName = os.path.basename(xrcFile.name) windowClass = topWindow.getAttribute("subclass") if len(windowClass) == 0: windowClass = topWindow.getAttribute("class") windowClass = re.sub("^wx", "wx.", windowClass) windowName = topWindow.getAttribute("name") print "'%s' is a '%s'"% (windowName, windowClass) print >> outFile, frameTemplate % locals() eventFunctions = [] # a list to store the code for the event functions # Generate a variable for each control, and standard event handlers # for standard controls. for control in topWindow.getElementsByTagName("object"): controlClass = control.getAttribute("class") controlClass = re.sub("^wx", "wx.", controlClass) controlName = control.getAttribute("name") # Ignore anything which is still got a wx name... if controlName in IDmap: controlID = controlName controlName = IDmap[controlName] else: controlID = controlName if "wx" in controlName: continue if controlName != "" and controlClass != "": print '\t', controlName, (3-(len(controlName)+1)/8)*'\t', "is a", controlClass try: template = globals()["Template_%s" % controlClass.replace('wx.', '')] except KeyError: template = globals()["Template_Default"] print >> outFile, template % locals() print >> outFile print >> outFile, "\n".join(eventFunctions) def Generate_wxPanel(xrcFile, topWindow, outFile): fileName = os.path.basename(xrcFile.name) windowClass = topWindow.getAttribute("subclass") if len(windowClass) == 0: windowClass = topWindow.getAttribute("class") windowClass = re.sub("^wx", "wx.", windowClass) windowName = topWindow.getAttribute("name") print "'%s' is a '%s'"% (windowName, windowClass) print >> outFile, panelTemplate % locals() eventFunctions = [] # a list to store the code for the event functions # Generate a variable for each control, and standard event handlers # for standard controls. for control in topWindow.getElementsByTagName("object"): controlClass = control.getAttribute("class") controlClass = re.sub("^wx", "wx.", controlClass) controlName = control.getAttribute("name") # Ignore anything which is still got a wx name... if controlName in IDmap: controlID = controlName controlName = IDmap[controlName] else: controlID = controlName if "wx" in controlName: continue if controlName != "" and controlClass != "": print '\t', controlName, (3-(len(controlName)+1)/8)*'\t', "is a", controlClass try: template = globals()["Template_%s" % controlClass.replace('wx.', '')] except KeyError: template = globals()["Template_Default"] print >> outFile, template % locals() print >> outFile print >> outFile, "\n".join(eventFunctions) #Generate_wxWizard = Generate_wxDialog # ------------------------- GeneratePythonForXRC ---------------------------- def GeneratePython(xrcFile, outFile): xmldoc = minidom.parse(xrcFile) resource = xmldoc.childNodes[0] topWindows = [e for e in resource.childNodes if e.nodeType == e.ELEMENT_NODE and e.tagName == "object"] print >> outFile, fileHeaderTemplate # Generate a class for each top-window object (Frame, Panel, Dialog, etc.) for topWindow in topWindows: # Figure out if this is a Panel, Frame or Wizard windowClass = topWindow.getAttribute("class") windowName = topWindow.getAttribute("name") globals()["Generate_"+windowClass](xrcFile, topWindow, outFile) # --------------------- Main ---------------- def Usage(): print """ xrcpy -- Python boilerplate code generator for XRC resources. Usage : python pyxrc.py The Python code is printed to the standard output. """ from wx.tools.pywxrc import XmlResourceCompiler def main(): if len(sys.argv) != 2: Usage() else: inFilename = sys.argv[1] outFilename = os.path.splitext(inFilename)[0] + ".py" try: inStream = file(inFilename) try: outStream = file(outFilename, "w") except IOError: print >> sys.stderr, "Can't open '%s'!" % outFilename else: GeneratePython(inStream, outStream) comp = XmlResourceCompiler() comp.MakeGetTextOutput([inFilename], '.translation') transStream = file('.translation', 'r') outStream.write('def strings():\n') outStream.write('\tpass\n') outStream.write(transStream.read().replace('_(', '\t_(')) transStream.close() os.unlink('.translation') print "Result stored in %s." % outFilename except IOError: print >> sys.stderr, "Can't open '%s'!" % inFilename except KeyError, e: print >> sys.stderr, "There was an error outputting .py file for '%s'" % inFilename print >> sys.stderr, "No such key %s" % e os.unlink(outFilename) print >> sys.stderr if __name__ == "__main__": main() tpclient-pywx-0.3.1.1/windows/xrc/panelStarMap.xrc0000644000175000017500000000661110773624641020256 0ustar timtim 1 2 1 1 wxALIGN_CENTRE_VERTICAL|wxALIGN_CENTRE_HORIZONTAL Fit 80% 50% 10% Box wxEXPAND|wxALIGN_CENTRE_VERTICAL|wxALIGN_CENTRE_HORIZONTAL 8 wxTOP|wxBOTTOM|wxEXPAND 4 wxALIGN_CENTRE_VERTICAL|wxALIGN_CENTRE_HORIZONTAL wxALIGN_CENTRE_VERTICAL|wxALIGN_CENTRE_HORIZONTAL 8 wxTOP|wxBOTTOM|wxEXPAND 4 System Resources wxEXPAND|wxGROW|wxALIGN_CENTRE_VERTICAL|wxALIGN_CENTRE_HORIZONTAL 1 1 0 0 wxEXPAND 8 1 7 wxEXPAND 0 #1A1A1A wxEXPAND 1 0 tpclient-pywx-0.3.1.1/windows/xrc/tp.pjd0000644000175000017500000302264310773624641016301 0ustar timtim
1 "" "" "" "" 279 "tp.xrc" 0 0 0 0 0 0 "Tim Ansell" "GPL" "" 0 0 "<All platforms>" "<Any>" "///////////////////////////////////////////////////////////////////////////// // Name: %HEADER-FILENAME% // Purpose: // Author: %AUTHOR% // Modified by: // Created: %DATE% // RCS-ID: // Copyright: %COPYRIGHT% // Licence: ///////////////////////////////////////////////////////////////////////////// " "///////////////////////////////////////////////////////////////////////////// // Name: %SOURCE-FILENAME% // Purpose: // Author: %AUTHOR% // Modified by: // Created: %DATE% // RCS-ID: // Copyright: %COPYRIGHT% // Licence: ///////////////////////////////////////////////////////////////////////////// " " /*! * %BODY% */ " "///////////////////////////////////////////////////////////////////////////// // Name: %SYMBOLS-FILENAME% // Purpose: Symbols file // Author: %AUTHOR% // Modified by: // Created: %DATE% // RCS-ID: // Copyright: %COPYRIGHT% // Licence: ///////////////////////////////////////////////////////////////////////////// " "#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma interface "%HEADER-FILENAME%" #endif " "#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "%HEADER-FILENAME%" #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ #pragma hdrstop #endif #ifndef WX_PRECOMP #include "wx/wx.h" #endif " "app_resources.h" "app_resources.cpp" "AppResources" "app.h" "app.cpp" "Application" 0 "" "<None>" "utf-8" "utf-8" "" 0 1 4 " " "" 0 0 1 1 1 1
"" "data-document" "" "" 0 1 0 0 "Configurations" "config-data-document" "" "" 0 1 0 0 "" 1 "" "Debug" "ANSI" "Static" "Modular" "GUI" "wxGTK+2" "Dynamic" "Yes" "No" "No" "%WXVERSION%" "%EXECUTABLE%" "" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "%AUTO%" "Thousand Parsec" "root-document" "" "project" 1 1 0 0 "Windows" "html-document" "" "dialogsfolder" 1 1 0 1 "GameServerSetup" "dialog-document" "" "wizarddialog" 0 1 0 0 "8/12/2006" "wbWizardProxy" 10000 0 "" 0 "wxEVT_WIZARD_CANCEL|OnWinGameSetupWizardCancel" "winGameSetupWizard" -1 "GameSetupWizard" "wxWizard" "GameServerSetup.cpp" "" "GameSetupWizard.xrc" "Game Setup Wizard" "wizard.png" 1 "" "" "" "" "" "" 0 1 "<Any platform>" 1 1 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" 0 1 "WizardPage: Start" "dialog-control-document" "" "panel" 0 1 0 0 "8/12/2006" "wbWizardPageProxy" "wxEVT_WIZARD_PAGE_CHANGED|OnStartPageChanged" "Start" 10000 "WizardPage" "wxWizardPageSimple" "wxWizardPageSimple" 0 "" "" "" "" "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 0 1 0 "" 1 -1 -1 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "8/12/2006" "wbFlexGridSizerProxy" "0" "" 0 8 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "8/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Setup a Thousand Parsec Game" -1 "" "" "" "" "12, wxSWISS, wxNORMAL, wxBOLD, false, Sans" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxStaticLine: wxID_STATIC" "dialog-control-document" "" "staticline" 0 1 0 0 "8/12/2006" "wbStaticLineProxy" "wxID_STATIC" 5105 "wxStaticLine" "" "" "" "" 0 1 "<Any platform>" 1 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 0 5 1 1 1 1 0 0 0 "wxHtmlWindow: Message" "dialog-control-document" "" "htmlwindow" 0 1 0 0 "8/12/2006" "wbHtmlWindowProxy" "Message" -1 "wxHtmlWindow" "" "" "<p> This wizard will walk you through setting up a temporary Thousand Parsec server on your local machine. </p><p> If you would like people to access the game while you are not running this client you CAN NOT use this wizard. Instead follow the instructions found at <a href="http://www.thousandparsec.net/tp/gettingstarted.php#server">here</a>. </p><p> You can load an old game or start a new game. </p>" "" "" "" "" "10, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 0 1 "<Any platform>" "" "" 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 200 150 "Centre" "Expand" 0 5 1 1 1 1 0 0 0 "" "" "Spacer" "dialog-control-document" "" "spacer" 0 1 0 0 "8/12/2006" "wbSpacerProxy" 5 5 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxRadioBox: TypeOfGame" "dialog-control-document" "" "radiobox" 0 1 0 0 "8/12/2006" "wbRadioBoxProxy" "TypeOfGame" -1 "wxRadioBox" "" "Would you like to?" 0 "&Start New Game|&Load Existing Game" 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "WizardPage1: Load" "dialog-control-document" "" "panel" 0 1 0 0 "8/12/2006" "wbWizardPageProxy" "Load" -1 "WizardPage1" "wxWizardPageSimple" "wxWizardPageSimple" 0 "" "" "" "" "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 0 1 0 "" 1 -1 -1 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "8/12/2006" "wbFlexGridSizerProxy" "0" "" 1 6 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "8/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Please Select the Game to Load" -1 "" "" "" "" "12, wxSWISS, wxNORMAL, wxBOLD, false, Sans" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxStaticLine: wxID_STATIC" "dialog-control-document" "" "staticline" 0 1 0 0 "8/12/2006" "wbStaticLineProxy" "wxID_STATIC" 5105 "wxStaticLine" "" "" "" "" 0 1 "<Any platform>" 1 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 0 5 1 1 1 1 0 0 0 "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "8/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Below is listed all the games the client has found on this computer. If your game is not listed here try finding the game using the Browse button. " 400 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 5 1 1 1 1 0 1 0 "" "" "Spacer" "dialog-control-document" "" "spacer" 0 1 0 0 "8/12/2006" "wbSpacerProxy" 5 5 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxRadioBox: Games" "dialog-control-document" "" "radiobox" 0 1 0 0 "8/12/2006" "wbRadioBoxProxy" "Games" -1 "wxRadioBox" "" "Please select a game to load:" 0 "&Test Game 1|&Test Game 2" 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 1 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 0 5 1 1 1 1 0 0 0 "" "" "wxButton: Browse" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "8/12/2006" "wbButtonProxy" "Browse" -1 "wxButton" "" "Browse" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "WizardPage3: NewRuleset" "dialog-control-document" "" "panel" 0 1 0 0 "8/12/2006" "wbWizardPageProxy" "NewRuleset" 10011 "WizardPage3" "wxWizardPageSimple" "wxWizardPageSimple" 0 "" "" "" "" "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 0 1 0 "" 1 -1 -1 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "8/12/2006" "wbFlexGridSizerProxy" "0" "" 1 6 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "8/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Please select the Ruleset to use" -1 "" "" "" "" "12, wxSWISS, wxNORMAL, wxBOLD, false, Sans" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxStaticLine: wxID_STATIC" "dialog-control-document" "" "staticline" 0 1 0 0 "8/12/2006" "wbStaticLineProxy" "wxID_STATIC" 5105 "wxStaticLine" "" "" "" "" 0 1 "<Any platform>" 1 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 0 5 1 1 1 1 0 0 0 "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "8/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Below is listed all the rulesets supported by the server. You need to choose which ruleset to use for this game. Each ruleset can be completely different game play and structure. For more rulesets you can checkout the Thousand Parsec website." 400 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 5 1 1 1 1 0 1 0 "" "" "Spacer" "dialog-control-document" "" "spacer" 0 1 0 0 "8/12/2006" "wbSpacerProxy" 5 5 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxRadioBox: Rulesets" "dialog-control-document" "" "radiobox" 0 1 0 0 "8/12/2006" "wbRadioBoxProxy" "Rulesets" -1 "wxRadioBox" "" "Please select a ruleset to use:" 0 "&Test Ruleset 1|&Test Ruleset 2" 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 1 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 0 5 1 1 1 1 0 0 0 "" "" "WizardPage2: Completed" "dialog-control-document" "" "panel" 0 1 0 0 "8/12/2006" "wbWizardPageProxy" "Completed" 10007 "WizardPage2" "wxWizardPageSimple" "wxWizardPageSimple" 0 "" "" "" "" "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 0 1 0 "" 1 -1 -1 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "8/12/2006" "wbFlexGridSizerProxy" "0" "" 1 6 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "8/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Server Setup!" -1 "" "" "" "" "12, wxSWISS, wxNORMAL, wxBOLD, false, Sans" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxStaticLine: wxID_STATIC" "dialog-control-document" "" "staticline" 0 1 0 0 "8/12/2006" "wbStaticLineProxy" "wxID_STATIC" 5105 "wxStaticLine" "" "" "" "" 0 1 "<Any platform>" 1 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 0 5 1 1 1 1 0 0 0 "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "8/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "You have successfully setup a server and it is now running. The details of the server which you can give to your friends is given below. If your friends are on the local network this new server should appear in the server browser. You can either create a new account or connect to the server straight away." 400 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 5 1 1 1 1 0 1 0 "" "" "Spacer" "dialog-control-document" "" "spacer" 0 1 0 0 "8/12/2006" "wbSpacerProxy" 5 5 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "8/12/2006" "wbFlexGridSizerProxy" "1" "" 2 0 0 0 "" "<Any platform>" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "8/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Host URL:" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxTextCtrl: URL" "dialog-control-document" "" "textctrl" 0 1 0 0 "8/12/2006" "wbTextCtrlProxy" "URL" -1 "wxTextCtrl" "" "" 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 0 5 1 1 1 1 0 0 0 "" "" "Spacer" "dialog-control-document" "" "spacer" 0 1 0 0 "8/12/2006" "wbSpacerProxy" 5 5 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxBoxSizer H" "dialog-control-document" "" "sizer" 0 1 0 0 "8/12/2006" "wbBoxSizerProxy" "Horizontal" "" "Right" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxButton: Connect" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "8/12/2006" "wbButtonProxy" "Connect" -1 "wxButton" "" "Connect" 0 "" "Connect to the newly created server." "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "wxButton: NewAccount" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "8/12/2006" "wbButtonProxy" "NewAccount" -1 "wxButton" "" "New Account" 0 "" "Create a new account on the newly created server." "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "MessageBrowser" "dialog-document" "" "dialog" 0 1 0 0 "8/12/2006" "wbDialogProxy" 10000 0 "" 0 "winMessageBrowser" -1 "winReportBase" "wxDialog" "wxDialog" "" "" "MessageBrowser.xrc" "Dialog" 1 "" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 1 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 "" 0 1 -1 -1 400 300 "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "8/12/2006" "wbFlexGridSizerProxy" "" "" 2 2 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "8/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Boards" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "8/12/2006" "wbFlexGridSizerProxy" "0" "" 2 1 0 0 "" "<Any platform>" "Centre" "Expand" 0 5 1 1 1 1 0 0 0 "wxStaticText: BoardName" "dialog-control-document" "" "statictext" 0 1 0 0 "8/12/2006" "wbStaticTextProxy" "BoardName" 10023 "wxStaticText" "" "Board Name" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxButton: Filter" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "8/12/2006" "wbButtonProxy" "Filter" -1 "wxButton" "" "F" 0 "" "Filter messages using this message as a template." "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 20 -1 "Right" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxTreeCtrl: Boards" "dialog-control-document" "" "treectrl" 0 1 0 0 "8/12/2006" "wbTreeCtrlProxy" "Boards" 10018 "wxTreeCtrl" "" "" "Boards avaliable on the server." "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 100 100 "Expand" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "8/12/2006" "wbFlexGridSizerProxy" "" "" 1 2 0 0 "" "<Any platform>" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "wxHtmlWindow: Message" "dialog-control-document" "" "htmlwindow" 0 1 0 0 "8/12/2006" "wbHtmlWindowProxy" "Message" 10019 "wxHtmlWindow" "" "" "<html> <body> <center> <table cols=1 width="100%" background=""> <tr> <td><b>Subject:</b> Subject goes here!</td> </tr> <tr> <td>A really cool message body should go here.</td> </tr> </table> </center> </body> </html>" "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 1 0 0 0 0 1 0 0 0 0 0 0 1 1 0 "" -1 -1 200 150 "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "" "" "wxBoxSizer H" "dialog-control-document" "" "sizer" 0 1 0 0 "8/12/2006" "wbBoxSizerProxy" "Horizontal" "" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxButton: New" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "8/12/2006" "wbButtonProxy" "New" -1 "wxButton" "" "New" 0 "" "Create a new message on the current board." "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "wxButton: Goto" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "8/12/2006" "wbButtonProxy" "Goto" -1 "wxButton" "" "Goto" 0 "" "Goto objects referenced by this message." "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "wxButton: Delete" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "8/12/2006" "wbButtonProxy" "Delete" -1 "wxButton" "" "Delete" 0 "" "Delete this message." "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "winUpdate" "dialog-document" "" "frame" 0 1 0 0 "21/12/2006" "wbFrameProxy" 10000 0 "" 0 "winUpdate" -1 "wxFrame" "wxFrame" "" "" "winUpdate.xrc" "TP: Downloading Universe" 1 "" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" 0 1 -1 -1 600 600 "" "wxPanel: Panel" "dialog-control-document" "" "panel" 0 1 0 0 "21/12/2006" "wbPanelProxy" "Panel" -1 "wxPanel" "wxPanel" "" 0 0 "" "" "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 "" 0 -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 0 1 "" "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "21/12/2006" "wbFlexGridSizerProxy" "0" "1" 1 2 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxStaticText: TopText" "dialog-control-document" "" "statictext" 0 1 0 0 "21/12/2006" "wbStaticTextProxy" "TopText" -1 "wxStaticText" "" "Universe Download" -1 "" "" "" "" "14, wxSWISS, wxNORMAL, wxBOLD, false, Sans" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxTextCtrl: Message" "dialog-control-document" "" "textctrl" 0 1 0 0 "21/12/2006" "wbTextCtrlProxy" "Message" -1 "wxTextCtrl" "" "" 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 "" -1 -1 100 100 "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "21/12/2006" "wbFlexGridSizerProxy" "0,1" "" 3 2 0 0 "" "<Any platform>" "Centre" "Expand" 0 5 1 1 1 1 0 0 0 "wxGauge: ConnectingGauge" "dialog-control-document" "" "gauge" 0 1 0 0 "21/12/2006" "wbGaugeProxy" "ConnectingGauge" -1 "wxGauge" "" 1 100 "" "" "" "" "" 0 1 "<Any platform>" "" "" 1 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 0 5 1 1 1 1 0 0 0 "" "" "wxStaticText: ConnectingText" "dialog-control-document" "" "statictext" 0 1 0 0 "26/12/2006" "wbStaticTextProxy" "ConnectingText" -1 "wxStaticText" "" "Done!" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxGIFAnimationCtrl: ConnectingAnim" "dialog-control-document" "" "foreign" 0 1 0 0 "21/12/2006" "wbForeignCtrlProxy" "ConnectingAnim" -1 "wxGIFAnimationCtrl" "wxStaticBitmap" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "21/12/2006" "wbFlexGridSizerProxy" "1" "" 2 2 0 0 "" "<Any platform>" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "wxStaticText: ProgressTitle" "dialog-control-document" "" "statictext" 0 1 0 0 "21/12/2006" "wbStaticTextProxy" "ProgressTitle" -1 "wxStaticText" "" "Progress" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 1 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxGauge: ProgressGauge" "dialog-control-document" "" "gauge" 0 1 0 0 "21/12/2006" "wbGaugeProxy" "ProgressGauge" 10027 "wxGauge" "" 1 100 "" "" "" "" "" 0 1 "<Any platform>" "" "" 1 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 0 5 1 1 1 1 0 0 0 "" "" "wxStaticText: ProgressText" "dialog-control-document" "" "statictext" 0 1 0 0 "26/12/2006" "wbStaticTextProxy" "ProgressText" -1 "wxStaticText" "" "Done!" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxGIFAnimationCtrl: ProgressAnim" "dialog-control-document" "" "foreign" 0 1 0 0 "21/12/2006" "wbForeignCtrlProxy" "ProgressAnim" -1 "wxGIFAnimationCtrl" "wxStaticBitmap" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "Spacer" "dialog-control-document" "" "spacer" 0 1 0 0 "21/12/2006" "wbSpacerProxy" 5 5 "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxGridSizerProxy" "dialog-control-document" "" "sizer" 0 1 0 0 "21/12/2006" "wbGridSizerProxy" 5 2 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxBoxSizer V" "dialog-control-document" "" "sizer" 0 1 0 0 "24/12/2006" "wbBoxSizerProxy" "Vertical" "" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxGIFAnimationCtrl: ObjectdescsAnim" "dialog-control-document" "" "foreign" 0 1 0 0 "24/12/2006" "wbForeignCtrlProxy" "ObjectdescsAnim" -1 "wxGIFAnimationCtrl" "wxStaticBitmap" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "24/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Objects Descs" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxBoxSizer V" "dialog-control-document" "" "sizer" 0 1 0 0 "24/12/2006" "wbBoxSizerProxy" "Vertical" "" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxGIFAnimationCtrl: OrderdescsAnim" "dialog-control-document" "" "foreign" 0 1 0 0 "24/12/2006" "wbForeignCtrlProxy" "OrderdescsAnim" -1 "wxGIFAnimationCtrl" "wxStaticBitmap" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "24/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Order Descs" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxBoxSizer V" "dialog-control-document" "" "sizer" 0 1 0 0 "21/12/2006" "wbBoxSizerProxy" "Vertical" "" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxGIFAnimationCtrl: ObjectsAnim" "dialog-control-document" "" "foreign" 0 1 0 0 "21/12/2006" "wbForeignCtrlProxy" "ObjectsAnim" -1 "wxGIFAnimationCtrl" "wxStaticBitmap" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Objects" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxBoxSizer V" "dialog-control-document" "" "sizer" 0 1 0 0 "21/12/2006" "wbBoxSizerProxy" "Vertical" "" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxGIFAnimationCtrl: OrdersAnim" "dialog-control-document" "" "foreign" 0 1 0 0 "21/12/2006" "wbForeignCtrlProxy" "OrdersAnim" -1 "wxGIFAnimationCtrl" "wxStaticBitmap" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Orders" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxBoxSizer V" "dialog-control-document" "" "sizer" 0 1 0 0 "21/12/2006" "wbBoxSizerProxy" "Vertical" "" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxGIFAnimationCtrl: BoardsAnim" "dialog-control-document" "" "foreign" 0 1 0 0 "21/12/2006" "wbForeignCtrlProxy" "BoardsAnim" -1 "wxGIFAnimationCtrl" "wxStaticBitmap" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Boards" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxBoxSizer V" "dialog-control-document" "" "sizer" 0 1 0 0 "21/12/2006" "wbBoxSizerProxy" "Vertical" "" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxGIFAnimationCtrl: MessagesAnim" "dialog-control-document" "" "foreign" 0 1 0 0 "21/12/2006" "wbForeignCtrlProxy" "MessagesAnim" -1 "wxGIFAnimationCtrl" "wxStaticBitmap" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Messages" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxBoxSizer V" "dialog-control-document" "" "sizer" 0 1 0 0 "21/12/2006" "wbBoxSizerProxy" "Vertical" "" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxGIFAnimationCtrl: CategoriesAnim" "dialog-control-document" "" "foreign" 0 1 0 0 "21/12/2006" "wbForeignCtrlProxy" "CategoriesAnim" -1 "wxGIFAnimationCtrl" "wxStaticBitmap" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Categories" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxBoxSizer V" "dialog-control-document" "" "sizer" 0 1 0 0 "21/12/2006" "wbBoxSizerProxy" "Vertical" "" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxGIFAnimationCtrl: DesignsAnim" "dialog-control-document" "" "foreign" 0 1 0 0 "21/12/2006" "wbForeignCtrlProxy" "DesignsAnim" -1 "wxGIFAnimationCtrl" "wxStaticBitmap" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Designs" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxBoxSizer V" "dialog-control-document" "" "sizer" 0 1 0 0 "21/12/2006" "wbBoxSizerProxy" "Vertical" "" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxGIFAnimationCtrl: ComponentsAnim" "dialog-control-document" "" "foreign" 0 1 0 0 "21/12/2006" "wbForeignCtrlProxy" "ComponentsAnim" -1 "wxGIFAnimationCtrl" "wxStaticBitmap" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Components" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxBoxSizer V" "dialog-control-document" "" "sizer" 0 1 0 0 "21/12/2006" "wbBoxSizerProxy" "Vertical" "" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxGIFAnimationCtrl: PropertiesAnim" "dialog-control-document" "" "foreign" 0 1 0 0 "21/12/2006" "wbForeignCtrlProxy" "PropertiesAnim" -1 "wxGIFAnimationCtrl" "wxStaticBitmap" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Properties" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxBoxSizer V" "dialog-control-document" "" "sizer" 0 1 0 0 "21/12/2006" "wbBoxSizerProxy" "Vertical" "" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxGIFAnimationCtrl: PlayersAnim" "dialog-control-document" "" "foreign" 0 1 0 0 "21/12/2006" "wbForeignCtrlProxy" "PlayersAnim" -1 "wxGIFAnimationCtrl" "wxStaticBitmap" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Players" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxBoxSizer V" "dialog-control-document" "" "sizer" 0 1 0 0 "21/12/2006" "wbBoxSizerProxy" "Vertical" "" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxGIFAnimationCtrl: ResourcesAnim" "dialog-control-document" "" "foreign" 0 1 0 0 "21/12/2006" "wbForeignCtrlProxy" "ResourcesAnim" -1 "wxGIFAnimationCtrl" "wxStaticBitmap" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Resources" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxBoxSizer H" "dialog-control-document" "" "sizer" 0 1 0 0 "21/12/2006" "wbBoxSizerProxy" "Horizontal" "" "Right" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxButton: wxID_OK" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "21/12/2006" "wbButtonProxy" "wxID_OK" 5100 "wxButton" "" "&OK" 1 "" "Continue to the main game window." "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "wxButton: wxID_SAVE" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "21/12/2006" "wbButtonProxy" "wxID_SAVE" 5003 "wxButton" "" "&Save" 0 "" "Save a copy of the message box window to a file." "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "wxButton: wxID_CANCEL" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "21/12/2006" "wbButtonProxy" "wxID_CANCEL" 5101 "wxButton" "" "&Cancel" 0 "" "Cancel the current update and go back to the connect screen." "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "winServerBrowser" "dialog-document" "" "frame" 0 1 0 0 "23/12/2006" "wbFrameProxy" 10000 0 "" 0 "winServerBrowser" -1 "Frame" "wxFrame" "" "" "winServerBrowser.xrc" "TP: Server Browser" 1 "" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" 0 1 -1 -1 800 450 "" "wxPanel: Panel" "dialog-control-document" "" "panel" 0 1 0 0 "23/12/2006" "wbPanelProxy" "Panel" -1 "wxPanel" "wxPanel" "" 0 0 "" "" "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 "" 1 -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "23/12/2006" "wbFlexGridSizerProxy" "0" "1" 1 2 0 0 "" "<Any platform>" "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "23/12/2006" "wbFlexGridSizerProxy" "0" "" 2 2 0 0 "" "<Any platform>" "Expand" "Expand" 0 0 1 1 1 1 0 0 0 "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "23/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Thousand Parsec Server Browser" -1 "" "" "" "" "14, wxSWISS, wxNORMAL, wxBOLD, false, Sans" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Left" "Bottom" 0 5 1 1 1 1 0 1 0 "" "" "wxGIFAnimationCtrl: Progress" "dialog-control-document" "" "foreign" 0 1 0 0 "23/12/2006" "wbForeignCtrlProxy" "Progress" -1 "wxGIFAnimationCtrl" "wxWindow" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 1 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Right" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "23/12/2006" "wbFlexGridSizerProxy" "0" "0" 1 2 0 0 "" "<Any platform>" "Expand" "Expand" 1 5 1 1 1 1 0 0 0 "wxStaticBoxSizer V" "dialog-control-document" "" "sizer" 0 1 0 0 "23/12/2006" "wbStaticBoxSizerProxy" "wxID_ANY" -1 "Servers" "" "" "10, wxSWISS, wxNORMAL, wxBOLD, false, Sans" 0 1 "Vertical" "" "Expand" "Expand" 1 5 1 1 0 1 0 0 0 "<Any platform>" "wxListCtrl: Servers" "dialog-control-document" "" "listctrl" 0 1 0 0 "23/12/2006" "wbListCtrlProxy" "Servers" -1 "wxListCtrl" "" "" "List of all the servers registered on the metaserver." "" "" "" 0 1 "<Any platform>" "" "" 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 100 100 "Expand" "Expand" 1 5 1 1 1 1 0 0 0 "" "" "wxPanel: LocationsPanel" "dialog-control-document" "" "panel" 0 1 0 0 "1/1/2007" "wbPanelProxy" "LocationsPanel" -1 "wxPanel" "wxPanel" "" 0 0 "" "" "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" 0 100 -1 -1 -1 "Expand" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxStaticBoxSizer V" "dialog-control-document" "" "sizer" 0 1 0 0 "1/1/2007" "wbStaticBoxSizerProxy" "LocationsBox" -1 "Locations" "" "" "10, wxSWISS, wxNORMAL, wxBOLD, false, Sans" 0 1 "Vertical" "" "Expand" "Expand" 0 5 1 1 0 0 0 0 0 "<Any platform>" "wxListCtrl: Locations" "dialog-control-document" "" "listctrl" 0 1 0 0 "1/1/2007" "wbListCtrlProxy" "Locations" -1 "wxListCtrl" "" "" "List of all the servers found on the local network." "" "" "" 0 1 "<Any platform>" "" "" 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 100 100 "Expand" "Expand" 1 5 1 1 1 1 0 0 0 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "23/12/2006" "wbFlexGridSizerProxy" "1" "" 3 2 0 0 "" "<Any platform>" "Expand" "Centre" 0 5 1 1 0 0 0 0 0 "wxStaticText: URLTitle" "dialog-control-document" "" "statictext" 0 1 0 0 "23/12/2006" "wbStaticTextProxy" "URLTitle" -1 "wxStaticText" "" "URL" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxTextCtrl: URL" "dialog-control-document" "" "textctrl" 0 1 0 0 "23/12/2006" "wbTextCtrlProxy" "URL" -1 "wxTextCtrl" "" "" 0 "" "URL of the currently selected server." "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "" "" "wxButton: wxID_COPY" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "23/12/2006" "wbButtonProxy" "wxID_COPY" 5031 "wxButton" "" "&Copy" 0 "" "Copy the URL to the clipboard." "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "23/12/2006" "wbFlexGridSizerProxy" "1" "" 5 1 0 0 "" "<Any platform>" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "wxButton: wxID_REFRESH" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "23/12/2006" "wbButtonProxy" "wxID_REFRESH" 5123 "wxButton" "" "&Refresh" 1 "" "Force a refresh of the server list." "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "Spacer" "dialog-control-document" "" "spacer" 0 1 0 0 "23/12/2006" "wbSpacerProxy" 5 5 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxButton: NewAccount" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "23/12/2006" "wbButtonProxy" "NewAccount" -1 "wxButton" "" "&New Account" 1 "" "Create a new account on the currently selected server." "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxButton: ConnectTo" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "23/12/2006" "wbButtonProxy" "ConnectTo" -1 "wxButton" "" "C&onnect" 0 "" "Connect to the currently selected server." "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxButton: wxID_CANCEL" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "23/12/2006" "wbButtonProxy" "wxID_CANCEL" 5101 "wxButton" "" "&Cancel" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "winConnect" "dialog-document" "" "frame" 0 1 0 0 "23/12/2006" "wbFrameProxy" 10000 0 "" 0 "winConnect" -1 "Frame" "wxFrame" "" "" "winConnect.xrc" "TP: Connect to a Server" 1 "" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" 0 0 -1 -1 400 180 "" "wxPanel: Panel" "dialog-control-document" "" "panel" 0 1 0 0 "23/12/2006" "wbPanelProxy" "Panel" -1 "wxPanel" "wxPanel" "" 0 0 "" "" "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 "" 1 -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "23/12/2006" "wbFlexGridSizerProxy" "0" "0" 1 3 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "23/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Connect to Thousand Parsec Server" -1 "" "" "" "" "14, wxSWISS, wxNORMAL, wxBOLD, false, Sans" 0 1 "<Any platform>" "" "" 0 0 1 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 1 5 1 1 1 1 0 1 0 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "23/12/2006" "wbFlexGridSizerProxy" "1" "0,1,2" 2 2 0 0 "" "<Any platform>" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "23/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Server" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxComboBox: Server" "dialog-control-document" "" "combobox" 0 1 0 0 "23/12/2006" "wbComboBoxProxy" "Server" -1 "wxComboBox" "" "" "" "" "The URL for the Thousand Parsec server." "" "" "" 0 1 "<Any platform>" "" "" 0 1 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 1 1 1 1 1 0 0 0 "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "23/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Username" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "23/12/2006" "wbFlexGridSizerProxy" "0" "" 2 2 0 0 "" "<Any platform>" "Expand" "Expand" 0 0 1 1 1 1 0 0 0 "wxTextCtrl: Username" "dialog-control-document" "" "textctrl" 0 1 0 0 "23/12/2006" "wbTextCtrlProxy" "Username" -1 "wxTextCtrl" "" "" 0 "" "The username for the account on the Thousand Parsec server." "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 1 1 1 1 1 0 0 0 "" "" "wxToggleButton: GameShow" "dialog-control-document" "" "togglebutton" 0 1 0 0 "23/12/2006" "wbToggleButtonProxy" "GameShow" -1 "wxToggleButton" "" "G" 0 "" "Show seperate game box." "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 "" -1 -1 25 25 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxStaticText: GameTitle" "dialog-control-document" "" "statictext" 0 1 0 0 "23/12/2006" "wbStaticTextProxy" "GameTitle" -1 "wxStaticText" "" "Game" -1 "" "" "" "" "" 1 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxTextCtrl: Game" "dialog-control-document" "" "textctrl" 0 1 0 0 "23/12/2006" "wbTextCtrlProxy" "Game" -1 "wxTextCtrl" "" "" 0 "" "" "" "" "" 1 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Centre" 0 1 1 1 1 1 0 0 0 "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "23/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Password" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxTextCtrl: Password" "dialog-control-document" "" "textctrl" 0 1 0 0 "23/12/2006" "wbTextCtrlProxy" "Password" -1 "wxTextCtrl" "" "" 0 "" "The password for the account on the Thousand Parsec Server" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Centre" 0 1 1 1 1 1 0 0 0 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "23/12/2006" "wbFlexGridSizerProxy" "" "" 5 2 0 0 "" "<Any platform>" "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "wxButton: wxID_OK" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "23/12/2006" "wbButtonProxy" "wxID_OK" 5100 "wxButton" "" "&OK" 1 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 0 0 1 0 0 0 "" "" "wxButton: wxID_CANCEL" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "23/12/2006" "wbButtonProxy" "wxID_CANCEL" 5101 "wxButton" "" "&Cancel" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 0 0 0 1 0 0 0 "" "" "Spacer" "dialog-control-document" "" "spacer" 0 1 0 0 "23/12/2006" "wbSpacerProxy" 5 5 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxButton: wxID_FIND" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "23/12/2006" "wbButtonProxy" "wxID_FIND" 5034 "wxButton" "" "&Find" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 0 0 0 1 0 0 0 "" "" "wxButton: wxID_PREFERENCES" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "23/12/2006" "wbButtonProxy" "wxID_PREFERENCES" 5019 "wxButton" "" "&Preferences" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 0 1 0 1 0 0 0 "" "" "winAccount" "dialog-document" "" "frame" 0 1 0 0 "21/1/2007" "wbFrameProxy" 10000 0 "" 0 "winAccount" -1 "Frame" "wxFrame" "" "" "winAccount.xrc" "TP: Connect to a Server" 1 "" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 1 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" 0 1 -1 -1 400 240 "" "wxPanel: Panel" "dialog-control-document" "" "panel" 0 1 0 0 "21/1/2007" "wbPanelProxy" "Panel" -1 "wxPanel" "wxPanel" "" 0 0 "" "" "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 "" 1 -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "21/1/2007" "wbFlexGridSizerProxy" "0" "" 1 3 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/1/2007" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Create an Account" -1 "" "" "" "" "14, wxSWISS, wxNORMAL, wxBOLD, false, Sans" 0 1 "<Any platform>" "" "" 0 0 1 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 5 1 1 1 1 0 1 0 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "21/1/2007" "wbFlexGridSizerProxy" "1" "0,1,2" 2 2 0 0 "" "<Any platform>" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/1/2007" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Server" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxBoxSizer H" "dialog-control-document" "" "sizer" 0 1 0 0 "21/1/2007" "wbBoxSizerProxy" "Horizontal" "" "Expand" "Expand" 0 0 1 1 1 1 0 0 0 "<Any platform>" "wxComboBox: Server" "dialog-control-document" "" "combobox" 0 1 0 0 "21/1/2007" "wbComboBoxProxy" "Server" -1 "wxComboBox" "" "" "" "" "The URL for the Thousand Parsec server." "" "" "" 0 1 "<Any platform>" "" "" 0 1 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 1 0 1 1 1 1 0 0 0 "" "" "GIFAnimationCtrl: Checking" "dialog-control-document" "" "foreign" 0 1 0 0 "21/1/2007" "wbForeignCtrlProxy" "Checking" -1 "GIFAnimationCtrl" "wxWindow" "" 1 0 "" "Choose a server to create an account on." "" "" "" 1 1 "<Any platform>" "" "" 1 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 32 32 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "" "wxButton: Check" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "21/1/2007" "wbButtonProxy" "Check" -1 "wxButton" "" "Check" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 50 32 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/1/2007" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Username" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "21/1/2007" "wbFlexGridSizerProxy" "0" "" 2 2 0 0 "" "<Any platform>" "Expand" "Expand" 0 0 1 1 1 1 0 0 0 "wxTextCtrl: Username" "dialog-control-document" "" "textctrl" 0 1 0 0 "21/1/2007" "wbTextCtrlProxy" "Username" -1 "wxTextCtrl" "" "" 0 "" "The username for the account on the Thousand Parsec server." "" "" "" 0 0 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 1 1 1 1 1 0 0 0 "" "" "wxToggleButton: GameShow" "dialog-control-document" "" "togglebutton" 0 1 0 0 "21/1/2007" "wbToggleButtonProxy" "GameShow" -1 "wxToggleButton" "" "G" 0 "" "Show seperate game box." "" "" "" "" "" 0 0 "<Any platform>" 0 0 0 "" -1 -1 25 25 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxStaticText: GameTitle" "dialog-control-document" "" "statictext" 0 1 0 0 "21/1/2007" "wbStaticTextProxy" "GameTitle" -1 "wxStaticText" "" "Game" -1 "" "" "" "" "" 1 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxTextCtrl: Game" "dialog-control-document" "" "textctrl" 0 1 0 0 "21/1/2007" "wbTextCtrlProxy" "Game" -1 "wxTextCtrl" "" "" 0 "" "" "" "" "" 1 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Centre" 0 1 1 1 1 1 0 0 0 "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/1/2007" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Password" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxTextCtrl: Password1" "dialog-control-document" "" "textctrl" 0 1 0 0 "21/1/2007" "wbTextCtrlProxy" "Password1" -1 "wxTextCtrl" "" "" 0 "" "Choose your password here." "" "" "" 0 0 "<Any platform>" "" "" 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Centre" 0 1 1 1 1 1 0 0 0 "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/1/2007" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" " " -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxTextCtrl: Password2" "dialog-control-document" "" "textctrl" 0 1 0 0 "21/1/2007" "wbTextCtrlProxy" "Password2" -1 "wxTextCtrl" "" "" 0 "" "Repeat the password" "" "" "" 0 0 "<Any platform>" "" "" 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Centre" 0 1 1 1 1 1 0 0 0 "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "21/1/2007" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Email " -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxTextCtrl: Email" "dialog-control-document" "" "textctrl" 0 1 0 0 "21/1/2007" "wbTextCtrlProxy" "Email" -1 "wxTextCtrl" "" "" 0 "" "Repeat the password" "" "" "" 0 0 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 280 -1 "Expand" "Centre" 0 1 1 1 1 1 0 0 0 "" "" "wxStdDialogButtonSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "21/1/2007" "wbStdDialogButtonSizerProxy" 1 1 0 0 0 0 0 0 "" "Right" "Centre" 0 3 1 1 1 1 0 0 0 "<Any platform>" "wxButton: wxID_OK" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "21/1/2007" "wbButtonProxy" "wxID_OK" 5100 "wxButton" "" "&OK" 1 "" "" "" "" "" 0 0 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 0 0 1 0 0 0 "" "" "wxButton: wxID_CANCEL" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "21/1/2007" "wbButtonProxy" "wxID_CANCEL" 5101 "wxButton" "" "&Cancel" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 0 0 0 1 0 0 0 "" "" "configConnect" "dialog-document" "" "dialog" 0 1 0 0 "26/12/2006" "wbDialogProxy" 10000 0 "" 0 "configConnect" -1 "Dialog" "wxPanel" "wxPanel" "" "" "configConnect.xrc" "ConnectConfig" 1 "" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" 0 1 -1 -1 400 300 "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "26/12/2006" "wbFlexGridSizerProxy" "0" "0" 2 2 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxEditableListBox: Servers" "dialog-control-document" "" "foreign" 0 1 0 0 "26/12/2006" "wbForeignCtrlProxy" "Servers" -1 "wxEditableListBox" "wxEditableListBox" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 1 0 0 0 0 0 0 0 0 0 0 0 "wxEL_ALLOW_NEW|wxEL_ALLOW_EDIT|wxEL_ALLOW_DELETE" -1 -1 200 100 "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "" "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "26/12/2006" "wbFlexGridSizerProxy" "" "" 1 2 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxStaticBoxSizer H" "dialog-control-document" "" "sizer" 0 1 0 0 "26/12/2006" "wbStaticBoxSizerProxy" "ServerDetails" -1 "Login for" "" "" "" 0 1 "Horizontal" "" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "26/12/2006" "wbFlexGridSizerProxy" "" "" 2 2 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "26/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Username" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 0 1 0 0 0 1 0 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "26/12/2006" "wbFlexGridSizerProxy" "0" "" 2 2 0 0 "" "<Any platform>" "Expand" "Expand" 0 0 1 1 1 1 0 0 0 "wxTextCtrl: Username" "dialog-control-document" "" "textctrl" 0 1 0 0 "26/12/2006" "wbTextCtrlProxy" "Username" -1 "wxTextCtrl" "" "" 0 "" "The username for the account on the Thousand Parsec server." "" "" "" 0 0 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 1 1 1 1 1 0 0 0 "" "" "wxToggleButton: GameShow" "dialog-control-document" "" "togglebutton" 0 1 0 0 "26/12/2006" "wbToggleButtonProxy" "GameShow" -1 "wxToggleButton" "" "G" 0 "" "Show seperate game box." "" "" "" "" "" 0 0 "<Any platform>" 0 0 0 "" -1 -1 25 25 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxStaticText: GameTitle" "dialog-control-document" "" "statictext" 0 1 0 0 "26/12/2006" "wbStaticTextProxy" "GameTitle" -1 "wxStaticText" "" "Game" -1 "" "" "" "" "" 1 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 0 1 0 0 0 1 0 "" "" "wxTextCtrl: Game" "dialog-control-document" "" "textctrl" 0 1 0 0 "26/12/2006" "wbTextCtrlProxy" "Game" -1 "wxTextCtrl" "" "" 0 "" "" "" "" "" 1 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 0 1 1 1 1 0 0 0 "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "26/12/2006" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Password" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Right" "Centre" 0 5 0 1 0 0 0 1 0 "" "" "wxTextCtrl: Password" "dialog-control-document" "" "textctrl" 0 1 0 0 "26/12/2006" "wbTextCtrlProxy" "Password" -1 "wxTextCtrl" "" "" 0 "" "" "" "" "" 0 0 "<Any platform>" "" "" 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 200 -1 "Expand" "Expand" 0 0 1 1 1 1 0 0 0 "" "" "Spacer" "dialog-control-document" "" "spacer" 0 1 0 0 "26/12/2006" "wbSpacerProxy" 5 5 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxCheckBox: AutoConnect" "dialog-control-document" "" "checkbox" 0 1 0 0 "26/12/2006" "wbCheckBoxProxy" "AutoConnect" -1 "wxCheckBox" "" "Autoconnect" 0 "" "" "" "" "" "" "" 0 0 "<Any platform>" 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "Spacer" "dialog-control-document" "" "spacer" 0 1 0 0 "26/12/2006" "wbSpacerProxy" 5 5 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "26/12/2006" "wbFlexGridSizerProxy" "0" "" 1 2 0 0 "" "<Any platform>" "Centre" "Expand" 0 5 1 1 1 1 0 0 0 "wxCheckBox: Debug" "dialog-control-document" "" "checkbox" 0 1 0 0 "26/12/2006" "wbCheckBoxProxy" "Debug" -1 "wxCheckBox" "" "Debug Output" 1 "" "" "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "configMedia" "dialog-document" "" "dialog" 0 1 0 0 "11/3/2007" "wbDialogProxy" 10000 0 "" 0 "configMedia" -1 "Dialog" "wxPanel" "wxPanel" "" "" "" "MediaConfig" 1 "" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" 0 1 -1 -1 400 300 "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "11/3/2007" "wbFlexGridSizerProxy" "" "" 1 2 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxStaticBoxSizer H" "dialog-control-document" "" "sizer" 0 1 0 0 "11/3/2007" "wbStaticBoxSizerProxy" "ID_STATICBOXSIZER" 10000 "Automatic Media Download" "" "" "" 0 1 "Horizontal" "" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "11/3/2007" "wbFlexGridSizerProxy" "" "" 2 2 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxCheckBox: ID_CHECKBOX1" "dialog-control-document" "" "checkbox" 0 1 0 0 "11/3/2007" "wbCheckBoxProxy" "ID_CHECKBOX1" 10001 "wxCheckBox" "" "Automatically Download" 0 "" "Automatically download any media required by the client." "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "Spacer" "dialog-control-document" "" "spacer" 0 1 0 0 "11/3/2007" "wbSpacerProxy" 5 5 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "11/3/2007" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Maximum Speed" -1 "" "Maximum download speed in kb/s." "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 1 0 "" "" "wxSpinCtrl: ID_SPINCTRL1" "dialog-control-document" "" "spinctrl" 0 1 0 0 "11/3/2007" "wbSpinCtrlProxy" "ID_SPINCTRL1" 10002 "wxSpinCtrl" "" 0 100 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 1 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "wxRadioBox: ID_RADIOBOX" "dialog-control-document" "" "radiobox" 0 1 0 0 "11/3/2007" "wbRadioBoxProxy" "ID_RADIOBOX" 10004 "wxRadioBox" "" "Use Proxy?" 0 "&Use System Settings|&No Proxy|&Proxy Below" 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 1 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "" "" "panelMessage" "dialog-document" "" "dialog" 0 1 0 0 "1/1/2007" "wbDialogProxy" 10000 0 "" 0 "panelMessage" -1 "Dialog" "wxPanel" "wxPanel" "" "" "panelMessage.xrc" "Message Panel" 1 "" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" 0 0 -1 -1 400 170 "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "1/1/2007" "wbFlexGridSizerProxy" "0" "1" 1 2 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxBoxSizer H" "dialog-control-document" "" "sizer" 0 1 0 0 "1/1/2007" "wbBoxSizerProxy" "Horizontal" "" "Expand" "Centre" 0 1 1 1 1 1 0 0 0 "<Any platform>" "wxButton: Filter" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "1/1/2007" "wbButtonProxy" "Filter" -1 "wxButton" "" "Filter" 0 "" "" "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 0 1 "<Any platform>" 0 0 0 0 1 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 0 1 1 1 1 1 0 0 0 "" "" "wxStaticText: Title" "dialog-control-document" "" "statictext" 0 1 0 0 "1/1/2007" "wbStaticTextProxy" "Title" -1 "wxStaticText" "" "Static text" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 1 1 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 3 0 1 1 1 1 0 1 0 "" "" "wxStaticText: Counter" "dialog-control-document" "" "statictext" 0 1 0 0 "1/1/2007" "wbStaticTextProxy" "Counter" -1 "wxStaticText" "" "100 of 100" -1 "" "" "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 0 1 "<Any platform>" "" "" 0 1 0 1 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Centre" 1 0 1 1 1 1 0 1 0 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "1/1/2007" "wbFlexGridSizerProxy" "0" "0" 2 2 0 0 "" "<Any platform>" "Expand" "Expand" 1 2 1 1 1 1 0 0 0 "wxHtmlWindow: Message" "dialog-control-document" "" "htmlwindow" 0 1 0 0 "1/1/2007" "wbHtmlWindowProxy" "Message" -1 "wxHtmlWindow" "" "" "<html> <body> <center> <table cols=1 width="100%"> <tr> <td><b>Subject:</b> You are unloved! </tr> <tr> <td> You have recived no messages this turn!<br><br> Actually if you didn't recive any messages it most proberly means that your client couldn't load the results from the server. Try reload/restart the client. </td> </tr> </table> </center> </body> </html>" "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 1 2 0 1 0 0 0 0 0 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "1/1/2007" "wbFlexGridSizerProxy" "" "" 1 2 0 0 "" "<Any platform>" "Expand" "Expand" 0 0 1 0 1 1 0 0 0 "wxBoxSizer H" "dialog-control-document" "" "sizer" 0 1 0 0 "1/1/2007" "wbBoxSizerProxy" "Horizontal" "" "Expand" "Centre" 1 0 1 1 1 1 0 0 0 "<Any platform>" "wxButton: Prev" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "1/1/2007" "wbButtonProxy" "Prev" -1 "wxButton" "" "Prev" 0 "" "" "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 45 22 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxButton: First" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "1/1/2007" "wbButtonProxy" "First" -1 "wxButton" "" "First" 0 "" "" "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 1 1 "<Any platform>" 0 0 0 0 1 0 0 0 0 "" -1 -1 45 -1 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxButton: Goto" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "1/1/2007" "wbButtonProxy" "Goto" -1 "wxButton" "" "Goto" 0 "" "" "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 45 22 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxBoxSizer H" "dialog-control-document" "" "sizer" 0 1 0 0 "1/1/2007" "wbBoxSizerProxy" "Horizontal" "" "Expand" "Centre" 1 0 1 1 1 1 0 0 0 "<Any platform>" "wxButton: Next" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "1/1/2007" "wbButtonProxy" "Next" -1 "wxButton" "" "Next" 0 "" "" "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 45 22 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxButton: Last" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "1/1/2007" "wbButtonProxy" "Last" -1 "wxButton" "" "Last" 0 "" "" "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 1 1 "<Any platform>" 0 0 0 0 1 0 0 0 0 "" -1 -1 45 -1 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxStaticLine: wxID_STATIC" "dialog-control-document" "" "staticline" 0 1 0 0 "1/1/2007" "wbStaticLineProxy" "wxID_STATIC" 5105 "wxStaticLine" "" "" "" "" 0 1 "<Any platform>" 1 0 0 0 0 0 0 0 0 0 0 "" -1 -1 20 -1 "Centre" "Top" 0 2 1 1 1 1 0 0 0 "wxButton: Delete" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "1/1/2007" "wbButtonProxy" "Delete" -1 "wxButton" "" "Delete" 0 "" "" "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 45 22 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "panelOrder" "dialog-document" "" "dialog" 0 1 0 0 "2/1/2007" "wbDialogProxy" 10000 0 "" 0 "panelOrder" -1 "Dialog" "wxPanel" "wxPanel" "" "" "panelOrder.xrc" "Order Panel" 1 "" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" 0 0 -1 -1 400 300 "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "2/1/2007" "wbFlexGridSizerProxy" "0" "0" 1 2 0 0 "" "<Any platform>" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "wxListCtrl: Orders" "dialog-control-document" "" "listctrl" 0 1 0 0 "2/1/2007" "wbListCtrlProxy" "Orders" -1 "wxListCtrl" "" "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 100 100 "Expand" "Expand" 0 1 1 1 1 1 0 0 0 "" "" "wxStaticLine: wxID_STATIC" "dialog-control-document" "" "staticline" 0 1 0 0 "2/1/2007" "wbStaticLineProxy" "wxID_STATIC" 5105 "wxStaticLine" "" "" "" "" 0 1 "<Any platform>" 1 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 0 2 1 1 1 1 0 0 0 "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "2/1/2007" "wbFlexGridSizerProxy" "0" "0" 8 1 0 0 "" "<Any platform>" "Expand" "Expand" 0 0 1 1 1 1 0 0 0 "wxChoice: Possible" "dialog-control-document" "" "choice" 0 1 0 0 "2/1/2007" "wbChoiceProxy" "Possible" -1 "wxChoice" "" "" "" "" "" "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 0 1 "<Any platform>" "" "" 0 0 0 "" -1 -1 -1 24 "Expand" "Expand" 0 1 1 1 1 1 0 0 0 "" "" "wxButton: New" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "2/1/2007" "wbButtonProxy" "New" -1 "wxButton" "" "&New" 0 "" "Insert new order." "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 45 24 "Centre" "Centre" 0 1 1 1 1 1 0 0 0 "" "" "wxPanel: DetailsPanel" "dialog-control-document" "" "panel" 0 1 0 0 "2/1/2007" "wbPanelProxy" "DetailsPanel" -1 "wxPanel" "wxPanel" "" 0 0 "" "" "" "" "" "" "" 0 1 "<Any platform>" 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 "" 1 -1 -1 -1 -1 "Expand" "Expand" 0 0 1 1 1 1 0 0 0 "" "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "2/1/2007" "wbFlexGridSizerProxy" "0" "1" 1 2 0 0 "" "<Any platform>" "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "wxStaticLine: ArgumentLine" "dialog-control-document" "" "staticline" 0 1 0 0 "2/1/2007" "wbStaticLineProxy" "ArgumentLine" -1 "wxStaticLine" "" "" "" "" 0 1 "<Any platform>" 1 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 0 2 1 1 0 1 0 0 0 "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "2/1/2007" "wbFlexGridSizerProxy" "0" "0" 4 2 0 0 "" "<Any platform>" "Expand" "Expand" 0 0 1 1 1 1 0 0 0 "wxStaticText: Message" "dialog-control-document" "" "statictext" 0 1 0 0 "2/1/2007" "wbStaticTextProxy" "Message" -1 "wxStaticText" "" "" -1 "" "" "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 0 1 "<Any platform>" "" "" 0 0 1 1 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 5 1 1 1 1 0 1 0 "" "" "wxButton: Save" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "2/1/2007" "wbButtonProxy" "Save" -1 "wxButton" "" "&Save" 1 "" "" "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 45 24 "Centre" "Centre" 0 1 1 1 1 1 0 0 0 "" "" "wxButton: Revert" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "2/1/2007" "wbButtonProxy" "Revert" -1 "wxButton" "" "&Revert" 0 "" "" "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 45 24 "Centre" "Centre" 0 1 1 1 1 1 0 0 0 "" "" "wxButton: Delete" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "2/1/2007" "wbButtonProxy" "Delete" -1 "wxButton" "" "&Delete" 0 "" "Delete the currently selected order(s)" "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 45 24 "Centre" "Centre" 0 1 1 1 1 1 0 0 0 "" "" "panelInformation" "dialog-document" "" "dialog" 0 1 0 0 "2/1/2007" "wbDialogProxy" 10000 0 "" 0 "panelInformation" -1 "Dialog" "wxPanel" "wxPanel" "" "" "panelInformation.xrc" "Information Panel" 1 "" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" 0 0 -1 -1 400 300 "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "2/1/2007" "wbFlexGridSizerProxy" "0" "1" 1 2 0 0 "" "<Any platform>" "Centre" "Centre" 1 5 1 1 1 1 0 0 0 "wxStaticText: Title" "dialog-control-document" "" "statictext" 0 1 0 0 "3/3/2007" "wbStaticTextProxy" "Title" -1 "wxStaticText" "" "Name of object goes here" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 1 1 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 0 1 1 1 1 0 1 0 "" "" "wxTextCtrl: Details" "dialog-control-document" "" "textctrl" 0 1 0 0 "3/3/2007" "wbTextCtrlProxy" "Details" -1 "wxTextCtrl" "" "" 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 "" -1 -1 -1 128 "Expand" "Expand" 0 5 1 0 0 0 0 0 0 "" "" "panelStarMap" "dialog-document" "" "dialog" 0 1 0 0 "11/2/2007" "wbDialogProxy" 10000 0 "" 0 "panelStarMap" -1 "Dialog" "wxPanel" "wxPanel" "" "" "starmap.xrc" "StarMap Panel" 1 "" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "" 0 0 -1 -1 400 300 "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "11/2/2007" "wbFlexGridSizerProxy" "0" "1" 1 3 0 0 "" "<Any platform>" "Centre" "Centre" 1 5 1 1 1 1 0 0 0 "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "12/2/2007" "wbFlexGridSizerProxy" "" "" 12 2 0 0 "" "<Any platform>" "Left" "Centre" 0 2 1 1 1 1 0 0 0 "wxBitmapButton: Zoom" "dialog-control-document" "" "bitmapbutton" 0 1 0 0 "12/2/2007" "wbBitmapButtonProxy" "Zoom" -1 "wxBitmapButton" "" "../../graphics/zoom.png" "" "" "" "" "" "" "" "" 0 1 "<Any platform>" 1 1 0 0 0 0 0 0 0 "" -1 -1 28 28 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxButton: Waypoint" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "12/2/2007" "wbButtonProxy" "Waypoint" -1 "wxButton" "" "W" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 28 28 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxButton: ID_BUTTON3" "dialog-control-document" "" "dialogcontrol" 0 1 0 0 "12/2/2007" "wbButtonProxy" "ID_BUTTON3" 10004 "wxButton" "" "Button" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 28 28 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "12/2/2007" "wbFlexGridSizerProxy" "" "" 2 2 0 0 "" "<Any platform>" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "wxWindow: Canvas" "dialog-control-document" "" "foreign" 0 1 0 0 "12/2/2007" "wbForeignCtrlProxy" "Canvas" -1 "wxWindow" "wxWindow" "" 1 0 "" "" "" "" "" 0 1 "<Any platform>" "" "" 1 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 100 100 "Expand" "Expand" 0 0 1 1 1 1 0 0 0 "" "" "" "wxBoxSizer H" "dialog-control-document" "" "sizer" 0 1 0 0 "12/2/2007" "wbBoxSizerProxy" "Horizontal" "" "Expand" "Expand" 0 0 1 1 1 1 0 0 0 "<Any platform>" "wxBoxSizer H" "dialog-control-document" "" "sizer" 0 1 0 0 "12/2/2007" "wbBoxSizerProxy" "Horizontal" "" "Centre" "Expand" 1 2 1 1 0 0 0 0 0 "<Any platform>" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "12/2/2007" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "X:" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 1 0 0 0 0 0 1 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 0 1 1 1 1 0 1 0 "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "12/2/2007" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "10000 p" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 0 0 1 0 0 1 0 0 0 "" "" "wxBoxSizer H" "dialog-control-document" "" "sizer" 0 1 0 0 "12/2/2007" "wbBoxSizerProxy" "Horizontal" "" "Centre" "Expand" 1 2 1 1 0 0 0 0 0 "<Any platform>" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "12/2/2007" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Y:" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 1 0 0 0 0 0 1 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 0 1 1 1 1 0 1 0 "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "12/2/2007" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "10000 p" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 0 0 1 1 1 1 0 1 0 "" "" "wxBoxSizer H" "dialog-control-document" "" "sizer" 0 1 0 0 "12/2/2007" "wbBoxSizerProxy" "Horizontal" "" "Centre" "Expand" 1 2 1 1 0 0 0 0 0 "<Any platform>" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "12/2/2007" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "Z:" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 1 0 0 0 0 0 1 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 0 1 1 1 1 0 1 0 "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "12/2/2007" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "10000 p" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 0 0 1 1 1 1 0 1 0 "" "" "wxBoxSizer H" "dialog-control-document" "" "sizer" 0 1 0 0 "12/2/2007" "wbBoxSizerProxy" "Horizontal" "" "Right" "Expand" 4 2 1 1 0 0 0 0 0 "<Any platform>" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "12/2/2007" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "N:" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 1 0 0 0 0 0 1 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 0 1 1 1 1 0 1 0 "" "" "wxStaticText: wxID_STATIC" "dialog-control-document" "" "statictext" 0 1 0 0 "12/2/2007" "wbStaticTextProxy" "wxID_STATIC" 5105 "wxStaticText" "" "A wonderful Object" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Centre" "Expand" 0 0 1 1 1 1 0 1 0 "" "" "panelPicture" "dialog-document" "" "dialog" 0 1 0 0 "3/3/2007" "wbDialogProxy" 10000 0 "" 0 "panelPicture" -1 "Dialog" "wxPanel" "wxPanel" "" "" "panelPicture" "Picture Panel" 1 "" 0 "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 "" 0 1 -1 -1 400 300 "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "3/3/2007" "wbFlexGridSizerProxy" "0" "1" 1 2 0 0 "" "<Any platform>" "Centre" "Centre" 1 5 1 1 1 1 0 0 0 "wxStaticText: Title" "dialog-control-document" "" "statictext" 0 1 0 0 "3/3/2007" "wbStaticTextProxy" "Title" -1 "wxStaticText" "" "Name goes here" -1 "" "" "" "" "" 0 1 "<Any platform>" "" "" 0 0 1 1 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 -1 "Expand" "Expand" 0 0 1 1 1 1 0 1 0 "" "" "wxPanel: Background" "dialog-control-document" "" "panel" 0 1 0 0 "3/3/2007" "wbPanelProxy" "Background" -1 "wxPanel" "wxPanel" "" 0 0 "" "" "" "" "000000" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 "" 0 -1 -1 128 128 "Expand" "Expand" 0 0 1 1 1 1 0 0 0 "" "" "" "wxBoxSizer V" "dialog-control-document" "" "sizer" 0 1 0 0 "3/3/2007" "wbBoxSizerProxy" "Vertical" "" "Centre" "Centre" 0 5 1 1 1 1 0 0 0 "<Any platform>" "wxStaticBitmap: Static" "dialog-control-document" "" "staticbitmap" 0 1 0 0 "3/3/2007" "wbStaticBitmapProxy" "Static" -1 "wxStaticBitmap" "" "" "" "" "" "" "" 0 1 "<Any platform>" 0 0 0 0 0 0 0 0 0 "" -1 -1 128 128 "Centre" "Centre" 0 0 1 1 1 1 0 0 0 "" "" "wxGIFAnimationCtrl: Animation" "dialog-control-document" "" "foreign" 0 1 0 0 "3/3/2007" "wbForeignCtrlProxy" "Animation" -1 "wxGIFAnimationCtrl" "wxGIFAnimationCtrl" "" 1 0 "" "" "000000" "" "" 0 1 "<Any platform>" "" "" 1 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 128 128 "Left" "Top" 0 0 1 1 1 1 0 0 0 "" "" "" "wxFlexGridSizer" "dialog-control-document" "" "sizer" 0 1 0 0 "11/3/2007" "wbFlexGridSizerProxy" "0" "" 3 2 0 0 "" "<Any platform>" "Expand" "Expand" 0 5 1 1 1 1 0 0 0 "wxGauge: Progress" "dialog-control-document" "" "gauge" 0 1 0 0 "11/3/2007" "wbGaugeProxy" "Progress" -1 "wxGauge" "" 1 100 "" "" "" "" "" 0 1 "<Any platform>" "" "" 1 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 10 "Expand" "Expand" 0 0 1 1 1 1 0 0 0 "" "" "wxStaticText: Speed" "dialog-control-document" "" "statictext" 0 1 0 0 "11/3/2007" "wbStaticTextProxy" "Speed" -1 "wxStaticText" "" "10kb/s" -1 "" "" "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 10 "Expand" "Expand" 0 3 1 1 0 0 0 1 0 "" "" "wxStaticText: ETA" "dialog-control-document" "" "statictext" 0 1 0 0 "11/3/2007" "wbStaticTextProxy" "ETA" -1 "wxStaticText" "" "43s" -1 "" "" "" "" "8, wxSWISS, wxNORMAL, wxNORMAL, false, Sans" 0 1 "<Any platform>" "" "" 0 0 0 0 0 0 0 0 0 0 0 0 0 "" -1 -1 -1 10 "Right" "Expand" 0 3 1 1 0 0 0 1 0 "" "" "Sources" "html-document" "" "sourcesfolder" 1 1 0 1 "test.rc" "source-editor-document" "test.rc" "source-editor" 0 0 1 0 "8/12/2006" "" "Images" "html-document" "" "bitmapsfolder" 1 1 0 1 "wizard.png" "image-document" "wizard.png" "image" 0 1 0 0 "8/12/2006" 100 "zoom.png" "image-document" "../../graphics/zoom.png" "image" 0 0 0 0 "12/2/2007" 100
tpclient-pywx-0.3.1.1/windows/xrc/winHelp.xrc0000644000175000017500000000640510773624641017276 0ustar timtim 48,48 wxALL|wxEXPAND|wxGROW 5 16 normal 0 swiss Sans wxALL|wxALIGN_CENTRE_VERTICAL 5 2 1 1 0 wxALIGN_CENTRE_VERTICAL 300,200 wxALL|wxEXPAND|wxGROW 2 1 wxEXPAND|wxGROW 1 wxALL|wxALIGN_CENTRE_VERTICAL 20,-1 wxEXPAND|wxGROW 4 1 2 0 wxALL|wxEXPAND|wxGROW 5 1 3 0 1 550,400 Help tpclient-pywx-0.3.1.1/windows/xrc/MessageBrowser.xrc0000644000175000017500000001312510773624641020615 0ustar timtim wxWS_EX_BLOCK_EVENTS 400,300 Dialog 1 2 2 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 5 2 1 0 0 0 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE 5 wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL 0 20,-1 Filter messages using this message as a template. wxGROW|wxALIGN_CENTER_VERTICAL|wxALL 5 100,100 Boards avaliable on the server. wxGROW|wxGROW|wxALL 5 1 2 0 0 wxGROW|wxGROW|wxALL 5 200,150 <html> <body> <center> <table cols=1 width="100%" background=""> <tr> <td><b>Subject:</b> Subject goes here!</td> </tr> <tr> <td>A really cool message body should go here.</td> </tr> </table> </center> </body> </html> wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 5 wxHORIZONTAL wxALIGN_CENTER_VERTICAL|wxALL 5 Create a new message on the current board. wxALIGN_CENTER_VERTICAL|wxALL 5 Goto objects referenced by this message. wxALIGN_CENTER_VERTICAL|wxALL 5 Delete this message. tpclient-pywx-0.3.1.1/windows/xrc/winUpdate.py0000644000175000017500000000647010773624641017466 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class winUpdateBase: xrc = os.path.join(location(), "windows", "xrc", 'winUpdate.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Figure out what Frame class (MDI, MiniFrame, etc) is actually our base... bases = set() def findbases(klass, set): for base in klass.__bases__: set.add(base) findbases(base, set) findbases(self.__class__, bases) for base in bases: if base.__name__.endswith("Frame"): break # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = getattr(wx, "Pre%s" % base.__name__)() res.LoadOnFrame(pre, parent, "winUpdate") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Panel = XRCCTRL(self, "Panel") self.TopText = XRCCTRL(self, "TopText") self.Message = XRCCTRL(self, "Message") self.ConnectingGauge = XRCCTRL(self, "ConnectingGauge") self.ConnectingText = XRCCTRL(self, "ConnectingText") self.ConnectingAnim = XRCCTRL(self, "ConnectingAnim") self.ProgressTitle = XRCCTRL(self, "ProgressTitle") self.ProgressGauge = XRCCTRL(self, "ProgressGauge") self.ProgressText = XRCCTRL(self, "ProgressText") self.ProgressAnim = XRCCTRL(self, "ProgressAnim") self.ObjectdescsAnim = XRCCTRL(self, "ObjectdescsAnim") self.OrderdescsAnim = XRCCTRL(self, "OrderdescsAnim") self.ObjectsAnim = XRCCTRL(self, "ObjectsAnim") self.OrdersAnim = XRCCTRL(self, "OrdersAnim") self.BoardsAnim = XRCCTRL(self, "BoardsAnim") self.MessagesAnim = XRCCTRL(self, "MessagesAnim") self.CategoriesAnim = XRCCTRL(self, "CategoriesAnim") self.DesignsAnim = XRCCTRL(self, "DesignsAnim") self.ComponentsAnim = XRCCTRL(self, "ComponentsAnim") self.PropertiesAnim = XRCCTRL(self, "PropertiesAnim") self.PlayersAnim = XRCCTRL(self, "PlayersAnim") self.ResourcesAnim = XRCCTRL(self, "ResourcesAnim") self.Okay = XRCCTRL(self, "wxID_OK") if hasattr(self, "OnOkay"): self.Bind(wx.EVT_BUTTON, self.OnOkay, self.Okay) self.Save = XRCCTRL(self, "wxID_SAVE") if hasattr(self, "OnSave"): self.Bind(wx.EVT_BUTTON, self.OnSave, self.Save) self.Cancel = XRCCTRL(self, "wxID_CANCEL") if hasattr(self, "OnCancel"): self.Bind(wx.EVT_BUTTON, self.OnCancel, self.Cancel) def strings(): pass _("TP: Universe update"); _("Universe Download"); _("Done!"); _("Progress"); _("Done!"); _("Objects Descs"); _("Order Descs"); _("Objects"); _("Orders"); _("Boards"); _("Messages"); _("Categories"); _("Designs"); _("Components"); _("Properties"); _("Players"); _("Resources"); _("Continue to the main game window."); _("&OK"); _("Save a copy of the message box window to a file."); _("&Save"); _("Cancel the current update and go back to the connect screen."); _("&Cancel"); tpclient-pywx-0.3.1.1/windows/xrc/winIdleFinder.xrc0000644000175000017500000000111310773624641020402 0ustar timtim Objects Without Orders wxVERTICAL wxALL|wxEXPAND|wxALIGN_CENTRE 300, 300 tpclient-pywx-0.3.1.1/windows/xrc/panelInformation.xrc0000644000175000017500000000227110773624641021172 0ustar timtim 400,300 1 2 0 0 0 1 wxGROW|wxGROW|wxALL|wxADJUST_MINSIZE 0 wxGROW|wxGROW|wxLEFT 5 -1,128 tpclient-pywx-0.3.1.1/windows/xrc/winIdleFinder.py0000644000175000017500000000271410773624641020246 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class IdleFinderBase: xrc = os.path.join(location(), "windows", "xrc", 'winIdleFinder.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Figure out what Frame class (MDI, MiniFrame, etc) is actually our base... bases = set() def findbases(klass, set): for base in klass.__bases__: set.add(base) findbases(base, set) findbases(self.__class__, bases) for base in bases: if base.__name__.endswith("Frame"): break # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = getattr(wx, "Pre%s" % base.__name__)() res.LoadOnFrame(pre, parent, "IdleFinder") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.base = XRCCTRL(self, "base") self.idlelist = XRCCTRL(self, "idlelist") def strings(): pass _("Objects Without Orders"); tpclient-pywx-0.3.1.1/windows/xrc/panelSystem.xrc0000644000175000017500000000324710773624641020175 0ustar timtim 400,300 wxEXPAND|wxGROW wxHORIZONTAL wxALL|wxALIGN_CENTRE wxEXPAND|wxGROW wxVERTICAL tpclient-pywx-0.3.1.1/windows/xrc/panelOrder.xrc0000644000175000017500000002117210773624641017761 0ustar timtim 400,300 1 2 0 0 0 0 wxGROW|wxGROW|wxALL 1 100,100 wxALIGN_CENTER_HORIZONTAL|wxGROW|wxALL 2 wxGROW|wxGROW|wxALL 0 8 1 0 0 0 0 wxGROW|wxGROW|wxALL 1 -1,24 8 swiss Sans wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 1 45,24 Insert new order. 8 swiss Sans 1 2 wxALL|wxEXPAND 2 1 2 1 2 0 0 0 1 wxTOP|wxLEFT|wxRIGHT|wxEXPAND|wxGROW 3 0 0 4 1 0 0 0 0 wxLEFT|wxRIGHT|wxEXPAND|wxGROW|wxALIGN_CENTRE|wxADJUST_MINSIZE 5 8 swiss Sans wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 1 45,24 8 swiss Sans 1 wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 1 45,24 8 swiss Sans wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL 1 45,24 Delete the currently selected order(s) 8 swiss Sans wxBOTTOM|wxLEFT|wxRIGHT|wxEXPAND|wxGROW 3 wxALL|wxEXPAND|wxGROW 0 1 wxEXPAND|wxGROW wxEXPAND|wxGROW 1 0 0 tpclient-pywx-0.3.1.1/windows/xrc/winConnect.py0000644000175000017500000000556610773624641017642 0ustar timtim# This file has been automatically generated. # Please do not edit it manually. # Python Imports import os.path # wxPython imports import wx from wx.xrc import XRCCTRL, XmlResourceWithHandlers # Local imports from requirements import location class winConnectBase: xrc = os.path.join(location(), "windows", "xrc", 'winConnect.xrc') def PreCreate(self, pre): """ This function is called during the class's initialization. Override it for custom setup before the window is created usually to set additional window styles using SetWindowStyle() and SetExtraStyle().""" pass def __init__(self, parent, *args, **kw): """ Pass an initialized wx.xrc.XmlResource into res """ f = os.path.join(os.path.dirname(__file__), self.xrc) res = XmlResourceWithHandlers(f) # Figure out what Frame class (MDI, MiniFrame, etc) is actually our base... bases = set() def findbases(klass, set): for base in klass.__bases__: set.add(base) findbases(base, set) findbases(self.__class__, bases) for base in bases: if base.__name__.endswith("Frame"): break # Two stage creation (see http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = getattr(wx, "Pre%s" % base.__name__)() res.LoadOnFrame(pre, parent, "winConnect") self.PreCreate(pre) self.PostCreate(pre) # Define variables for the controls self.Panel = XRCCTRL(self, "Panel") self.Server = XRCCTRL(self, "Server") if hasattr(self, "OnServer"): self.Bind(wx.EVT_COMBOBOX, self.OnServer, self.Server) self.Bind(wx.EVT_TEXT_ENTER, self.OnServer, self.Server) if hasattr(self, "OnDirtyServer"): self.Bind(wx.EVT_TEXT, self.OnServer, self.Server) self.Find = XRCCTRL(self, "wxID_FIND") if hasattr(self, "OnFind"): self.Bind(wx.EVT_BUTTON, self.OnFind, self.Find) self.Username = XRCCTRL(self, "Username") self.GameShow = XRCCTRL(self, "GameShow") if hasattr(self, "OnGameShow"): self.Bind(wx.EVT_TOGGLEBUTTON, self.OnGameShow, self.GameShow) self.GameTitle = XRCCTRL(self, "GameTitle") self.Game = XRCCTRL(self, "Game") self.Password = XRCCTRL(self, "Password") self.Okay = XRCCTRL(self, "wxID_OK") if hasattr(self, "OnOkay"): self.Bind(wx.EVT_BUTTON, self.OnOkay, self.Okay) self.Cancel = XRCCTRL(self, "wxID_CANCEL") if hasattr(self, "OnCancel"): self.Bind(wx.EVT_BUTTON, self.OnCancel, self.Cancel) self.Config = XRCCTRL(self, "wxID_PREFERENCES") if hasattr(self, "OnConfig"): self.Bind(wx.EVT_BUTTON, self.OnConfig, self.Config) def strings(): pass _("TP: Connect to a Server"); _("Connect to Thousand Parsec Server"); _("Server"); _("The URL for the Thousand Parsec server."); _("&Find"); _("Username"); _("The username for the account on the Thousand Parsec server."); _("Show seperate game box."); _("G"); _("Game"); _("Password"); _("The password for the account on the Thousand Parsec Server"); _("&OK"); _("&Cancel"); _("&Preferences"); tpclient-pywx-0.3.1.1/windows/xrc/orderPosition.xrc0000644000175000017500000000371410773624641020530 0ustar timtim 4 1 50,-1 8 normal 0 swiss Sans wxEXPAND|wxGROW 50,-1 8 normal 0 swiss Sans wxEXPAND|wxGROW 50,-1 8 normal 0 swiss Sans wxEXPAND|wxGROW 8 normal 0 swiss Sans 0,1,2 tpclient-pywx-0.3.1.1/windows/winBase.py0000644000175000017500000001161110773624641016313 0ustar timtim"""\ This module contains the "base" for all main windows. It does things like prepending "TP:" to the title, vetoing closing of the window and raising all the other windows when one is clicked. """ import wx import os.path from requirements import graphicsdir import utils class Blank: pass wx.local = Blank() if wx.Platform == "__WXMAC__": wx.local.smallSize = wx.Size(25,25) wx.local.buttonSize = wx.Size(60,30) wx.local.spinSize = wx.Size(50,25) wx.local.normalFont = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL) try: wx.local.tinyFont = wx.Font(10, wx.DEFAULT, wx.LIGHT, wx.NORMAL) except: wx.local.tinyFont = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.NORMAL) wx.local.largeFont = wx.Font(16, wx.DEFAULT, wx.NORMAL, wx.NORMAL) else: wx.local.smallSize = wx.Size(15,15) wx.local.buttonSize = wx.Size(50,20) wx.local.spinSize = wx.Size(40,15) wx.local.normalFont = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.NORMAL) try: wx.local.tinyFont = wx.Font(8, wx.DEFAULT, wx.LIGHT, wx.NORMAL) except: wx.local.tinyFont = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL) wx.local.largeFont = wx.Font(12, wx.DEFAULT, wx.NORMAL, wx.NORMAL) class ShiftMixIn(object): def __init__(self): # Bits for doing the button changing on shift self.shiftimer = wx.Timer(self) self.shift = False def ShiftStart(self): self.shiftimer.Start(50) self.Bind(wx.EVT_TIMER, self.OnShiftTimer, self.shiftimer) def ShiftStop(self): if self.shiftimer.Stop(): self.Unbind(wx.EVT_TIMER, self.shiftimer) def OnShiftTimer(self, evt): shift = wx.GetKeyState(wx.WXK_SHIFT) if self.shift == shift: return self.shift = shift if self.shift: if hasattr(self, 'OnShiftDown'): return self.OnShiftDown(evt) else: if hasattr(self, 'OnShiftUp'): return self.OnShiftUp(evt) class ConfigMixIn(object): def ConfigDefault(self, config=None): """\ Fill out the config with defaults (if the options are not valid or nonexistant). """ return {} def ConfigSave(self): """\ Returns the configuration of the Window (and it's children). """ return self.config def ConfigLoad(self, config={}): """\ Loads the configuration of the Window (and it's children). """ return def ConfigUpdate(self): """\ Updates the config details using external sources. """ raise AssertionError("ConfigUpdate not implimented") def ConfigDisplay(self, panel, sizer): """\ Display a config panel with all the config options. """ raise AssertionError("ConfigDisplay not implimented") def ConfigDisplayUpdate(self, evt): """\ Update the Display because it's changed externally. """ raise AssertionError("ConfigDisplayUpdate not implimented") class winMixIn(object): """ Applies to all windows. """ def __init__(self, application, parent): self.application = application self.parent = parent self.config = self.ConfigDefault() # Set the Icon of the window icon = wx.EmptyIcon() icon.CopyFromBitmap(wx.Bitmap(os.path.join(graphicsdir, "icon.ico"), wx.BITMAP_TYPE_ANY)) self.SetIcon(icon) self.Bind(wx.EVT_CLOSE, self.OnClose) def PreCreate(self, pre): pre.SetTitle('TP: ' + self.title) def __str__(self): if hasattr(self, 'title'): return "" % self.title return super(self.__class__, self).__str__() def OnClose(self, evt): # Ignore close events if evt.CanVeto(): evt.Veto(True) self.Hide() class winBaseMixIn(winMixIn): """ Applies to all top level windows. """ def __init__(self, application): winMixIn.__init__(self, application, None) self.children = {} def PreCreate(self, pre): pre.SetTitle('TP: ' + self.title) def OnActivate(self, evt): if not evt.GetActive(): return self.RaiseChildren() def HideChildren(self): for window in self.children.values(): if isinstance(window, winBase): window.Hide() def RaiseChildren(self): for window in self.children.values(): if isinstance(window, winBase): window.Raise() # These give a non-MDI interface under other operating systems class winBase(ConfigMixIn, winBaseMixIn, wx.Frame): def __init__(self, application): wx.Frame.__init__(self, None, -1, 'TP: ' + self.title, wx.DefaultPosition, wx.DefaultSize, \ wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL) winBaseMixIn.__init__(self, application) class winBaseXRC(ConfigMixIn, winBaseMixIn, wx.Frame): def __init__(self, application): winBaseMixIn.__init__(self, application) class winReportXRC(ConfigMixIn, winMixIn, wx.Frame): def __init__(self, application, parent): winMixIn.__init__(self, application, parent) """\ There are 2 classes of windows in tpclient-pywx - winMainBase, This is used for main windows, only one of these windows can be open at one time. - winSubBase, This is used by windows which are children of a main window (reports and such). A winShiftMixIn is also provided which allows the windows to respond to Shift being pressed. """ __all__ = ['winBase', 'winReport', 'ShiftMixIn'] tpclient-pywx-0.3.1.1/windows/winAccount.py0000644000175000017500000001612310773624641017040 0ustar timtim"""\ This module contains the "connect" window which lets a person enter the server/username/password. """ # Python imports import string import os # wxPython Imports import wx from extra.decorators import freeze_wrapper, onlyshown, onlyenabled from requirements import graphicsdir try: from extra.GIFAnimationCtrl import GIFAnimationCtrl except ImportError: from wx.animate import GIFAnimationCtrl from tp.netlib import constants as features # Local Imports from winBase import winBaseXRC from winConnect import usernameMixIn from xrc.winAccount import winAccountBase throbber = os.path.join(graphicsdir, "downloading.gif") okay = os.path.join(graphicsdir, "finished.gif") class winAccount(winAccountBase, winBaseXRC, usernameMixIn): title = _("Account") def __init__(self, application): winAccountBase.__init__(self, None) winBaseXRC.__init__(self, application) usernameMixIn.__init__(self) self.application.gui.Binder(self.application.NetworkClass.NetworkConnectEvent, self.OnNetworkConnect) self.application.gui.Binder(self.application.NetworkClass.NetworkAccountEvent, self.OnNetworkAccount) self.application.gui.Binder(self.application.NetworkClass.NetworkFailureEvent, self.OnNetworkFailure) def Show(self, show=True): if not show: return self.Hide() self.Panel.Layout() size = self.Panel.GetBestSize() self.SetClientSize(size) self.CenterOnScreen(wx.BOTH) url = self.application.gui.servers.URL.GetValue() g = url.rfind('/') url, game = url[:g], url[g+1:] self.Server.SetValue(url) self.State("start") winBaseXRC.Show(self, show) def State(self, mode): if mode == "start": # Enable the host entry box self.Server.Enable() # Show and enable the connect button self.Check.Show() self.Check.Enable() # Stop and hide the throbber self.Checking.LoadFile(throbber) self.Checking.Stop() self.Checking.Hide() # Disable the okay button self.Cancel.Enable() self.Okay.Disable() # Disable the entries self.Username.Disable() self.GameShow.Disable() self.Game.Disable() self.Password1.Disable() self.Password2.Disable() self.Email.Disable() self.Check.SetDefault() self.Server.SetFocus() if mode == "connecting": # Stop the entry to host self.Server.Disable() # Hide the connect button self.Check.Hide() self.Check.Disable() # Show and start the throbber self.Checking.LoadFile(throbber) self.Checking.Show() self.Checking.Play() # Disable the okay button self.Cancel.Enable() self.Okay.Disable() # Disable the entries self.Username.Disable() self.GameShow.Disable() self.Game.Disable() self.Password1.Disable() self.Password2.Disable() self.Email.Disable() if mode == "details": # Stop the entry to host self.Server.Disable() # Show the connect button but disabled self.Check.Hide() self.Check.Disable() # Stop and hide the throbber self.Checking.LoadFile(okay) self.Checking.Show() self.Checking.Play() # Enable the okay button self.Cancel.Enable() self.Okay.Enable() # Enable the entries self.Username.Enable() self.GameShow.Enable() self.Game.Enable() self.Password1.Enable() self.Password2.Enable() self.Email.Enable() self.Username.SetFocus() self.Okay.SetDefault() if mode == "saving": # Stop the entry to host self.Server.Disable() # Show the connect button but disabled self.Check.Hide() self.Check.Enable() # Stop and hide the throbber self.Checking.Show() self.Checking.Play() # Enable the okay button self.Okay.Disable() self.Cancel.Disable() # Enable the entries self.Username.Disable() self.GameShow.Disable() self.Game.Disable() self.Password1.Disable() self.Password2.Disable() self.Email.Disable() self.Panel.Layout() size = self.Panel.GetBestSize() self.SetClientSize(size) @onlyshown @onlyenabled("Check") def OnCheck(self, evt): self.State("connecting") self.application.network.Call(self.application.network.Connect, self.Server.GetValue(), debug=self.application.gui.connectto.config['debug']) @onlyshown def OnNetworkConnect(self, evt): if features.FEATURE_ACCOUNT_REGISTER in evt.args[0]: self.State("details") else: self.OnNetworkFailure(_("This server does not support account creation.")) @onlyshown def OnNetworkAccount(self, evt): self.application.gui.Show(self.application.gui.connectto) dlg = wx.MessageDialog(self.application.gui.current, unicode(evt), _("Account Created"), wx.OK|wx.ICON_INFORMATION) dlg.ShowModal() @onlyshown def OnNetworkFailure(self, evt): dlg = wx.MessageDialog(self.application.gui.current, unicode(evt), _("Network Error"), wx.OK|wx.ICON_ERROR) dlg.ShowModal() self.State("start") @onlyshown @onlyenabled("Okay") def OnOkay(self, evt): username = self.GetUsername() password1 = self.Password1.GetValue().strip() password2 = self.Password2.GetValue().strip() email = self.Email.GetValue().strip() # Check the values are sensible if username == "" or password1 == "" or password2 == "" or email == "": dlg = wx.MessageDialog(self.application.gui.current, _("All fields are required."), _("Fields Required"), wx.OK|wx.ICON_ERROR) dlg.ShowModal() return if password1 != password2: dlg = wx.MessageDialog(self.application.gui.current, _("Password fields do not match."), _("Fields Required"), wx.OK|wx.ICON_ERROR) dlg.ShowModal() return url = self.Server.GetValue() p = url.find('://') if p != -1: p += 3 else: p = 0 username, game = self.GetUsernameGame() fullurl = "%s%s:%s@%s/%s" % (url[:p], username, password1, url[p:], game) self.application.gui.connectto.ShowURL(fullurl) #self.application.network.Call(self.application.network.ConnectTo, host, username, password, debug=self.config['debug']) self.application.network.Call(self.application.network.NewAccount, username, password1, email) @onlyshown @onlyenabled("Cancel") def OnCancel(self, evt): self.application.gui.Show(self.application.gui.servers) # Config Functions ----------------------------------------------------------------------------- def ConfigDefault(self, config=None): """\ Fill out the config with defaults (if the options are not valid or nonexistant). """ if config is None: config = {} try: if not isinstance(config['debug'], bool): raise ValueError('Config-%s: a debug value of %s is not valid' % (self, config['debug'])) except (ValueError, KeyError), e: config['debug'] = False return config def ConfigSave(self): """\ Returns the configuration of the Window (and it's children). """ self.ConfigUpdate() self.ConfigLoad(self.config) return self.config def ConfigLoad(self, config): """\ Loads the configuration of the Window (and it's children). """ return def ConfigUpdate(self): """\ Updates the config details using external sources. """ return def ConfigDisplay(self, panel, sizer): """\ Display a config panel with all the config options. """ return def ConfigDisplayUpdate(self, evt): """\ Updates the config details using external sources. """ return tpclient-pywx-0.3.1.1/windows/winSplash.py0000644000175000017500000000322710773624641016677 0ustar timtim import os from requirements import graphicsdir try: if os.path.exists("NOSPLASHMOVIE"): raise ImportError('Splash movie disabled...') import time os.environ['SDL_VIDEO_CENTERED'] = '1' os.environ['SDL_VIDEO_WINDOW_POS'] = "center" import pygame if not os.path.exists(os.path.join(graphicsdir, "intro-high.mpg")): print "Could not find the intro movie", os.path.join(graphicsdir, "intro-high.mpg") raise ImportError class winSplash(object): def __init__(self, application): pass def Show(self, *args, **kw): pygame.init() screen = pygame.display.set_mode((640,480), pygame.NOFRAME) pygame.mixer.quit() try: self.movie = pygame.movie.Movie(os.path.join(graphicsdir, "intro-high.mpg")) self.movie.set_display(screen, (0,0), ) self.movie.play() except: pass pygame.display.flip() def Hide(self, *args, **kw): print "Entered splash hide!" while True: if not hasattr(self, "movie") or not self.movie.get_busy(): break event = pygame.event.poll() if event.type == pygame.NOEVENT: time.sleep(0.1) elif event.type in (pygame.MOUSEBUTTONUP, pygame.MOUSEBUTTONDOWN, pygame.KEYDOWN, pygame.KEYUP): break while hasattr(self, "movie") and self.movie.get_busy(): self.movie.stop() pygame.quit() def Post(self, evt): pass except ImportError: import wx class winSplash(wx.SplashScreen): def __init__(self, application): image = wx.Image(os.path.join(graphicsdir, "splash.png")).ConvertToBitmap() wx.SplashScreen.__init__(self, image, wx.SPLASH_CENTRE_ON_SCREEN | wx.SPLASH_TIMEOUT, 2500, None, -1) self.application = application def Post(self, evt): pass tpclient-pywx-0.3.1.1/windows/winMain.py0000644000175000017500000002655210773624641016337 0ustar timtim""" This is the primary window for interacting with the game. """ # Python imports import time import math import os.path import sys # wxPython imports import wx from wx.lib.wordwrap import wordwrap # Local imports from requirements import docdir, graphicsdir from winBase import winBase from utils import * import version ID_MENU = 10042 ID_OPEN = 10043 ID_UNIV = 10044 ID_TURN = 10045 ID_EXIT = 10049 ID_FILE = 10050 ID_WIN_TIPS = 11006 ID_WIN_HELP = 1105 ID_HELP = 10057 ID_ONLINE = 10058 ID_ABOUT = 10059 class StatusBar(wx.StatusBar): TEXT_TIMER = 1 def __init__(self, application, parent): wx.StatusBar.__init__(self, parent, -1) self.application = application self.SetFieldsCount(2) self.SetStatusWidths([-10, -2]) self.StatusTextCtrl = wx.TextCtrl(self, -1, "") self.StatusTextCtrl.SetEditable(False) self.endtime = 0 self.parent = parent self.timer = wx.PyTimer(self.Notify) self.timer.Start(1000) self.Notify() self.Reposition() self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_IDLE, self.OnIdle) def Notify(self): sih = 60*60 sim = 60 left = self.endtime - time.time() if left > 0: if left < 120 and left > 0: # Flash the bar if int(left) % 2 == 0: self.StatusTextCtrl.SetOwnBackgroundColour(wx.NullColour) else: self.StatusTextCtrl.SetOwnBackgroundColour(wx.Colour(255,0,0)) else: self.StatusTextCtrl.SetOwnBackgroundColour(wx.NullColour) hours = math.floor(left / sih) mins = math.floor((left - hours * sih) / sim) secs = math.floor((left - hours * sih - mins * sim)) self.StatusTextCtrl.SetValue("EOT: %02i:%02i:%02i" % (hours, mins, secs)) else: self.StatusTextCtrl.SetValue("EOT: Unknown") def SetEndTime(self, endtime): self.endtime = endtime def Reposition(self): rect = self.GetFieldRect(StatusBar.TEXT_TIMER) self.StatusTextCtrl.SetPosition((rect.x, rect.y)) self.StatusTextCtrl.SetSize((rect.width, rect.height)) self.sizeChanged = False def Clear(self): self.Progress.SetValue(0) self.Progress.SetRange(0) self.ProgressCancel.Enable(False) tt = wx.ToolTip("") tt.Enable(False) self.SetToolTip(tt) self.SetStatusText("", StatusBar.TEXT_PROGRESS) del self.progress def OnSize(self, evt): self.Reposition() self.sizeChanged = True def OnIdle(self, evt): if self.sizeChanged: self.Reposition() class winMain(winBase): title = _("Thousand Parsec") def children_get(self): r = {} r.update(self.windows) r.update(self.panels) return r def children_set(self, value): return children = property(children_get, children_set) def __init__(self, application): winBase.__init__(self, application) # Setup the status bar self.statusbar = StatusBar(application, self) self.SetStatusBar(self.statusbar) # Actual windows from windows.main.winDesign import winDesign from windows.main.winIdleFinder import winIdleFinder self.windows = {} for window in [winDesign, winIdleFinder]: title = window.title self.windows[title] = window(application, self) # Setup the AUI interface self.mgr = wx.aui.AuiManager() self.mgr.SetManagedWindow(self) # Panel in the AUI interface... from windows.main.panelInfo import panelInformation from windows.main.panelPicture import panelPicture from windows.main.panelOrder import panelOrder from windows.main.panelMessage import panelMessage from windows.main.panelStarMap import panelStarMap from windows.main.panelSystem import panelSystem self.panels = {} for panel in [panelStarMap, panelSystem, panelMessage, panelInformation, panelPicture, panelOrder]: title = panel.title instance = panel(application, self) self.mgr.AddPane(instance, instance.GetPaneInfo().Caption(title)) self.panels[title] = instance self.mgr.Update() # Setup the Menu self.SetMenuBar(self.Menu(self)) self.updatepending = False self.application.gui.Binder(self.application.NetworkClass.NetworkTimeRemainingEvent, self.OnNetworkTimeRemaining) def Show(self, show=True): # Show this window and it's children - also fixes menus for MacOS if not show: return self.Hide() for window in self.children.values(): try: if hasattr(window, 'config'): if not window.config.has_key('show') or not window.config['show']: continue window.Show() except Exception, e: print "Showing children error", window, e winBase.Show(self) # FIXME: Hack until perspective loading is done.. self.Maximize() # Make the windows all reposition themselves... wx.CallAfter(self.mgr.Update) # Show the tips.. wx.CallAfter(self.ShowTips) def Hide(self, show=True): if not show: return self.Show() #if hasattr(self, "tips"): # self.tips.Close() for window in self.children.values(): window.Hide() super(self.__class__, self).Hide() # Config Functions ----------------------------------------------------------------------------- def ConfigDefault(self, config=None): """\ Fill out the config with defaults (if the options are not valid or nonexistant). """ return def ConfigSave(self): """\ Returns the configuration of the Window (and it's children). """ # Get the details from there children for window in self.children.values(): try: self.config[window.title] = window.ConfigSave() except Exception, e: print e return self.config def ConfigLoad(self, config={}): """\ Loads the configuration of the Window (and it's children). """ return def ConfigUpdate(self): """\ Updates the config details using external sources. """ return def ConfigDisplay(self, panel, sizer): """\ Display a config panel with all the config options. """ return def ConfigDisplayUpdate(self, evt): """\ Update the Display because it's changed externally. """ return # Menu bar options ################################################################## def Menu(self, source): app = wx.GetApp() bar = wx.MenuBar() # File Menu file = wx.Menu() file.Append( ID_OPEN, _("C&onnect to Game\tCtrl-O"), _("Connect to a diffrent Game") ) file.Append( ID_UNIV, _("Download the &Universe\tCtrl-U"), _("Download the Universe") ) file.Append( ID_TURN, _("Request End of &Turn\tCtrl-T"), _("Send a message to the server requesting the turn end soon.") ) file.AppendSeparator() file.Append( wx.ID_PREFERENCES, _("&Preferences"), _("Configure the Client") ) file.AppendSeparator() file.Append( ID_EXIT, _("Exit"), _("Exit") ) # Windows Menu win = wx.Menu() # FIXME: Hack! def OnMenuWindowItem(evt, self=source, windows=self.children): window = windows[self.menu_ids[evt.GetId()]] window.Show(evt.Checked()) source.OnMenuWindowItem = OnMenuWindowItem def OnMenuWindowUpdate(evt, self=source, windows=self.children): menu = self.GetMenuBar().FindItemById(evt.GetId()) if menu.IsChecked() != windows[self.menu_ids[evt.GetId()]].IsShown(): menu.Toggle() source.OnMenuWindowUpdate = OnMenuWindowUpdate source.menu_ids = {} for title in self.windows.keys(): id = wx.NewId() source.menu_ids[id] = title # Add the menu item win.Append(id, _("Show " + title), _(""), True ) # Bind the events source.Bind(wx.EVT_MENU, source.OnMenuWindowItem, id=id) app.Bind(wx.EVT_UPDATE_UI, source.OnMenuWindowUpdate, id=id) win.AppendSeparator() win.Append(ID_WIN_TIPS, _("Show Tips"), _(""), True ) help = wx.Menu() help.Append( ID_ONLINE, _("Online Help"), _("Go to the online help page.")) help.Append( ID_ABOUT, _("About"), _("About the client you are running...") ) bar.Append( file, _("File") ) #bar.Append( stat, _("Statistics") ) bar.Append( win, _("Windows") ) bar.Append( help, _("&Help") ) source.Bind(wx.EVT_MENU, self.OnConnect, id=ID_OPEN) source.Bind(wx.EVT_MENU, self.UpdateCache, id=ID_UNIV) source.Bind(wx.EVT_MENU, self.RequestEOT, id=ID_TURN) source.Bind(wx.EVT_MENU, self.OnConfig, id=wx.ID_PREFERENCES) source.Bind(wx.EVT_MENU, self.OnProgramExit, id=ID_EXIT) source.Bind(wx.EVT_MENU, self.OnHelp, id=ID_ONLINE) source.Bind(wx.EVT_MENU, self.OnAbout, id=ID_ABOUT) source.Bind(wx.EVT_MENU, self.ShowTips, id=ID_WIN_TIPS) return bar def AccelTable(self, source): source.Bind(wx.EVT_KEY_DOWN, self.temp) # File Menu table = wx.AcceleratorTable([ (wx.ACCEL_CTRL, ord('O'), ID_OPEN), (wx.ACCEL_CTRL, ord('U'), ID_UNIV), ]) source.Bind(wx.EVT_MENU, self.temp) source.Bind(wx.EVT_MENU, self.OnConnect, id=ID_OPEN) source.Bind(wx.EVT_MENU, self.UpdateCache, id=ID_UNIV) return table def OnConnect(self, evt): self.application.gui.Show(self.application.gui.connectto) def OnConfig(self, evt): self.application.ConfigDisplay() def OnClose(self, evt): self.OnProgramExit(evt) def OnProgramExit(self, evt): self.mgr.UnInit() self.application.Exit() def ShowTips(self, override=None): config = load_data("pywx_tips") if not config: config = [True, 0] # FIXME: We need some way to programmatically close the tips dialog if config[0] or override != None: self.tips = wx.CreateFileTipProvider(os.path.join(docdir, "tips.txt"), config[1]) config[0] = wx.ShowTip(self, self.tips) config[1] = self.tips.GetCurrentTip() save_data("pywx_tips", config) # Show the "No Objects" warning message foundanobject = False for id in self.application.cache.objects: if hasattr(self.application.cache.objects[id], "owner") and self.application.cache.objects[id].owner == self.application.cache.players[0].id: foundanobject = True if foundanobject == False: wx.CallAfter(self.ShowNoObjectsWarning) def ShowNoObjectsWarning(self): from windows.main.winHelp import winHelp help = winHelp(self.application, self) help.SetMessage(help.message_NoObjects_Subject, help.message_NoObjects_Body) help.Show() def UpdateCache(self, evt=None): self.application.network.Call(self.application.network.CacheUpdate) def RequestEOT(self, evt): """\ """ self.application.network.Call(self.application.network.RequestEOT) def OnNetworkTimeRemaining(self, evt): if evt.remaining == 0: if not self.updatepending: self.updatepending = True msg = _("""\ The turn has ended. Would you like to download all the new details? """) dlg = wx.MessageDialog(self.application.gui.current, msg, _("Update?"), wx.YES_NO|wx.YES_DEFAULT|wx.ICON_INFORMATION) if dlg.ShowModal() == wx.ID_YES: self.UpdateCache() self.updatepending = False else: self.statusbar.SetEndTime(evt.gotat + evt.remaining) def OnHelp(self, evt): url = "http://www.thousandparsec.net/tp/documents/tpclient-pywx?version=%s" % version.version_str if hasattr(version, "version_git"): url += "&version_git=%s" % version.version_git from extra.Opener import open open(url) def OnAbout(self, evt): info = wx.AboutDialogInfo() info.Name = _("wxPython Client") info.Version = version.version_str info.Copyright = _("(C) 2001-2008 Thousand Parsec Developers") info.Description = wordwrap(_("""\ This Thousand Parsec client, written in python, is an easy way to \ join and start playing in a Thousand Parsec game."""), 350, wx.ClientDC(self)) info.WebSite = ("http://www.thousandparsec.net", "Thousand Parsec Website") info.License = wordwrap(open(os.path.join(docdir, "COPYING"), 'r').read(), 600, wx.ClientDC(self)) icon = wx.Icon(os.path.join(graphicsdir, "tp-icon-80x80.png"), wx.BITMAP_TYPE_PNG) info.Icon = icon # Then we call wx.AboutBox giving it that info object wx.AboutBox(info) tpclient-pywx-0.3.1.1/windows/winUpdate.py0000644000175000017500000002040110773624641016660 0ustar timtim # Python imports import os, os.path import time # wxPython Imports import wx from extra.decorators import freeze_wrapper, onlyshown, onlyenabled # Config imports from requirements import graphicsdir # Local Imports from winBase import winBaseXRC from xrc.winUpdate import winUpdateBase throbber = os.path.join(graphicsdir, "downloading.gif") okay = os.path.join(graphicsdir, "finished.png") waiting = os.path.join(graphicsdir, "waiting.png") class winUpdate(winUpdateBase, winBaseXRC): title = _("Updating") def __init__(self, application): winUpdateBase.__init__(self, None) winBaseXRC.__init__(self, application) self.GoDown = False if wx.Platform == "__WXMAC__": self.ConnectingText.SetLabel("___________") self.ConnectingText.SetMinSize(self.ConnectingText.GetBestSize()) self.ProgressText.SetLabel("___________") self.ProgressText.SetMinSize(self.ProgressText.GetBestSize()) self.ProgressTitle.SetLabel("_________________________________") self.ProgressTitle.SetMaxSize(self.ProgressTitle.GetBestSize()) self.ProgressTitle.SetMinSize(self.ProgressTitle.GetBestSize()) self.ProgressTitle.SetSize(self.ProgressTitle.GetBestSize()) self.ProgressAnim.SetMinSize((32, 32)) self.ConnectingAnim.SetMinSize((32, 32)) else: self.Panel.GetSizer().GetItem(2).GetSizer().RemoveGrowableCol(1) self.Panel.Layout() self.Panel.Update() @onlyshown @onlyenabled("Cancel") def OnCancel(self, evt): self.application.network.Reset() self.application.gui.Show(self.application.gui.connectto) @onlyshown @onlyenabled("Save") def OnSave(self, evt): dlg = wx.FileDialog(self, message=_("Save log as ..."), defaultDir=os.getcwd(), defaultFile="update.log", wildcard="Log file (*.log)|*.log", style=wx.SAVE) dlg.SetFilterIndex(0) if dlg.ShowModal() != wx.ID_OK: return path = dlg.GetPath() self.Message.SaveFile(path) @onlyshown @onlyenabled("Okay") def OnOkay(self, evt): self.application.gui.Show(self.application.gui.main) self.application.Post(self.application.cache.CacheUpdateEvent(None)) @onlyshown def MessageDown(self, evt=None): if self.GoDown: self.Message.ShowPosition(self.Message.GetLastPosition()) self.GoDown = False if self.Okay.IsEnabled(): self.Okay.SetFocus() if wx.Platform == "__WXMAC__": self.Message.Disable() def Clear(self): # Enable the cancel button self.Cancel.Enable() #self.TopText.SetLabel("") self.Message.SetValue("") self.ConnectingGauge.Enable() self.ConnectingGauge.SetRange(1) self.ConnectingGauge.SetValue(0) self.ConnectingAnim.Enable() self.ConnectingAnim.LoadFile(waiting) self.ConnectingAnim.Play() self.ConnectingText.Enable() self.ConnectingText.SetLabel("") self.ProgressTitle.SetLabel("") self.ProgressTitle.Hide() self.ProgressGauge.Disable() self.ProgressGauge.SetRange(1) self.ProgressGauge.SetValue(0) self.ProgressGauge.Hide() self.ProgressAnim.LoadFile(waiting) self.ProgressAnim.Play() self.ProgressAnim.Hide() self.ProgressText.SetLabel("") self.ProgressText.Hide() self.ObjectdescsAnim.LoadFile(waiting) self.ObjectdescsAnim.Play() self.OrderdescsAnim.LoadFile(waiting) self.OrderdescsAnim.Play() self.ObjectsAnim.LoadFile(waiting) self.ObjectsAnim.Play() self.OrdersAnim.LoadFile(waiting) self.OrdersAnim.Play() self.BoardsAnim.LoadFile(waiting) self.BoardsAnim.Play() self.MessagesAnim.LoadFile(waiting) self.MessagesAnim.Play() self.CategoriesAnim.LoadFile(waiting) self.CategoriesAnim.Play() self.DesignsAnim.LoadFile(waiting) self.DesignsAnim.Play() self.ComponentsAnim.LoadFile(waiting) self.ComponentsAnim.Play() self.PropertiesAnim.LoadFile(waiting) self.PropertiesAnim.Play() self.PlayersAnim.LoadFile(waiting) self.PlayersAnim.Play() self.ResourcesAnim.LoadFile(waiting) self.ResourcesAnim.Play() self.Okay.Disable() self.Save.Disable() def Show(self, show=True): if not show: return self.Hide() # Clear everything self.Clear() self.CenterOnScreen(wx.BOTH) return winBaseXRC.Show(self) @onlyshown @freeze_wrapper def Callback(self, mode, state, message="", todownload=None, total=None, amount=None): self.ObjectdescsAnim.LoadFile(okay) self.ObjectdescsAnim.Play() # We do a little bit different for this mode if mode == "connecting": animation = getattr(self, "%sAnim" % mode.title()) if state == "start": # Start the connection throbber animation.LoadFile(throbber) animation.Play() elif state == "todownload": self.ConnectingGauge.SetValue(0) self.ConnectingGauge.SetRange(todownload) elif state == "downloaded": self.ConnectingGauge.SetValue(self.ConnectingGauge.GetValue()+amount) elif state == "finished": # Change to the tick animation.LoadFile(okay) animation.Play() # Set the gauge as completed! self.ConnectingGauge.SetValue(self.ConnectingGauge.GetRange()) # Set the progress text self.ConnectingText.SetLabel(_("Done!")) elif state == "alreadydone": self.ConnectingGauge.SetRange(1) self.ConnectingGauge.SetValue(1) #self.ConnectingGauge.Disable() self.ConnectingText.Disable() animation.Disable() elif mode == "finishing": self.ProgressTitle.SetLabel(_("Update done!")) # Change to the tick self.ProgressAnim.LoadFile(okay) self.ProgressAnim.Play() # Change the buttons self.Okay.Enable() self.Okay.SetFocus() self.Save.Enable() self.Cancel.Disable() else: animation = getattr(self, "%sAnim" % mode.title()) self.ProgressTitle.Show() self.ProgressGauge.Show() self.ProgressAnim.Show() self.ProgressText.Show() if state == "start": # Set the progress title self.ProgressTitle.SetLabel(_("Getting %s" % mode.title())) # Set the progress guage to be empty self.ProgressGauge.Enable() self.ProgressGauge.SetValue(0) self.ProgressGauge.SetRange(1) # Set the progress text self.ProgressText.SetLabel("") # Set the progress animation self.ProgressAnim.LoadFile(throbber) self.ProgressAnim.Play() # Start the throbber for this mode animation.LoadFile(throbber) animation.Play() elif state == "todownload": # Now we know how big to set the gauge too if todownload == 0: self.ProgressGauge.SetValue(1) self.ProgressGauge.SetRange(1) else: self.ProgressGauge.SetValue(0) self.ProgressGauge.SetRange(todownload) # Update the text self.ProgressText.SetLabel(_("%s of %s") % (0, todownload)) elif state == "progress": # Nothing to do... pass elif state == "downloaded": # Progress the progress gauge self.ProgressGauge.SetValue(self.ProgressGauge.GetValue()+amount) # Update the text self.ProgressText.SetLabel(_("%s of %s") % \ (self.ProgressGauge.GetValue(), self.ProgressGauge.GetRange())) elif state == "finished": # Change to the tick animation.LoadFile(okay) animation.Play() # Set the gauge as completed! self.ProgressGauge.SetValue(self.ProgressGauge.GetRange()) # Set the progress text self.ProgressText.SetLabel(_("Done!")) # Stop the progress animation self.ProgressAnim.Stop() if len(message) > 0: self.Message.AppendText(message+"\n") self.Panel.Layout() self.Panel.Update() self.GoDown = True if state == "failure": # Don't do anything for now end = self.Message.GetLastPosition() self.Message.SetStyle(end-len(message)-1, end, wx.TextAttr(wx.RED)) self.UpdateWindowUI(wx.UPDATE_UI_RECURSE) wx.CallAfter(self.MessageDown) # Config Functions ----------------------------------------------------------------------------- def ConfigDefault(self, config=None): """\ Fill out the config with defaults (if the options are not valid or nonexistant). """ return {} def ConfigSave(self): """\ Returns the configuration of the Window (and it's children). """ return {} def ConfigLoad(self, config={}): """\ Loads the configuration of the Window (and it's children). """ pass def ConfigUpdate(self): """\ Updates the config details using external sources. """ pass def ConfigDisplay(self, panel, sizer): """\ Display a config panel with all the config options. """ pass def ConfigDisplayUpdate(self, evt): """\ Update the Display because it's changed externally. """ pass tpclient-pywx-0.3.1.1/windows/winConnect.py0000644000175000017500000003245510773624641017043 0ustar timtim"""\ This module contains the "connect" window which lets a person enter the server/username/password. """ # Python imports import string import re # wxPython Imports import wx import wx.gizmos from extra.decorators import freeze_wrapper # Local Imports from winBase import winBaseXRC from xrc.winConnect import winConnectBase from xrc.configConnect import configConnectBase from utils import * from tp.netlib.client import url2bits # FIXME: The game really isn't part of the username, it's part of the server information # You could be playing multiple different games on the same server! class usernameMixIn: def __init__(self): self.Username.Bind(wx.EVT_CHAR, self.OnUsernameChar) self.Game.Bind(wx.EVT_CHAR, self.OnGameChar) @freeze_wrapper def OnGameShow(self, evt): if self.GameShow.GetValue(): self.SetUsername(self.Username.GetValue()) # Show the game boxes self.GameTitle.Show() self.Game.Show() else: self.SetUsername("%s@%s" % (self.Username.GetValue(), self.Game.GetValue())) # Hide the game boxes self.GameTitle.Hide() self.Game.Hide() self.Panel.Layout() size = self.Panel.GetBestSize() self.SetClientSize(size) def OnUsernameChar(self, evt): if isinstance(evt.KeyCode, (int,long)): key = evt.KeyCode else: key = evt.KeyCode() if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255: evt.Skip() return if chr(key) in string.letters+string.digits: evt.Skip() return if not self.GameShow.GetValue(): if chr(key) == '@': evt.Skip() return return def OnGameChar(self, evt): if isinstance(evt.KeyCode, (int,long)): key = evt.KeyCode else: key = evt.KeyCode() if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255: evt.Skip() return if chr(key) in string.letters+string.digits: evt.Skip() return return def GetUsername(self): username = self.Username.GetValue() game = self.Game.GetValue().strip() if self.GameShow.GetValue() and len(game) > 0: return "%s@%s" % (username, game) else: return username def GetUsernameGame(self): username = self.Username.GetValue() game = self.Game.GetValue().strip() return (username, game) def SetUsername(self, value): # Split the part after the @ into the game box username = value.split('@') if len(username) == 2: username, game = username else: username = username[0] game = "" if self.GameShow.GetValue() or len(game) == 0: self.Username.SetValue(username) else: self.Username.SetValue("%s@%s" % (username, game)) self.Game.SetValue(game) class configConnect(configConnectBase, usernameMixIn): def __init__(self, *args, **kw): configConnectBase.__init__(self, *args, **kw) usernameMixIn.__init__(self) self.Panel = self self.GameShow.MoveAfterInTabOrder(self.Password) self.Servers.SetMinSize(wx.Size(300, -1)) self.Layout() # Use better Art Graphics for the EditableList custom = { "Del": wx.ART_DELETE, "New": wx.ART_NEW, "Up": wx.ART_GO_UP, "Down": wx.ART_GO_DOWN, "Edit": wx.ART_REPORT_VIEW,} for name, id in custom.items(): bmp = wx.ArtProvider_GetBitmap(id, wx.ART_TOOLBAR, (16,16)) if not bmp.Ok(): continue button = getattr(self.Servers, "Get%sButton" % name)() button.SetBitmapLabel(bmp) button.SetBitmapDisabled(bmp) def EnableDetails(self, label): self.ServerDetails.SetLabel(_("Login for %s") % (label,)) self.Username.Enable() self.Game.Enable() self.GameShow.Enable() self.Password.Enable() self.AutoConnect.Enable() def DisableDetails(self): #self.ServerDetails.SetLabel(" ") self.Username.Disable() self.Username.SetValue("") self.Game.Disable() self.Game.SetValue("") self.GameShow.Disable() self.Password.Disable() self.Password.SetValue("") self.AutoConnect.Disable() USERNAME=0 PASSWORD=1 AUTOCONNECT=2 # FIXME: The config should use proper URLs, currently you can't have more then one login to a server (and a server could have multiple games). class winConnect(winConnectBase, winBaseXRC, usernameMixIn): title = _("Connect") def Post(*args): pass def __init__(self, application): winConnectBase.__init__(self, None) winBaseXRC.__init__(self, application) usernameMixIn.__init__(self) self.attemps = 0 self.GameShow.MoveAfterInTabOrder(self.Okay) self.Bind(wx.EVT_CLOSE, self.OnExit) self.Bind(wx.EVT_COMBOBOX, self.OnChangeServer, self.Server) def OnChangeServer(self, evt): server = self.Server.GetValue() if server in self.config['servers']: self.SetUsername(self.config['details'][server][0]) self.Password.SetValue(self.config['details'][server][1]) def OnExit(self, evt): self.application.Exit() def SetFromConfig(self, server): if not server in self.config['servers'] or not self.config['details'].has_key(server): raise RuntimeError("Server is not in the config settings!") self.Server.SetValue(server) self.SetUsername(self.config['details'][server][USERNAME]) self.Password.SetValue(self.config['details'][server][PASSWORD]) return self.config['details'][server][AUTOCONNECT] def Show(self, show=True): if not show: return self.Hide() self.Panel.Layout() size = self.Panel.GetBestSize() self.SetClientSize(size) self.CenterOnScreen(wx.BOTH) autoconnect = False # If the server value is empty we should populate with a server item if len(self.Server.GetValue()) == 0: # Check that no other server is also set to autoconnect for key in self.config['details'].keys(): if not self.config['details'][key][AUTOCONNECT]: continue self.SetFromConfig(key) autoconnect = True # Is it still empty? if len(self.Server.GetValue()) == 0 and len(self.config['servers']) > 0: autoconnect = self.SetFromConfig(self.config['servers'][0]) # FIXME: Gross hack if self.attemps == 0 and autoconnect: wx.CallAfter(self.OnOkay, None) self.attemps += 1 return winBaseXRC.Show(self) def OnOkay(self, evt): server = self.Server.GetValue() username = self.GetUsername() password = self.Password.GetValue() if server == "" or username == "": return # Check if this server exists in the config if server in self.config['servers']: # Check the values are the same (oldusername, oldpassword, oldautoconnect) = self.config['details'][server] else: (oldusername, oldpassword, oldautoconnect) = (username, password, False) if server not in self.config['servers'] or username != username: # Popup a dialog asking if we want to add the account msg = _("""\ It appears you havn't access this account before. Would you like to save this account's details? """) dlg = wx.MessageDialog(self, msg, _("Add Account?"), wx.YES_NO|wx.YES_DEFAULT|wx.ICON_INFORMATION) if dlg.ShowModal() == wx.ID_YES: # Add the account. if not server in self.ConfigPanel.Servers.GetStrings(): self.ConfigPanel.Servers.SetStrings([server,] + self.ConfigPanel.Servers.GetStrings()) self.config['details'][server] = [username, password, False] # Save the config now self.application.ConfigSave() elif password != oldpassword: msg = _("""\ It appears you are using a different password for this account, would you like to update the saved information with the new password? """) dlg = wx.MessageDialog(self, msg, _("Update Password?"), wx.YES_NO|wx.YES_DEFAULT|wx.ICON_INFORMATION) if dlg.ShowModal() == wx.ID_YES: # Update the password self.config['details'][server][PASSWORD] = password # Save the config now self.application.ConfigSave() self.application.network.Call(self.application.network.ConnectTo, server, username, password, debug=self.config['debug']) def OnCancel(self, evt): self.OnExit(evt) def OnConfig(self, evt): self.application.ConfigDisplay() def OnFind(self, evt): self.application.gui.Show(self.application.gui.servers) def ShowURL(self, url): # Split the URL out into username, password, etc # ://:@/ # server = :/// # username = @ # password = server, username, game, password = url2bits(url) if server is None or len(server) == 0: return self.Server.SetValue(server) if username is None: username = "" if not game is None: username = "%s@%s" % (username, game) self.SetUsername(username) if password is None: password = "" self.Password.SetValue(password) # Config Functions ----------------------------------------------------------------------------- def ConfigDefault(self, config=None): """\ Fill out the config with defaults (if the options are not valid or nonexistant). """ if config is None: config = {} try: if not isinstance(config['servers'], list): raise ValueError('Config-%s: a servers value of %s is not valid' % (self, config['servers'])) for server in config['servers']: if not isinstance(server, (str, unicode)): config['servers'].remove(server) if len(config['servers']) <= 0: raise ValueError('Config-%s: the servers list was empty' % (self,)) except (ValueError, KeyError), e: config['servers'] = ["demo1.thousandparsec.net", "demo2.thousandparsec.net", "127.0.0.1"] try: if not isinstance(config['details'], dict): raise ValueError('Config-%s: a details value of %s is not valid' % (self, config['details'])) for server, details in config['details'].items(): if not isinstance(details, list) or len(details) != 3 or \ not isinstance(details[0], (str, unicode)) or \ not isinstance(details[1], (str, unicode)) or \ not isinstance(details[2], bool): del config[server] except (ValueError, KeyError), e: config['details'] = {} for server in config['servers']: if server not in config['details']: config['details'][server] = ["guest@tp", "guest", False] try: if not isinstance(config['debug'], bool): raise ValueError('Config-%s: a debug value of %s is not valid' % (self, config['debug'])) except (ValueError, KeyError), e: config['debug'] = False return config def ConfigSave(self): """\ Returns the configuration of the Window (and it's children). """ self.ConfigUpdate() self.ConfigLoad(self.config) return self.config def ConfigLoad(self, config): """\ Loads the configuration of the Window (and it's children). """ self.config = config self.ConfigDefault(config) #self.Server.Clear() self.Server.AppendItems(self.config['servers']) #self.Server.SetValue(self.config['servers'][0]) self.ConfigDisplayUpdate(None) def ConfigUpdate(self): """\ Updates the config details using external sources. """ self.config['debug'] = self.ConfigPanel.Debug.GetValue() self.config['servers'] = self.ConfigPanel.Servers.GetStrings() for removed in self.config['details'].keys(): if not removed in self.config['servers']: del self.config['details'][removed] def ConfigDisplay(self, panel, sizer): """\ Display a config panel with all the config options. """ self.ConfigPanel = configConnect(panel) self.ConfigPanel.Servers.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.OnConfigSelectServer) self.ConfigPanel.Servers.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.OnConfigSelectServer) self.ConfigPanel.Username.Bind(wx.EVT_KILL_FOCUS, self.OnConfigUsername) self.ConfigPanel.Game.Bind(wx.EVT_KILL_FOCUS, self.OnConfigUsername) self.ConfigPanel.Password.Bind(wx.EVT_KILL_FOCUS, self.OnConfigPassword) self.ConfigPanel.AutoConnect.Bind(wx.EVT_CHECKBOX, self.OnConfigAutoConnect) self.ConfigPanel.Debug.Bind(wx.EVT_CHECKBOX, self.OnConfigDebug) sizer.Add( self.ConfigPanel, 1, wx.EXPAND, 5 ) def ConfigDisplayUpdate(self, evt): """\ Updates the config details using external sources. """ if evt != None: evt.Skip() self.ConfigPanel.Debug.SetValue(self.config['debug']) self.ConfigPanel.Servers.SetStrings(self.config['servers']) def OnConfigSelectServer(self, evt): server = evt.GetText() if len(server) > 0: self.ConfigPanel.EnableDetails(server) if not self.config['details'].has_key(server): self.config['details'][server] = [self.ConfigPanel.GetUsername(), self.ConfigPanel.Password.GetValue(), False] self.ConfigPanel.SetUsername(self.config['details'][server][0]) self.ConfigPanel.Password.SetValue(self.config['details'][server][1]) self.ConfigPanel.AutoConnect.SetValue(self.config['details'][server][2]) else: self.ConfigPanel.DisableDetails() evt.Skip() def OnConfigUsername(self, evt): server = self.ConfigPanel.ServerDetails.GetLabel()[len(_("Login for ")):] self.config['details'][server][0] = self.ConfigPanel.GetUsername() def OnConfigPassword(self, evt): server = self.ConfigPanel.ServerDetails.GetLabel()[len(_("Login for ")):] self.config['details'][server][1] = self.ConfigPanel.Password.GetValue() def OnConfigAutoConnect(self, evt): server = self.ConfigPanel.ServerDetails.GetLabel()[len(_("Login for ")):] if evt.Checked(): # Check that no other server is also set to autoconnect for key, details in self.config['details'].items(): if not details[2]: continue msg = _(""" The client is already set to autoconnect to %s. Would you instead like to autoconnect to %s. """) % (key, server) dlg = wx.MessageDialog(self.ConfigPanel, msg, _("Autoconnect to?"), wx.OK|wx.CANCEL|wx.ICON_INFORMATION) if dlg.ShowModal() == wx.ID_OK: details[2] = False break self.config['details'][server][2] = evt.Checked() def OnConfigDebug(self, evt): self.config['debug'] = evt.Checked() tpclient-pywx-0.3.1.1/README0000644000175000017500000000342710773624641013545 0ustar timtim The wxPython client for Thousand Parsec (TP) ============================================ Requirements (all versions must be greater): python >2.4 wxPython >2.8.0 python-numpy libtpclient-py >0.3.0 libtpproto-py >0.2.2 Recommendations: Pygame pyopenssl or python-openssl Pysco Python Imaging Library To check that you have all the requirements installed you can run the requirements.py file. It will give you information about is installed and what it couldn't find. On Debian (such as Ubuntu) based platforms it will even give you instructions how to install them. How to use ============================================ The client can be run from the location you downloaded on Linux, Windows and Mac or installed on the system on Linux. In windows, double click on tpclient-pywx file. In linux, change to the tpclient-pywx directory and run "./tpclient-pywx". Disabling the splash movie ============================================ The splash movie can annoy some people. If you wish to disable it you can create a "NOSPLASHMOVIE" file in the top level directory. Keyboard Short Cuts ============================================ The client has a number of keyboard shortcuts, Menu shortcuts: * Ctrl-U, Download the universe * Crtl-O, Connect to a different server Star Map shortcuts: * arrow keys, scroll the star map * wasd, scroll the star map * +, zoom in the star map (at the mouse position) * -, zoom out the star map (at the mouse position) * Esc, change back to mouse mode * m, change to waypoint mode (shift will add a single move order) Order manipulation: * Delete, remove the currently selected order * <, next order (shift will add the next order to the selection) * >, previous order (shift will add the previous order to the selection) tpclient-pywx-0.3.1.1/version.py0000644000175000017500000000343510773624641014723 0ustar timtim version = (0, 3, 1) # Add the git version if in a git tree... import os, os.path __path__ = os.path.realpath(os.path.dirname(__file__)) installpath = __path__ # Get the git version this tree is based on if os.path.exists(os.path.join(installpath, '.git')): # Read in git's 'HEAD' file which points to the correct reff to look at h = open(os.path.join(installpath, '.git', 'HEAD')) try: # Read in the ref ref = h.readline().strip().split(': ', 1)[1] # This file has the SHA1 p = open(os.path.join(installpath, '.git', ref)) del ref version_git = p.read().strip() except IndexError: h.seek(0) version_git = h.readline().strip() # What version are we trying to get too? import time if version[2] >= 99: version_target = (version[0], version[1]+1, 0) else: version_target = (version[0], version[1], version[2]+1) version_target_str = "%i.%i.%i" % version_target version_str = "%i.%i.%i" % version[:3] if __name__ == "__main__": import sys if len(sys.argv) > 1 and sys.argv[1] == '--fix': print """ import os, os.path __path__ = os.path.realpath(os.path.dirname(__file__)) installpath = os.path.split(os.path.split(__path__)[0])[0] """ for value in dir(): if value.startswith('__') or value in ('installpath',): continue if isinstance(eval(value), (tuple, str, unicode)): exec("print '%s =', repr(%s)" % (value, value)) print """ try: print version_str+'+'+version_target_str, "(git %s)" % version_git, "(installed at %s)" % installpath except (ValueError, NameError): print version_str, "(installed at %s)" % installpath """ sys.exit(0) if os.path.exists(os.path.join(installpath, '.git')): print version_str+'+'+version_target_str, "(git %s)" % version_git, "(installed at %s)" % installpath else: print version_str, "(installed at %s)" % installpath tpclient-pywx-0.3.1.1/setup.py0000755000175000017500000002542410773624641014403 0ustar timtim#!/usr/bin/env python import shutil import sys import glob import os.path from setuptools import setup from version import version version = ("%s.%s.%s" % version) print "Version is %s" % version arguments = dict( # Meta data name="tpclient-pywx", version=version, license="GPL", description="wxPython based client for Thousand Parsec", author="Tim Ansell", author_email="tim@thousandparsec.net", url="http://www.thousandparsec.net", # Files to include scripts=["tpclient-pywx"], packages=[ \ '.', 'windows', 'windows.main', 'windows.main.overlays', 'windows.xrc', 'extra', 'extra.wxFloatCanvas', 'extra.wxFloatCanvas.Utilities', ], data_files=[(".", ("LICENSE", "README")), ("doc", ("doc/tips.txt","doc/COPYING")), ("windows/xrc", glob.glob("windows/xrc/*.xrc")), ("graphics", glob.glob("graphics/*.mpg")), ("graphics", glob.glob("graphics/*.gif")), ("graphics", glob.glob("graphics/*.png")), ("graphics", glob.glob("graphics/*.ico"))], ) if sys.platform.startswith('linux') and "install" in sys.argv: import os, shutil # Clean up locally os.system('rm `find -name \*.pyc`') def makedirs(s): try: os.makedirs(s) except OSError, e: if e.errno != 17: raise return prefix = "/usr/local" temp = None if "--prefix" in sys.argv: prefix = sys.argv[sys.argv.index('--prefix')+1] if "--temp" in sys.argv: temp = sys.argv[sys.argv.index('--temp')+1] for arg in sys.argv: if arg.startswith('--prefix='): trash, prefix = arg.split('=') elif arg.startswith('--temp='): trash, temp = arg.split('=') include_support = "--include-support" in sys.argv # If temp was not set, it should just be the prefix if temp is None: temp = prefix print "Installing to...", temp print "Target is...", prefix # Documentation goes to ######################################################################### docpath_temp = os.path.join(temp, "share/doc/tpclient-pywx") docpath = os.path.join(prefix, "share/doc/tpclient-pywx") print 'docpath', docpath, "(copying to %s)" % docpath_temp makedirs(docpath_temp) docfiles = ['AUTHORS', 'doc/COPYING', 'LICENSE', 'doc/tips.txt'] for file in docfiles: shutil.copy2(file, docpath_temp) # Locale files ######################################################################### localepath_temp = os.path.join(temp, "share/locale/%s/LC_MESSAGES/") localepath = os.path.join(prefix, "share/locale/%s/LC_MESSAGES/") print 'localepath', localepath, "(copying to %s)" % localepath_temp for dir in os.listdir('locale'): if os.path.isfile(os.path.join('locale', dir)): continue print "Installing language files for %s" % dir llocalepath = localepath_temp % dir makedirs(llocalepath) shutil.copy2(os.path.join('locale', dir, 'tpclient-pywx.mo'), llocalepath) # Graphics files ######################################################################### graphicspath_temp = os.path.join(temp, "share/tpclient-pywx/graphics") graphicspath = os.path.join(prefix, "share/tpclient-pywx/graphics") print 'graphicspath', graphicspath, "(copying to %s)" % graphicspath_temp if os.path.exists(graphicspath_temp): shutil.rmtree(graphicspath_temp) shutil.copytree('graphics', graphicspath_temp) # Private python file ######################################################################### codepath_temp = os.path.join(temp, "share/tpclient-pywx") codepath = os.path.join(prefix, "share/tpclient-pywx") print 'librarypath', codepath, "(copying to %s)" % codepath_temp try: makedirs(codepath_temp) except OSError: pass privatefiles = ['tpclient-pywx', 'version.py', 'requirements.py', 'utils.py', 'windows', 'extra'] for file in privatefiles: if os.path.isfile(file): shutil.copy2(file, codepath_temp) if os.path.isdir(file): p = os.path.join(codepath_temp, file) if os.path.exists(p): shutil.rmtree(p) shutil.copytree(file, p) # Fix the version path os.system('python version.py --fix > %s' % os.path.join(codepath_temp, 'version.py')) # Cleanup some files which shouldn't have been copied... cleanupfiles = ['windows/xrc/generate.sh', 'windows/xrc/tp.pjd', 'windows/xrc/tp.xrc'] for file in cleanupfiles: os.unlink(os.path.join(codepath_temp, file)) # Create the startup script tpin = open(os.path.join('doc', 'tp-pywx-installed'), 'rb').read() tpin = tpin.replace("$$CODEPATH$$", codepath) tpin = tpin.replace("$$GRAPHICSPATH$$", graphicspath) tpin = tpin.replace("$$DOCPATH$$", docpath) tpout = open(os.path.join(codepath_temp, 'tp-pywx-installed'), 'wb') tpout.write(tpin) tpout.close() os.chmod(os.path.join(codepath_temp, 'tp-pywx-installed'), 0755) # Executables binpath_temp = os.path.join(temp, "bin") binpath = os.path.join(prefix, "bin") print 'binpath', binpath, "(copying to %s)" % binpath_temp makedirs(binpath_temp) binp = os.path.join(binpath_temp, 'tpclient-pywx') if os.path.exists(binp): os.unlink(binp) os.symlink(os.path.join(codepath, 'tp-pywx-installed'), binp) print "Client installed!" sys.exit() if not "py2app" in sys.argv and not "py2exe" in sys.argv: print "This file is only provided to do the following, (python setup.py py2exe)" print " producing py2exe executable bundles for windows (python setup.py py2app)" print " producing py2app dmg packages for Mac OS X (python setup.py install)" print " installing (a release) on a unix system" if os.path.exists(".git"): print print "WARNING!!" print " You seem to be running a git checkout (hence you don't want to be running this file)." print " tpclient-pywx can be run straight from this directory by just typing:" print " ./tpclient-pywx" sys.exit() if sys.platform == 'darwin': import py2app from setuptools import find_packages print find_packages() # Fix the version path os.system('git checkout version.py') os.system('python version.py --fix > %s' % 'version.py.tmp') os.unlink('version.py') os.rename('version.py.tmp', 'version.py') shutil.copy('tpclient-pywx', 'tpclient-pywx.py') arguments['scripts']=["tpclient-pywx.py"] # Py2App stuff extra_arguments = dict( app=["tpclient-pywx.py"], options = { "py2app": { "argv_emulation": True, "compressed" : True, "strip" : False, "optimize" : 2, "packages" : find_packages(), "includes" : [], "excludes" : ['Tkconstants', 'Tkinter', 'tcl', 'pydoc', 'pyreadline', 'numpy.numarray', 'numpy.oldnumeric', 'numpy.distutils', 'numpy.doc', 'numpy.f2py', 'numpy.fft', 'numpy.lib.tests', 'numpy.testing'], "resources" : arguments['data_files'], "iconfile" : "graphics/tp.icns", "plist" : { "CFBundleSignature": "tppy", "CFBundleIdentifier": "net.thousandparsec.client.python.wx", "CSResourcesFileMapped": True, "CFBundleIconFile": "tp.icns", "CFBundleGetInfoString": "Thousand Parsec wxPython Client %s" % version, "CFBundleName": "tpclient-pywx", "CFBundleShortVersion": version, "CFBundleURLTypes": { "CFBundleTypeRole": "Viewer", "CFBundleURLIconFile": "tp.icns", "CFBundleURLName": "Thousand Parsec URI", "CFBundleURLSchemes": ["tp", "tps", "tp-http", "tp-https",], }, "LSMinimumSystemVersion": "10.3.9", # "LSUIPresentationMode": 1, } } } ) elif sys.platform == 'win32': import py2exe if os.path.exists("dist"): shutil.rmtree("dist") bat = os.path.join("..", "scratchpad", "setup.bat") if os.path.exists(bat): os.system(bat) # Py2EXE stuff extra_arguments = dict( windows=[{ "script": "tpclient-pywx", "icon_resources": [(1, "graphics/icon.ico")], }], options={ "py2exe": { "dll_excludes": [], "packages": ["tp.netlib", "tp.client"], "excludes": ["Tkconstants", "Tkinter", "tcl", "pydoc" ], "optimize": 2, "compressed": 0, } }, ) else: print "You shouldn't be running this (as it's only for Mac or Windows maintainers).." sys.exit() arguments.update(extra_arguments) setup(**arguments) if sys.platform == 'darwin': if "py2app" in sys.argv: basedir = os.path.join("dist", "tpclient-pywx.app", "Contents") # Need to do some cleanup because the modulegraph is a bit brain dead base = os.path.join(basedir, "Resources", "lib", "python2.5") for i in ( "xrc", "main", "overlays", "wxFloatCanvas", "Utilities", # local excesses "netlib", "objects", "ObjectExtra", "OrderExtra", "support", "discover", "pyZeroconf", "client", "pyscheme", "discover", # Numpy, numpy, numpy "numpy/oldnumeric", "numpy/numarray", "numpy/doc", "numpy/lib/tests", "numpy/distutils" "numpy/core/tests", ): p = os.path.join(base, i) if os.path.exists(p): print "Removing", p shutil.rmtree(p) # Remove the pyscheme tests pyschemet = os.path.join(base, "tp", "client", "pyscheme", "t") if os.path.exists(pyschemet): shutil.rmtree(pyschemet) # Need to clean up any .py$ files which got included for some unknown reason... # Need to clean up any .pyc$ when a .pyo$ exists too for line in os.popen('find %s -name \*.pyc' % basedir).xreadlines(): py = line.strip()[:-1] pyc = py+'c' pyo = py+'o' if os.path.exists(py): print "Removing %s as %s exists" % (py, pyo) os.unlink(py) if "numpy" in line: continue if os.path.exists(pyo): print "Removing %s as %s exists" % (pyc, pyo) os.unlink(pyc) # Clean up any ~ which got wrongly copied in.. for line in os.popen('find %s -name \*~' % basedir).xreadlines(): os.unlink(line.strip()) # Create a package dmg = "tpclient-pywx_%s.dmg" % version if os.path.exists(dmg): os.unlink(dmg) print "Creating dmg package" os.system("cd doc/mac/; chmod a+x pkg-dmg make-diskimage; ./make-diskimage ../../%s ../../dist tpclient-pywx -null- dstore background.jpg ../../graphics/tp.icns" % dmg) # Restore the version.py back to the git version... os.system('git checkout version.py') elif sys.platform == 'win32': # Copy in the manifest file for that "Windows XP look" shutil.copy("tpclient-pywx.exe.manifest", os.path.join("dist", "tpclient-pywx.exe.manifest")) import wx # Check that msvcp71.dll msvcpsrc = os.path.join(os.path.dirname(wx.__file__), "msvcp71.dll") if not os.path.exists(msvcpsrc): raise IOError("msvcp71.dll doesn't exist! Copy it to dist!") shutil.copy(msvcpsrc, os.path.join("dist", "msvcp71.dll")) # Check that gdi.dll exists, some windows need it gdisrc = os.path.join(os.path.dirname(wx.__file__), "gdiplus.dll") if not os.path.exists(gdisrc): raise IOError("gdiplus.dll doesn't exist! Copy it to dist!") shutil.copy(gdisrc, os.path.join("dist", "gdiplus.dll")) # Repack the library.zip file os.system(os.path.join("..", "scratchpad", "repack.bat")) # We should now use upx on the executables to make em smaller. os.system("upx --best .\dist\*.pyd") os.system("upx --best .\dist\*.dll") os.system("upx --best .\dist\*.exe") # Should generate the setup.nsi now. # Should run NSIS now. tpclient-pywx-0.3.1.1/graphics/0000755000175000017500000000000010773624641014457 5ustar timtimtpclient-pywx-0.3.1.1/graphics/blank.png0000644000175000017500000000021410773624641016251 0ustar timtimPNG  IHDRh6bKGD pHYsodtIME 3!IDATxc?)$գF5 ) Um=R!CIENDB`tpclient-pywx-0.3.1.1/graphics/mousewaypoint-icon16.png0000644000175000017500000000155510773624641021213 0ustar timtimPNG  IHDRagAMA abKGD pHYs  tIME4V,$IDAT8MKh]e羸qinF)jb*ZJ8QbJgV܉3q ;5`8c@"mFDmsrl ^^Ht$QPxIfۓi75=_Fa?^HgYH"H% ^T Y5ߒX%mC2dI"! ZqM't{ԊȮмoR7ڜQDZ̶Β"2+r7i|'{v1iE HPk7/I$L149xDlcGqv]i|^:|<k kǞtw먱lP]Ɨ)g~4ܿ$2*59{?$p(Jtozo2.2kwfbt |ձ;~(a:^ z 3EX-I, "sL]S7Hx+S[Pi{`%クOX׀ :=~bP8= %P=͚~Ӊ##@M:2OݩSs3[Y7<]n' w{_D5,\ |Hn.q۶pJ-(Hk c%d8DH}IȄe*9uE$4}}/VF9TIENDB`tpclient-pywx-0.3.1.1/graphics/mousezoomout-icon16.png0000644000175000017500000000062410773624641021051 0ustar timtimPNG  IHDRagAMA abKGD pHYs  tIME-SH2IDAT8ҿ+q(Wίdd@2X 2LFl2,dHj# \]ɯcy]ɻ>}yyTA?JSUjX"qcl㥑,vQ1]l1ꚑ0[σ, 7L ÓV% dmⴆc'r)* J+Ï!+H V1Y5.$G\KO%{P+HZ6I Aٛ47LHj3y5IENDB`tpclient-pywx-0.3.1.1/graphics/starbase-icon.png0000644000175000017500000000041710773624641017721 0ustar timtimPNG  IHDR7sRGBbKGD̿ pHYs+tIME # (IDAT(υ 0Dx4@\? Q*wgUD^Ũ: `L2,`sd~,ޝjBBH ~?,twdY,&+BOWCWS4zP bIENDB`tpclient-pywx-0.3.1.1/graphics/downloading.gif0000644000175000017500000000337310773624641017461 0ustar timtimGIF89a 򺺺444ėTTT! NETSCAPE2.0!, I)KͧJJ5URK(&05+/mbp z 1;$1CI* HCh`Ao"3qT5\8aBdwxG=YgwHbvA=0V\\; ;H0t%HsrY™ ,bLv|?4BvʛPu9+& 2x& k& U] vo opraT&!,{ 'e7\l-)S7@&4+`yTSL\:=Jk:;eĈ8cA8Oj@b/+:{ tyt#|- mN qK!,lI+8b̠y h*Zp=3`C`B"pX 9bPB`Z= 8>u,St"ΦOT\um|; 8~*!,xIA]GeAPb)"!s BI М V 5q((X2=,I n#&AVq5t sny\)_g|r5!,gD+8[{`&y_hI)(L "+gN8l5"LA .%@%O@8NgL+Ƀpus/ jȩjVj c7 I!,\0t p hQm6Tqmx( 6'sa@`]-lz0 _g ir!` !,s ءXP\|)pWʄQ稊G.}!*1p v;Tݩ2 X )|f%9`}0PFd~ezGw);tpclient-pywx-0.3.1.1/graphics/tp.icns0000644000175000017500000013025610773624641015767 0ustar timtimicnsics#H??????is32۳- M8 MpdQ:-B '-t65N~3 p\&vR 1IUrzDV"hSz AwUwQJ<7FU ^=5h3- {XS}-M[UbYV- M8 MpdQ:R-B '-t63V+ p\R1cU1HVrzDU Qe<+O @W4D 5_O71.9T^7:o$tC MV- ,VJ#$.07,)- M8 MpdQ: -B 't6 o\EVrzDS  @ s8mk1/=2tbePoW AM0<]d(Ϋ38JICN#??????????????????il32P> v& L 3K[\Q<" X,sȩyX' :fJ1 3LB)2ܺq*   kwH0 ɂ  z) 4rD ~x/7 "FwD&1[~E74I616C^H*; o#P/[U|P# ^ -,R;|  #&vrT]>l  _%b+w =rSO/ !x@߸FV?6T_ J9M'?NSB;m@F2IE5f\A+常gA[f5~u` F}g=d.Om`/RQW~bgK> v& L 3K[\Q<" X,sȩyX' :fJ1 3LB)2ܺq*   kwH0 ɂ  U) 4rD ia;(t/ "FwD&1[cJUL=84I616C^H*;C`8W'OV|P# ^ %"YwxBTcC`s  #&anAph..cE  _&OV -V>vy(l' !_#vp3B3 q{yw,P >$}u~~4 `'@4)<",uv%s:E|"ywq}H+4FTKTD;0 #DB7 D_*:I1*-.E44%> v& L 3K[\Q<" X,sȩyX' :fJ1 3LB)2ܺq*   kwH0 ɂ  ) 4rD !   "FwD&1[ =6I616C^H*;  [|P# ^ #& _' !     l8mk 0g[%Jޖ7%>$@$) }X3 ARd $) AU* kt塕&3]@*Tr5ѼX)I *pǼI %$ich#H????????????ih32  J6$=1   +X %*-+%   %:a̽c6" @c$AݭkZRR\pk/! yG(WfPC91( &Lmc-" Q$',LwU8*! 6,  /5=ߧY)   VZ@O +  %d в#  < n[b Ñ = jE< cP(Z>  /`K60?0&2,Ǟ #-9Ph{n/'%)1jd++1ͱ3@\&(09EYn- " x8g+Uϰ>#&wrlo|ЌF&-݁ 3렼p,0Z~÷{T3"  o) {³"wB4   .Q Q29a '  _`V/ \ pL u  s   =&n$੝ @/V .E桑Z SjOm /172Qؔse Ja^_YU)C▫Y?jOQ7郏1K2ۆw}~6YW.0BPo4{hUD. EW,FN %zGgst+ 3\pTPF3 J6$=1   +X %*-+%   %:a̽c6" @c$AݭkZRR\pk/! yG(WfPC91( &Lmc-" Q$',LwU8*! 6,  /5=ߧY)   VZ@O +  %d в#  < n[b  w = jE< cC tL1  /`K60?0* cs #-9Ph{n/'%)1WTn+jkpB\&(09EYn- " `+Y~5+:z\|& # xrlo|ЌF&-݁ (Tc=,zyh 0Z~÷{T3"  o) c`x}=wv}N7*   .Q =F~z\2TM   _|bU1, 0R au   pL [p Altf  =&Rctji 0w^&G &9QyyajpH Fwuxuza952.+(%#! "%(.:Qz|9! 6b2"#(.9Ke1ɗ}od[UOJFC?;740-*&#  &5YڞJ   "@[2$! $)/:Nm2譋}rjd^ZVRMIFB>:62.*'#  )PéV  &K\4'$#!#&*09Mn…6竒}xtqmid_ZTOIE@;73.+'# &ZP )Sd9*(&%%&(+08Ig'yskc[SKD>83/*&"  2ir8  +Vt@/+*+.28C\)ȿqcWLB:4.*&!   ==  *SۀJ5/149@Qv݆˪lZK>5.)%     (JȀ[>457;AI_џrWF8/(#   %A M<89;>BGRllNADHN[v̟܎XA0&    /Xف `MEFINUa{ɠdC0%   'A eUNOTZe|mC.#   !3Zԁ sb\\`i{ǿm@+   '?{ϐunmq}˔֩c:&  !/HǞ xporQ2!  $4O ُtf_\`jA(  Z '7Q saYSPR^~ہ \2   ;_  !)8Nߠ p\SMIFIW =% .~?k  ")6Jl jUMGDA?EW M+ 7E $*4DX aMFB>;9:Ebʀ c0 L  %*2=L`zVE?;76559M{4 JVC% !&*08CP_udI=84202@g 8  ;M䞅>b@ #'+0561.,++,-7Uŀ 8  -䷂㨅lw& #'+049?ELT\dkqw|YA5/+('&'(*1K 7 !,# ]" $  $'+/37BEIMQTX\agoz^E5,'# ' !#*Ci. r#1*sSE& $'*-147;>BEIMRYbmz уYC4+&!& )EQ( GR6#Wu9+n)J=0($!"$'*-047<@FLS\gy#kQ>2*% *K=!  3"  +m|^I<40.-,,-.0248;?DJPZh| vXF8.(#.]u0   .#ֿ   Yѷyog`]\^agmy'̙nVG:1*%!5H%  jy æP > "?i šu\LA7/*&"$C}1 .Z)Y$<^/ C '3E_{ǮxbQG>70+'$!.iB"  O%߀< !&,3=HUajw|ph^SKC>94/+'%#!  !=_* (~%-3g܁q31F !$')+-./00/.-,*(%$"!   -s2 RC @ޅ7vc &  #H8 ߅䢇0 L    4?"  ~-:JZm 9    (B" I l7'莁 ]'   "h?!    <* 5 &X8   !H P, 6 /ZM1& Rt! w ? md  WK sh Sڀ喂 Z& M& Pjf ހ愄  GI  R@wHti܀rCA0ނ#0;MXkys ށ`h2"ނeނN ߃ 塚Z܃8{# ݀܁"jrJl(b2pn~  eYn}wog`[SKE?;jh}p^憲 q!矫P 0ހ嗫L☠߁呫F 挫AM懫<Y܂惫7/1+('&$  %܂~4߄ ݀܄x/ޅFއn)ކ݂R".ށ * 2F\rY=ɺ~hR> 4%w^G2 Rf Jwt1 & &כpF!ra^E<ֽnE", Ajh%Dؿ?DoɌB IɎH"-9I,|maHAߎ& *  M K{#   4 M՝  %a&   )p/   +r=     +kU$    )\~,    %J<  8  !!#$&(*+--..--,*(&#  U :a*  "$')-16:?DJRZclruxxvqleXND:2+&! 4 .q;  #&).3:BJUf{îx[E3(! , $Gg. $(-3;FQckG0# ( 1F&"'-5?M^{(κxtrrtzċU1!  #E:"  %*2=Ma,m^UNHC?;863221236952.+(%#! "%(.:Qz|9! 6b2"#(.9Ke1ɗ}od[UOJFC?;740-*&#  &5YڞJ   "@[2$! $)/:Nm2譋}rjd^ZVRMIFB>:62.*'#  )PéV  &K\4'$#!#&*09Mn…6竒}xtqmid_ZTOIE@;73.+'# &ZP )Sd9*(&%%&(+08Ig'yskc[SKD>83/*&"  2ir8  +Vt@/+*+.28C\)ȿqcWLB:4.*&!   ==  *SۀJ5/149@Qv݆˪lZK>5.)%     (JȀ[>457;AI_џrWF8/(#   %A M<89;>BGRllNADHN[v̟܎XA0&    /Xف `MEFINUa{ɠdC0%   'A eUNOTZe|mC.#   !3Zԁ sb\\`i{ǿm@+   '?{ϐunmq}˔֩c:&  !/HǞ xporQ2!  $4O ُtf_\`jA( F '7Q saYSPR^~ہ \2  /̞H !)8Nߠ p\SMIFIW =% %h*̨T  ")6Jl jUMGDA?EW M+ *y'j $*4DX aMFB>;9:Ebʀ c0  x(wuњ  %*2=L`zVE?;76559M{4 <ȵZ.ytvк2 !&*08CP_udI=84202@g 8  "+g־xS>4zur3tܫ #'+0561.,++,-7Uŀ 8  #՝nsxY9|uur` Ҟ & #'+049?ELT\dkqw|YA5/+('&'(*1K 7 ϕ·sux_gyutuG $  $'+/37BEIMQTX\agoz^E5,'# ' !#*Ci. nϲ `rtuya fyus${VSE& $'*-147;>BEIMRYbmz уYC4+&!& )EQ( 5@xsuya 6gyux.>yz,+n)J=0($!"$'*-047<@FLS\gy#kQ>2*% *K=!  βTdvuy` 3gtxJewty} +m|^I<40.-,,-.0248;?DJPZh| vXF8.(#.]u0  Ԯwn ruya  .qevuuyI  Yѷyog`]\^agmy#̙nVG:1*%!5H%  SwtyD@xw^ mmˤrwuy* - "?i šu\LA7/*&"$C}1 #Gsu xxux//L&Ńsuuvok5 '3E_{ǮxbQG>70+'$!.iB" ~`xu r?%GO}tuuxZה !&,3=HUajw|ph^SKC>94/+'%#!  !=_*  Ȱ Czu s.36xrqqrrtuz<3'7 !$')+-./00/.-,*(%$"!   -s2 |4$xusqrszp"xuwaP &  #H8 c kvuxUmuwyz(ywwf<    4?" Χ m}uvvwxy~C'0:CLjz_ ,    (B" 5 Jwxtqlf_WPk{K1y   "h?!  n _  q|KSw} &X8 ͆u&u{K mvtwkP, wϯv֜0x{K)yuuw_ Rt! gٻ|y?џ :yzKPyuuyX~M  WK ; FsxaƏ*EwvfsuyP Z& < *vtuus>ƅ3awuzFy GI  >"xut=7þ~pbR̋suz=63ghvutsl  '1=HTdXoѫztuz3Jқ(ҌrvuswR gtsruwtuy){ϭjϬ nvu twuuw/yusstuwϨffwutrsstulW|yyxwvuux8Хa<oyuz9RUVY]`bdgikmowuvv4zС[KeȊsyzyyxxz^  Hzuvx5/wќS͛JiԿzvSDB?:630,($! Mzuvx8Ezq՗NΟu`oˏwBSzuvx;YxtwGѦsvn sxG Xzuvy<kvut_.wtuwv׵~wN\zuuwovuxO(wuwQԯyxS ayuuvuyM%xuysyXcvuzJ"xurry\.tuzGwuwc 6jnsx|ruzEwuxW")#" ʺsuzCvu x _~{tqqrsuz?uswX#kywvuz:tusqul(JYckrvyzyxwvux[ uvvwxyzy` %0qywz\  OxwxxQ PwzzrR;%ZD2lzwz`$ Jiy~|yrdQ;%$qk "8Obpz{xi7%$Jkyzz{|yseOW{]'.DPcqxz{|yjJ# 'L`ejnrw{Hktvz{}zv~|{zykK&  'Xyyqjfa\TOHB:4& #vL  M K{#   4 M՝  %a&   )p/   +r=     +kU$    )\~,    %J<  8  !!#$&(*+--..--,*(&#  U :a*  "$')-16:?DJRZclruxxvqleXND:2+&! 4 .q;  #&).3:BJUf{îx[E3(! , $Gg. $(-3;FQckG0# ( 1F&"'-5?M^{(κxtrrtzċU1!  #E:"  %*2=Ma,m^UNHC?;863221236952.+(%#! "%(.:Qz|9! 6b2"#(.9Ke1ɗ}od[UOJFC?;740-*&#  &5YڞJ   "@[2$! $)/:Nm2譋}rjd^ZVRMIFB>:62.*'#  )PéV  &K\4'$#!#&*09Mn…6竒}xtqmid_ZTOIE@;73.+'# &ZP )Sd9*(&%%&(+08Ig'yskc[SKD>83/*&"  2ir8  +Vt@/+*+.28C\)ȿqcWLB:4.*&!   ==  *SۀJ5/149@Qv݆˪lZK>5.)%     (JȀ[>457;AI_џrWF8/(#   %A M<89;>BGRllNADHN[v̟܎XA0&    /Xف `MEFINUa{ɠdC0%   'A eUNOTZe|mC.#   !3Zԁ sb\\`i{ǿm@+   '?{ϐunmq}˔֩c:&  !/HǞ xporQ2!  $4O ُtf_\`jA(  '7Q saYSPR^~ہ \2    !)8Nߠ p\SMIFIW =%    ")6Jl jUMGDA?EW M+    $*4DX aMFB>;9:Ebʀ c0     %*2=L`zVE?;76559M{4      !&*08CP_udI=84202@g 8   :   #'+0561.,++,-7Uŀ 8        & #'+049?ELT\dkqw|YA5/+('&'(*1K 7      $  $'+/37BEIMQTX\agoz^E5,'#  !#*Ci.      SE& $'*-147;>BEIMRYbmz уYC4+&! )EQ(   1 +n)J=0($!"$'*-047<@FLS\gy#kQ>2*% *K=!  ) +m|^I<40.-,,-.0248;?DJPZh| vXF8.(#.]u0    % Yѷyog`]\^agmy#̙nVG:1*%!5H%       "?i šu\LA7/*&"$C}1    '3E_{ǮxbQG>70+'$!.iB"   % ;   !&,3=HUajw|ph^SKC>94/+'%#!  !=_*    23 . !$')+-./00/.-,*(%$"!   -s2    &  #H8        4?"        (B"      "h?!      X8    P,     Rt!     WK      Z&     GI                                                    t8mk@   ")/5:>@CCCA>:60)#  &2>KWblsz{tmcXM@3'  !1BTfvxhWE3#   3H_tǵvaK5"  +B\uɲx_E-  1LjϳmP4 2QqætU6  /OqϭuS2 'GlӬqK+ :`̦e> (Mv{R,6_ۭe; CpuH#  &N}֥T*,X氋^11_f63dėj83fəl92e˚l8/bɘi4 *]ɕc/ #T[( IP =w~C 0ip6#Wϖ_( DK 1lt7Tҕ\$Z Cd# Fl% Jr'Nx(P~*N(?"  (kQ :~i,3YD!  jxN$  %<-J ,Q 'nK!X6F, 5b# %E=* #1;BIWwε{kT1 "8jb@40-)$   Bf3 %1422AjЄI( !! ivRHKPVXS=  2 P,2d$  !J9-oQ$ <{0 %R?+sV& +Qjsx~Ƽm*"')*+,-3Bb経m]VROLIGC<0! &Kl?(   !He1  !"(8[o<  &?OX\_bgu^D:7642.& Ǻl&  E .}%  4ln/ /V[0 (EI*!9q|<" +Gi˭[1 ")/49@HQ\hxŴpbVK?/" !%)1?^wYJA94/+'#  ';kׁG1$  +DQ1 0Na7#!1Jtڦk=(  *8OwܫvN6&  +8Np֭wO8*  $*/369=BM`Ȝxog_XOD5*   0NޛV;1+(&$" !;A5)    tpclient-pywx-0.3.1.1/graphics/splash.png0000644000175000017500000057462710773624641016504 0ustar timtimPNG  IHDR,br pHYs  tIME !jtEXtCommentCreated with The GIMPd%n IDATxY$IrhzyVU3=R,|Xݿ, 1g]G1,ew#=>#/JbuN^?~@_R`돻K]aO+{q|m;}s)?}ߊN^({CxmNoBNW Ϻ?='~,l G^( ~N DQDNqI}|׊ :$# 츣,G5KyGZpi;;ø~'.MX4P~t0<~A;~oOH8ק|>.3a6Pk>Ep~)T#O'NWҞIeӞ[@aw;g~Թ;YO&~`A(|!IE#O8䁁'|R'"ndux,`Agf}p>"|O]iSTuD.G@}Fg28ᔤt =^KSq~`X?ʬD g)vI =~"'J!O=jOey{MYKXdxsD!Gq#v(Cg l^85m76g~’ T_BB8upb *UãS<>nHwp^ [i|TsFjx(3{z{wvsK4mvr?<)"9|6~fu_ #c?|م#J'ANɂ/yKI?HEN".Ͷ{_c{'ƒX}_@;Dtr&r Db#?w*@KhsV4/*ciZ` Z''>s0? B7Z:x_jE@pvyϵ @e"P%Q}H}DQ(A}f7XETj<:_T{{{Br֞*wnQB*-cZቪ!U9&t\572,H[' `y#5^m҄V ?\{@jSfq/9yG>0VMg[Dr1|/U,AD4DiۛE#tRrTnfv!4&QQQ@8:W3 OƱE=vyjuV#ZR{p{'f}n9j[#/S$+OHcScUgD{R_BY3{8}?X 02~DLLg5yyV?wZfQ'pBX#R*@92O\ ,6HF>: UeZDDuf@D[pc9gd~i!1sva93SUQ'2GB9^|NKOxxHHlo3jQ!"Z|5ٕF2RN蓎FD.NCZ [.Lٺ n&1S$D$D;vLluIWDXr!J)NIN+G~V$xI3KU*MYjpC8Bt8CN^.8յ ,X&=Tzl!r*U:8f/Zrɧ|V" -F;3\Vabc eB3i If44+d0L)e-&dgO)(*hgba h4Ow;k  ""1svWDK)JHs)% ;W'h5ZD2<"bA|NvmۦDZqڌeqK.#`۶iLUl QTj)Uuʆ:JpL,hB3hQk1&y=9Dx^X@D&ST~Eb/0<|8)n)iXS:"sLTgϟ}7/(4ML"{fR{2[="$f  RBD9>$"̜sш1}!8T~h|3ZC$<[8O΂N:BDT7))2y3kRԩ+& ө*4:ԫ։['L^WUcaOTuZK] jܽ4"(O"L˂Abc޷Mbtr)t9Dx\,ĀsRD$`QFrsbq8!~遏˓ BTB]-3^\^춻3#R JuV9)ȤbԓJeD*j={2qJ":w~v~{w@k"e/:dzLk&\N^w)*BpU_nh\ggf,3 dq2kE*朓*Ĵdʌ+ZΛs.F?$UDq\ERnHdЩ @2Kus <4JD)%"z7_4LT[ ',Ŕ51Y\iAI{o~71XJDR, h悬o5Ms9/A\UgνsJZdbh}`8_u*ZET%D: Dhv}Υu=8?}. سmAaTsγ &\m|vE;Fj-&%a09`m`)eƜfc[a7d7*UTgH)Rĵz0NO`.N)Oq(YA.ELvSH\߭ cӕ 51 eu&C*gʩֹH~zUA8ww}Ysȣc_v{@$vmӴ!6c:VBEt 08?w)RkLhTB);9eL`LV+5ْ↙9Wg[Y`2q{xt֡K)1ZBĪ[[Jaaw àN=Ʀm=c7X}5fJBzݦ4Ό 1Z8B&"Rj!*<\jq{!416R*8@=!!HLG XGLKDZHrie18矼y0Z1٩-Ebd"i/* F&X9G(j爈LU!bߝ֋g/"P7/"*Dl>69YIZLD{.IFB4gF+ݶ]lnQCOʜV:6*!\ PE6Mk!̐,4:qX23"sۮ]4sȵ*q$RC`Z+ <0" ,e"KBqR~J.W*=Yʅ<{0G@Q>D@a gmF&?*K+"Ht%Jt+"Ɓ$IqMӊHJɩkSJ&咛R@D֔S=,bF@:H.]wldMOQI#"w~qak%"f FQoް+*꜆|ku!prǤM*H9'2.T !LjsfS sÐz}Sv uW&@{9؂sŦ=BT%(JN1"&q8aX>PP q(u]׌cZvݪ[{b_n* 1wD8:@<\kێ/.ocS2JSCBGsZـG9[T-GT-icIZA_3Bd=4MQ#{uԴ-Mcm46O_aZf16쉙ТP٩3j=Km]7MSxafϞ0DHja LT D;"3-7CU*{_k!v]m"UΤC$D9ruuy{{C@ď1 sh y16WW0r>UuclkE2'/>sLk+ zD

mZk*2 ê_E+1Sl6[U9gˮ^^^R?R"*f$KB0Ʀm;+XAe!BG:J)3:ͥ)ep&1@≙2p@,B4Um~^"S߭x9:b?][&/Db8V5${?o})廻;`Ūvm4,IE5Y H$(\ClؤTٷMD\߯S*]۩*i:M)L>cه Vg_Ez}~}LUoooooo-NxL"5NUOuT$O.*HhIVQ!e=/iDTkuR=DV)*95[pZJTUi2)eS...6*-\d HBYi-p8)mv]áOfZc)jeQFfUp<3`=P K\5|~~> |Ͼ "]!K>PِLS7"vmf؄qiL,]R~__T `„ð@Yc>[כ}%3s͛7UjNaL)m4paIs#Q-uq*-8'T!zW8&OIއ0"Dl,d !U 5䂄HZZT4+r~~C3bJΓp&VsMvD9W~/Ս89? .UAre$v"8]u8""3ZKͦsIZknjuRd:\1o]?,X "3Bl>6 1h44}_^^Vijr32ymcnB $i%UC 4އ2{o k[BӵΑ2tdGˇΉTB+<{=sVg(BL4h4 TCH@SisfJLKWgw9TmWj9_]]w]fu]0OE ۶j_D0T{`Do޾b@DcJVi.O4Ϧi RQji*"13Rj2b3Zk"z毾 -c}ǵVKcuT+!Z<ۛa-KPJZV՟Hu0*:@-&WH͵ҕ!BLiԂ*uL)!8E$Ryׯ&M|9xӛPJ5'D}}hTmT31Y,`ΐ:ƦbW+:xqqlWu)U\]^71ZCcZWQEkf ̜`WJB{T [DtZtAnqHxR&DL0B~A&cdFCC:K鐈'}!XqGFhbB"+z}^rz`"={~|uu= c׿g_|xyyZ:&虼s9̤Nm^)JJ1>iڜGva0̞[=RDf$¾ﺮQph&Z۶!kOۛcisw@j> yalVUǔeM)j!bMz|A6Ϟ!JEo9`UzLBjn9lC]ץ1xa,cզi,F$[a@zUJ06oX%HpPumY϶ihj y\JǔR=&bl,;ɦ d8 Ng"$mv]ꑬ@i7$bU*y 1scJ9k_}c XVoSL%4Z0FUw~X뜊9{JP̭C&!$TPkZ4Z) t]; NYVĞ'ZbuD$:;ՑO"?[\~UK!BSb.nӮ#2ӄP1MB !Į8Ʀm[?!4!D~ZV"j!8"2 xҴmѸVB@DVHb`W땈waLdl IDAT|{@Cf6?J)~?/_vꬔ9R~UD 4ԴAT;!J:CJ8=X <1fvj =XSUs?=ڮ8`e)&0D uiZn?u7w>Dc3]e"#e&665MӴ 614&͚'볳i@&Fbkӟ~rٞ_fjZ#lE3uqL!YZl=i똹z{sk=c׶*S"gsryao[> 97MΩz~~V~p8m[|Ϟ=>Di9VչIγVB?{տW^Z0s2I%ĠL449ZG$Kӏ?J%U)f+"6?٧/_ls$H)NJItLWZK}D+q00 J J.f4p0e}b8T͝:;%E}-z04ƞc}`<ч&6!ƶg]__ow{@n6[@ !TCuKh޸T!mΉ?ŷ|v`u[֜ VkE4&]vfĶcAD/ !ۻEs΀W\10ahp.W04ms8 6 66MV2#2H8LـZ4Sn%qL)]^_}z)VU4|lx罏''ݯ_zulg+88Z&v,v}|iyomN2b94L;!؏{bB6M=[cH"pցEL?\rfOض]ʣЩD1 By^V}Jͷwwo޼ƱL"p;pMKͥdG{oVS귛lY "өq믿bDC>u?ǿ3TJ^a S͹J%ugbt)"Ձ"m_D"! q}vClƚi& yR+)/E^"d*=Wط]r"f@4!a8}}}}}8=CWѮٯf̱%I-u"Ł8@g?3y"SWKͥC*בVq?~/~g/kbMdiVv S>j3SJeVku~v&RMy)q DB]YF׵o߾aO_W"?="M3^̈HUiBʙr.>}͛...7oow[+_M~vww[cp0ڪ}6lfCJM׉0M96%`U' 1W}wwVZJ8nn2;蟌dbB0qCMs>dJ>3Ob:3W6m#"mvq^RJFrH0 Tk].0i)KAF=mn/.c}y}vfKV*eJ8HxqqaIV6aʳgǔvꎺ~ZD5}*DjY|."S ggwBhnP)JjU ՁSD{bv8x朓UE\r&gmDԮEk;Hc\8[9KaRsڶ8&t>܆k-p>{6D][7ZTѯnwngD7oo_J6jn9H)!Xj >E j)ۻ$.??;RJRkYg|2$B1QسN cn۫Sf&VlDpd|yyszzJcQqsVFPENs"ϯ_kUҘ{9'"%t0$޼yﯮ._|5 Cl*ҵ-")5MƿZ]?{~ֺJ-DNclr)~R9hSgZ-%eqƶ7;'U}.wW$.Q8>:!_}g4!FkAˌHqp؋Գ{)ӿJSCCy{oc^Z '_nc,Z⬮gww6䜾~9b2,3a@qjR{Zoo^SNMÐsιL8xKfGe.&믾K*8"ӤQ.nn⣮Hض]䗿ؚQ޾qah6*ZE!̌}׹xR1F???9voGˠmZ3ZbL#8@«+% h^zn+Rթ i@\I'ZQIc 1+b_JYW];rJ* Ӳ&l߼1RnooO9NULu-3'mlXmw{⫯qdA4d&XtcMq4n֩+S[xbrwww{w ZSNISW]@t~8 !~~q'vi../onnLI+9uX[ fa<(R:vL.8%g@R:ڰyF!DVAie&5+:qA7}ѩI8Pdꈳ zȳE7?y4M:1{Q !61B)z2Jpts0 ޺D1LLDcJ9etx5h}/"SqsM[dΩHuRHD {nomڦn<^-n0{#,M4Mk.~Z}4M}PiZ@R1S:W~M9vۛ۷ooD6_v))jePJC 7+%V}},Ơ/_k-P dҬ84UaWWWMn;+k :-l60A=c>ι_FMqk-{+)wmv~HUb>;;\^\)_\^<f K8J{U8;;1{ַmnL{O6zoۄYTD6~!z}Ui?v,?bI5[l0O-s}SRvMƶR5fUQCCQD6Qո6M{u]gєY”?Edۍc:8E{#9aXkn-9EԪ*KkBӧr72I>f☫64B}hr^uX;R~G֔~sεmL6pa^RT6 ,[A$qNd@Bwîk;|`&朙ȇ`4Mc]۝_|Wo...s.A)%fZ{Әa8ӆRIZprm-/M8޾}k _w(Z*n{Ufs?C ,9V2Df_TU}Na~F$|AmE;Y-%J)Teݾ|m6kmYMcm%4 B]0 ̲y89aVvJ)>R@O؁ef;D*~Z.~OkCX blrNWWW`",6%a|D-Y02G}{ݙg8]}LF Ҵhn-^R m|s{+RqշJDsӂmLSl@DlR3at)="BM1Ŀ~ŷ~qhb̥qׯ_ 0-"D^DR9Wuk:gggι~oql۠aSu_]]DsND...RJ_|Ѷ+0jZt%^5>[o6wVΞw-*BIeU&nݪpMIw//__99mal ߈ʕ頮r`d,5璋rͿ_|j9vkYkKAZ&CbĤTq57 C&y!‹]]]v;RV;CN(EuQgֵs@S;N; 8}Z3`~*Q[*$nY3?L^,GI)Em;ՊJijd#|/rz4~ 3̲*Tk%&oNuW3 \wo\p؊HӴFyVuv˿o۾A ܍yY{BwO>daSncl{? CJi^J: ,ce+mVwwww׿߽zLݙ'v}w0&]^^:p^n2Ϟ=ɫfmw}?fAq !q={vۭV>{U9avjm6m"4p}}U Sݖ'B6c,D?ðGpֳﭼ:ob6#wϟ?Wuކ3sܱ01FM _5zJUnM9:ιgϞV+e}ٷ~LuJI"uǜfqNZ:t"ZJl6'b_&??˯-6 J&,?aBM,!`=`uj1Rf@J"Fkq`i.f'4`4j/w$`6f j%g[wBb)daW7oj~q3=eY~cͽ*kcuw5["rH!60f`O4dÀLh$Ð9wr=vvx"ne7)ÉΈ8˳8L]a_g?|>~9;`~P`vZnq޽n[T9YiٻBH. d@!(XE͂<۶%{vdwy%I1~AMM{zz6FM-P] }q jXe']x/c5MSJml6SX Tj$~Z8~zƞh '6˲kRwp{M^Yk[׵R*JLӚ%lkPPPʒ$ >_F IDAT@FGm3$S4.zͻyN~MsޥiR]&p! ;,Wkk}ǐ'IGF Bch4UOݿgt xnEQ .AJe)X-#F{'2`[cr =>$ЈȲRu]$M,-*D!D!W`z2xO"炷Mӵ-cL+e:k)%\gM&~ N!NB8N,wzA /6дҊq.i.D !a"Qd}8 J>{> sm,vɴ1XBI6{T$2LJqttO@٥V(Ʉ1Hۋ=M3Y d;cf㨪&(CWWd2ޯ+Z]#"'- ᣣT9%Rblz\v]W{77f#_ׂ,9gZ(d$]VUն`PBUY1Q$Vu]B~izrre>#!dӶjk)8cUEySJ׫5<3-7j;/1e9R}777^G4_ Q1/􍝳n:W*3BHvR\\\k]i ۶2pp0w((Z#gDu-l1>h1Jr޵m7VH٬wh]Zwm&Iz{JfisOAG]ZkRB !u>b*ﺆ 'x2GyK)RF4I-|5bw9 Cs rF$i,Jemxz{k;)oX0(@a; c朓 dh49;;].Y笐30=‘[n0(9g:8gt:Iy`Dp#πVC @9=;mNF9Ci4DNn/j0u5FeyFFBn(tuJT4z6ejeyy\/˹ $ ERH*Ii@nog N0P缔!i*t\7 r8ݻ^Wژ$:m:d!3&8 IQ{D$ݻo/ʲn[J` ,jgRj]W1z흥l9m.Y7MX,ՖR'jҶkRMSquV#m$f_JqrE \x׷- 0JL&8NPJ1L~ˢSʬu:cl [1{i=c'_ qR4>_e;5gƚ``4l,04B4M9gYs3 c>@q܀!(8-A',ut:Z~ZJY6Y=q#n=|zpR|ǸZ8/^PBB"oOaJ+ȖpgG}fge*k~5BPU£ K)EfmZڪwF$mXgZnnk`s=J.k;r)\HSE+!Cmt]U]۵yI)~BHR NB 㬗;d$Á=Nƙx R ER yD$I,&=գCq[m !$i2 ]FfS*">|bX.A5mE'XGGGȰ0 _\\@]1nXDEyw7z`VU*o*tGysbW7 ^`pqgL@xCͻq 瀞Z{(|$G\q<ƚ~K)նm~lk,"ۣC 5x`V)iZT$$ӝvRiT!xJ ǩ7Q ݦ;h^GK[WK댐<$198bMS;X(8a'd揵=KI)4 i .wP<,#uqu \5MGp>q!F lM&4M#.jBV˺d@Z㜱0F'z&$VW_|fXg@yKRzlzdOAD 8o?>|m[>0@ufX i8AX̣(2F) M(ҶmU9><<`7I4p`dp:/':FuNkei_5L&}Gn֢BJNuب} 0A۶XCLaRVvERk}!`a.;y<|Dw?Fj5FSh5vxx6]jB|'4hUL=H{, ^pht]KHXVyW+ 9g%'0)K~~DZ1Xk8liZ94-D4BVi7=F[ P)-z~KSL ?ydZV˪ڶm[7M5U]-H&qz$MCسg͍,/RZUzM ,kGBz !dpL02 PrQ(ʲ ggg 8"HN<LCT.1`ч'Iɓu]cڶ`EQ6j'l6C1Cr{^x1A 8H+z뭢(s_i>Z $H7(B)Z PA٬לqk,x<9==*\YuHyGS^iAn rVi=@ۦOvfgYVElCG6ӆ2̬`El6WġlmZyZ-P 䀴ӳ |Uw@;mѝ nFq ང2I!qB8|wSл,huzzJ)-"Ibq ( pHrε 7޶6Z "/) Vλfsq:Rcuu]V+pln0@edo~pwZKX-ozY4M潷`)H(sWt"{ΐ%T+p|||{{{yy J 1ikǏ///Q!1}Z{=DKmR6(ƱwnnnX,-Xz- ...~bL&777eY"ŋ [cR]Ju֚bִ?3>rD>@>mۥiN;Y(AD'sI+/_LDpA AZ h[\ZuMӌcD7-_Qqa'''F쫀ŋ Heav>v92<ϗebؽkD^1 4}uI(D!4KWeG֚rP?oYGGuOrEQ$]=zĜ1ZfTPȲb4Ǔ|0/bH`<GQ = \k]U5mZq]ׯ^*RJnc(1pa`p7y vkͲ j8j8zAǠ4#___Rt ^\dwyg6u!" RP֠%l*Cש$I49key(R|8?NR(2ozW6[) F簽NKpB)=\DJJ-ϳ<˻QZqΊ"OO8x_Uۛm;)ahnqšY:YAk·I?{lY7؋Ub^i?D9@]SA)QW4V/_<8.˦iB>]C*8U|mm:v]:˲tz=d} `Q$ !ɽ{>Cģ!IZaȌA^Hk!&@4 w{65"puu:HQGGG;>~gv x:I~2/sZ-ooo4E D+[DG!A#[X 63Js>)]~Lhʈc=<2Zz`B]=}s2e)Vb6!aw8^,:9+)e]׈Ps\,<BsKkPѾ$s Myd6a*"+Kᥭ I o2zuj0ͦm@E`3F)r|L\0sO0. 3~r6K3uOAr^8ch|wy뺶mbKc {>CG ˈD" IDATXU[c($I㰉wj6f9aoDGlvGfe !|ߍ_$1 )FSBiM c8]6MwTFyfDv\IkmDA*VJ鼅FJin 8CɛlTwzvBp|H&F0Z ƙGFfY.C4BpC y1w!8pCϲ,afӺ Q$ád2yf M&RcA#NeQ >W9Iv{yyvk;aOB< )^qXV|2<~V$yQ]W5N Sh8^.8]}BrTZY4d2F@a^`Ӵb60MSV˶mʲ|l6]-9d+HF0(p_Y<ūcnMt:DLR&QEC}̲U|q:9/yFKDQ$qV+{ $IVi |pGzF`AV{ml.Boi|3K]=c\) >i2m΅q};/I6YM =Lć(`}^K7SB.7M͵( c44+2J9nH7TGH!>뫮k79 $dyԵ7Q$E$ƚ<$wqկ}u\19qLӯ}ڗ/?#>QA,$J0c(ƭu/$l&v~qV yQt4u]0tYH]۴Mɫ+ƙf8IJF2@B4EY?/nzmMH(bl(@E^p;=l!el_rBRn h݋jfMۮW+km^f^#k <>?~E/" )h8{f7y|7 Z0(;!8 U$۶YDQZӃ/_AZ.H4E\VJ{ldQm:g">Ắ8oy{Bq4߿QϲZ(2%TJQnbheuV+%wY1ikc-TpnAGYPBy||<} J$hDyux'l+ت&1ZEr8!]g) ƱLt66pΆz:<8(Ŏ &xpE2ǬgW_]i[>)#R{41V)}t|B{ٻ٬[.e'EYvZ7MWemy%!eqmtAHI>k?~*(/f+d_fÛLJ B2=~&zJXkEH4żTJll;E)+Gom^o\hc3ŠZuvp4vcˊiO2{k!h0]mVzKD{cVV&b] [e:qE.h0&Y%wkg EAiNNNoo@2骥J};|S e9Pk9}y}lj+ڼ(~_cƤ6ֻ(Ndii38ADއIժ,m9I IXc5FeYSZYk< k{qߞG=B@7Mq>1b\%I:^oa]5i}_.R)}Ȳx0bر.w3B<_V9M㓓fCfFh442ޜVj>i݁q e!x׵j5 PI}0ϫ{o0!6ۭ6.ŷ/_UU[2%d[m8mW*14X纮 yURF!0qxQzO6EQ&I۪Nl4/KBiκ,1zFw'vS$~?0˲?|K}|Z&s :%M61l0L2F(l8,1N)-K5ƻtCS-g~Aix:V$/˫i ɔ:Lu]$?::0bXZmڶ"xZX,j:ky9*34MWWz뭶˥`zew2ߨ(f$A˰Ec'`D@^ )P4΁:::y۶hW))w]&II1Q060je<:t5F ĄU)lVu*r]K-KxMScYU!_~Β>|(ͺJ4)cƄw$x<"ӷz'4MI7DUza?9x4` !UJnoѨJ&QkOvJi2JѡG \.b(hI1G(?~}q}yYr c&RޛRFoY'2:Zq Czu~lM6)EҀYu-{c hءk=m3L<_,Pq^O³ C?::ZWnϋ8??ZC0o04,0oQ莡:{;WO9'rM#dnoo֓Ýf3Fq7ʼG)iU]__H3QԶ-FB;IJYvtp@fX̕2Rpκ&xS:i ¢F#`MUȋMQ$d`(z 6y-KcÇկ]]]Y`ɳ2:]W1f2z8νI@hV)vj2:g陱1peϪ?>b4PJ(6 >ιV]d)!,SuSz$'_zwNN7[f:":W^cq{^UUO>=>>><<K|<Ǐ !noo,2tc:-{)PĐ-Ng.L@;==-61$GG?O_@ߢȳAY?;-;lfnL<!\gY)oGJuyI%N>_A>Bp&8"  S8 eY^^^E9>=QDŽQf Ȯ A PEE_rX?ӿ?@96aq/>g4AϿG],BCRBжh.]ً]y4x4.roooNIK%_0Τ+)A]8'wYR:_|Doo[L~' rC@@"0 $qޫ>8:t㮔 !Dyxt{Xrm2γ|8O>q=6xuqUU=u}xGd(v0 60|Z"^xEQ= ;>>FkU?7T"a 'Iޗd4ٿ}Ս}@H):1YgyN EFk9QJ8cIXk~_Cok['.<ϳ4$<~0Z%9烲I!Rʪpe[m; )01I J >s|`kڇX#O>XͯGHiޡG Ḷmӓ_<~bWڐ@nUY6!1z@<v W> ǣѨS<'  1JyF7+] kM5=c9)#<)!FDܵ hgyA0qlK>/Cꝥz?] {\.Ϟ=bXi:Y6L0a|w۶?^cYdO/|'}Ï>BIal]##QJkeM08gJw1Z;kR,znI˼6%X28*`2=9>wz:ƣt299::N>yMFt<vvxxxrttr|LNNNpE4fl$(۶k9EEZfi,@_򗯮'֖ReE:)Sm5 9UM>h׽ΝN=82FLV}ZzzЧҗl6CGy${|=sOa~Hj91覣CDFa0@kEv UEZ C{TJk=~?/=~_O8^IYmv$Ƅ{(bZ;{5gjsP@`Gwwi-vRmS{")qspD!p!gg` @'$I5Ƃ Ú*6^=wEg?>?GdFd2y'?<Ͽ9CpO> '"M(_w -f04mc~Ye~ D{#DtttP7ۦnuLHgᄒxM[ևp(gTkL۫9!G59ݻw>/'Ir}}\.CYE݊u[Z{pp4 @Йs76DZK_|>dXl6{ ,/^( ,͑RJ'''1(;kVx|dm,M9wZSnoyi֭Vˣb(t@>BuTFgy]q۶qJ y$㸧qj&ȭzr%?H|>} <f,F#P4Ia~ u:"t:Mw2>LիW= E=|,Kt:y~l6g >3.D ls.M"/V7ye NM ØXӻ{ZZojKӴxyBsεo e)c䴪 *N8)x!'7<;"ْHQH2-ei[3Hb166Gldb8Nc[lɶd")Q}MY}}|{OE z};`TP}j%nU`x @ WC |rs=eka6)ee2F0Bahۖj8샱VZ#$z}AT4ׅTkIbF;'%kײT߷Ç_J݉4f4 GNj/믿~`𑧞z$V[۞q[űM9tm[B|yPX`a }mmuBH jvkO؋sVn7 Q OVS0#ha.Θ IDAT:Q !mǂRG`C)y* oll b7>u۶VIW CtO^HRڂ ljJi)X(@#y`膄>r|ڵ`1Ɇ$b 0?t' }wT*ornA9!73t{aYltzZdqK@D‹ nr9xp8oCA((q d+r۶Lв$IQ81Ƙ0nw}: #N0HkGQ6_B:){ﻎ nH~ jJ`"%s{]L cs LͭO<?8wl}_y^ISO=l<.<ϻp믿~P&fl6V b{օBT,B=M|j \ب2yLpbcf~=!4P`jۖ4R0T*V5=3l4=`iƸeYlxsJGRF^@D)T:1ߋE<~0ZbٶG1!#' )T`Ґ F@ckz{ doሃ40!`N0 DQt k d2AȮ`x76<ʘ4Mc<z?z0( -NӞ~P<σ2gϞ۷oBǭV'VW-ӑBY4saXǢ6>joA $,dw9QJs&8ÿ`•|NqZeJjP9IkTXw@l6 JXe0 wy4m+Gp8` Q5"  |)LPRJT! A Aeq^8J<߇eCA&s"Tvm q̫?ũo^|nU x`jfff&''ah4._|IHjd%9.Nm!Oi"~҈1nVnJe8`Y,Dg$J!5Faa`CJi4R(5 q ױ5BܣQ F`H)j47ֆ ֌n\)%X)7M^o0RnAq,˲|7M0,B7,ːRL6 tfqqq8-ja`6 + 8RC0f&~RiP Ӵ<6`Y܎BHp7?ɿ! }jjJ)uΝZaMh;ia"[/zgZ&aZPD ctee8?uJa 3v%Fa?+KmO)JDRRF9Z(e!x@Z 0:8C~."m x `& \)97,J3`HXBIĘiRJ .ʝNGklpP3Xeyq#4Ă!=ϣX{w9-v,%)#SL>t)B* c$Fa"Uq#{:UBLXg2 2M~&z_i;#f_6 4QdžpNv/ʕ+f 2N]}ڸlnnnBOh;t8A{~6rcc%˜7  3NJK!%Z(A)H+JXx l0DxJSb6<Fqh6lW]tڥRѶ]7Vf8fYԪ*짡7QJ0cRڃaZޘD*8rj---0 S)g~Ȩ9"1Bű-fӲVWע(Ra)Ŝs)FjA0CI KHAh{A X@{C]p( }?@H>LHJapB@N, f@77dH gVVWP(_)@"8(l >yġ5668)Tm 4 jE7d<#qfJ87B"Vހ4E\#5c"%VJ~,%cň4r%FSa(sl0z? #dT I(B)1ӻz+p2ɂ@j)婔Qqv>4cXgu*u3qΜ9K 9~xz꙳gXpøaJ LT*%`VS/+3J1B0>0c0 R=]oZI*E x!3abQq8nLS{Yv]GJ9 u|/˟o<裟'of2Y}?.Pp8\[[~ 3YQ1\z鉉ZVXol6AJ) |^_߀"hv}_&x%J)9*#h{ֺeaRRE!XHDZ˰AAk KR(l۶4-700 SiҚbc< 0 ܔcf߫gΞq499 r dryTLA: n1&D|TRKv]S(XEa t:p ! fڹfdLeY`e 80OA:[;t҈x= $׮]{w?򑏼k0Ap_ D!0ti?7Q DmpCqe͛7Jqv&D[G뮭ȃX6XX턾@H]+*JA ER$|9xccF@pzUX!?JXۡ)eJ{,њ\nkks>;;wPݡc<[E,`%eٳsfhPJMP$8؎ ){’!cl~~ݻ`!cn!g)7 @{P[x!\.s>Z I t5x ӫ++錫(Y1Ƹ LekN";=ZBB$uw}E RP inp˶"!ʙib"r3Ziu## ÔJb-$ei?~28abX0ơ:B$%q(Z)%dڶJm<?XY=BLm/YC払sX2&RǑ~ zІb0)J0S,Iy>w|E򊣈Н@xМ Fm;ac;b4-F9 $Rb{!,qSݼ=4+BXir zQ!Si7¶m!i(BJ)fP*BőT0 LR*Jmoowm]qQRFFZ?B^ֶm50=Aܲ,B)!$ "R2t:]a rJS`LNN5t:hnۖ z}۶("K%ҫq<Wp8}"fsYǶ-(W( |_nBL잡PRJl6WWW!~",{ FH ]J ,:k:`¶D}%1y'/IĤFgjGb2B0#8D"g#]!`el6Az O;d̀3dYPa(z&9ge#&,k8jKbV}GΞ=ùE1clv,Ujii%\.?õJbZe @P.pKQE1B|'Vf/Sw8`W}74+#GwԄ`Zk%6_TÁi[[[\ 8Q;5Hm 0*I!x!H%$k09 ð/LLL0n߾&M8|weH m;0>SJ, 82 &;CJ#(]0HZw(&lQIgR)qF01MXq!0a0X_<46v\J .W,--Z-x_.JiƨeYiB|( ÜFQ6 0tԝ"JԩSBv;GX,))n6eneh)MNN!ڭVǾ|ThfzjϞ59B:0 v'nBJX;̬n>*  ¹YA|vʕ81FJR855)L ;vbbE1ciK油P!}@q,/n aRZQJ8L*ȩI&+UjG8IͣhAu\WimV.a@)7H.Hй/#L)XX@`k+ -2x0hΰ MaUVʶl:MgJcn>:_(?<qq݈DD(;S*8%xZ mcMjUJhZl6rwT,(ڪv] kd*<kಖz@dm6~ u )FQJs\.e:5gv}} !r(m#AoP1 &Ma?aDFS` ۷wyyld2YJJ/^_AEe$fl6^0/^b0iPO> P.KT.Yܮjt`(Fu{ƶJJmێTbqjzjZ~f;t' "J U{Zr !0av:p7v{L&:v.+ vPRio/2t}+Z׋Prr2=5я|K+^0{iTJI 3M܉uxoL1 #7! $(%]挆aX_]6d=ǎj4Z.^jہ^f&F׻Ik)c;RI5q8U5J Qv<ὧw J"1P75LS#EX l.t lp*%xɓ'wST"#۶#+%cĮRhet^yqq1IxWiPJrP@ me-.-B~dSK.?QDq]'MW˥^/~K_|qeEcvP{C(-8bpct?]ai{T(.ܾSJRcĤ9DI%֍b.?_Z^Z❼l T=?pgZy|SS._ #e۰cJT ㉉ Nv/ ^K33_3C_zs׮CtR)Wxccqe>g ﻳpŻө|4-0BZEN-↱w/|sꭅjF 05K hZfu)FxӼtL`:cϞ8ySNo`"q ce4 +kť\6w۷ozz\)SiXY2`0^O<'o}+Bfpx&k0Rv9SSxթɣG7OqNSH'zBQe{{8|iX>33ps~׿~3锳oﭭՅZ#n:R ŕr9JWk?Q8^>NOOjX6!@nAXڷoX,hnn0&,4 _OǎWձrX(ryx8 nu]x=X_~66:& Hd22 hڀɚiR" fa618KG<яDŽ,/-a,Hg2myTR~OONN&1 g ?(_o͓q1d1"[Xn= |5"Ƕ2RݪT}S*at{~J#?%MB)F<48 "ƀHa( X b,8Vn=ooGF28We2ӲV0͟|X eBhm۶ *3ܽ{z~@ed2\.tp!R~L'K%`0W̱ť%Q.O&Mme2G d Y +T*uOݾ};")e3Sc7;rO}Ξ9sΝ/\*W*n;xAo"Δ֫` +{K"7Mjϟ8y?;b! h }]i: \aB)4L#C0ZO}WK?|iqi1[tܴF3MjQGc?+K˯C>> IDATя7nܸq˗ڝNB[tT*˵Z^znB~&>0h xh~O|{y杅PP¸J * ! a{fqc0RRj9c\=Ӄawkk3N=zTȅAP;vlLOmm jnj%~_O_|yiqqqq$=eKcO~ɯ 8Oh I@w)5*#2R;釟|{/^)=SfEp8>}•^gۡ:m;i%80!RiFD ! } (CIwQatJ\#=8ٳ'B<ϋ!86c 3cDMlS+w3##twqJ"l766zf"ȴ,TǛܼ{.\Iܳ2J?(_?tVT:=91qcǎ=#Jp?cnaI;`䀹˶i?c!{꩏?RwYXXhۉ;e&j=cG~iɠ?ol6˕J[%u. bmooCRI%FZH|vB ld%vN:h48BKvxg'n޾p'_?+_ʭ[677!"Q\J J2===;;[.N8q%ommaΫTj}}shnT.{'!c7ViWIާr<77wG}t߾}pkzj5^iČsH0XXMURKL !,Ϟ={t*U,}ꝅ۵ɧ?1ױ;rPsog` 8zء{Nc77(b܆Cl$LX'?mnn_WWW[6x𡇎=zṹI`ҴZ͖Xٶ]VJ# âD q@0BQiϣ4W t;rp%)քRT@gn9ji әJu:] R4<()e7iܠܷTJQEv7RX޽{777(DQJ(j6=Bhmmm߾}TTx/~s9SG5p92>>wW&ጝx͏?owl@nײ /]bѩR`XzOO_}k_xGVeA~ a6G߿?JB>c üx(ڻw0?kn<6f3AFLckˆ`%v,a0hwZAw&'ZkFn#$J֊n޼θbT+ Z董???}t^X_* 1X__uFH+uݍ(8lz}m~j WxDbш9׿o6tϞ=Ju]˶GMu#G:\!D:[O}^Sā-MZ. 2a#0Ǿ '&&rܹ^{ /SVFp {#GjZr >ug~헿RJLa0V 895:Vg6^g?տۿ}饗]9@(bh4}ѣGΟnu+1oRH""08ch%A3V б9G٠(Y'8A"b R*J`#M}OHq\׶Bdt1ȵQi?˗ evKu,UKM"ѫ?P# -֦BØ0TZo߾RT(JŋLSnA zǯ^r…t:JLh6[U&^O3O?|WvÇݻwye+AFn2J O~_A.Vm*^Zr*zRГO>"dU*ƘsQR `vvvcc}kku|u;L]AU4k˶c  _:|31 k_ɓ'rV/-/{_!%%qmicٓNWWW!2C)g|yyywNӾGq\_+OrŻw(19)~_|O߿ӨWʆRȲ B30L&],*}կ~o{͛7O>9==tֲl Q?'ߙjߟ5ML9iARI@Ji%-2ƚP̕Z)ap0enpdkSkFI6QNLCD+3V8TF tP-`M|&1Vj #TzDZR1bA1v]>,˪n7Ii4~޽.]:{2vMC0w;>^=X>Oӷ?JrV{jQ{~6 n={/](cO[˗s=t;JkʘBBJKV ~ر`3jׯxa󇁧rS) 1$~M ٱ㺷rG*1m+ ~Wq q<@N\Ӱ(RJ|?y.[Ƣ}?Rqiێ JJQ$:JJRIg_x'Nlmm !M~o4AK8[ng0 N3zQie0L&h6}?~?q[oh9xpllR`^Jiuu1P # A033C)  Zhff6ay}l4[\rn k šJAx?z{§{y;00V@Oi%;??w]?`oC1q1C).#h>}ٳ[[[Oi̻:!$FXX}ٙ|3?o޼y?no^4BȹIwܔ( ca(jҥks8kkk@N@GXI%d2ņR $d8v[߱Eh 3wk5%VDS!${q؁\Nm^+sssccc!! RqG)-o&#1X"r0ؖ59^KA6;x)%(@^_ƶm]vmqqhhSN--/sèVm7Jga L i:ZjullT*YuƍO}깳.llomm):^ZٹU&zǿ/_tRכ3 +P*f0cRɩq .aZLNu !mm۵ZVMOO_|| }j L~ysC1. ֔ LB@A{1@k.pA AĘVMIgT>sL,DXU+;l8gaA`B1d7no710i]6'VQXwddҩɉ_c=/| _W8Z/ܹ+ML''g4VWIpm20b ,[LǏ\Kӗ.]eQB aR)Ƙb۶bi H#)b{)Ujw,FԏӲ`[ iOL:3^:6 i4;gzj#iKM 3t:h4:Nq}uK2"D#]+QJ|HK%SGRJݎx+Ɩ޽[,0i2JK0`<6VZ]Yeydcc͛^OJ9==^K%M2MSiJS‚eY333|>Y@-jwnʽrʭ[  M@ 31$&I*"@Z4JG}XJ*5 !fggs,1m~~V!PM5ܷ0hffn[ƔkI+Z>_(0&qs8턃`z!R\aVۿZ!M"pHe r9B4.--_zu||[qܹ9==n:1j6EmiM!AFg6n!Tx(I"A Dzp80}h0)av]QJNmDZ[ z8.'P^oLiggg N;ahnEQl<02ƕ`gvt&ɴcGB`L0d㘎3d \6Q|>ȥKX!R)(p6Xw] kc!vqCA/{칻("VU(ׯ_pwo&Rj!ر7x#1 )S Νc},t'{yyu8\|l SO=1cmᴀ7˹\ׁ ^d&&ƤX,ݱLQtz}zfΞ1VT[YYQJumXɉ(s fZtʍHit` ھxA4 7n{mCR<J H vJOqSe3fJJ`@05-3Bô=/xiTi }R[o흛\r\s\`ȸiZaqR"YfpTD5%uѤI)è捛[jƐrcYgNMM.^9CH[*$aoeysU=Vh @@$C ID*N,gyؑV¼Σb%MrE$["i$$J@ 'tXs՝Ͻg<[Ƚ]S! a IDAT:GQf18Rgk=UcQjU؞GCSN93jy4c#vkmuP2 x0 \0e֒Po'B˃+n7nfSƔ֥,](I q,XsnV},sYkh6L&,M0wh>sLU8^ sA$R5T2Ɠ$#cEaW޻BΙFan5MU7Vu–Q[Vb΄%Ս>r<=tRͦcA}(spJƄ`hx4n|p8RݫTί[ <V6JemuVݹsgowo8]-S,xBp"F#l-K w\}8\,!xbz}!" A(%G""DTZCz֠BrYJX}CQ!Q` \JTYm%b,Z m ̪06Qe.yÚf)L&7}  )zv'O޸q(ƆV}WO,G8PZ#80SJEyQiB)YZZVQ}B"RJj-$y׷f,0^ۛkeW@¸=תT"$ɧVVzh4ȉRzԩ[0]RJ*4Z) ?9R ?5`TTgaa=VRA cEE#U8, m$B!X\={Pp|ImB"2[L} #d)>+W'1Q^P.Ν;Y9Cl6jQY/2R^TQ5/a? ].J!T)R !cX*5=f;+!0 0lbRfY$)ct2I |Z"- v1I8u Qe֚0!Fc@}BQJ+ptv$kk'WW4v:6s4u͍7ɤZXZ_Rߺ1l\bq"_]]׃lB2  AJ9?>}tVɏ~vF7_^Znn|~V=Q.gȢ~XQF8(8QTFA:T;i͘GUH+pue֭A k$=GB &@حrBVR)UR"',b4Z &ӜUQQTw.%NQ(SH *1"l"|ڎj-jpx\tc%EX0Ru=%4͋ #“qpyyIv7,γp4 0|g.^>zPEX^λI"t=A)q= kzJ*ь0zss+w76~t{cue/򫯾ꫯs7o޸+WdE.%>Ͽ민 V՛7o,VйA !<$uǘpJ)cEX+^t:v+ C0*B29eXlFX&QEĠt4VXcu0ȬO#qk-ǘZTfF0"+ʼd!"kVFiZJ5O ue +r1Ҍ`d ̙SI6&XQJYxTxc# V0JB9d^).HR*=??/?edWS ҇0”JƚfD3pSε"q%f%Ɉ3Ap}Z#ʨy<Ϭ%ް =*c;0B8Z#R&M $Bcmfĝ}DI%!0Ǝ9k\q*FR6NY̏86uzYQB,'XV)L&ҨJb5B(cy-$?3y9xQu,F#Lz?|tڽc-U٘k6FV]pgFnnYA`gګ_x};F[lk %ZP1m4F* 铧|~`^~k_گ?槟,er pccc8>3+++kkk[#-XaN9QVbJJqA FZm }/u}QʔB4hZ8&{-"341L]Ȳi64" BϩkV8F "N)e2Lc4ɂҡdS0H`Ecg}3ku(H€1NÈc\8{~17RZk̦RʹR)|  cEEZ&R2 J6ČRj+taY{A،HQJBA):޺Ê Zdˢ$:2@˂ Ƹ, t/"x"M0j)pf!  z0*p;w{q5qYuQjgۍF#M<ρ?h$8\_? ֽ@.Sʢ Y^w?|?V9???77jZVlgϞp8 ~~_~+?D<πQ%I8:vxʲw~|w 0Xokkq. (J5zEv/:Ͽ0k%Y29|.raqN8( (ZZ.j6[#"x (l c0%PPB90 4y^AΨès01X,`-(dI(eZ(7+%4"BF) NĘq8QdɲOcX 3&ASy?”cRiRʌeeQXE/ݻ[Y)VJe>=j}wP($ǹ4, YJc-&Z)Kc Yy Neq\ $>K1 =lFBnk>t@EFGI! T*KKKLͰZ֎v)ߜSJ1A?@?!RƘ@'If v? c˲Lc(r bxdn=~$R),#8Zmܪ('i ! df|K(K0`"1U&B Fx,NJPH2+qK;ɤ=7wG"pk<N0ZYZkH0Ē疅FdY sV)&w\|빞(EI0 d.°ٜ3zZ`fQ Y!5v!)0 Aj 8 ~7AR<:#R!3zJ(hγQ˛[ ?o7-..B8RZk[~̡`"R^2 AN#q\<ϭhmT [ oti:!Z-ea)H6kW{W.ϋ,2(9@CG +Zʲj5JYYk D+Kp8N0ӔRş,̩T"16R) rm4qa4A tE+)%Z"/1OI6V),˩1t0a%6`:r2 l*[L&~|EQj(M?cL+YT F,KJ)&Z΅㺕Jcȏ,K tg'Oc>@,s >0 (=!LhqA1&ZNrb%F89 #\5}ImZ`+nvkaz{ҥ>:u{޽$1a7nBiC)1JRc?88쬮,k<+8!DiM8[{d$ '2}_OBsssPDUg^ҭZy&AkO;da I )$iPZ6M8J)IYÃ`{m,B1BXQ`(k4!So֒4qod2.r^Q!00qQFKUZ!'M' cEXk3Wn ǒv҃ }XJdЩ1Y6ME;7P]*dicD|/ck OPasRJN˭E~A)G`uBL}ny jj8y aPEՔRiZTͦi~EU,BBUTEQ(F) ` 0NjZ g9Bndc)DY81v]42΅gz &^90`$I2]kJiDaRx~*Na<ڍO?ݻBIqdEQ@Jx٫׮yj}}}sks$2?wxB(XM9S4␻1%uG#x7cjg0,2RZ k'5EYh`3AZ0VC`Uk10]M4rdh[m)UQ-,,(I01BJIcHiY9V)YJ'W'BuG<τ`eYE[K)Q<# R)-˜~"Q֏}>(K ,ˆ p( Tz IDAT̲"4]jLGa\)uG)1Vu[;GI=AE!lk 6I&I(*~ٜaPYOwa3 rDQzl0Ƀ ^O¦ǘ<4hEq_\\\YY(Gzx4 !`X乵((ZO& c4MRq涷>,1Zi0~yI)R Z (cj5|DْYJ9YBs8w"J= `*<ׅ\Y_(JθARaULs KaT;տ?ovcc} y~JpN$QY׍heezQ DU |l2boxEѩSnݺ% < (s)z Z F]ιV f@ΧnGOpLxVeYef=sp( K3PB?.(" 2643m s82%L8~!w$L Pw4-ϟXWPgph6<^EL=c;;Z 6Q=~s.`4MI=XhͰTVJIj~هHj4WuX֋ ,Պ6JeAX+] 8"I,`_V^EvYo !Z7,Ki2J+S*:ZdJYHY–,c ˆ ~K/qGvظLSNW°ިu0X)n Z[D s?bc*:<<&>}ŋvY,x2و?Z*x+W =p%ڔq~1aZq AZΙrxx8 - #7+b]e`¨޻u\ok`8dfiB6ZgYVT\X =2tdk,ɝu[` (y:Q4777u]3)J~y<ϟ\0r`Ad'OFlZSƌ8;zrOz!sΝ;wZsIXBEJk)H󜵵!XYѠ,s+I'qv{ :NC*<ͲDB) p*k5$SFFp͂# /JRRYZZFijE`  %8յÃ=BHQO͡Y.ezgal-J^o6)/ $̈`O JNl1f4%I`` !FV=8 .mI:e,Igt:nK9{˗777N% "s0U뭷`}vZ{w9pBa}sx(t\l.//BjΔ˙jaqpw7nH$xj64-8`qu6ZMk֙ӧFzԤNFfPb&I 1J*HcӕٲAI޹{04Aа˟E"0ꛟqº3*beYen)QpU!"͊!d4afBh4hT1'=yuPt:![P_(&}Hj(?ͷ3XIAJ^78ܙ%FIKq4h0Ȃ)0Ÿt>&@3n)#8gZ9c2JF#SJ%\ZZ|"c uÃ7nj>\1Ͳd< +k_o?yfƘnC0w'"h4ըY]XXxΟ?SU9g s iyvZhs@z`04jQ:מ[ZZHu^E^m2q􊼘L&syyfc"MJ48f^o=n‰qe)s];`Sz])Ϟ={…9B{ 4)4k<8RHB\17ߢ߼~V\uTX{sΌY cB8yDiaR"8~bN:Y՞kզ,TR7ءA7:Zb[2x$IVXaD@yԩ*Kc(2RgIZHsvVVA<jd؎XjiEOR1HpNAKaɱ3Ǔ'/wΞ=ExuuVkL@L|θ(j6/{wa~͵?ϝ={hBJ^QTVzNT {FqҥAyJelڰR3#@ >jYEZdUjUP?ECHRT*e *n3g?{[6Ξ=[Tcj޽{7o|zBk,<8EFJոt߽קNU*g.> c`lAi;^輬F3 pTd-bȢ0;-m{gUZ,ARZMJ &(tS0\\\VWU}d"`dzE{11KKjDO'BcqgPX'gux\TvwXO0l &!`¶vw܅DvJ{n+W+1D˲|R*}| W_W~F_xʕ+uZs f{BZ\V)˃à \S`ɨ8|v:'N N7RkTg(Z^ZnopphT"P2=:RJ kB@7~y#>۩zs8. } u p~YDS^)a\֢$I !$xP8ظ x9$,7O>;$IRz8ZF% h~8`__xEԦ>zu]Ɯd$i*%Q egRJFTR[dg2vX 3`пz*B(VR ϞM4ǞBPbmm ^=c,Ms>}:I&@n5#r$~8iXJTY!9GQ%iz?M;wzQeA%]N(OwY8V8N;i1hNaOsDOdxa~io\[]]BXH)AccVL0/k_/~[1~7obLpxKY^«?*Bʕ+?l5")%wH B?"J%%jҋKKKwܽqjQfEUsTi+ZI潿Wo-sO>}壏6 s,,˲(w< \?vE {q-y^e8Bkdtn^vbmW_~Mk;wvvwx~nGeAUK 8ZMqΝzF(c1”QO̲!q wy(uyyl1(RFh̗E$I+J:/ );n߾a`ՆRFJ_X\8<<,l~/ap[q---=L0ee6C;Ymu=g8k#IiEcf6 F'4@e cyzIRkڞqjc@|o߾M) hl덚:ܜY4ke)* i%̲\Gzlv;Ja)p4fYrK(G9zOY ·K.eY SNmmmUM%e0jéi8+XB{J^;+j eĉZٻ?vO~PN/>+/}/zMW}&8,Vab1 ޽ D-A&Ͳ_9~,˗c'W(QX;//#7n㱔w~w4qϘXVPDZ'͚,3=31ʚQ ЖH$ꖬvPa?؏~aێpC(5Ւn"@ @LUs޼y3A 3*U'=gַ!Ԩfe`ks駟RѣGwv>xXM ‚oA'o|_{??j|EYu=R3cH|K/~a<>N^;wB^o~<ٙL&UY98n͛[~m>}ߜIO&g1lp9WWV4򗿼3Nq(uU[Z/7FEAih%Iʲ ߏ56 cch4;5 C9K @^J{ti5_[Řl) -ݽʪSJj/ @%Gq4WGӿz寞/}/1MS7R P1bqֺ(L=;#++͝B'~ٻB{d]]Մ =q,8::S)l6# T IDATDX?/<»N .1N(OTv;W{O?YUՔ`pƍ^xa4}F((#)t:& (]eYy{_vOOO8/|;wkמ}ٝw~ӝ~pi8RsPZJi4{FP>/~_|q<;_Eqtttttt:M'A/ʍ7y|_O=!WR&C؂._+˷oߞf0$ɭ[n޼_?99ɋoݼ o_'?uUU)>\yvv~dXQ{{{2>|r> !!B(˲޽{/~v ((dәf5KU9arFgBҧc,ˣFsc-2kmY֯ޞsn$I_wz8޽{7y裏yWp8Ĉx{Z,R g1ZO0!f7 1&cI줥OHְ̯4s9wAsr)_o0%t?|ι<ρ~>W᪪߿t420R^ݸRE^_җvvvF |&EQE]W :i )xmmnnmnVUuvvkSO=u~~>:1.$9<>~뭷]6e1I(rsv:uKӟ7 iv:N> /!E1NONN~o>z쬪^x@ 0M:=!DpP׀)pGJ>Xg$I40 a+@,;A;s~~^?^z饯zy{Y)EEFAicƚuAo6~VUet:QI)S{c֕"uaNNoΜst00s0jV+Gim* LΝZȓ6֢n}q4#?nݸqΝw@mwF`wܹvo3IBr.BFer$qc}ivοܝxヒ.i;{XeYUuz'_|ããE $L|G'''?y-ȘBIYyQlo_ ,{;WBf⥝((YX7֩&")ee1Xk|r:읿LX4M  e5c@ q BPJ$M;m\*2cb2FQXxtUȂd:( k3!L(}ۨKqS^C)yݔQUUųKvGiD2N'''Qi1KMEL|M9UM n2jkeVE Pʟ}yUU*שׁ4I3>=9=Ng 3CfABF3!d x~: J@sVxRʫ[[''Xg≛V+GGGGGb܏J'''''łs)$M1a V47tBw}[uTB)4tZyY!X# tĤ <(Km JnoUUe SSC&*Vb12HxAwd6icLJ!F8 `spȢ8I^@ (gmeA p F(ݻO ?8,a}FQT\&e 4L'G'Met-z M g4t82y 8>>OTc7www@ ]0t29>>U6HڕEFR=V rg2Vu>LB72F(ŘPN2NcSʂ0Jn7ڂ-Q B$>W^qbǓ]|IsAgȥuNGSJ!𦮥 sA qy LS)z*˲d؄&$ щ1^1 #5hs@ ` L„`eU{ƍ}xp]PY5RQ AUΙ8Bn@p^5EU`,/s,%)BHydcIbFq >ks{7?|Z`uS{)Ql~>KJscs^ !XY rS?{睲(;TW58(y7x[nZi)m&EQlo_{NNgOU0ilqs&ReY0Ɯ%J8g #¨0YSie f2Re/(gseݔ"930qwAn2a3J#!L2O'MBӢ@yƨuL撰R:g4aօP{I'ZhiK4FޥIlRl4vUa,o޼O&ǎR1SJI)uyWb^BZ8k#8mM\`vފP Γp !D(eZ=ϵ6# Ɣ`\,0\*o{L<ƑP|Y]5!I.0#S2pʲ-+` a1.K~fUZ2f&9;0F)EQ~RJZJi]W$ɱbȽA>!+8;Cr}  bbBC^f2qA8gEIGPf`:&FHdH \1Ƙq`iis2I/boo~`؏d66".e(ՀWpR.9Zc1CMɩ!NBQ0{(reG2k8B0 )J7Z[w}* .4tRE F!8%'e$FeaL0qY.@ R# ,K)&DY{mZ]E0B[K0Ax("3U]SN9a sXX: ІFFM Q,&8 cg, cGJ%IRMZ0$q0\A{t.ip-2hm5@Ga5;E&ė!2J!#D)(Uw;FʨK!󳳳;ǁꦶ: v!=ƘrÔJADuXp ZЁ*`ii-'e*k6/ c=g<".$eXy8M`Lj?sedRk=fo>ٜsI'_FQR( pDGOOG8) N 5y$\X:ݞ֚0*D45!(%3!㤪Kk c,B'304FSF)R˜Rcqə#DŽbDINEQ* `vTk UZ3.)X=&n ]J)YjR/:"FdR `h(l1J)%uu}4뺁01dF,;99iiҔ2[\im`A$ֺ0 BH|ńRXQn:??M-#XAp9n1Ѻi8JŗYBƿ [ƹ~sjWPDE>@:Iu%7ۄcsI{*þkv.SZS/m`oCd"lHpU5Z1D)dr]jxKm?6`8: 㺮A( E:xq3B ˆsT㽋c45Õ)  +8^,~B0 dai(nEPU- X;Kb-hcs>$I j(j3 th[WkI[zt;sʇBn[WXS B&pK=@@X˫ r@ ငrlUU9(F'C(*^$"7޸q|.)cJ(AEY'I;QO?dJ0 ;K) snAr#BcGqN 1n- )yEFZnJ) @O;Ν;wi߇Zk4 .LnYm#45B:ێ<6C/^X˙YB# . ak֦nTC.t (r2x,ɂ樂, ~2/K O|N &`Z? !3<Gb5"z*9X]]e;,KctPg"S))% ,::anC)P1=;ooo !0xy!q !I\ /n`PmE6b  nQ- :GB$I >Xq]AIe@w:s!ʎ(  cVc8;_Ԁb.<>X-{֭e7t]P̈́w|atvḴm1Lu= ``tl -B?p)!1HtAFģP糺8 9TՅL1֔|&8뤔Vr0FRT) IDAT\%Iks,Mҧ?woL'3)θYT6ER2rkk+˲˲ v쟽4MAzuu9kj{9ǸK> 7g<wAx9gyyPoBqt:BY_,PCt TRRpx,? VBȍ7 ඞ!ay8CIp3*1 -EV ,˲,:0$ DXx!*Al!i 8JUUNnY;OAkoch/CKkmyݻ>~Zkac %6c1Js!dIV3(%BqָbA|3RJ(tqba$UJy(]3FYƌ1Js,f`0 V43A(!t:?>:ZqJyR+h`^XU<,BK L?<< MS`RM$/wcD0m<kֵuZ%kE*!!$ 3!$B1@1T+')etƅYjrNr52*0s6,Iby#@Dh` Au9hQG7n]5r@x0+J wl;~T yPpVonzeeTSU >Y(b޴Rʛ7oi:oC.HJ GN( :qnw4a1arA뜇qC )Uk| :hW'sȲܢ`p7766GM&.:rs{$e y!16,+LYb=;w9\Lj P /&3tE%Bp\ QJ{,ctZeeD6`i{as8Zaw͹.U4Mau1R= [7n\ue}uee:X[Yݽs{ue2nm\zukkpqe}ߏ0M"0$"KTJʲP4B=*XN)\x/*` 6 a2IB9S DZR 9$@ڎCÓ rRs`iH@n{ATjPaw]t7~.#HctaL44B*}]zu8VUb8Qݼy| vR ".ڀpssR b3[\p4 :Gf[2F/b9K)0^z~I|ɝը`4 &y獱0c, en9=@ B)BnjPk<u]z]!dQ!"`e1X~NGGagW`4)˪L&~h9?GQ<w[bn2N5B|w&6P%bvC6vAAtپݿNư].BkBR !$⪪0nI;.B 'o_yw~ܼӟ>Lwhd  =حS[|F6B^0|'C1e-ݥGZieFw67u%d5$<99Ҳ,[13{UYQ6k׮e*&d=>]6-iVg giz,??w֮eT#.q,ZFkc8(&Tkf;G2J1$ Cy"VQM&+2g>A3 R@sxL6T)@#ҦQ b{'ĵw}dAө&c8NgIY1u]RG"xO" XB!|HK \#sX1Ɣz EE;b: J\k Tcht20){=SJ9gL5|>38 ʚ` r("g}YpZlg{"J-0F+kzáɊ謵ZZ((v|ϭ *Gva! ХZB'{)\:bP}!,id *;;;oc\0"k]ןg}j8A7Mù(b6̈́,BHȿ6Ji!HWUUUYI@1Ν;>= (`pVAc$b52cCЪj ~|>LfUYsC;6AtY+y:+($n `50 ]zнD s_|ŏ? f3H6Q`(QBJyFIXgcʔ: lg;D`ss[|eY a':㫲β|u1e4j<¸*Kmt eJk igcq]Ui1F{K7 e Mӄa"9cA[!Xiʪ~WᝥL*U_Y%"9ﷶlfZ/Y^,9c%2缔aqR2$ݝ+`(güwZ4*C0"FSE^x)yV`Ov8FFYO  8D, dy'u;}ﰷ$ { %\4b!XiԖ)d__+׮]WVwȖ$Y]]ߧz7nܸy[nݼyukkeuĭׯm[R ^͜r#EFi RE-*ܻlYF[JYɳBiS|A)eh)shVkM y^`z)onnVeKM0w-ts#=HkKLcD5ʳcLnIG-3*„ja[]]ںqƵk[P~<< )emSRjS0X!l `7 P1BF#PIHʚA10eYAniM eyk,supp?2NsY<~ ^N@5#1AmcqJe,i5 0l8\}} RFQl6+  4R .8B-P'r/nvH眇Z]1/:ϸhAxr7[5Bnxwy?!̎=ֹhajuu͛>o߾a`8"{Տ8WjS&q.Z^9\ΈREQۉKi>C#-  3Y>Kj@AgY6L\2 FaLΈ?BOek׮2cR5E (QZ<7PZe1ǡQs/SauUY[ Ak˓=LK i:+ČAq j0*,1QQ:r`[@j,9JS &ocapQd1#! F.,p(qfh.*06J@tVU!(/2|E_zS)$!ttkF-G4>C`[K_8K1߅1 <夔``f;~_eyvS7U^U]9g^w-5#k6 #syt"KDq!g`Nz=0PDHZ.ɥ~kBm wӭͿW^y>;^}ڍ7_qͫW^H9wppX5tIݺON}g==BrVBcq3VGFm󥚳s:}蔭> ! P}t:Y Kðn8`[~9f]VʫCk,bmi 8{@SN0x0=Zu%;9[7u+p`.3,H~!P^ Pe i+Gq>LIi`?nXc_ @"]YfY6 Tl^ރs. ( J)t{ϧi:MN:g7MSU]pXS!!Ke 7]/$a1a(EEQhi=\(jy`1;?h9Zf !_7uē4IQ-/&)R8(eju8yYB,tPHwzzjaan{{ \֠40F}`Y`Wq] PJQZe֔,0= Ilo><p&Ix6h,˲@8nEoNR^sނJͭm.fI 2mK Sf9nei%ItxY8YAy*h'i0K pBffMȯnL{9pRJoD,^Xuyd+x (,0C (l; CXI7 tqA)1Jx=DFZЦ!`62=\)^TRXTpGx(ؖgl:s4P`n̢Qxm |hH< IDATmtx+`jn6nDXpa%!i .T B(M2cr+3$NX-^oN`6aSifYV݆+ڻ)4vA J5a)RGvLcj{{{J$ 4麅E I û:DI j/V {0+evG613XXl4(c\rrɍrt8HҤna:M;:\.;w8iYH) 0$ )a] qJ)S8(l۶m&i4_d#>)4j|Q0$4ٙ7nLO[$9q>3,7 8D2Tu4%ByջjEp0 wvvVWWܹx>! (ȔajR=wfccY1h F?M4AZ8re}}q`[jwf)R e[r*ට qH㚅OG?N0 B btKFvk&,K,Y\<?|Mv5MkmJIbq2\EC7+,aTU)!xjjģE!(R `F P#QV@hM,ru!x cdZ}~8Hj<)@+7^r Ð[)"/:ƨFB Mr97q BraPJff(! X$#%1&lq΅t:SǦcxmQs]z`LZ$PTh;l4frxjzʶ,~ (\{Օh@X,40,DZM X)yɷ12FB:yT*ek614C4sy7B!aa5Nif؋K~V˥\.lx&0&N\+;>z0[~Fxڃ t:+^sd@.e)!$l !J \`0BYA~`fטn'&'faaVa F /?8z^`1=yx\]^{km;S.MS!H,Y~ieYj?XK&zvZ2JG 8u-4g!$q\V''&j?F4c[eY^>W)z(Yf7Z}vzZ)H!<%Gi 1^.urd܌W(s,M (z؋ @01Iݭ 4?|[[{'FH&q\.^7Y,"{J!.8cBRyfLLLqrwuc$ -4 $M҄0:7?j5Ӱ''wV4A`m/\֘vj*XY]H 3aYp. lp@$D+]Rc#K)Ά+om0\%91=s[EqSF66j[YYMdZzaR }X6?B*M33շ~2a p!4uB` 0B5M%mYGĢ,%|92T 1M AaOiy7^ I^Uf&''&Z^.Ţmۀ"iA GӟZ&tWQT>b ( ,/LMMIB >yb'BAαV\8ͻJ~LOMMNNe|G˿Z ꄔ,_$j~vڕ+W BQ.;OadaYo~_߽tG0-+APRe$I"fQPJ&D*2Q>$(;G˲)œ$8jXU0Vxi M3T|$1t=K3`L])ąxEQuRjD6;;ǘU hh4(J\TC$Y33twwvwafϲ1 OZmqqŋIv8v{}0^4Z.VՇ5hBH%sBZ5M͹j?ss+w8wtR~챏u;_zwX_]AلG4vqY,5F~o?__y駿߮,/7 `qlX0 ^;v^7K.{Q:}fggW7L0 4M04,abyEk?/<3=3| J)}Wl}mjAbT8u l!왳_* "R,ib,bqR1f$IJ+:y07̳/ |W_]__oZ` p%juvvviiibbn_|ƍq:uj#SnLTe(1m4ƈHfP(P Bq%PH)ƆP-SNL/Y=?,KXyhYRH9?;^׿+ܾ}X'N8qXRm+5[KJI!aZݻͲ빮;̅.c}}=I #.|C>t##=cEFh|0F͏#d"RJgx?:GQ8Ή'5Mk4`۶54-`0,JH*-yk aTj481RB:xmWt(%GH ?w::qMrk^ þi.)%N?ReՏbXG1H) VJljk ft!oaX:"1@AL:ˏ` ~ X $Y\\L]YG9 "AXmKE;}M<ϻyؽ觃)p1j _CӞ-//;Aw0|ue>㜇D|4Y&(x~il8޼yseeg}oolnp! ӔJuH8'L'Nnc)gg窕a#ϟ??;sxx裏۝;watñs24q#f9!H;>D׍8T{n csY){O=_/~_~vvv.^|ڵw6R7Mre`PQe*c?k_B=񙙙[>(W*GX%Il]m] Wηsg~~_~K_zWwvv '?ɛ7?h&a0QڽĴ`f2b{@;=ΥiBaNo$sS1,>z8B&vMv1v,{'i¥B]3mRʲ!i04DQ#D(I$k;b$Qw0AyB)љIA 1 !?#l;$$RF>Z'_(i x(0Yf6UU.^l<A Y uG,V . ,AKɦc1>0c ]4=Bie Xe`Y)a׳a1JW;x/~DzǏ?7@ ni4~6eiYӉ)T„ E (#uhZ6BJFX*08nZRijj^3~y|0Lz^P(88 p:y$ #j8Mgy uD鄒(1e5|>_V76\A*YTlzm4667!|vvwƉ򅢦R)J(ssBp†nHM¡fX6J*f8y6gf>Ou+WfYvf B+J ՄDr`bb*_ N׍Qs.T*3Frˆл[m? K.E;c%L{s:w `d@҃ J$osssx[5AI $IAM O|!)aXW:~iؚf2jDaI'J44F p%9[ āRH!eIJiY1TEBJ4*er @ nZmz7o^}?ˁ0F1F N{s8k+p9~'ECJɽni={vrr\.?ٓ'O΍i[rB~]Ǿp|~w~OO`$IٳRG4͎ƛqsi{7):q|}}nMNNyxhZ,cjYRh!i"MYZC rf}s.4Ӳ]G;ʩͿvEQniRŸׁIPiA?|$FHB AcAJEQ f2JD,!8!M)Иm"HJ!cT6L#KP aJJJ )A`I$R` # tybhT>"9"#`y/䅔eq!hXӘ8!!JJ0BaB<iJcÊaF)m4m/,,\t Vv;C=v 1a z:#& | Tk8|'K/]W^$5Q7tJH8?w'?_/xΝ0 S}: ӂE[}A iJGil8ږN:RII)t:ϟ#fi;yqP äPL`$H'O6,i0<[gh6šJӴZQF(*JO<cRB8B>XG@9_2Kt@.PB aa_~ݶ'Ood̙3w OMMA $]JJdsu:]=ϓR ˸i^Rb'W,߹㶔nivulx(Y磛7j#U)B Q^&ӌ mǎdzzE<:\@ Pٙ@Qli&$c[-T}~_q#%W[__׾V.#ܺu@ d&cR^w x]1SDalۄb(;4RJ)cj.mG8J#"""JI ˲ӳLd43FbM!V2ƂId `F19# ԽE 4XG(OB"I#BqI4s8׈iLYlMM,.-]B==>ne`t vS J*C7aZfa( aHs' !Lc('>1;; 7߸oaivƍ߽~j}c++&TML!ycJԔeJ5M~Aap{ !R㍤Z\2M(O9FN)s(e \t4PR5M2$hǒiHEj?tΞ9u |/r\L/ً8N`0/}8Zh@M}W^UrR!Yu{}0gff'n>x݇zu.+ѰfJ7L%T$Ni7 nKek;cAeYbI*%rc}cA`zS! )(McM3\'Gp, :8&q؎n뚮аRbffZFQ<== -Ӣ8!u4 aIB+r>_`°rd!RȶvKq].a:x{{wqqT1&cCta6{|єƘH%-o+6`\vuy1jRBB\N vSenAVNu Hb|}rrLpggg[^^#ι)Bi)I0f !œ+R!1ceY6=x#aµav׷ZýFva8z'tzS0N;~mŬ 4-\ZV1ر$!\.'X~ɓ/~{8*)cuEaƜiSJAu0KHbD)]l4J2 Um~׮_Gf5wO!+W*8cam{m*d*J@BXQyGAR)?yեzq9v^+m'?ŢBmYY-,,PJ!D F3O{(JQǫk)R*,uQI_kkvۭ-Ij>(SO=U*֏߽{wcc'ג8-˧OUgOZDe^yXZ2JFbZo~w{7}{|aGM RYc`[c*{8 !\ac62۲^Zm8m3c0g z1 2qL0ʵT$JB !kP(-/5'pfd3mfY6$Oln}dG)L.plJ VR)ԡꑑQ4o! IDATP-`eYI 6 !,gFB4rOI%Ju!g|V !4Sx(~1:;4M֏l!$q"tGie=4C`Zhir^TVVVn޼@XrWUugHX%jMB!,/ cctd#Ԡ x8ȲRiooRFRb B 9;a(8s@+QŜRmL 4K6QV BRD[s$s5(q,SҘQ2J0M P; 2J ÑR&P0 aƹ0Z+1`FØ0S)!BAS>1^1+@ێ 1BPƤjX*u3=gs1eII`5 Qk#SNmmmsj$bv0ear2sctȅ;mA;qs9J)BFmb^j=J1qƏ?q3:~j9%C Cf[[rqh̸E1h}TWW77t;_+_wIo{キ7O𷶶-8,ٽ1Fy?~8< \ܫR9ҥK_n>g58(8n!X]*juM0 _}?0r\*|_o|GZh4z^j OR9o0~? 4K|om^$@F44MֶܲeKho\zgsiy>GqZ-JHуDJeYn$N j' |R*=cjm8(iUga\ՆJ #/5DB~(T qJc 8 PR#H cFF2%bij# B@Hk$xcJ+4B#EHl?kH?ŧi2Z$4S0>'J)#%tx$ZTqPe~yn{%zd$YXX<88(J0Ƃ]BGt:9䜏F# %8Q?dͽy1ƶmAp61HTI9RpWx2Tr[!n۶(F3sI!(ծjRb1!VqEc3g޽m3z_oo}O>vϟ嗳,V;RpL@bRFR~R^ܲ_^.oݺ4в )Ǽhc,űAQ CͲ|wwtϜ[Y[v0D?~q4֟~/GW)%ryaaayyl.///---//8qڂ("͕+>}')%q,"@~RR:`0 z\b}̽gAvims sQ:􀬱lgn% i;>4y_ Q93@P!m{mԳ]F Ø " ;ʐžQE"25c( IwX,Ib2K)³CtyMpc# 'B((4@4ĆapX!d4@&J fZks ŸQ# 2Q#}exzbL JJrcۖRH; Y)c@Z.RJe4Eq@]GA|R^vm@\.C^ϧ] /0aB݆"ӃipP !_җ^uPZ9UǑcZm8Aܲm7 "cr\QJeBAs 0%GȲ!R t_FfT qo--.cg;KPim  0qJdf@.-;28 bz(E.2p*Ja?h?P %LI0xir!"$*dY>_BIt[naVWWϜ9sٓ'O...¨.76׾oA>d.M:+ B)x;;n lfs!rx;|8D1 ҜsuFBMrb* Kr2 qΣ(2Ly.vQR3jL}t? e1@\FqfaĉTʲǏZ-!:Yuʕ~; ,KVH1 |Qrx_~~'?I{Wx2K%q` I0aL%F+ck=VVs{=p$Cg̲->Ke!7𥔎c+0"C(b 2hJGNՂ89$7wz[ ArPƯk׮=W\9uSdYF "z_w6 m8 FJ8޸qw=0`e^q F`[kZiRq;r֥RYi-RߖR4 c&Ƙc;R꺞Rj4* [!(ki%qlk϶E(eBJblÆs f! "F13>väZaڅ!qgL3+`2jK)RFjB|9%TF#řA1\dyD)3H)-_hpTsXJE)I)hSlJk6:sc\բ(]wss\ln2 +G p83z4GRjPPJ=σ[ dvf3׮][#"xmATν͛zG?@?˅}_+~&V 8%x<> ? GR2F;Csxqgg?t:'NZ?|1bB 3M4u1fY6gl2 + <*KB4~F#sqcL4XQs*NĵmLBsMZ-n)dcL0Z`p:<|Hu6@ic(!`M) \y\OJI9l!ϧ3`&IRR'cao*Ez<mo/6~yydAM`8u]]XXz~JhJ)| U&,KO&qhad \* ?#f\۵-;b˲6Sl`a]GC1RLV!cAfKD i#aTٵmq(1m@W*5A/&R 8Ba=306BI QaY#aFj# Rƨ$d)O#t'ad@ ߼1B1(%J3V+Y]]楥%qg@b+ǎy/6M@0):W zw" !45;;;Q{7 8ѳfeY0 m7Z-\=88y`^!$PkeV) VW[VZB0e/.-8,^n8KKCƨ`st`ۤCĜdCh{|nAEag<\HLk3CR  sAUs-4N0\sHrV+J}1+T4歃?xݻyy,K޽:Tԛ0Sb <v xfRXE0K'OjFp)MZ^^s BdIr3F---EQ#̩Nj {n߻woi;8 IDAT4MSJ6K8'(E̠1F̟M9!Z*gM g,JM=SOoëG q9jp{cA>~;GD fQ۝Bh4YqZTW5< 7Z MS!d%Cs2+)%Ȣ,I?I}ϵKs\`3$'VqݠJZc0LRl<rfkAB()e<*2b8?|0 X{mT;uzlIyT2F` 6f͉Liy d,̠]mQ`n:Jegg !゜̡45 u{dш3jiߟ{MR*#LU؈69s)^Ŝ1.Vr\.#4}FߏO7\YitzJJ\E B( }߫ժVׯ];z3gj5 oι!,9|I BI!O) 9tD'|.P#B8cZ$IÍFy͛ rdm[J)Z8?EݮRiټ{ғO^w f?bLl'2t~xwΝǏqKs{h e!l4;2$ 1˶9cq!CN:sfP8N1__[[;q/_77cBHkd[YQ)UgY61CE$ 1j9cفR|/p[;Ɉq3qovľ'S42BqNpxvIhӢcqijY+xidi>Z2Ƙs}+!r= ]eAF C)-DI u]R%B$ #?,~6[;X#G,eۅba8c  g<駟͛xqqr LM- aP(/)G(1VA-r0M@Qǎx<|IP@q)JȏǜqL8**HA$(޻w祥= !!DIFRaspppYP\t:~xBfV8znS.KÃV_~rt+++GAȞ<ZNT*L\ug8<0~󜰴ZUK4M{Qxףu?(vzq~[wΝ?KW>qsx`VJ2amT:#˲,{,vw_ ֭[hwvA1cPT-,9PJAtSN<ǎ4W?ww?J Ji)ъ\iI{g[vRqyigիi%t[J=( gx3gΔRt vwտ?rF8MK.0&[kX$<˳]Fi|#*u5RɈRlHkMcƨ(kVqBn` َ7LOR:ps>c̸`WF-Ǔ Bp0RZ_?vJjp`R,2.Ń$CթS'nܼڀe4 a?~5Q!B~OAxa=ZPnWc1FQ]zܒsSPRɂ16 (CKwMӴnÿ]e?ǃ>t"!ǎ߇XeA DEQRŏcqz‚RʱmDZTeQXv`+(!@xz9`^QB$I[Bf?tVt}?887?;a*RJ#c8rx:gLwK++hd) se!b;w`:DZq,!cFJUhA7 c E7DyЗTxc9hJZF>u,Ah$$ӛj5WVmݻ{oc?OtaFA .LJ~ ŸܽjZ,)%_W61W˱, |R*XΟ}qΝ᠏+Q<mٶc#gkB&WRA!(0os·ñ8kq !b\nQ!0GXV.Wbg՚2FO)h6 9hc=Ppy8j`8>Ӝ SR L +Jo@! 2M&r ԩSv{qqt𯀡ik`: CBH !`T R\(p,hl6>@F~aǎy d2*c,Ň1#f5Ţ>8]a'Rnmc+諿_W?yoo~m4\_<c+B.fGB ϲL‰AT,)sh4L1[Sks>l6;w`nigY޹}cggkyy?lo︮{ɫW)\Ǔ0nM&uax.K/4RX(@y1~\rsu5 ,͵sqwww0BZ럼AXN< _|`#2T((\⩕!`6 ( _GZkF8é*"6r{q໙#EØfYJ)O #<!"J.)%˻!ACHYO\~sܹ[n"OaF@چEE0J>Ѓ\)坝Po4=<DT*Ǐ;=i$9/õP"Og}WVV(%nyb' >fߏ!lYT*_?WFwhut;qdN ȲZuP5v acp8Biy.0g?{w?^W;wN&W f8cY~?x_vh4 j?T*5_~_Ae6*ri|套x_x>sM)a^5Iz]g iDq?W8y'bsi飫W]A082a9";(,Zbjcqqcc^7o|v$Ǡ;D]PBrd6D!TOP! j[ς #.\6-!sdƚ.\x; Troow wc ĵVU(Ff`W1m8>oݺ8NݶmhFC 'O8qi(T*SN>Sׯ_GWT$EZ,˶n Q7Zk 91Gvs/ ӧO?s|r@~&^9">'4M͟MH..\y^xjן}(ZuL&$[}߫_'Gћooɵkoooqn}+_yag^)"8w„Yo/cBB^* /3lmo Nbx[,ϝ;wpppڵ'ܻwme!!1Blu^jYr ʬ}/?YTkt~kܕ666vwwǣq.W*fyՕ^{?'[[/^:*/kDZ2Ijr,ˢq)rfSF5b)-C5 $G;;;2L0L#4 A)&kPɑ֚ڧF`VIB&DSpB0J &J3 էj~8u ixr3zX+ET16jm2llb$lމ'OuVG?eY`؛5Ia~\kefzz03`peJamaG^- +DmʖER m"`jˬ\x2O@ Ȋ鮮 xB#>C1dpc+iz}0<{o~?]6Lggg2#0bgo2q}kl6[.Ӟ?>K?\?G޹,4 ?z|7pOeCы@bkϿw~_z",vA^ReiF8V_\}?w}wsp8{g$X {yy~_O>fm|_G?G2RQCvyb'jldKʸJWooR%c078]]]oox|^UuNe|֚4pKd8l6k2~g/Mt:wy> >_~;􋧟/ֺ6!@ vaf&(.XNSv,O5ƚ)|,M.B"WIZoɲ ^DF7-L!9&|Hiy^b(eqZhs1fsWwz| >;LfZk>==}x2Ν_\<{bҬGd4Ͳ@)eX9#kWs;nEBz#\h?Ou] yNOOկr.>sn۶ eu]fI"SG+=;:_\g~H@:m_MYH}Ù=Pk}1Hh$|'@a"Ǐ?SOOORm&͒MWUU$ohmz8wO׫v*;x<Yzqqquu^o*4KҬ, lAbX,z N~g !CXB3^Hpi*r4(w0Q(wPHJ%Qku6(LHὭ;&! IDAT*x$M,N;wUUUۦinY;I<aUUfru&r0IqD s=cQCB / `.K)N6땒ݻx, $]cb `$lZmնZx\Jb<<<F;WYܟ d20B8Yx}\^]^.zV)5AYRyuuZ.o˦KR5888>>>}zÈE_c e48G s$D))" q)XRrttɓ  )r.()RJ#29D ! ),c ]1Ί|h:I"]$c]c\c\Mmmlk\cvz>8\.D;Hb?UsOSIuF*?:>nXOzJЃOTPbE*™ kO \*EoOPͽ{7W$e;aq8GRO4M۶UUͅ$DQJONNnnMSé6I!m[h29oMkL׺tX80j@LH"q<g ;#He]5tZyygRQ2mM4m4\Hcl^R%I2.5hdiV$K,rw.yyᜫW%ct~}UWk%}^ ?X? b 4"vy왔+JB[ׄD)RJ$ ČAwYkm auHq4OT:\:b!ANlv Zc}zBL'H h\B)(2N]۶ֺ,(T%zFH'ϟ? o=y}hچ}`d2?{o9'(ƐI((;5]۶m.FZ׍muYBQt< z2e<_/7sFi1MSJ)\g:=צ;rB,KuSL&"w}OOVD u*Q ̇صz:^^]ܻslL9HɗeәF*ٮnƇGgq8oCt>]AtJ:ͦi4ύ\p!xvBG4Kg?0u2oT `ܓ{!O߷mgmNWF)ٶ6/<˶um!1ZSBuUj9-1)4;D&)L!dK$zp8 /뭳>rE1/4+&#kwijkN*Nb4F@ xLǧ'Oݮ&X7Ah45_׾ cl>t]ǹM@z(M]ӿ5?yY4R%h@@"RbaOwW4K޴w}XOh2=VuY^0/e܇X(T!Zs9[Q``pXt]7n6R$Bqs 5B㱏Q[;=8R"/h4.ʒ1 SꪗI)?{Vm7'z 6!g\fy.L1ɘT2"!T"Ji+$?<0*I@ڝ^?fs}}\.у eƘP1vJS 0i[eEݹ #0 qG׈PήhŋEYZkGXB<s~||\.bthPcߏ(Ɠh0,CGGZYa:^__}[矎#=yC$V ^m:iJz6BmdVh]^^j5M$* n9_V1캮+ ͦӚs1 fUUDeƘ픒B`I?@B䜂u'/WK!FJkӺUJ7^0ѣGRʦm4m۶({4նҺcYcRRJ!&/ !|6Kӄ jicT"IXwOY;D*><&I{bz0RYknn!$QrBbv|#\Մ笏>R!sf[U>ömGQfz22pF"ݮK_z{qD%Id2<6ں.,Uxx,Hd<uu DpJXtw^3N!Z3(p1z(%R'E^BI _cGlg2Erm(\Bieژ$M{c8qۦ\T)Us\۵eYcy8c)#!qİ j}⣏>nm[Yazp }GZ+8ݣ)ŕ`ZwQaЌ " b_O}pw$|V;cov٤YNࠡ-yvlP7 )-DE,Y~1Tz{b}5;wl*xʬvYw] !Qqvv9;amNB[ϤObF1N ZC)9::tή+,!QkvOYY77703Fc9C\ p#k->Yܻws4mrZkM׵Y!ݻwnn&|>W*wrBLtuL0NJ,"5sqyY^QJ!|^yY.4vsrs?w5du ɭj$Zv$I !(s.b,BV?j8PJ۶;>>01ѰfEgYZ[B堜2B}p!z!8$РMy_z|߱%=@$riJytO#cT|𵛛Ua0rCmr.F  1| ֦iuւc%@ՇM g`#Zp/h hQFk<} yl6.2VGGGl8%18U%|@0gy]WyϞ=[0@;ps9#=tAеNvqȰ-ݻw6.ƀ9i-8Ot\$P~qITCi(<BcmI`fYgC֘H*OHu]%F9h4F=H8;'''p_.8zl60za^|?Hy Fyy:IjeY$ڲ(A#4O2B> $!y5B6ژN%2_7~IZC2pά5fHFιW]Wc M1Mi~PA΄wiUhYq{CǮnO"%1t})W)ڥTPIGJ!,eh1F9dZmnnEQ/m󦪶dL)\,4hyCpkE,16M'i8.Mx<5#H!` !ܻw˗cJ^O; v{?^!^L< X^Q<=eC% %dZ&S  *Ahf8"?PtZ˿T gl ~FS It{5M!z2bDS@圆jsvv,,LX!d}TIL(^Eo1ns@p_rκ !]J(v޻|UWmӤYyykfgd}( TyXu ìvk1z%hBRD"T2IS!{w0L6d4]}88'Z )~Qk &,G~js>(~m麖 3qM''';7]fW#7MSMEQ4F3*(!P)%cYO=::*"Y < !l4uny7mXfOE g>-  hPy?~n^qLGG޻NJzIяcBcp4q;U' %i^c̓q:o=>':oR6z=(Nwl,׫m$QNw1Ed\ !x`P-c@[]5Us!PNB Ym:]]myaPX,ۨq<ϼwJ)Rw鬟]kszo2>X6I)e$yG[g"HŅm[}t>`o uI!F)$?$0S(Es(((|%Eh9on:ȋlL=zy𴪪ãz}0=n+X]YeԂ@VeYVUI09x/F-Z|`@)oAQYt:{W_м1~ݻw'b%wu GCG0=N!q>rĬuΝvNSxżc81] pʤL0i?0xVK)u]m6k)%4M0axz0sf_888opЫB&1Id|uuBDT|@JIJc`0apz>_Mj,`L9'''?~JN֜۫RBu1eY@bcmal-Lkgg&\P1cZ0Ff,lzڶ5F;WRbYs)'Zw>x!TK9$yr||pu}qqyV#4QJwmY3| !jeN$drQbޓ`,jfa$Ιyr缓wͲi*JU@81g[$} ԚLHUEۈvGڅ k@eLbX+_{ι|pNNz.|^3ʖ )e ,uXU7n60nw;W25ZgM*uAN[ok /GGGJr9 zWo?jJQ1Z99<<\ RNݧ@;Ǐ?`hmw~emh4Niڦm;c,缪*8O˲ ǣ+qLJi6jX8(%]׎!y6!y?LJ7>}4,iN#ڶ6T$7Ƅuiv]B`c YRx} IDATRFq-(&/0(#>8c5^Z$QIFaTI`mG2>efp,$YWfqqo9JEa's:3J)!sGg9cIlI(h/4ͲqJiZ!i$D2NC.X+JɵϞ?MRc@1m[!RZQFmg12s|<|pZJgJ"J4KRH!5Q10B\d8BTqbUmR\#esSj:vut]o"DrSCZha,"p=1MTiSK~}}i 1*%e׵*QyGBuZ+)E&7,F, LӴ!JXKH:&c1SʣmkDRGFvpN9`prr\.cDeZs>B*mJ,[0Y,fR" $IR1TUؑQFI5MpMw0úٶm\FsV mQ.ko6Bd3m4%mjkJ$1#޻,9$Eqtxଝ]_9\ !X1Νjͥ4 YTi Fꬋ!eQ99ϼ赇Rja飯{ ,%ci. $QιvJd49TUy&1q-MSn e9,4ͺNk"Iz惥e* qFH $FɅ`FFT b$!Fd(Q*xշ\2JhP%R2" a }mӒ!XJcޘ&D;$D[ .WKMzq!< kݥirrrl w܋dYqxx6]>=e/ 1k;m,)cth$s{c:!R) Bl`CG q3VnQJ6!VL{]^^fPT1H1Fj]lںgsʸ1n8(yn9wuu!t!UYכ z4MS_Z7 vk=Ź "RRҝqH~$m NOO"Q Q>Zw&{&0hAZm Xh !p+iFZw] ee1ksu w]GI&J̷ M42Jb9rv4If"9=c}k*Iڮ;V*v!eFi/Tu5*Q;LXビJjݽ޻_|A( 1YL'S!,iR8ƄR%IQAcj[Ց0Bݶ34׳KmriݚZ'BT1*')ܓ5e2)$xR86U,B $ȯPbFH"qCҴ,KBx%e5kc$'''𵯯kMM}D' ^Ag0+t:]_B Js.]BH*ιHT*JΎBg~oCۭLQ&Z C #EQِrny3ڶcPƒ$ ʛC씆}n*X;<<@}DSftpp,4M.//Y.ObXo6p~|>$nсIU 98sn:H~(㜰b(J7x&h$G'>D=<۶Y_fkh7N`%|>;;Ɣ0\H"L߄zߙ^I3BdY{z9%g2;EQ4m9Od:w6vPBp19xh>2>8u4R%Ƙ^rəJ;`2[k޻=  `Oc;ҿm$kJ *R 4a1sΙJR^_fdr}uutt~k#hBk, &ZêYf{υLx gMu}t߭ LUs{JyH0vg_-qO zhY/8{6.cƚh\7~2Ljk,oޯ˗/!.qmV$="ago->\B% 6zhCE:;;FR~7-RoCkGLdU}N#N\4M!HJJ4IRs&oW2/>}ڶӧO*dq`?N)~'`b'oJk=//f'UQ${ $ sd_aE ! ap @]/sU&*5FJB$l"'GB"%3Dd88E.RZFB:5Mm$TH@I$d_I쟀*,H(c1ڳCuh!$sh[7,VUQ +\\^^|k_>w)t`(u]{ch6NhBRu*yCڂRGk@zRFb,9QhMiw7_ov#`Lo޶2`smۆ197Fk uW+8bU1j]dF;Gl)wAD(Xu@A ^9V}/h_PpQwٽOMS{ c|s_#Ec :*жm9C_`ꂂs;|ɌF(Zp#^d Ge( (Jrm oa\1F$Ɀz:o~ N.g$IXZ@yk{kH9莊j׿Pg} AF2$ $x9o0 c Q#B% %1!(LymTH)!HŽ Ϋ/vZh$HxrIBHRbTJIP'!BRH嬧+0>6 l6NNJ];{( +d?kP(P;q ,2Ff8&(hn3*YUU!__裏~?(?^f42_.EYb1uE`H euhn3 ݻma (lnq|~~ӷ!/^iZ.WGw?:,qh0 ;^$ԫE c>m !mBgFߡrJ)"1z-0vB(lv_`-h@IjȑRfy"sJHe>P c]q\P{m5L Yu˳D)^}B5|ٳt_c< }!\@͗/_VGa >Hh$f6F'TJ{pBֆӲ,`)_җz뭷77 E|%4N ߌ> $x!bL)GgBpƘ4Mcm۔eٶb{u eHEYr&i–W)u.|>x 70`Q%%!D`kgggƘ/_;vh<lo ]n*[۫/#Fūs?`͡%$"ZtBiriM-%ݻq\- IH)D9M `ὣ,|۟~)^9@߿>Ùt8UJruze؛GYvVx{TU桻zVRKj!lla`'~ cC<9Ilc,^@6 H4Znu;{oz{ VEo 80:fF$I"OMy~6f@q7 ш eT%vlLFAEx[-Iږ%R e'II۶ABd〨J% }u7 o/=1|C(O04.B> gWC%bBNҔ1R])%fR~hRRn^__]-EJR 3,gTPbyZ9&:``oR]ARHd0g~,=` zVRQ>EP@K%RP4=Z{ΙePT,cUCJ$I)8N$ \=:bh63' G3W¦|rr<֐fM"{ͅ`Yr|&r,oXr+4m!-0)3S233s֭(BLʣZY]jpEqnVlkccCJ94-m90Y@gjb‹. ` b ~ϲ,z0< HI8wꟐA !u!|1!8ʲ.OTBG54I/Z LO:EM F B K Z83@ Ewda|}shf'1F#۶Z d&''mnZBBolnz8 v4z^EqĮ];易@i@4d-ܜv{{1E1:#n+% B\.5 RQ yEJ0w:XZ5;; s$7cW|;QTJF[[ &6hqrD)1F#0Bq()9e[[,0c,I%=9e~B!ðv:~&6()Q693J+@p>|vljj/NV*Uq*KP# O Zf8`R*ὁ8z GKΑc*_ZAbpjc@eSk]V9V ]`1Kiun!{ \i~r@h#Li58,RPm{cc#IuSy݋.ڵh moo:2'BFG{avaG9??(R6 +xWWW~; H(|nn.IXF\^[[*1RmTqc$MSFi*ҷo&#nYZ)–mcRR,[[3,RJz]c`iח%q\}+ CJmٌ1 YYȲiQ2. $Mh[#QJw;af: 6mdjBN(bBڊԒۜqZ5T*2Ƶo>XaT8I9B!I0▝ Y,Ķy(0-,,83!JRG0M4K3FrhhDI-BZ TIaO"0"Z#/Q 98q]OJ톌YVm NTe۞Rdcsv#(.;(? ഓ hpw}wsss@Ic4(%l><2l5mۂQ@ )Qwac#x3>Zu:?/~ AP*fӽ{VO>O=ؗ8q`}(HdY{.RY6" FZ{S.K~ 03p+]\\t:0UݻRhԣ$F4v\;NNI҄\Rh])Jv°f{]P/xi-^*Uzfk|l|ckX3n+D81i eiuF*%e/ 4C$-Ja˕rG YjYF_'>qZ֍zCCj5I+zbRGQ+i2[~\XAՔ`fB`Y #'Ba)QR&iѱϟ3U˕WΜAnMNMj/-^*KBd`!ض-@Vbs &[4E[[B*Fy ˶T]0&8HJeY^/EQ%wNR*^ijj80BnJJIȞPBkFK2eMUxhh ƭhJmۂJ-^74ˀ }n{Uq$wBPB[[[_׭T*^rmq1˶nܸQ.W(Ƽ[ )Z c(:@)iqlR29)'j$I@j|; @F1<< [(3FnWh80\^^sq\uֽ^/D)5!D0"s1mEy3PZrr 2P J)8|W)Uv\wddde` ن@q6"pHzP o{{P(Lgy6 @LkS% BP0 a*2%c|͍^*>3!n!h[a1mˑB>2L{.?5>YvڋFGFNgR=;wkkNv8Ն{c$㓓JJ3.2(s]HÁw^Sp{~{ٰ#qb6!TJ0m;#}{\~m~ĉ̟CcR0eR [tm @)nuhlJƈs 2z !YrleH4F &^I E(" `]!-'! 20M‚ c)4<ń_8 P pnc1v B_:ޡƸ77U CV>9IbLX ,!Bʶ@:.NMzJŦ펍}ёzG=~כ=;r]3=ۋ"JcvrrqW?8CdΨOF_|%C-%{}ԩ$M]׃gO3OQRC7=3O˥ju(bj3ӓ/>'X_ a|=K?奥뽨W,^/IbREƨɉё_x~xF{MLLH)[t5'H݆4M$ѻw횛^,»S~'w=rd||СCryZt`vCCaA h;J)>{29>͓%v"#mY{vLN]rձG=x6-|_>teCRJ}Zvթѱ韱9o6[Zm~vkkCÏ<}]?wؘO<Ϋw||,=kvٯyҕ=O8o߾x3^vlLjK/2/h'FBq)֦hŒѦj cD-,l6[/x$'eQ/r/ӳLjMͨÈE( t62PL !fiTZ"d JI4{ݿVxf.)s beb,njcc?cg;a8R%qi-y6"TXYY*h%QZ,@r]cMMRI$)}}qffg>o}{'sҗ]sϱcdž1ƍF1fp6S ?T!P"Kv{~~_p:vwbJ9|>я; " h,i! mll||O?{QX 7Œ1a;W񙙹, !#IS|;ޣGfYo~6MF;l6ׁZ-gfrO=RʯJalTFwr d"-vTgJs[71_җ?v+333:rHe?KJA1z|TJv]@ 16>6?O}SzrMnZQuX8?k_{ɧBcccwyJ+|oٞ OsucǎNOo}Ի/~X,>|뮻Mw _J c[!;>?9;7\t)驩K.}7?q9:ixgX`v,N7cHM4m3<ϕR*-'&&.^\<^oc=ЙQfێc"EFbL (ƆP&0F,IB,$Dm$M(h'kgF!X$*/KS!:J/ )DZ;R$BGye/+HonZkkk@s紏ׇR. uoo}[ߪjS###7nZX_Y]ݸqcmmm_VX"6;ĉP*rvGFFvTNsn>ԓoxG/=su`Qj`7 R:66ضܹsRIsՋ_zNxߣ_ozP*CtSSS.]'>k ܍vmm-b;R l hZSnk 29&i:55NKƨi{NLBIdIrR)p9%`=VJ%4H*Ly_c{To:,2 B(h5eԲl՝]v% H IDAT8}ڡC9^{3jnƍsssAfo9|ӧV6M0cxjjM&`sl6 ~KJn'\__ڂ/X W\W^̞}Pr\v4Q^r_گuбH$\oL:uرcSSS7o^ϒ['''d0/JW忬y睷n/JQG(KSSS_Wff776J -ZpyPBFGG/_l~Qȝw+w~Q#L) ^qk~=~{_}.b!S2Yŏ}>͛7yWΞ5677aW+'qPl|X/Zd(C [X8v̙͛jcSC$4H0NEm;L)dm8(0ڝvBi#7ٯo/..-oyPf#y['W7֣$fE|\n[A1m'g1ٮSV$]ʵkJUZ̈́(W+j>ǟ07~1+\F9ӧoݾ}QgM(Ehkz!L l'EX\\|'N>9f0\LFJqtfr|쫋|ixv{=QJ#EԢܵ'~|zz Rg]v9(ֆv[ Rbn&I,E{Q/.+D[{j0l[RJ׾蝝BBx9Wk> `A!q777755nA0664Bn$UU@8~W,~zi>PPʅ[NTmrJiY9B(JwO9viN0Nҍ+g27z{`%phXlgΜA2VqRlll!a/|}n߾]KVQ.o߼W^=wեϿݻwue8A1r]i8qbiiIkj-nZ{JE!pb'>ӵZ]zC'z;9;9]\~ĉ{JT*QB&x:Z#w9Z(\1Ju睏=Ʊc667G'&&v8N_ticcƍ2lt:e6ҥKz}jj9o׿.e7eq>t?ơC66 Fc3Mׯ?`n9z8DZW1r\kM ܶfIqUQBHmr fG!,@Y)+s]lƘ8K RB&|Ȱ snv  VI1vc(,sJ %(8 "p uR^wb(EB2!17*!|`YwZx%仳0k@V}:CpBm4a16Ms~(Jmmm]r{<6\,T. sԞsMA;T@gרRZC׳$c;aBiGiacD(Amnn6 e*O޽۶e)Xk]oz~N}SSSn^GF|߇ɑ1:11jl>Љ˿\YY;o-x~P.j5y2n]zN g47 ~Qݺu ZI򑏜>}÷a@ybr @y4`T¢PѣGϝ; ANQq V!D^hC+7Jb Y\yazX}jXXHdvvv߾}EB}'P$a]xqffƲ۷oSB)s5A9'CR*bu(`,]ގz( ð jaǶ]HBsoeEH)Kʂ TR244T+?pO)c4.+Z'B?7`07ٲm!ݞ cڨkrjY0!zC)0D(Ҙr,ǧ҈AV*U:r {]e *cTJI \tyRy+Pܶ텅]vAn(qγ$aeNZPp<͛.]}?… 0t:Rinn1!}$BF)eB&$!e",VV7sm[ck-4v\})2 caĸ7 K&F4/?~gz^64tZt:ADQOrb{12XXXxg&Tc;ιs)ab 9z /ngff,+U*u0ٍ ؅#6'37o޴,;'?OAP*۶*!O:߾ё񉹙ٱhw"$aE0v `bJW.1 oDn#~Pa Nwbᡡoϣ9YT)E ur?k3`ll62vOMLyGNNLܱpăUU*H;9jیqJH8MR%QHV-A L)+xG&X*ܑnoIm;ض[ YAJi(ePeZ0 +yz[m'( "T+D1zQ$FkBS6HeReR%&`DD,5IjPT?Iۭ޷M/!cƹBdZ@k )-B,sPA`Hdqq6hCWkJ^/Lz.28ܲ`U0K'CAg[w+U*n1Ę*3яAyۃxӻ/txL beQy)%؞(ҫrg4#yJ[^۔d-cYMR" cחMZ^=9 z}2,\i渮Z\N=9],_<5^p½o{zz38uxkŋSSS)uل'N@@^=ѣMOOߘRpζlj7~} Rr RZ}啓z;zs}]kW>??KӴT ȳRԛ>SEb~qaqy~?y^9 1tRpyގnz QuhAm%<կ}{OS.ښ{I`Jҏ"pV*V*U BfsmYYYi6[7g02We3M&)`<$I\_/JJʡj~ǿr߈BabFw/_ HNSڔTtd~!rC2lPqq0̳s\BC@0v]*ra`FVXNr{jqPhd1LRjB(kظQ:GOfojm("s1\8 nKK~ mG\sgC(,!mFT+,0F)r2An ̂5ȝxIXkߏ޴cܜ%J %\.F\-EQ^ P!"`.a cd`?!qC A 0VeFW\\5s(%21AgY1J~ԇPJ9׋zwV죣óW/|7?V>srX˅Vmju޽尔&y/<#_җJ*eso>k׮W_}U)aG)u뭷^~cR^ل {^ZK><555<<|79w9q655jeE۷o~#y5VY1RL0x+%7,Ap1Lyh)M8 !|5Ƅa_\\Jh4JRRC:QQsKgb|⟾hw󩧟hL1feeDQt|gΜټÂ_c.]tdqTVC_ BaǑZC>55UT1q@*X$YhA3nb@d#>O~L}RVkU5(En߾3&g=־\Xss_,qƄZ)LO߼o߷ʽEVklrb FheeDr}n)JQ !Ԑc<11mMK+yϹcMT J zZ[*jd1.FRG %Lc̸#u<ῑZk9%9EQ`Sl4 "0KEXi6H4@9~=}8@CgcJZƍtcƸsBl'c~[pV׮]\.,yB<}}dd~~o(l@'s42,q$|\YX^n7$β , F8N$WJh4 IJEe. ymY߷wq֭[O IDATniT޲}dxt+_ʍ7n罠ZLih<]0aiM+ܾ}_C8G?Q9pR),ةSnW^y2_z+\(Nsw.//a(׮=\BY+ZmeG"R*d9s-rwwZ)gޓ'OBPBMXk鶌5'O==:qeY^|G=˲nk.l / frm20RLNN.,,ݻ7fXkGnƙV}… 7uEՊ"c4tXJ)`EQ$X^YeH~1uˌ??RInEbr8:::??2a4,tm`}t:dԔV~s_uBȖ-[GqsssO=Zk`daBR%oAP ˍ)U^UGښ4M_pwoٲEkrc .(FnZ+✊,#06Aү?!xԒAl'CEI ZRpwo|s]BI),8B(<Rƨ` hfzmZ333۷otFPZd9sI.<;n?zݸRXu۝~62:V-W,Mҋ=/ qluƘ8xI6y.ҘdBÃn֢0 daihuW* !8ℭHRTPL\c6Xk5U!)՘kSc"a\쿮?=yE#f@@ET2(~? Rz~Ð;1˜PF0! #~xrr:9aTȜR1Pݼwzz[^)"X`obq\!~޷oߝw޹pAu9!֊PY{W._|䑷8q"IR$42"kM;rȣ>Kh6hwzJ I'i"c P.^l _x')=Ν;#E<ȅ^ieA1EhtiEjmt1BhtzXJ0#`kRy {B9e9N񐱀PSN(ÄQι .L]QV߼VOWiؓb(!V`^i6NG98NԆjƚ4zQ/NU&B?|#sכM/\u:} ڝre$Nn?~NG)v1ex\r,N8!//,9%/yϾS/|;w "_Z^Z\Zzowگ|eBJ!`}ЋDTQ<^ٹs}];wo5V.vz.5ƈYsw2L}2B=]{Rǰ"KJ)7ff麮E̹Q,../ӧNmB@F{ gyիN A()ƽNl2BѯP^àRQL")9tDYfZL'k-F,91DB{:rPZrXի`2ebˁ[ãqDSƔHV1qy& ;0ƮQehO''GF|\jU؈یhV.W*cmV!}uu\c0fS!XJ סUdV4ZS !I#k0$i0v=ohh(2BȓO>9??\ʅ̥pR$Is!;J-F[k`Hm "k ]v}oZYYy7{fy&(Xk9~3V)9z]jZeZn櫗.|?Cj]F)%# eYX Jӧ]םxᣏK_CfgsG*%7"!$Rҥ 8ʲŋn"oܸrc,MR0ohZΝvґW^y̙3y3ʲ,,M,߶u+$T[orm<2==WWN;xRR {SOw;wnZi\s"AXbH- rzY~vmЇ17mߖ)htxS00rN*t^Vz&J0q3uPd؀;0@ $q ?swoo 3LD"9?<-uޚEHi !Zmj&_0IRMNNx y{o~Fs++k,-->|xbbbjrr!T;aP*AC̖۶))$~ )[!9~-Ƅ " - cR;} 6 B)sڃ`a:l=srﻘG`QBk@cA~"UM@n*ck4%JaJ%GTܹ⥋^xU/":O~_~ї_y9N(M@6K=ϛ]v奥\)9e.tNի:Y6JBCz /7ill?V@14}'Irw~ߴ*T (G+b fRJg_x经?C<<3!#44<\\쇜C}oS˕J]][6C,.--'ATͽ82P.ܶmc[yҥG}ln2su7T* ))cZ6/uj\M 4lЙS(dZd&&8axpFm:}ҥG>c^Om:jkF3JT*i-h})RX3eJsv6yW!E`c,47r`8xhC1DfF#e!LƘHERYEcFCġsI+%ւs Av3ݸu"`=/ CF׏iRL\-WʌW|{ߋ8 V"E$i6^ 4.nghhЭudln tCN?W(z5>2O>n뮣GrXt~4=5~ # ݼq>FB9v@B)_h߿߼=B(zjcq9ECa呷??J+mM?QqųFNB4Mժ8֠y"z^H )ϯ.,,'&&{8'o<Փ/o>}v._X r4MaJ \ 7 5VZƈ:ģA[Caz;%m.tL3$s2S3B(g.2:ƘlPuӔB`7uB(gIkk~Ā\.o(!8yP8pIh GHk]n %8:IZ Dаim۶$I._w/}qx||+;v;}ȃ>ɓP/(dE`A^`ڨ6^'MSN DjܸA!9e\.UiJ5qK/^PHa$޵+Ii1Ƭ1+++/k@f9w8AFi㛶oz|î~+_;a)x́%KοΝ;A=66vch% xƠ#fyep /O:yؑ;x#l.,,;w~VsNիW t$9wH2B7mnz=6GT$(K|ԩwFo8$I*L{N8vKahUJ2v[(p)DHu>|5{_d` 4}DqrWo&TʣGx'~ϟo-ܺ_)2uA. < w4M)#)eQhH0@c RN s|#C=cQZsPbX0""F -UUgQjj4S9!3B Bc SgzcdaNet^XjcǎFH{ϛtE'|Ƙ+W(gφaXׁ TaZ"D )Tkۯ_0?Eneo K;YN iĨXp}֛͕<9##ozӛf];u0Z-c7Rsa\*$Pe4IǏ7^u=_i1RrsP8 lhhhee1f$u+o=G> PX_gIr5SO?}mc|JV| !k Ii12<_|?}[_~+WڝFQ)BK˟>|ٕ$IM^t:'O8[t[~Ϝ9sƍ7cs=RW^9{w]VWxp%*JsOG'O^\A,-.}~0򴖙oy[}YxO}Q@q5gV+sˋ72=5tvy17rKQV,[[_'XO^TpN*o! />?Z|#ʯ IDATr\MƦLc87_ݽ&k cvyy9H=( 8|$s]7hVZB<9wqA {EP#ctPR" P8)M9RVIM M4KsuF']q9ZL”2`12`zTBB_S.}㮳ZcF#|jPHk׮,Fq!cŋ[A0 !3JL@eZUJ%!ZP(5yR,r,pgyAKezj/뮻^y[hSF gɅ0d en>68w]74Eg[Jŋ(*;w^>?;olj'C#Zj]][l6$bT522V͕v7k<08@(< *!”YV|pj0R,CHX.s!0Ʒ~,OŽKA Z~ilRP(1Pb"E@oW_et() &±(!+6PB7ͱz=KZ 䝥~)]ZZMdD|m}}ȇA0 r%`]q U;:F8!h"js)1!~),Od=sp엺CU(βL"Kqڑ:n$Jzqғ*:T4fùuXkE;^$)Uac x.Zfs֭/8 cZ[`?o-\v(VZrcǎ˗/aHˬjj X Bk-N \**4I[nHJ'%w ٳ)Jّ̖Ņjm9wxa Ƙv  Z:㕵,RzX;::j`Cy !iYF)UZWeNm۶MOO;v P v7H;gyK euccBZ+q5vtlɓ#KŬW7acP*/p!jVB)D !r)q)!x[VQYs |۶m F -<;tahB:tZ7<ϋjlG Dopeevpޠ*W*`d纕jj !xZ/--S‡jNWH! c4J!PʚPB39V:*Jv]/,w,ϡ3opxXʕJZ-#(Byk9L!4,cl v^ ^IBU✗BB  UC/贻ZIL(FbdVeV%7\ΑYt0#B"J1cb2!x9^?ŭasx*c~% " ȡ`AA9 It`3 -^c}1mI]*8c QCp/?BcV]* Bq._[V@ &b:99 s[nys.N`B1nLr&۶m"!rsё\޻>s Z3w]Б4M$aɥ~9_3m e Z pԀ2:>>9:Jz~&ro`S\UN'BIa L skmZzJ(V8 z#Á뭦YIvzyBt`Zquv=6>6==>p ahY\Y e)rF(rSp~`UMȇZVT,Bs:iE!>S #:a~lـR(`R*"8bJ1-f8]x aKkty4J>V# J5(Kr%ÞU80h(ϥqc27#BZBaI Yt# k`2cy\VJEQmvx0 cLgX4%% :2uc5Pa߯zeeuRKdyypya b%"4 t:B! IÈ TT E ha1a.-!:<L$9=22ufE1&KsaXpb+B(VIi-1F1%Q("c"r$$kA~RqG,.A@p6{2ʕ2w(Q2H)̕0]2 尒wJ9Sʴ6 @BqS.8γ`-aD^eZJ8D)8!%dgAR)DI,REFkeJ fk-})рe# aJ\\7M,M1"9q >,=\kM}9\(ńH)<fqYAq8>1~RjF J`<(<n2`211tJJpKcL)B|c5Fi QZ NL}c,sx~Gq)1&hB纔P5&(z ,˔%s=d3yK1B^jCm*[ JZx>xhxbu@[]]zwBh 1Fc18 BZiLsK`brT*qns8$VR1d@ki"EA);!"ZXC(AbՄ $aDkI" Yd8 =d5C0bRB88*R+-%VKm2ϓ4MR(kueI)Pf~*Qe55&J)pΝ,ˈÌ`B5zdlj9,RB9UnJ;cFTJ76uH:pc-a@VZ]X'-(UBI۝r9R\ oMN Cǁ\)Yk`f. mJdJ!r%|GFˋ ӟ?|y?,9}1 JkM)AٳիY )< !R2ʊ/q:60@18~?"mT}lիQ(2"dX\GV2\ƒ$a&ibiZ @B"WZLھ}{р0J@aZVVۿ?nрR,..j5Z1ƸdY $%28{"s=7ˠPכIr}jumm <8VJr\!BDJKR*L!(32: 0 $m5۔ qА4̈́aI`_.a":.8uJk.Jb,.--mhq1Nz,K e14̐\Ji6J0Z)EZ-D69Qk {&ɲ:o9<̈* Ua¸L2RQѬ{!_!BO؋7& d,bt^[^ ڭ ޽Q^A Z h]i0AMZgstɼZQH~oJIVqh<~M&2\1cTI,|Y )"!,$sģGIڸ_ 3J7!HS  t$۶mR>:ua?Hxrp7= ;LS Wk]wo~sxxbsS?qwjZ!888t8›cX<<#6Aն dr|||{{lZhf3Ԙ$C+ XFk00 :??ꫯ`31Kۦg o*lKTi_8Hӳww *T8!ãj˪*=e\pR#x!9;;|?E'}+rEӶtaWDזĦqqqsR'bq)F\ݛfSpD,1ZB<~j8.K<-mqV{R>`Zx Z냃~ydц e??/l6O.s N{[#ZV+>OG)URcsΫRO}w"˃m{x(H0,={uׯkXg:Z~ݷыŜ2B(Y*g cC_8Q|w }=%G6:FJ;g<2N#%(#d˼wH [wgc;cHPrԫciuvޡo$2+ 1Zk!L?yrzvv;"FvU'!rr P&ۦi໰`@:Mlr[Q>2p.BE+r>,Nd3T.9Ϟ=l6;}ux|G/ۿ[rm:tz!KkH [Ѱ08'e_lX}G<,v]98'D`#&Q<^(@;\4R`Ք1/L5#2GDx)4ذCP@ E*)g`X Aa,~/_/~m{PX^ -p  { %L&B#DkX,@L9WQy߃`*(`c2kHi?<< eGCpE`8xb8}ä[K\.777777_ur kO1酝~~կ~A Ƈؖ;NG#4ւlg_|n\々!w z$cP8 3 )G ,RiykvjJdXo"`6wB Je -.oS'Aq1| |BY9,!)ZiP'lDZB9W!9u0C _;`4z+Xu]7Ί—Nk ܴ[ % pub <2T٩d 8q L=1Ə>{^"Aߢ6z3EB:m2>Yeoc=[N~?\-B0Q OHX{VosDb#GRJžMt!Ϟ=˲?W_>+WKRRB]1BRJ %-|,W|,x2oIk KP_Y>X^*#tƘzxBw.َ)"^Τ`QN+8bRJ}B2uXTXVU]3tcQZm>Dy 0*XO3E$QeTJHɀJ඙3w)06rq||$\><\^^?~%D1szzzyy usȌ(Ie3<)a ~FZ.5l*",0,΁l\kc /^ۖ! s'89sppp~~~oi_ݎR5\3+Dk$Sbm2uUUaNs\M8;`8 `aFJ #ݾ@ހmizvvocOirV7bWn_9=m!$%h6MY.EYb7.:ʲ<8ybѣSc619#Z{h|0Rb-⢮뇇}0ά7˦m#&`4UQ*U5~6)q /em14"X1@#3"HB3MƓitBI$Lfs1("Uz^mbX .xvL5wNt(3E ac J0 "hbq$3;c:@s' ,yf]5͓~uua(?JiD!PșI-`:J76D5اO)9xadNMUu]e ({Q}7ʥ,0w||<@b rU52Zwy.97C"]߿?s4ahe#Ncx:jgctn6!@ 6"2UʳPOJ PMq6!/}'''O]G#-[y2Z=ieَb^EȲ;XP_h6)yљzeh Űu]lUzI, JXb'y<9ǚK6 :<śg J8؜sJc17~4B}jkm߿ zmWep8N<)B̔A;mF' z&Ltի(1Q&TQdT)95&rQJFa!+UGO^!_}jB3<17 4| jÂ8OH"p8c["gamK%p7,@.2A}%{o.BwVjn!|:>|ZB@9 餮o'2Mc|{DWQJ;gMI$ FD1Ιm>ʞ2#aBw"ϲ,k뺭[5H [mmc;m;k15BLA>E8<:/m/Kƙ,{-6Q2}d4-Kum;!`8t>4]k; T??{9B0Z1B%u72S12ǫjsttG,/rZLx:Rt#PG{7Mǃ E o`ȊKv<Dg76MS7,4ҝ !C :B"`okm5G8Ycj# ")QYnnnL1!ӺsI%.{%Ux@Mp!L9+{Θ\pvQJc\ R)D$z$|p2"egl]gkkVpaLIK_ƹ 8Bx+uQB~1<,BHp5M^( sQbt'8}7WW1xhu׶oFp!$1PBڶ+F82@ ORnnBhz<UUUוs/7[q{<>իWp6h<ߴM4!.2gP Bi*ϋ"/Pp\-RM%.y^DF鳷fպ./JOȄv04m82΄t2HYJJ5}ǯ//}1R\~)_.x":M 36MK)'JB_x:_o*o^8_~I)|}x8eVզ+Jc19~f6FK%6q΄Bp1%yU"TBW̔TYe?|B .eJ YQp!ƗE) >*$W9 (2(!RBdY.<LʺkQ4Y\eINOOWtPsfLMBhiZƸ4-b3w9r1:kYHHhgT:c R N7u=>=Z,ŠhtsH9̵] A1\ε;y\gL }bq4|'N L,+"/JcMȾ%U!ϲ?>`]|rK8քĺ&PMuwpp 7DƘ?|%hCL<ཻ|}cvʶmwC{n$ J1F`{έ ſd2^,RPD@3Kh46ƶmgs΅g1bnHEg5Cpq!s!TsgyѴp8, NhPF} شm^`pv~ִz] B!%Pj%yGRJUI8B!2#hnXcwj[yIFYu1d_w sO<)2D yyR?];@vP;F3CӴJeia,(8筵ۊȡ Ln$F%4(\7.xTMBY<}/4?<:cySh$(SBjnAUmUJ1M0XAjkm;1c-\` a@ߎ_{_bOBQy;דּ~o8h$rRXMQI08eYYn6,s޸`7[^IEʼn$ mz'̲|B암Px<>@{Dpϕ߇-Ё^'Yd)`{x Iv>WO+ࣀxS+s)3T F~hCC؜N~!%!9 k+ZB1",.jVRJ.!q>b!DܙR(}٬Vd#8-w,hxj6-t RjZeaawŰ x u*F>)⛯`_]]biUr3h1Rh"xΙO?y.3]$Htk'oH5)Wj{Ȍx'8Sik k֘`sȴܩZ$B1vӵRB[d/p!;KZen/2Bv]W7>˲ܚ)BN"/˲$$U45V9u8+aXPI=ar24@|LYp.;[틮8gB{`ͲXڶ>f*C 2ɐo6,Ϭ6{8Ih~by|>׺NmTPJ:)VkiRn3Ɂs,Sq?B$JB 6l#dAb}\vkɪx˼8;;ׂ۬ l4W=!Xo(} cM@NDFAemXc,s;Eg}U ͨ_,!D )y(10N(cXB)I躦w{qXotƁ5mh6"9gOWeSh<s]|<_7 i/x z FaO<999Y,?FT[N'NNNzfuX,,zmӆHeQ8v&%޻ )=Fc"8X(f3|*pl6CBTjD"ef1Gmއ(J;{$(X%cChtʞF7sSÌk zHҘכ1uy98eIAs+J\Kl}j̋\,l/>LeQmءPGsBR]]E~?6kXVe2D:6˕yc1V7nFB1DqVkjjXAB㰓ai}[A!B Abv}Q몪ڮ:clY qſij5Mx?bR`<T99&69~?Zk`yg4m645M gq1_C i>s(MS}yxxU7z[q {J9V!wN8l(pV;er`jS¤Rde9\r.S B H)}0}1x4<5J4m*'O>Йm\\\`0!DLƹ23SYA"/sxzrv||ʘL0GgQiɚ~|wG$h_B_ׯ^ʱKY9tDLEܾ;)eȠ24[p'~l: pDv<'54-q>, MJཷy@y2"ԒXRa?8<:;M>XH !G  U&6-!Izb\0uڶAXotH[ 12γ,&P#2XCy"iTa)]V{b j+sE?ap j(Te+F3ڔI*=?%PT*ֺ,4w(ӬsyQL&x|s{ hĠ|Ia%j%nYmEԪy|}XxtS'Nj)Jyp0=?\.Ns.(e!Dk]>4f1k;-9}]* 8k O&5xFpATB9#fO(Y(כ?rZ{]J)4p8>Xk)6/b0L~z wq9}1,!| FㇳH>! pV&1JcV()EQ_ٟ}JL~{g} tQ6Fƨ+`p20 *֚q}M]{RqJn9x16U]ey~||,\,nn9g~״P3V7MR}1)>GK@UULIjГ~- Aqrz瑴cKsi%y,g)\N#ÂK![J9cPQygбEA 9"0N)= ɲ<Ȓ 3ybǂ+|` JĻ|YjڎRyI~vjsx8MG28V m8s#ߐxlggg>oևhRO#UU)H)BE^dY(E7Z9}&/$7lΛI_f޵]b"E/ի^vѶy٬|v!Viu{>$V^ IDATJ,@Dn#Fw~Y7=8@(`$MNV$80w1L0J>z8!%P^b)S.S1`u wMz8d6zxxիr@2 c S`1RZ볳ԉüVf,ìk(,vXD8?яnooobEٵ]y)UYʲ#}%O.)%!`x9u&k!t:QqCmtZc  , !OqESZ!ɓG1"/9)烙4&fqu^w޹G捲w떺{A',z=v䩃ӺBH!^z5,o&y5ٙunX1\xqaI%PJs<9!D h!Pb-T^5C!\%StWE/ !j< fgJ),ƺz׺5#$hjzֆ`Đ? Ip]cr3LJ/lezI?<<%^v@H"9EQpƬ",X Fs kI)ѦJRF;U}.ئεՌQ)U׵>X笱6-7Yvv4;܄2Fb!@K bTzo}ww%eF@[7+裏>::: l9te~P}cjk_]!0~xaι[ Y}'WWWۉIl.f“'OW rVU"9 X.Ƙ"&9F1XgC]Jfp+ ({[Ul>ۛFi}i˳'7AcP9c״$F]5j $#I=8c V2g`*4-ue/qCkQL Da8W9 /RȖę:T|קH1F9 z>~ |\bum׵Lgb oV >4'bq{;g1f2s.BIM˻˛E{ʔu٣ǛM%eBbET`ʋ2Rx5>!PFewI {ջ@8JZ2ĽwscqB>hX<|>_onnw4%BM !=zk!$1=!PQUF2c`%1FB 1I@Ico5zb䂇ι,Y5]?>(du]IP`Xcm( ɸxh Gk˲׶#h8L%MXmze:y2BR.HH$4c%f^JA4zo# Sltj봳fg?w ~Gs.$^7--uص9ML&} q |Z)EfnZI!uuSp0z-v:^FP&A^)eFt9w$8S-\auQgcL9H>1E٫6gd]IBǢ(A@6ˀVK;JǏ! [y/J!$gb>[81"/uSBmֻș@1RB%,Hhh&1dY]mL,VUyq*7p.!^(%(0 z.dg !?-Wyƥl6 Vp8Ez'O\_fPBt޹pXj8 CMu5Je{w{匙LƙT]*Bz0dj]ǰ;"6m5;sBιN{+E(t❇+z#daaqj'R5m{:7{}c:{ウ3۶}x_ūׯuvZ;ͦ]A ^l@@ d E{bol6K¤HC6x'r@|mZ{{{{ww+`ʬ*#NosPJ <AX.(!><P]>ƦHnjt5UeRJ<ݱ?~a6KTXxH$x6ƠxeMe=J m[-\'茡]CeG$PSRB#D+1ZwY5:E XioYt[$ۤYg{BI[/_'w4|!a^l6:y?-eX]ŗEv[}fJDJ<<)RrT .PS'(zR qEh8"ãywONNg>OU!n eY@81{ſe zݶ1i/;h|+Q=8qz C8v$.zEq++i>+M[%5$G'V-rKzGu^@62nP}])ՕRɓ'_ƭ6Tr1 ڶՈ"H4MPB& &lrWYCn u iKB|"! p2CQ"6"ewuu6Me~fY9l>)nh4zz5 {W_}_|cIF<1'VG$"B ht2(azJ*X @c/L1~0`]r NldF>n+\1vz9kg9|bsR)ӟy "oRzm9އhL)mێQSGpXmmz^׵# Tuݗ'bQFۺ%'C L&_4P*_FbbUUd!XJD/~2R9\'"( HȯVDh"~z82Fҏ߿j>x(dtO[]lZ,2 ޓ۶;#Bz.B9. 2˓^612"O!l6ptUWQd"a ]'E-gRCYAZof6~kR_klH~9Uȶӑ$FC P!8Ѷӽ^+FeY׶kr>;U? 'H{0c|R$@Eڙd/gcRSت5,>۷J8P b{@zv>8ձg \-=M>`\NWFS줬6kťAq09JHYUuUh7!2_Ji[YnWUioE"N"v7M\.փ1 8x%FsJ˲TY(M 2\e!ؚYY Bq[?}'Feq.ZVʰ d۶ySB,]-Yu_Eh x<~?_s|(u'3e/G1D*P!;FlɂIs^W-LPnQ"Xz*9 ѬZENX,(!Ѥ{ӧOFK8?$5e(%Rp''}WWWyBsxx8N??7MdӟjB];;0F}cq-l~C$bBq G A(BSM?zc)zw]+zќ_}5dzI 4A<,ĚGO6"Gkm–~B}+|Ir1Fow6x~_k?d/KqXcDtD ۂ|5b!ox4fe7ޠuMSc#1z|[ &H3Ɯ>ʲo-ˏd{cuV>Fp$|ܓk[m CB Z.xI9Z2Tʼnbw٬J<_| |>뺦mT`:VMu{'m C::g\Ir-衮HU FpA>#(=#$83%R]}?{of&w3m@!+3n䜫jr64dg*6q ).iGN\۞:C7ٍC~)4m??F 7t<߃"h~b^/<ׯ_k/////Q?z"D,KfnxF8z"psٗ_~ެ/..<@faȊUp"$(ӺIx'}򣲬ƈ0͛ϑ_LaYO qIWk2>KSrRs֞cZp#)&N5@!iaK3m c8>!,'~_ r&-RJyΟ2j lnZ=|𫯾:.+Xϋ!!krl:(?==u΅clhmx(8x7}O F!ȃڽP#`,RPT@iEDeU^sU);c"P ZBf@Ef8MPXed:gfXܬic.RX["ud'}$ aL.ɞw hQVLw DUgB?HMzneγYGaKyJd<9;;^__WXa1;~_bٕR+aI)XG;﫪tξyuuι*xyv~Rxvy&'o*htN3tW_ ^ mwjDt~v6 nr=5d \mB[?я5C(|,7) fs\V(E'pҔXgiGvp7,1kFk4@V?w$vqq ;nMM)k 脟+4T !KfmSS ?qUU=>LZX.DmZy"bΜSJ1S1RDiGR^_BTHĕt$"}ۮNO/^>~W_gHM a/ (ȌVi[JH C1jB/~V9˿kml5nj,UUڮDD, "3!!\k)Bz>cJ1"ÇJBeF=4R bBƐRxIn]U]"X.&',15u:DScK9/}Q5b-BsTg_۶ [ȶJNumc!ý:*ik-:tHЀ}cI޸ڶ}Z<@/..6upV$g'hEDe99?}vgL~Gqyy4MQeYZ03-U $8}ߏp;sN]/Khݜju}jaF ɣ9j4r !L17ea6q"Olc A> Y AD /ڶʲn61(onn$k5}E$8nnm7o^O5#FԔ>D4," VZ)h Uۿ'ٳg?YK?{= j>&&{qqX,23fa[ZdC뚦-lZ]^^N*l̺Sqb !J L QHr"|5$CҚso E w-_ooRΒ9xo >|jRxRaa4zr}ߝɟUܴ- =T@%N0]<ї/_:^zcq`e[yAc4wOS%Gx{=!rb`OCKry}uŗ_"[ޖUUUeʩv[i0nA'(~Z.w=b'IrsWU\,k"klY1* vcfEẾ#%n\?*1}a%byͦH=#fJ[ȝSJVŸKkuy|ipy?Ov3@hR bktң9WLz'Dhm]]]5#9(s0f+l6F@WUas)G6k1zp*3eY^OcY/~ a)J2Sv8-w֢lE S2Z'uvv6?CkfAslXa>s5X@<8r6 2B̒SF1b ,T<9AʝBrtx'HkbwEhI)7-WrJXcBJ֘f΅QssX×_|ctNmm}?9唒V(;sJ}i NO۶cΤl6[.خONOHƸ80cI )>ƨVJIDkw0g6} Ә؃:p R/'V׶W1R۵eQ6mSϪ}ӼzDHQE׷ه3:?yd^Awlݢ6=9*'O>|9~פ)rbYhu]iĤb߷EᔢrN]>ztc`Ejιb1g+d"90߃ 1!Q̂cc17Ѝs8-Kd7}tfFEQG4Fk\,}c'+F=4-2r%Dj>Wއc]ϺV%/|'vm}a7Z 0v4DD = 9t p&s`!Ι>, E(ʾއ|.D}j~X0(:gC"bcR=̳zB\.W?SLuUNVzml.$f}Ι >U% >"sF|!|Ed)q(e07F)!JABZRFcz ͍3F甬6"iB;J87dokʼ\%ft 16WRk5[GO?]כbRZ;f*/_,拦k}Bl&%1Ŝ3VZkA\.)eۛ8kl(4iU(F)}W?ɧ~as֥֚JH&Ʃ0k޿y&ˢEQ(犜%gQJ_\\XIkCn߷ѦvnoJm)7Z)0+)*|rv E9WFɜ}TBVVJ|*ʫ7oEA:Y̤Ru=mwU=?99RiZX%e߷u= F1PVwm}|g]aKaR WQkN'ϟ=/S"c!iRGkmhC $"`?y&ķ)R"F`:xl0<%$ ;:0xujBX AAD>_fIYݮ,cYm_Vh/ZNV)FmR WՕ]b/m%+b "lDX+sω8̊9Yuŋ>oֹb˗ﺲRnӺv9Aw/ Vj8ڬ3s S)Rʙimfu]%TKBAgC }ʙuNB4Z}݋nn3٬b,y%s!?hn\??w<~8g޳$0o>m6tYJ(*L*ƺ_~嬫gthMBF!eaD?Z}"2=sJ{`EQ2"_~9vbHu]U:0(4_NSӽJkmUͰ9<D sjlM p6ֆ(e]M[TMe W= 1T47 *RxAOjWUri"f9ǔWкuf>_E|1US7bu=)H`L"!0nt쨆AWT#0)-gϟoo9"_cPc9O9瓓7oޠkUUJQ}YU(p."ܶ-J>ZCXii[dEʊH6ZDRdOHY U( \u7 s.6-5ϟ=[PY]Gb8ި8e:I&%wu_V05S45^DeP?s޷M3 Zë)|>j]U=+ۮM1uumNq(j@nh)AW~`0sնl61M{zr UN5H&̊ffMCDSDFk&EF{o̯^!YWi"Zk$cfs9]_z?ro1fC98=Dlhj3s6,9Ũ²؛ka?n)g[gϞuOrfctZӷfhtD \?xVXbXpwzS5dum ww6iڛg?lV+egh!)e"urrϽm}ʨv}㽏)SDs,:h3:z.ZP~ޯ+mt4z9_LjGohacl@O1PBh'22ęj]ȺӑREQu)a{ob(\Uc"s#e, 0lY[Ӷ,|zrr55TFc P뚅OhXB1K 9yI C0G>EʲXgSLf F01NΝ4M\, NZ+QUUa7^kJY8̷"a$D'J욓Sc, ??_0'ճZ-\f'UJ% `+kuR]ϫ}MJ9c ;ߴm1gFY Eb!M'"W]?~m!s"!Gc j@Yh \_]Bo&g0hiɩAk""UYe"\uߵ1&4#8硁@zܠr.hCuׯ˲Trv3Ij&`'!ct;ƞ*NX /_Wo~V* +bh`9c=;r1DgV(eofu)*7sEU]a a Ӫ|" kO\NDsW_Jkݶ1zaK铫b'לɚbi\QW3M),b DT|~v>k8m8J)2s,ʲf" Db ,P'pS$LeJ-;<+dKC%"RRj}5|)qΒ*_|ū_ma)DZ\t)+<G_1WasfVZֳF^m1fn Wlۓ ЃuH\߮}l1/fC$9q}4047rX4qx0c6f\0>mN D,|kAhSiO"=c- ޕ֙C1նm4>MQUUZg:sF#d+3ڜ#΀Yʜ1, p,D9+𞬵9EL$xH씒:l9!J1jBZ)Bsk( Y=o~]fmZg HZ335K'Ř^xl>/*+E3>u]v6aEcF&,af"p]Ͷ]]W%"iQS)ճYylE#;ӳzkW_f25"Q)F nT=2EvzoBZ[?@$hb]Jk3$B{, Y Y"t3O2Іы˳)1u١)ysHʲTB)|6XUeL4iULyݼxbX׾S=6Y3:֘]eP[T^ YnJ7bRJ$ggJn'"?̙Yhuu:W8k F0B9 nBCB$h G ctAYUYOE{/ۮM)P1Āw^+_lYkOB9B]Mў9v9#) lE~ԃmے(뺔mZw=}1_lVw}oC$2 (R6m]1%")gk ۺi,Z1k6Ϝ!SM BFkam;$mӊpNi(:ˢ_gg_~luo~۔bQZ=`%,9 {!ڬu]qz|(˪*QN̝qܟSJ0aH) sӶJIu''m}QZ)M1 l ̲)GhIXXAD1= o.@ZW4HcrL֚Ǐ]\8gkmweU%mv:떋eA\3gc__~*Am;n5*DsIi6ɛͶo Wh*O9CŒs6F}w{{: :FRI!03m6m64i4 c) ZvyU|F kAW IPtxx@0}ԡIE,,n]um.'O !䔋 )aF \-;`6WnΙSʑuΌQ5h^AoHҨFsJV9WDY|zzQY(|ƙ?m7~服!期>}rMYѬgϞ5MbJ1E˺bL0mgؔ߿-\R<;;6)&%ZiV7\́$gN* s.{5Zi7f"彿>;;0૪Z,Zcq*Y{uf?}򴪪m]eY@o) ,05DZ㬝/MJiMM7}wu]cB9'PXnJ \$;SPE 1&"QZ!AD./ 7>z}~~m6mCJu6cpEnC;6k?,g&YXV(tSrhíDumzo|(/UUs} ˇ9qp, k9?nK9;cH)]b+;%4`5||)Kx{m,iXqbF7qjGIg'|i;w!Z3gMiJJzVk sogmi\/DŽA&(R1g H]!+ ! (a xu!sFǝqJJ% .}c0,Ǐn:oo\Ѡrv)ƃbJD6M۴`6MC1[3_7Z?zmTZ}2i1ʜrr19x] 4h@GAR0,9gn%"VSD[G?՛onn///R3J1$Nԭx9G^ov]v=E/Aff:N02bVF,gFi41O1-}upl4{軶D>$kE1[cЗhV]>qQ]XrwXZv&a҂hP˗hx|>c0b %H1Ei !8?u]}Ӕuն-Iy>G?. dFkYp(-D9&gRCnc$))%;k'kZ攒6Y|>xV*u-~)z6{bs6y_E߶o1j}YV h#"vS,"9gB !TWKH#R,92Gta` .YIDikmhJ)(sO]U6`u5;ŶIDATg]g9K\9剖pfx݈90Iy6yNzGQOks c¿ﻪ1e{WJ#?wKZd91!e9_CMg-P*E.?_mMN#Smj) RL1犮k[9!-kvXp٩=):9=d3g"z|h&C~5A^/pYU$m۶Q+S)Y1\1L>ڦi}YfzG{(z:2@xu4W@" V#|f&x 3Ðя~W_M2EQkCXf d9 mc8̤횅gkΌCNv=8"EH3yMa$AeS037~j<|]iC#oW''p"@V>P Ϊڶ۷ʘ.Vjabo,8pXN)EqJKclJqP@k2\#E],'C"kJoti愈x&B-gMdN)&kVvg^-ٮk8AxH%9'"]໥SL,lE1>Ҹm19x߷]7$8?ws7{X|8BFtIZ|(`^9kmRO< !>仾뺜1}+V:"sI9bNF$^'(hjscA Eߘk>wcI1$CN{bVisH.k,h 5qP&?? =I"vbOTIvvn'\{_嬮YoeUg35gM_c*c$gNcL124ڬ2SJB<8?A @K suh )^9d]L#UU|1&PV*]Qز, W@(q. gYh$ͯ)L!d&!L]+߆ɉ1AN+r,R8fZ+"zv ClUC:ȇoȺ1_%nRxNȰ$#" 7#PhGFqJ *sLQ[܁"Vmۆ9g4@ `En6]߻•ew(SN*̋JH{{~n>(fu|vMӦVX}!#Qlnb*9K9Yt]5ѣGp/1 Z}xHxYZǙlq@b@`ؑs]1 ˱֊PD@hHNioz.\M|W]f@Db52Ix gXcPv9eckGuL(ﺢ,$r  ȜSL"\u 񠶪1n_8bZ-f"rIh\4 Sk16,,py5QRjEw0)Uٵ"X=!2Z3NnCaY,ѳϾK*#n!%4UfEiCRNS9"Ia 3@(()"]~Z Wp:<@@Wѓ8%6)@ڃ23APr#!R\Ę5RNI( 0R 3Hʠaa"$4lj%`PLښ ZÞV+ECEAZV~G4icsno63:Y+}v~;a(1sweQZk{___Tu/%!6Whe0Ӷ ooo?{77![EL#~)Ӵ) N ц+9Թ*WJ94y+N7=N)kHOgykbbڡp9O=DiB)uU 1tSvΒ"e{U XV''N;[H+лA=2[RG2jQP | U[+J1M*L1C 7̼\,q‡D֌Ǜ u$RCt1 6*7Yid0O5|y1;Ae8A@3ܶ0[ V9' = 'Ch󃯏4 e,!GC BH1LcC< ԅyZ(EhcRwPcb rd:56m [k:YMFTWQCzؖ!0Y9 :Bй`0rjT.fE jֺ#V4]rJP N)[k'MS֤h`wSjP`_а56$y%h%"9۱C l\bc"0xρM=$ 'q *M*oq5(\c(SS &D9e15B[>% 2fY"wA"&4Cer]MC"4)XQ+f&<;-gVDڪz۶ac,1Ō4WhMBSh=84w6šVW F0 ͬRIVHsuqPSk s 5xB{4&A0f1p GfM8'JDRan1)цCab59%npL8%g)(>CKJ)Нj|tTN\vyG_TXaaV< 3'(5xBLPsNVa% y/L\)qAN7;MևҍH =w:Gs t?XO݋b [D(={;#15%=3[A )[Rnd3ќy ѐ`!` (N9RC4p#aZѣ^~u(B+BFUP : 29ݽ/o5B &&G l)={QRC "(RYU9~BNy1L&v ┢;vXfLsI<TRi=HGM就*˲{Lim[&9.x9dwvP:gG*1Y{/2}R$48*8 cj=0iPk3t 8}̶@`UxxGF >7Fu}UɱA}%yk[ҮwƩ)zg]9F5{6Po[-XؑaD'5qjι*pC0(9̯9+\ a/h<ҡA|B\]T/Z~>!!dm%ՇeiPb rn8u$6P`jJ)ߣ !k:sJ)Z w1̈́Rl#ȨVсhAS|z< T"DžRO{[exCR΀ŗ|8Gq؍̛QKjÏ;ށCծưO ForM)#SL!L:w*HGW;ڑ>caM9ދ)j2jǯ>\*Kq$!\ӳQ>s>/82G𷘧t[v6+1B+ԌNySup, 14 #c8Т!X r<XGof /cFy'Ak@$c.j;AQGEXGC 8ZyCyށb SF LW/8/;D ^dLC{X5&g>L,0 tϧq\fe)X/>(8H7ұpMQ5~J݇u Zm@ P3zG8>ʔ.8* ˏP%t7?:ISo Y|SuX{8mUE=w<#E~s2kr/{.Q 4lKQD'Ryy7~~YkRJh; Qr=c=̙ѝq M5冨Cd?Nޛ 5t'}jz[w2wpԡ:\jQIߣ>?SݿW(!$}u';ZBǀۏ^yg(z|x]vtgZHgh΅V-rMNՔH M6L:;cSu,Tq8h}GsG}JNu 2}}KZ.Mvso?2{ oȢ;w;ro~=_5w[oA Bޏ?i.GR+uoS}ÁG 8d;|D%89|uhMG5kJO9@`o{X(=~轵ݽHW~c;މ ]C2Q߆ q{/&Grrd8$ogBG(w̞޺=T_4{I<!HwR{E+o7[ӷ,pKSIENDB`tpclient-pywx-0.3.1.1/graphics/intro-high.mpg0000644000175000017500000367000010773624641017242 0ustar timtim!3Y#) #)!g#)1(p#JR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")! ̀#)H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H!3#)".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RW?;hND%& 6' [< e6 dHNZw XP$:ZngP<Q~ItBw (e\Ej-ȣ)0FDܞ)Ci͑ )1EQ%<˳DIs4˹j'P' ܎)P;s}rtA<^Z% y5\mƐuC^6[@!5@ 3M|[Sī<s 4 A냲!:F@#i^>+jQ B"8"&!?A;?X#xc<,uvX+vc$d1sږk/'q:clĤahLʛ[3 >6we_ P滓 R(ؖ<RJJAP4Sw`W )zG]iM’^(cO,qwaDY)pI?<ݐ?|N|YG80R?cE$mkv41e"F7}FP:Q$NCb043p2XUZipnq$⿱Sji2g1 *ØͬrdU'記L/7C>{g_:@*n[3`OG/#p?9QbKu|ݖGª]331bEX< boOkȐZ!#5(`7 +ҁp bT  :Ƹ!؝M&:Qi4hlJi@oul(/QEb sPM2vqEz ICRCs{$,:! HJ"<[݌0A3-ÇQda*Az+I/8y7g71&s2P)Y;<an>jARqNI#(آ\ɉERZlƸ)rtR G^24dȃ׳?9N2PڂAx';w[%75> ! n&݇d H?^؜\Bwg{YXaA=mu1]NfQ~bCw۷nt X4̦u3w'P,ݙƩ!71LE͢a0 Yߒ>fSR YdFGpz&aIP߳ d͋%Bf8x4Iy@>ٝg"c\H }촞:BFH@@p2p~a|!#)399Y-:D xMJI 8%q72 K3#{(Yջbm_ `@!k<2[& @9<+t uXX-*rNO<^ bc?|*ETK-y̭6& F2]Va L:IK$u36 FI-sac" C;{M%}n=Af[7N T;JEӉj9Nj:wqBèk ,ھݸ^ `%Cs,<01!U= 3dXhs6w4`84RP7t0 -CtQA0(K$oHk2P dy* ΅[dmuґƍC7PṼ % _g\B%}dIV^iHo-9(dbGrH:aua #6ц]CGԽXLUGl>,>%ftic RZR&␆JR%.Faݻǭ H ώ35/A)FIZAYiZ~d:;&j-9AFٰ)쁽 91Ha P47Z ${ZMζn$fa݈\!(+`ݘ%ߜdڲ6q}ȑ 2bBcp Ѻϛ8$ jn$x26,tՓYR|(TKBqZ䝽bvKA-\۵hLGFoE2IbC=£Fg4 1i!b ptQ{06 B䔌#I’fu /e Yb B;<07'\wwpzD?JFg"' e>{ ƒqnuT?<w"H}-H7ZQx>A~m2erg*ŠAlZU YO"3jFh`U@09+9#݌4V'# 66WNR pY/|J6ޭ ՔiFTƬ.8G1% Ʃҽ/ G)JDXpRה مu(H)c\g9v4QrzsY̯3ՠ]Z2P---s(Z0l{)9!;ϏխN}]L9R4K+T9KP j6gba'yL+,% [0R1SLJFُtһ 0,8t :XD.rxy08a:ywB ~, Dt=τpe Q $HP6eguluOlu=_G-GɈ(h߳ ZFsVagGAD?JR"Sґ a vBHh J&҄(Ą!(,cv|l~;}ob0(Cv>cn hHūn쥋8?"$?mZY'3ƚ'5,?(##U!ӅZ "#jcXna-5*-=\c7a­,Bڶc[d$hC1.8RԶ9/ Y1$̳ y=gr`Ad=1e2iXq)B;@2HN 'e0| %5[aRCFA|8-t/w b . Ͱnw\yLHS(:LḢ(b@#vg2kB0ͱ~l @nt@z?G'(qmG#3)X--1{p{=.Wnyr?p|;C^(LJv\S0`BfֵarpԂƶ{Y:]ؤk?2)1ebW_DQ)H H;3`XJDW si8vT l5_ξ#&wpHOʲ,qd3n5< QYGx3%2|L. kđnglߋM%b[qs& dXhÜs M92 @;: fqH; i9p:FnDjIO#W_p9&; 1 -wut쏓q[ڏ)H!#sB wg¬ ‰%&1d)2 @ l-YOlu:)A I=ּ(w=*P:a He H ߜrp"͏"ҏCf Ba3)FG~ܞ؍8picƇAhݟ?;]!4;춆 J$'*(¤'Z?jR#V#^zwl:Y/htnI[!&g#) -vǯ0(B2KlМsNPw̼h7Ms:vrwfR_cdw=jFtw6 ̤]1a/\lN!IXY{tBr@0RJ~[Xz~4۝KZ'u~HDtdd .f<ՙU'pna­ h@gs0Y( ˀtJv܁bIХd 6a񺠑mCѸ킞ඔX cH$R~ñ#ƲmV؁BREl-f0~=k>pl3uq{(pZЏ]%b,gGd ?fwgeu:-p:-%W XKO%KA%uw ?*+۸Jy-Co;wZ$%Qܑ }gRwۊڱ< ae dtvS)e%J߯eg?)8X-8=8pb1':P1B~5{a (sD#䧺y-m>?Oo۩j²){ ,neɠ272RbvJR" >H22-JDN h 1p$%Imm6."88lBi ~QGEqF)X?D?aAlmIHptny' xX]@&,Kمjji:M&@ S@|sȭ?Ҝ蕓 (XE1{N?Z N߭P{(CQH- FN)ׄ\AH}8\)k Fk06h)HZpwĥGE7Q`,T )HC`K.* ,aXOa`iRw8 ytDxb'֌WG(䓪-13zJzHpi`cw@p:.¸G A y|~u=7#9^~GE"~Vb/wXpZd~sVڿ@dpo5N.U|8`U?հ?.g-۰Տn O86 l>Z&0n%nd Q=S-Cp0WŶ҆_ ퟜa S<3tUtn{a>(hfsWuq DŽ嫻-j}yt1^7Is ]<Â;y,@4Yd$բ, )Slogϰ9:^7纎eA?o xp`a4nrݾjRVt oqCHA`0k|>88?IJYV"#ic$# Oյ ?2w9x^''nNw| $Im )m.å@MS>ƌ'!:_I4waQ?!}҆%p&I޵5PEB1HlO"()Fh-aFHK&~܏ HafnpsnS[-W1cKwQ:vm-#CJ5TDf , Ef AmF͛) DB /Y$7яR2nr5 DXpYtZG~2(!Ͳ88U')jnN]ai)h@6A, >>#Gv} gQZ-;b9~=Np# ÒvLjr)PAL-ghGZi7S1<KApPLvaX 0=eq)NZEq?m@IJYX=Â|px%())FtmJDXpSJ-{U2bo|u3ȥTn Y0acwug| 0a>cJG9y,8,ۑb``x(S3 ldvճŀxSe_ep=Qٰd#~`,ْoRnve8s$ZD_q;,;roݾ⹜yp󲳞j|OM()K%<᚟2.?:eȑq_ 4YAMMb?3jœ1z"rw"tX+3K:Q]ǫ8pZ .C+1<+  py1#X!9pk0&n8Iq 3{:r +puSܐR21683kJl‘w1s|+;~R`Ug-AM]ffcto;cp E fC8w 0Xp>)<6ul7F]y9x;̅ )p O~p a@PsWaƈI(oݖHtV49 w0a! RRwIL7osx Ye bZvZYYp&F34d}L7uD A_nj_!]R09$}7f'"3Â'd΁ޏ)ţ|u{͍2_}bHsqgV-=1I۝ݓq͐?ґFV@PXTf ,`A8t-" †PFf#CRgd}۷c80Rxb e! a8 Na2\8-o҅1kfacH[9pD@ ,4FcbH{4Lx@5FA0cV 1=v׿ffW`aE>Z %ew'݄pn?)x+BԄdlmmm0=ݾF!Тya-- ]/rB BosZlI <G mܒ-W:`w 1$<a?qOb :DU5*NEh"`/?KR?R>}^SעD¸uO%c:ab oȌ^0I@vrq<?ғ`o,b2Bsn)g=]CەX:xng3ݵWTr3ؾIae6ۋ6! (J(e>DH8> FJ԰洎c@yxpq@t@k+tӶܾۧl?D?Ďυv8 DXr`apo8W S\2JcdߋKq¦|0w@amd8AJG޵^dfsY (k i%$p j[D3n1:@1!pߙ=G]6ZDXpZrϿ,ylηq w?R#s"Â-lw#P_ E,:6XX`~X 9}"`|jqg$H$}\`=_scMƒ %$bJO[ ?eoa?Hј3l(ၨ, JN@T1#pf 7;2X*n#''`="d+~(E FF(xe cx 0?4c)8X-ho33ՁE䯻~^WwW(0%#!Oe?O4}4$c`ӌv>pL>0hC|7w̹)HH"L!!% aeް/mq7x %ݏ1ry} !b  t,a z]BsjYddx LM!Y 5K3l"OrJDGdj#XX!|-I05ar 3&LoE#DX@ p=4 ˠhwϖ ;۟}t++v>7)c7s5BpŎttC JP;,#u]  ͸11=Ԏ,C'0ithuOg'6 :Ѥ/̃ Y}: RBwv^jya<#fDVm_~`mٔ[+,[O<XZ(V5ihu2~+Xu>QFԸKcJ~!XXg ZQqxfnԠD8 0eF)flK~3c| N1&2FtČmVHq?ٷݿcwa3lve~kRC Mps.ޛlW ZMss6p #F2cMvlE! !@#)|z(Lݾ۝n;(1ZM//\:<3Af$nqI)n[&ep0}tԤD?w=C1Mq 7wp/, 9ΰ\P b NK1\`˜BM5IOnûv>{g:g |`tu @H'B$;LPK BJΎp&X83?gkVS8ŷvd>Cd ubO9ūcU> QUh0` B& `aYS\B7Bo 7 )aznQXҏ7Zr FJS#cm,[Mǩ൓A %}$3 n],Eۺcژn?",`l9ua߭[g,lE#PNú䯲[HvO6#4bz#_b-H@P0!?P RM(Ʌ`Ԙ8{vg>~`q%x;X'tuv;srhGjnݱR=F^ƔJo_+ +=.|s |I ۯ"e` @OHO7_vhj I-0gBF aiᜮKnKpS|wT# Dҋ(Xc 0/a$a zCrhjY@lrTyw'EH$W`5 o՛Z14Q0̎|R@ZICo(j'!?aHa}{Y{uolrP1= 걡 }و%i)zkM( f-!GS:$wpoۍ`"Dw0.C`>#|Ra!3C&C+}X !]'+lk`7`Qh?ҔwsL<[C i%j_~csmv`2w|_aڲHmqe=9MqP1d 7@u(7u5Hl7sI3j-G\Yݎϱfv-@H屟?-Åv09C}eyѫvf[aε~;] [3~:+O$aٜ% cBHI/>v$psx;TvRl{onNaݸwp0& |RFG-ތv׏aqD$Y|5;l߶SR *M,J%M0`F%~A'@`ii BQR˛P7%QvK8X nq‡JDAc- ݿN"()H|UH6>UޙY _}>R#6J[rWx _5 Ggg)~וycnC+4z;hdX1JlM&B4Ҟ}?Ҕlƭf;43ĥ0K04آ`jXBNv45u<5mێ8w>t`c~TuV0'$oVb/YM1FNo  &@ SFٻ- Ph ӓnٺr18mv @ ,|5< σ šחN;n ~^@j ے8Ċ}vpd>yVvO(*gd͆ag/2Z^^Ѓu?K8X k` q io0jIK) Rϳ}v걤J _ 40iI /dQ7 %@04&/B!lE#HBP|Ni/O? =fp衵CDHqPDS -Bx԰ ~6޶AhCu-KOhnծA(,$hjP#bg 8[] X0x } B)=O6|znΣ#tLBRI_%CFFu҆}~a'PHCm%ZW%h1EQw4E 5h\a[`̕S-Q /S&'p 1-% SK0T4#sAo˲h 2H %~L` J/؍Αz2@P @W= QX3+j!'*(1w'8X"5RP7"MϾ0"+Ϙ K+li,8y|:ĔJy|p`1>)e!=3 r@3A(jYspMPѸpqy1\*W:hbcD qe053:sZM0 d2Z,fN5ýM"I@o +K@LnGɯЪqAՍ Nct3~݄a#(f;3?x]];-Żn!H9EUj JDA cQd[DQ-gl^FU>ZDQX FOٷ>' VoYVބ3An(|:"=1j`Po@Jؔ_R8bv%9~Ay-v 'pylq1< t+Q} <'6nl8 %$j,bj=쥐``B]JFϐ%ֳ΋r}? ӆ>';/>v;.΄$l12TpJG:"Ɔ%K یppVq ,33{dtC8_ڒ5e8\+JHKaw۾S= baRdu6!b|}99#v0a@Wx@Fb[mL7#Ե͛ue?uj֢NO*Ab#5Z2eAKA+b@ͶV̀|)HɜL jr3x?(|>ZnqtwJ @|r"rY)A,7-#3:R7cJDV_*j)m? &7djn n>ζIy |M R1rCGm(fN%nc%!0vra5evv=s1S(Zwo.)ǩoﺚB?ܴnJI-(:C08 t->ġ %0ݶʃ IhbmՓ@NNtqmemm obHg $4dduBh ~yIVW.s> wpbHE$4- [|澭fDCJK?o xq R"CJR"!99{z <'~$e;crmT"B&pݷ/v)@&&/[rH]/`$?",]@BL!\F߀:_CϭJQh Q} l.QSI":!d[dU&$  ̄L=\WG^>2!JDYX$jRƖ\LH` yh !?R0čd[S3.0!_7;P^Lc~VR![+auxq-?g[ CnP~O^D$ ьM ^,Ԇ8< )'$VsifH^ţփH`d~V V?H>`QXi4in0_yаnvB_#8R(B0OښM ^=4U^ 5 +3nrs:ڏ)H`$`!%NM0*;3dl0iyNƴ(rGм?8ᶵ=Qs+[tueNPp7sx3!7]E_y@P4ď fÎ_iD/K(1x[0+`AK|γ. I11N|-' PgYf!)X+ɽ"##02!R[5Dr[/P䁠~ 0 $!$0=$Yl>pRfOs#vϷk~ g݋BJtJHŒ-q։0q[9b3~ė,KbH58tPW=a4ot)`IψI!p`2Bs۲p5lpNmG/= Y)qݏn*8Y_`¹4ħbqic{)`P̈́+q.ծ{]=5,凩OfnL <iFnKPp7l\yKKJDAD8YȘXbs$~`NJ p'PaAIHZYNZI)!ĄI` !S3#)J A$Šu8mn4Vb+k؄?øg+sֽw8H9/v!9ƷnH ?y{#jXБco_O0#{ wZG F 賫B>ncT[>Tv)Lg >USAdtSa]j>Xl7|s8~fmdme|M%[;([ B%K+8:HSoFpf in2ss+s9 :^FUgHg#4il/j~I+dKBlvK߉|S]0OKCd5Ƹ^t5TLk%1e! F:ݏJ<8?ґdreC@ؚY\QF1n^Ý(d$0 SH( !ZX k'6@55Evs;,]p׆}jԎ6tŎϊ ( RPݏBNN^BqB I-V9ۊm᰷Y#v$ gnVdAN!Fq[- C@{ƒzW f͢{%5.0XeVӛ 糩xnR PZ ۸Wg#Ba_u7sB靏Oc>Xku>`&,c8PoFdml5P(n@n+ .W++8y bu`ݻ8[$@uQ(.Fs?ߎe2Rm 59;ӂ+n39(^_:{l[h0?Ҕ[1p||@$ h3!CI:8NpܿfÂv7;ӹХ"')l?z&q@@Hԁ%(CfIY KkE>FC8OO?-"0G$CLJG(d O- ( tB@ (Q 1)%'_ӐcJDYj|׹epŁ ۿ8h|_v3pX?H5C>k/.0lLhO, f/ي7r l>Zтӳ!ƤVW/|qQC0Jߚs?bG1[1AHِqeX4(Lq1)5#6F [4+$2tM ᥶ kv< : ! e4I O,Õv3fLK%\π>yZ!mx _3$~Sa-B 0 72]$B$Po,d;Vs8NP Rqٳ?8=)*~Mj?"#pL&:Q)@BJ NݔNd [9``Иt|j["n::`!Y#)b0DQ aC91J6ѿذ;pjG`aC˽5 "'.E[`>71N8#?V: -h:$t!C(5! k1.c2B?^dnQ)naAbW&(7CF8 J% 37?%8P\N"RP8!!ͲJR"=֛8` hc C,%;ؖ4Hκ?e,CZ BJ2r(N|?H䱸RJ&PėU͐)l!G: n- MyVE$P_[ `4bajEb p?;vnHG4c$rn0PXK?I#fFfA}90'NR jVtJ=ߺ@H1CIC/˶C04WnK+GJ @J)ѫfqC-2coQ$nJ0ľܡ~ڏR",`wKF8(0Ԡ_I#P1Ԓ Jz]IgK?%`qp6pZ0e7|u dV$0&cJRba8h(CILB,o/ ,_BHNgo~ aN8=4 rbI)g10ѽ PźE"HF& #Kd' N=@_Ha=y 8~wicqcY@agW?ҔAx0n%Ӑg'^WH/q6p ݟ-qήN e1D8VRҩ/:=btEB^͋zwK,fJ̜·]Wz$v HjqHOB7=[l㶜cRJP@j9e%)(n7 Ͼ, .OF!%!\*)Ɩ8e]eI&$R:xҖRS#˱0>]>g TM&QlLHDK`~p Ex 3 & NB&(ZXgu),DOAZXh퇉E?|NtPy4G)JDC:% i-mnzŶtp*| !&咉ieqlon}h0jK;< ZT(Owx^Banf[tM&$4׿@(BI0jvSa"d1ue9y37 &#K>?ù|qq7ݜϹ-'>NANss?.6)'03О>Oa_wVl C,Q1xELӖ<>y %!`#)RB3hwP3k.aϤ c#GPv;W#OqԤ1fFahٌ ξAlQ%f1AE`€o9Fwg?ˈr@ H s[# ONj{ ;SD &<Ӑ)?D VxhOY%`N5"<Cq3JzG)鈸~& B 5*()p;psgg? zCC'N:(|9_>BR?2)JHvp(i%Ř<lyNJՓjFq]3,~1wVtf|wcD+~TpCDm9j~Ô;W.6_G$%KYE '`ܡ?fr3y$2pn}r(¾GNK7Wݺ\ZA1;~CLEica.<>;0劁Vӊ9f6i)eK3WIJQKۉ9qQn;4tB&pށJY8YMPaL,02YE(9YKUg0IKfl7eKs)RSuT?s@L!ɀ`56IJP4XÒĄC4!ɉ&1iFŌ^GlԓkUvF 0P`AyoqF8>ݞ$|qGVq}j TCJ[! Fö; kJE)Ȉp?",` d0$VHv$i, nLs$qba$1H<;8#q4,r]ou33A.!&X r23IP` bf`JWWb-4}epLCRԎ7n=t8f!(͓- kI|*`g x6c(Ѧd#[fat8 U~ٛ\:ge;YVag8tvY7cB hb: ,P;gm nXFHXja iiHc BV+`Ԇ]9jF f)#m7j?K3F&CѠF## !w.8҇PeQ@&#Ʊ5R,_'9:1!K(lWKC`.pB0C Ad$n)#6,u p܃?্`+,i)$ضӆ-ٿӇnJlFOfKU^YJ9Ky'oY +'ֆ]۔ȆK0уA\%C7::xUITXJR_nsmFܮQy%t87V^n쵎h hĺ0nfadr_̔ZtY|g'E_3?廬V鐸mR!ĞPٍ$T@G !fg#)hg rfa $wh`C'&Z^B% Ť e{zkqlz?̌,o˵Y6 ^}q9y.RǏ-))H՟m|VhIskw*j wQ\TS@:, R= rD2Ydʳ]V:V1e !' i( a%8-R`i4Q0AG&IA jPd7-ԫxM2ٜ#V㛸)prkET+Y8JThG̟а$ze c 9݂wRv}=joA,tBHenC105  :P vC,J%!A_Jy-((rؐHx (Ѩ؄҄tY/l4I0h~(hO@HBPO/6N3W7.3+8GlbƤ!t@Z}f cS=W#JR"B)!QY\jҥ,<4i-';Qcs u/9f / GOm-HCx6쌅#6.0X{=Il^ByA $Xcl FND̷QcIJUcZђ54YaҀVQeElHo牐F1 RU L^e|ΨNsrД/'gW;wlB|۹mvؒZR4H"QIaBF$j'(ns/?pg?>sL Yl3iɜ. F,-H=|—m\&uM` 7f(Q$o%P(ap%!}+d̞n4(K7k++:ExtL):Nt)%Y).1roGfG7t|;j9YUV&͒|{Ż1!Bzvt ; e=+ 'sb[%ZCF< b0pj,̘q|C`,r3%tCP'LvsͱE)a`_̄d$f$1FR dz]*.4J촏cx\}Ԩ !dƷ4,T!W6hJrGymַu'JD@pej٧5+?<1 9 :p94D-2&d> )oR=#",(ft,5/j]ՙK`.ηuykΕ9P כq?0 ٿeje 4A9-~KJαu̷C K,a-9 ܍W8h/댤Fϵ+w؊Wy`5pZvHwR!)g <w X"9-)HG:0Ō~~e? FsX}}0؎xt&yB_XjSkm2?ר|>˫KqocWHcu]{[Bd!l̀#)(q\)mØ?٩H",`wnnzݫ+e~+ ,_a⛓3[=(}İ HΔ>;Jpkk0oT5򆩻wnꬔ'n}9|ng|;^( @V` ;I1bQARE/30#K uxH!ǝeǀnp͒5cg\cJR"$*P-fnK]3=-a5'@!gXBHC=(5NK% [;eoJv{ܭL ID MHF?Y%!9U[4i9 "Sa|q5kugrٔ V48bA|"6m~?[Py$"^%7/Ye(t!`O̘kbS+5َc 0it(C'uyxqHrݘ a#qyf =)O>dw37c;:<+[s4w㔥H|Y#+@J?6>λd"žE= 1grƖ!Xfqtfq?H4en',VD+)fݏ'HjʲI#  [;y?ґ,d}ו3 0X`dԒC,bC_wKr1DJD@tpL&20Җ_jA&N?eɥN'a` 2FbdA 3cψH˓HiHaA,YdWN Jqcg_|fӑZUԽZ & f$ < /7SȾn >y!s3#) Saau'/p[}{$3U3]|-`@õ;~Qq\s|nFA,?v5爣",p؊ׅ 1#-YYEh;H' 7nX`ĹX y$BԵ\ *?ґ `P=(=.=t @E fO)e^sG}$wW+;ʪE“gqJe,[Ve-Hx3?نH%@g7I< Re(3RCz%x~Qf<竴&ҭ'_;Tn=n,34ҍ2`,ԸCRyhBz9CPNn183V{t2r0O% H(ΐ2G倯ŔWoJw2$@T HBK)x03:K&t [myq rrP3'0K%' e`е`0 ;,cdV) ٲPzANM $ L, HID/,&)1A3}=+OJu?cVS~\ZFQA0 Ŗ$ih )H#oNM'arvIJ)mKmR0͑eK0dP3FK䵬S|уPYIJ,BwBp~ݻv;G@0|MOPGI-f''aHN/d}ɂu~ѯJTvoϕo~LC݀##C&흝߳:M⟎*c1:  %>:!@ @@bkbX|P ی91)]GN0ab;R0$*4u8В^G~'5y<K&/8-补ēPK`%[;fϐ_a8E0R6FFd#d#cc6DatC: Hjuuoۥ@V -; J9hݓL\,bX${1lKNbjC);6< ;XG BENWd JJ\Fƶ_Py0.G-ȡv͑ d.@+_txr>'4 n/0݃If0$8<@ ~13>)R@pں79_)ht:'G}7|u|G>RL}Ϗ6Qp Q̑9ja VO@-H Ϸx\d0Y5 NT)G)GD!&gv>wu.#X\?)x)h5LB?lvP͈@6!o1n9)+pԊʶ@ Cl fI: !y#)%[rr- vĚ~t O 瓟O;Ws,/+^>|4le 3bQAsCzRKd4GKn$Nƫ  !ba!‰cHG7 ܊0i4clߋ;\B%rG9. ?;),$/"  5<`˳=<!,?vL.J,9B P&d|mDKE|`nC@MFY<[U`AGjCFE~)M?ҔJ 4 3~~blT 26SŷbRNv>9]kġK!#*cJR" hNb ]fw}qAe0QEnҞB23lJDYϷ3RJpfY35~9d@7`%a q!U7`/KAx"hX SA`)&KT-$i3ӱ!B Q[74m:pBVbV0ff݀~7X%%$g?|;%gƿ[ D8Ӏf6ղI`P!1dFņ | ə쭿s7Aeoߣ'h3}#OI*MQ`78gFKq'>@zʈWp|؆ŁP0pԁoŌts~@gW3Q ،vG\]oXh ֌a?B` ~!13M-( |5(@o\ Є~$h O5,L0k$qFݱCvlqsY#7K7E3#2Q@ėUtEC !3#> 䱠8-';pCuR0mV,'`RC ݉A!'*>`HFJС  <ze[Ṟ|vPWKtn5;]A-IO~(.<)ZL@"9%~'a WmǷǷst(#~ej҅uFʈV7~qDC(͟DQ̰:u?e.\0s=FT:SU(lw.=qi[Z`!#6E8xEorXa0dCO^CհVsҾ֞r!PR $xM dPgЄM}h@$jP -&PaadPZJ䴔ih%1I1@jx V^ 4(SM Xm\(¶a;@ 0(R;PB @ |j8 ԌBFOnlj[8ht@;!p>V\xGE%ŀ>$v s.L 4t|gK-?'h? ZA6fO  Ae} BrKe+'H 6ӱ21 w ƍX)3 ԍdA)wUΩ)0ix1?vC ha  &'Z2J- BQ 3䟎H/rÀFp!#)p}y4L2aFs)d#Oc))t-Xog#/ˠ(L(|Mš!HH ~7,'!qő`a7`<_ 3b6#X b3ݎU'##6ͩaH՝{>{UEmKξ͝t `f7u5ږ7_eF6 %`ƒ56VKYRnHB23eAD7R!(/ +䣛?Ҕ0PМǑ\JP a߭G1|BB] F8U-qpRPpP_-NO ۀ=% a؝By)H3/k5f?",p |Q@a8oI=t TPb4XԶCėJvVªc=8P\q\u`ppJn6y|~!8N! N0lSp XKhtJ AaғP}$P  t#T3&;@ N` H@w44aI IEьPH3:Qu,m] Q/ saJ=G)qt2|[ƺ4j#o.]AjFpp @;@1,1 !߀2HncMcP+isyŝ8>:K4bX{xR]zCֺޠ\t^rW;:ZR!?",`ؐ|! nKI5brȣOS- pkBszjt->DX)u2owS]WR ds g P5^zH6NAe(&$0$$^tn/%ܓ-َU! 7lyx㙷l+65=0-',M:ٸjƾe6^oFU0$9-M2R2'%a%NĝƢ}( 3a }IݾK78K ͥSnsÚ u%3ytqtt'f" XJDK YaZ pzLh);bR0c')Cş!js!g#) 5AlfsCr%-fg[Ws߯W#F8o՝oW+;wN4VXswq<,ePDq-]ݿjn-}֕#'qmq:!l )H4F`F`2JM39톥x?~/”mLOT;6֙J+tvN[3<]⇋70R0m1<"*Vq'ҙd#cTA V r(7'_!-nggß8 {y'R YIZļm܄?=nf=͙8nSigMϻ_}}~:D3`ob֧9Lrli>F xJ=s"IJZLJFL##cm;1"&?@R'ISwFJؾy6@(@ DLe[ve2x~ $1XZV@qm~m-NJR"ºζJGƪ/||:`,xt$a1! xM[df r@N-y{t^>&VMA340o͋G J(w?eL3gH lIӃcm9;lZ7in|p`BqR JBW;|w\I3['u~1 ='? pf>7^Ra0grPc_%lԦ?6&/a%f伐_JF!o/8~)U@8I47JP !<P LNWMa`& lRKtS15 <03eGH5blΒ0HbF(I_9ؠ'; RZ6ͷf+ol#e2#98ׄzr)^ScVgl5$PBܱs f┌߷f?"'6SZFױSbԥ7q/ Sq%WhPiE'#4 }H"<},nPj8hg %PRyE'/yhYuk H'vi~#{r*PIydN#]qwIv8qnw5nHBm![ F ۞b3έ尝ٍs̶[gKaO?dlm`ƻuag_ِ5ıtlRFKPH@ u-Ɵ?#t#omUqJ F-М{3o!̀#)wPŊwP? n32Q"?"+3XpqTc׃ -KŖ)\Yx vno8]aQ-SԒ;?BgS6v70Aa I#Ѫs ný ~o.E1Y)Y[}j1a- j)5 cbp]ҹk:Ŝ[N}J~'j?xfKsyWlZ5c~!X8o[yL=hOܦ 9lrf#Gߘg8`XoG Oٟ1~%}t'1xC|Ex#*me,.~-  +y xqn7RPZf&ZF#_¿aN)ia@\%6a92lL(XJXr8\(nnlE.g3 1DCC[MJ7UYy"rWgZ6@fJ/־F®r-a8A$e;?cJDXҦ`?dmƯ”8IO?V ?㵠Åփ rB:RXͱ-,5,g !nQ[' Wk!\hN'130`ɸ n<4HÀ.- iHhppPA ΒRŪic =99G$߰CsDhVl\"0j1dwN<wd|61{DIeui!&tYAr>ճ:?# Bp5F\GD7 )=99G,,۪Ϛ ;/ADRF`.xgj[aVwК0IS59faFO9+Log_A)76\m/ j)Ɩs?O,aH!)!|s6#Qe"Ua<3SiXZpWBp Nph1c4 pW A  b-+lqG:߸J'JH8Q󭛓V=߈e=8[穨^zǎ! R0png,4+nO%}Pݟ8|(;);v`fp?+{nKp z \cbci,T[! lcb*܊`XPf7ߧ PP;$hKsFqik T?FЏxCNm'bB H7i{ Ögy3m[l/tBz8̠Ig! tYn1Ƕ58T,vod \6y)HM ,4b6?f~3 Fܰ8S4lj÷=]]L /Ёp@x0 RHd bҁ) d|B(ۀ(7f &Xf@iY%%`7D2ޮΧ 3h0brt>`8l\|ہi沎^#QӲFS~S:.Y=jq c;},S>TzY(eaS Y;JBD,|Axn? St/۸G dx8^1>X3DYlߨ4ӃgݔQ0]a@C,ie-0mײ_Rcg95G`}P  BB~V -`(x #Jv@|44 ́WIF,i+X TZC~ЌLe%dTJVd &,#!#p8VI2>bXM^|j : )w;)%cqe'&QtYB:L]/?~1C?{a[3ftء$Yg,}m9 [ ;anۆgs`ءN|Bf:Ě%#3:ߗCgb_=uf$Hnl3GnO'_32^[e瞡hRr;0py%1D5g(Pr@[97ΠbF|fr*vfueRp4o=x,Z ἢ17l|n=nEP>U" μ;{ R0h|8]vzϖ0Λdl+ll:q»b Y//KH8 jK}$w2Cggal>wI;$rw`'P`s`X0Ԇt3!.ے|3nJ &R7@𣭪(hP+Ls؁= DwJqhuq |iKLq8vgg4lE+q+ǀ tn!98x?JFov~ D@ 7!B&&9,<"[g[eiͨZBmo]}=e(CKRPН9îxv Z hgd=s!#)<ۣJR"!`A)_j?"+HBR1El#6B3mmc~}] Ixap|+έZ xGn'y?"+HpnsSN~O˱ņ+X҆ ]&ܮZI;!<>7!?{5W͌XhlPF~3[>cϜNracFbJag<е8sP@+5Cc0Ġn؄ۧgRY?ay2nD`/-K,@4 0  G9%Yj< `*yH ))IHS?;Pݏl/l'~ѳsƸ6ƍ3q.$Z:]ӄd_p9 A|hӇnVGb73 H09BΖ8Qi4mJ|jGX- `e sX& uZ;}`WK|5/mi,54}1vauGw|8CnvL[vq/|JDX{L ab/OjA+PNe?3,~|ФEjF| 0z~%74݅wb4b:Fol<=eo#]1?} $<`@°aH)0/p=Š,˴l#B{PM% ?Fc$Ww3~u8I_wW[s r6!@(A0ie)JO-+Oٶ p#RHOC#-,3p1Ik5pޞ J;S4RF2)CV lW^p]It"wb-ŷGGaXKQo9uY|yl#m\(4I#ceOC'u ^~Ԝ޻R6d nZz[C̨;\Y`7%aU]")8nRF+1-(vCTI"8m[lska@5D ѣJ;usO0WnQ+qݽϺ& `VOZl4h449]]c;…w'XN(,}7`wxJF>߳a̻FunJ~,xü,vY=aY;J;r7t!q ;l_\=!)ߛtq# ^SNjG,w-)1:!I LN~r|(n0 `j%n1W}K PRaoBFx2c4ћ9pQD?OpR" 9М~Zv=:C+s9ϩlj RU}kw\FHޕ|ݖvf|`q?Yŏr}[@(LAi`Β~RProƥp&0vNJR"cJR"1.8P foM^'``4') PB& 545fna䝅X3#q;hގbOq ! Jq#' @ 8%XK31O;|e U$:W\B (Q)\MUht$He7 nykq݇cC؈ퟲV n(T[&[d+mVgߋ5uZ̥C =  @LL:J,7JG|м!TƼQS*SX,Aph\%@b:y7vP:Q1=P:rSE p\G城rpuR#=̱r_/4cnĭVu˦g[4 B SOwvN ytLu|Eh 2u፱!J]5a pb1!#:Kð԰.?",v#ŀC&Ɔ0[nK+q beZfoNJlG~"JUtn=P20cnJ=O9"(&9)s~_0' > HH!Y1(@J(^Z3 _2@nd@]rsUЗ^L[ㄇ@5rvyELG x"ac9$# PCA51%lpW0\@K$ȷp"_aq 7 ~*4gW1xL>qQXP4k e|d>]~ >Y (=|ۺY(E%|p#JDWEeVpϷt'e$!?l^ny];wG A1.dI\F.-6Y66J%vVfڜ*"QO><8BCzsC&82Ͱ7Zz&F%DP8$t#}Fm9:s:bhj cd 'C4GygD7 $cNZHxVB5=?|s2}n]S8-?e-=l?/|ܝm8"mFձ)H aw;9wܱ !4ve GDG9I?͒ی̓K 55Z P~mQwƀtϳS oGnGS:[nxbHDb,M1QMx^H@>uQT§g9ĞA$׌!̀#)KYG $K`8 ݉m*n6enzr֓[eB1YߞʎրtE %ZFgQ1a7tsD\&fQ4NǏ2r޷v6(QLbG( +|LHIGt`a[a?,虐XIa#\iY57_;5g~vc+$gGqas;>|+ [':@+&bX4 G!7C\FrR5,tSJs),/Xvlb9c2wD⑛1›wBA |9rhAH ;z϶f2u6acRO6aOntNpG 0M!$0C@t'0` г 16Oۯ{cf5%#$kw5`Ԁ CSleۡa4ypak@ÖUYPI vd ߏZ `*RxJ4hsfQ6?") sRxo|Em{߳|sm<a2]$VyOܠcfn@Єbzs;y4?qζI (_'q`dr}PuqbWcS1t000J/IXkPĤұ-%Q,s`oG'O?یݟ9p"KΥ fA Hp98׬b߶q;/'X#Fg?vlFYن[!1CRO*B8|qѣ݌S%=cDҎΣ}׾NޖAc33O)r;=ķ50 #l7Ygm'DL)%dnQ秣)u<RG3|K:-|!3#)}z{^as:$y9K>e'uWnup &0Ԑ f0F8쵿/yTLX HR 90Rp0¾+-/ =Hz! 3((VXEjWnGQyF0n@`xMh0 ɠ7M,bB$(Tc$0C %kfM &L^onϔ~0`:hhi01$ܿ󦑁1:g4S|va$#cw2Ì'Ͽlv7FDGy?Xq,fAV])#|ƾunηfa7O F,~3'Y#7a޹!ήnJDQR*?z]OeoF}homA1qL:l" Z3wda*eFP7, øħ9;G`W_vz-BUSK=]C;- minHRW0%+n1ҖF7̍ >G<y(Ĕ/-.nC%9@:&I4f !ƿuaշ ^< Ccֵ̠?GB%cGK|8%bx#x̅w!JRu!!v߯ݖ7R7`&Vߥ0Y&}{q]þ[1[6^#ᮞ;nqXfBg93 K3s`ՠa/tlX#l{z=5 Qþ1=#dRzFeg8lR43P,YƼ:Ҥan߈~ v!#)3ܟcRt%Oh}6ŁA#{nwJ( -oFY:r6xR"fLXu0᜖%0WKjg:<0ZY_% s^h[@aH&t)/?.D#lwn`JY@ul{StF+~JR"Ɔc(FfO=JDlcz0b$`Jv0h3لCɺaJ A|%'$bFRYGRP?Ҕ" iIXt;fY@*`h(R@l\K`,KXk-U7@K 4c竱U*(frX M2lfBRA)ah̕%Dqwf|6VVa}?'g,]glR2ƿ7ț݀]HJD@KpB ҆ɝӉE#2Xjw[uQ$47g_ϻv;  )9ñ)Li##ooΉ= ><7fsa=u)J6q, q0j۶qu-sg@L@ q K)$.0±] )A$iטA'P( BICRZ JF `3%1J nl!NQ*NWvڲ~hϷa= QÏBELN4Vz(η]\Mٹq4[fH"REc[0h HI;0 1I pRӀD-P(Zg1xRCmC63,2í cS!̈@iA 9sꨕiQ! +$~ XWHt3a-ea!'.ջQ S?n?Om+ DX מ7*RٖmDkQ1%dbH@$5J(7GP!񂐑پgǞ;> ؕ]4m`Ҁ1H%WB@L1_ I ZtEx`/3n5MՅX@n S+ބx"2zoS~Cd,CF|)dB`$Qxz2+!J G m0K2t-< 7wf @L,0bJG$#mX 0&U|Xh"` мM)1ߒV$'h- ^8JR" nE)cCtxOw# &'%;p"ڞ~^jragKcfbM`n78]!9*'&EWp̦}s{~BwC(?/cP`Bxi` JJK<5$%;e@j I4 A@DО$04gXbRKPW)]R Q3UZJwQ% g\5pLv b / A\-v5|` vM&‚I[$i!`P 9H zF`C .g!n߹@a ؽeGB@9PhK9i& A WJ @1!rQD7tbWM 8{:XqYx0CtC<49H K` 2 3Xa#0JP4=sL;<JDQRc`ɡ5.Zn$=tdcG,`1Ɣ8nϖ~|.|޼ }?N9c;6!#)s4?(^sG4 u΄-hf}Gtwi vF#~{BWW, +% gAlv` W[Tٙ]c].w!alK9)HCe DpC -8R^|JI7N`ܐODL4 am! f~@P t*M Ŝ%vfllJ~av3оYL)k<}G@bY`: B9g>C>l*/ɠP0ucq=v,N9#}@TC5JviǛ ~pws9pɔ}L=0x?ҔFtR3)݀9wٖz[ݐVܞm98(tcՇa?gw? ;8y=AavdfRҍ*Fа/n&`D,L#n)抂Tߪ (wH$HWuHSDž: @`i-0=vǎ&]P!!GIY@PPb1sf0$P̌Y$)hWw 3t⎀8=Jo BF+nd}YsCwtA?}v> SAo8F߀>?"),-3 R43NP[ S;\$5lx%=qYMϘfX }Ϸ à &\PL8]o9c0/ vhbaQuHLlĴt?TXZnHto۝$Q01Ho%! 9 5rqn|Z(9)wJ3 } `0!ws 5Q99_@"x?Ҕpbןc+20Cn,‹G홒`JC|-qL4 %h8׶hF֥Z-gl/be=bk鸄KNC4SԮCJR"NJ'eZB]{hPDcAPOJ-gv0]můөXKG]ڜ6^P(~u@&"9=L^a -Rǝ#W0\ٶT?;m:]TK ܿ]~TQչ ٱzn {EH(9ꐥb'Hy7 F- Wd(n8#þv@`3Bپ-$3,[Z(00b?78YJDX;;ml[8>9k?K%>%ӐhgzDsƅ[5(gKxc;~F#@Z" %l߲Ea\֫@/b:~~q':V5|mTK,Do\0gO5^a~T㣰DX3y&0[,@,8a7mGp|wʓ*"oa/(޼&T&"Kuˀt([,01 (-v%+)Ɔq kcD:nB0 ᅠIIb G`>N?uzOճZIKQ%ƁL"J҄y9>JDI~f/Q)\Uq!)# @# ü"[r$1-ȶޏpPF(wP?ΊtE h0<d $gNB~TBJ!g#)RKO,7$ZFkK@u [9~>(&g;F"|Q}(+ P0$zfWtY)>r0V/'~KP8@Xl 7b n,\vE@0 KplF;?cU7Ԡ2N<B}AAA>"t@9\t#,. w& ,Z:?<9;w6#!cuqb6Ղo;|;Ie,!p[RYK!2f_mj8U1s81&2R3 R/[QP5}(HƆ|Yi ?P,|))HF]Iq)&`0 $݆Ŕ(crB bX$g:;zRxPO cSHa+& 6n,U aEh((YE^BC{#_^ JdwG>KVGpg- 7A@c4 b>2>Ĥɘ?Ҕ",%ą5 0c.B|DP*ݳEH ( ؏""3A 8\QP&I~~7&LXCby07I-P*@DrJ M+RrMv̄lۣ¾cV_krؑnF#?nI-0>}.JQ#+;G};@hi hB ݅QB>0a )썉\8/DE ,3e3t=!M.hOl<`RvW,(C\4*Q| J9/.?",T %9 &!MHn5y6!MIH Ff t!=I/Ύ2&IZ EX-%|W/'tx`w ׶)4z8q(N9J G\bpZ x?ٜk"WO!=r;),tT38JY, uǨ[ζvCΐv&4@(!`rW1fKd퐟(kYٳ: Rfƌ3arOa33NT<)y+5K33B@ #3rٺ'>$O;jv6fV0|e_Y;>;OiO'E ,G|r2 DQR8K7ӏ1_<xDSJ.?Ҕ2ug峏dzʺ1& !2w1}1QZPb\  @@0Xh*XXS囁fXs}! R-\=oK߈[0x8%9>DaAFf1Qh,/߬)_~^0R̠҉$459Ր|qVlyRFqeJ+tf%1,[`4b t3X'xI@P PM&bI(W,41 ldFt?$$j|nDX τ;lt)&I3Umw:DB,HPXiċ"~SbMKᭉ}9m3wf6F+mmc2JG2F(Eb%V Y,䱭1Hf%=Y8?Ҕ 8YINvn;G$,M+҄!$ rY1  ClNoeslv* (8W@õ9\bg:K ǽݘ!̀#)YA`.ݻr5A+?K-? 5_H!'s,{DASR*?"+VFLY,Jcn%,tPĔa-I[=mGDN9%E//=]~}m V( }((v.,Ӿg9b+4NjdZXj0nn,+,)@bH`%rXӀ:ޥ'(?xAp7EYD%8V_%9H8b-@p+n@D 4)!rДr[bQhny$gOy)H\D`{M?N9)HQ@/XS1>[B c㯴d ٌNV2xy?RԦ=N]#1F{JpΦNw=8[D.Hhӯ9 `KfMS*!BIEiIű['$$0gs5ghB ri5:!2Q!# _BJ A# qA0F/5Rm+"GpMwOT C'[,,%b?Zl36Nyvm|*i[Z1hI#=#!9ƤbqY}#` 0L?P5sXPa4 04 cl5K`HP2C ]ϝL$QZ~_fV~y|yghFU>olO;‚MAJ@hbqe'd(wEQ1dB3mc4[C.O:g+asy0C@ ,[ GJ[t!Cr icA/m}ųBGxiMb Jr9oYOXo~/?^*-,j߄wJDX`M&J&B (5?[#.N8E&ݺ~šPI,$W^~YfSݹ)1cFqu#~1;Z*,BB?dywiZ\3 HhͲKHZX?!DX4B*,40L-˒ "Ȼy>gu>u=05K(~;6s (BWFNtqN uu ݂Fs(k C1TwgRRG!3#)R9̜2f79 uO:ѣH<{vn}ǥ s./hj:.cװϺnA#7 r-?%yg`5dP$C 51<{d@ x40 9@L@ U#ϻQh),w}ddfٵR>i%#}?|:%$[γ: 9g[k3a-:재:$inh To1:Z-(j?R\ptzaYV@F+3 0ct4 H݆)50jfñ8Iv~~ۏN̰ԆH}m{tФDpaEJ;(LSw_ͰܖlnǿQ缫B0 Htë@PWĄQ j2FQPRBP$C\%x@Fo%.\ 7(Q,ωda{5(A|   0M&FİԒKK@GqH=+ad'C8@b1`42ɁO+ [dz3 unpphF[g;GEwS8ꮀBha0(4 C~RJng:d¥V @`d HOYKBP$q9>4:1”nLB`*Y Ro@_8ԍb?1E6@H l HKܡ`,1 gP˙Є?Pљ;{ t~:%3១Ւ ֔df> 8#cA0B(_c\& ϥu,apL,c:&`9EIJY(idu m`w(Jqy șV&>b %󲜐jƨY }~??#t" Zao(4 j{#%-?Y}Z<3΁xn/F0nvǹc3Q)fhوaMn VmiR+X`AIj8_X vL08hbKO0HA5@9H̐-G .T$W+ؾ `hqChĆ JPGjB0`brp!AiNr~WVjT5"0t0vJ1ݠ( I B[+䭝(R*sLo,^@ˆ`' H@T$l3 o ˣe{a& Q:Bx/0|VQ.15,-V<ss`H&hD&ii_S@ǐ!IRLJ `/guuuuGyxxq`O(5(dGo9( %!%<-'t|ۙZpZ[p1̃ZٜӵÅHt9y mIbI ,( p,+V{My$;/b\0\ J/rZBFRZ8Ld K ,d )(%9I LXa) _`!ٙ#)l\BN~?AnWW%Id81.!, ji $$_R[tn8@ܱ0k?c@)@!(0.Prv)$X4R28cd3-j Pcks~p( b(Wb K&Qa$↠r-7 Y1\(l5\Yd?_`c&pqL0we1R|CpG@ҋ=^IdbP%/$x Fv="+6gJweݝꘉ}`x,kc),5n1nثB2w+Bu>|Qz$e;w08ntП#0؟W oK G{C;J$ m8>jd9javz 0d0dPIJBДNJ n3%pp-P ,0\K+2 &de$L( (@2FrtBO~h0p# &xA5aI?#tNq bX ~JNBqJ@,j4 HD2iI Xr V [rJP @L@ntNM L@i,ܦ@n 0L[jKB1e<ŁȑfrP HI,%hjIh`Ld> (KO!7KE uMN?",¥Vf#F=,c]J߅]{Lr (Pb1Ec-NC;aH_t0kō=; !adyyy__tFo̬Sg[kL)H r;W)JY>(fPO{]6Qww&`1; #JwNlkA3ↀ0iL܀,3RU:cqg'oGBh!:_/3u@gk&`BW^ab0 A1m;gV 0]= ք ʣ1q$1)pZBw?~YRE۟5$ >)H*aVF[F:~ttl;RN5|r|pRO@β8K~PGL'S>?s8 %`2Ga:ĭ`*@NN (sJOu֩.jp*AO!7&!p*[^*G3p,t3 q -Y C[)aWGpt` R~Q%mN-_1A!0n#=sseIK87=Qlb2F]8$Wu(bI([kAyJ57@4!hю'Er >FwQ Rs;3Hƾm ' FV #dK/a-BRJGJտVse9qu|~ul36ǀ~vVRR A,o_)%a%)*R[۲R/%3dio l n!?l+fVg|JV?~r\*i93A?Se}DZ(RAw&lfu- ܰ _`00b7u7cu`j B~}(Ow9 RTFq($x s#l ?rz)ԷHz/E;b QyCm?A!waQ:b%p R0!bD9@0q!`|7c,Nn1=)P4#0!$M@ CL5$4䆠A\ A#t-yNXHZ>,7t; HvN/kWQ-R1$aG1!f#F$bF'Jq]o>f-,fAbiI ()<IC%rQ1[2&XH,aÜaij^,}[íD"acrpqe# .b yS cq?@. "CY|c8?QBE©Ncyl覙4ӈ)8 j::ǡ;%W'ߊ'2[YLs+a5j*\Wio 8C?=$x0Na?ZGD5EXc1EndC $0 4T1JPY!; b`a\lm) EFX'~[M#\ɩ pA4[ Ĥf@ʛ@4> wrp2InCԳÂ㕍6w0 @*><_ ~!`7/7[/GKHx.qw _I|(Y@Q␔Ӷ=WHrYyRQ;˴-Oq@}~;!a Xu 9)ª?"()H4!(^sQ۰`a}| 崔p L l1GI+Au+y~?-`lWxxBV wytX~N|@Y@l#hL嗉( ~WB S#ጏk;o·\{w5:BwI@ć֎S/.ynSKd 8uPKK/g"uYLD®m)JxyO+fj$܇5,K`-)Ӥ8YЃ>|euZۯ>qW`'x;uq4輾 %፟IN`#)D},)eh  (4ZI-+11̆!==6,{Pޓ~óU *#9>.o1X~fpOu ߂My}):Pzhۭ uD?"+up ,?"Voail?jsA'3 }c~<Ԓ]n0 !pw;8 m98$Br}׎+)\(*W4}6M?dk\pY:/-3wcqw5tMee-0(18A{@i7/zz  ',:-;$'|5?RoDX) ]ǑAK@@ J:-CIY@`52FcЂd7A @]u 8AqpݹχNĨ2H:GD ^Uݍ1J|9ØpK[N=}5ɔ4| raNP(Ct}71˺,/o߻l,Z,Vv//|ø盌mtq1',Sx0ʆ,H*D :,4A|z/ JAǚv`3 ,0h!#Ih@`Op+s!Ɛnl2i:7 @rniq vFa RP! 0$"Je F]VZ n~a10YDԲ IIH(% 7Sbr@:07ēK*@W,uX4 0CA % a %w)<;vt+?Ҕ (4R!3#)z8&(frݲ6C w^ &ДKs,-L`|/XM()3LF?76 ; Ax9~re钁AbԻN10 I@ØwjH@0 (Hу:Ik _vِvЃ嵽qRAsliE疠<" H`@ǜn2]caf

NG˦dRsMnqsXy#ձ!',zLOz&"іO?E4ӀFwgS3Ѩ9ΘEQ8L7YWdrZSlA9px0%yÂ'1, ݇1pK,:?"()Ha!PēJɋGS8BrX''2XbT?fiHA[!!6[lvu'Cwn qHC,k5ФDK}XwW/BVn)b` DZʢ @ my䱹#Q)j=|PBփ$uF Hlr֨hBG`% T\mO($,['5CLƊH)v]FI#}53vyHõ>ʮ~ s*ߙ1Qڞx?Ҕ?0ŞUiٝ.HClAJFB4eLw$te;/3;[~W-Rgb:8;,18n~f=YQE!(dkvq*Nf xJp$+v `rޘYpZ+svpd i gu_ ̼=f2nB'j oK`͠9C`*6 ۳eisQJu&BhQb~zœ^c! cTDE幄Syw qp31¿$'f+=mdϓ*"vȦcVDTq "Dvrj d3E!&J-9;o[oUH 3f͢ nQ-߿;0C6޶hd]_%l/qR)cy ,W#ii!9@ rIhI5%Kl+(f;,o k M,9\ ' 9(dҿ)݂ۅq>ϻ|9_݇p(4x.-8U,b/9/|wcvPw?IH Aa4` (Rqh%$bqw찾 ~Q!72Էr3lq+q]$'␒I(ݰ[ I6ݔjDǝO<6Vy,1'|M,Q??Bi )ςz8þ}{ZQҜ1j*WvS5X;ugeͼc8gXuKvISP*?dݥ m$fte`0Q+tHGRN3$dӲӀx\ {/tbm] Xp J)}FͲJXcJp>pGŽS1݇(s 9g΍!m7' ξA`_NQM}֪lgtMb,RJbq-.1/S`>% 1T Y-QBX1<1# , r{f,Q,f R]rXZn}eaDZ4|-;˼f5V2:݂ŀtQ䏯B)2P+PЏ= 9,Ňɟ$ Kb ,%Vn"h;p F $4.ߕI%Kty'}sqZ XE@ux2ӇU W-Z@oh"6ٌbIffwGֳ35`jV2oyv!<|̥NS|fM.呐O$(20VCƟ0{F. M&b'aH-%w)99etv|bN@̓-y<ZF#‰A4ne+D>[0]e 0SZXù|l[=/e*,|KG%7[/ZQy|-zVXFoY؜2]{7?)3@7%Kp}6q5SqP.?E2,ƞgϙ|cm]NݻtrCnVnN[osa@j?"-4?Ҕd|7c.uqd=;'~Wb,gf}1Uld )$W7;'Ya+LϚ3$WHK=FL!9A7Co!)ۖ+~RGs]@ d:=$VG7'9=  e9?Y>=C9Ff8)n{78̕>[/ 4ԏݓN!#)*l J3`lj W%{c]dEmud İ,'9u K99We>p?RqJ$|Ӽؖƺ1FrK_{ێ8H8?Ҕސ4'[q)&8]cpc%k#asYWoO*TTBIo㭴J&dMO/#Pݸ xf}""%%Ɗ6%%B~ka cKҋ~{v1#q-9lԣ,DJD[ʰ8 GWEgyvW'3:$QBRd7>4Q:wϤ䠱E/_~>;E\H“dpKlPu6Œ,Wu p<䱂@1xuTԈ0bLnDB% w-yG5uBqHk*lnsM<;㏺-o?*~e;we3vZV10=Hׅ!ė_> aoBߜ|:bKR; 4VrLA|<n~)d7`ubRDEO ҹN@yvayPa(o%j  }K.KC, S>4 &pԠ&p 0gndv9jJxn{*0f79%tI4~ ,w(7VN{s֐S?~X /`s\,,r,:^ԥ=J͖'3)HR/0Š+,=K@4@gP(}@P_bTi?n[:D Ű߃xhm A$ }r Pa@')(%nt FNo(buF _#uc`jQ(i+q[T |΢<ېBp HؔC/nv _(M,1eMLr4 ҇J$p|3l"4LԖ wCn~ahu),J>A4,]'R/y;O7ZvGbz2rB_o! a'2z N;v>а (i)? %qI&yGg㕜S-Y|p_vWfN5nlk,`Ajd 8ĶSvTtMvwX [rKJySJh ( F%<1gVOs[mM1 Xbs@'&Cp8b@ɿe2RxB4q4Kl.C -jF0+Mi@_Q+3mt^n3v1$KKKX ,΁ PPL , ',D6N +J݆h V 3sP Cv&`kԤXnBFp2CRo@9Y<}6\CZOc?G?=;R9̣ߺ!g#)q=nq!N1;;/ ۑ]; [a|uYAG[_OvX4l1[jdP@1/nA ;&p%% u`J` `rYE촒܆JI(5 &D04# W? h@X'Tbo!'h 00`% 7 HADk +nM&0o?Dp57(y@X*?" rq2Fk7t;$7Qnh?ҔeʻejJ < v2)ƀL1-ۄ}ۭkA<<#0yMqu`w;8# C~Vf^;)rIIrwg= ựY&a/!&I-?K~ lPPK+ ^(9]%=B@p C?0XV4o#`.[:'H0|JDX3 `0x4p@PX8ьly9,S YIqM;Q\$,@9U)nOqlc;4W* $bǀAg@ic@lK! <)orn"VMlO>y2rWP?Vr6ދaTsȀ>F-2J#˜:4Z9GЈ6 ND3jR3Ns(fˣ'7ۚWXr@_GDnԵrhV  -]R; yNe aA3H"AeuyGo0 V%QٷiTwR'FGqgf8 |v]@ap% 7@}<4xK寄ݖ,cvaP@V~m,aXFƎOo)Z`K[)`Kc20 ӯ3b=ag9&ѫ?qĎU !dyx?ݺV 5t 7c+ER1 Z@hu@W ?)YYЇrJlHf8eO+}PG!!ᏔQrQ1?"Z[bȟJ)H)Hy!3HaO8 C /ۓ~@(2W:@YBsb v+wΣv;mlL}2);-K2dޅZ:\ϙ|m Y_q=TKJ >+[gG밠=0ϟx*>$&Ym;"IGx}G0<@|$r%)tjldtͥq25zӖArP@@Б IA W#P4$`gaCM4'jۻ)nhr(|vQ/>9$0χ29W3BFZw_MԜ7tǨ'.r:PGπH7tܒ01Xpa<;~N4$'!(J|' w|ﮈhԱ)IhAً3d&؎!e 5j1Yq+R߫'NGA@g䠖:8yIAh J7KۤR F)M=tY.WMlO O.:7QbHe#@5Ęm,JR"Ӹ ַvϺ\ {uat96Iw^ѯ' S,ǩ)loܞp<4 |eؓϰO?ap`$S\ cӛ}%9ߘi( dr%=J)'? I-J1n4n3SlNs^&[j{_f#m9j xPp\Μ!C9eݸq؞ c'u 㓭>۰_hcfka{ ^~dNr(o5czz?"&GpK$7 Q k[2lCqC2xKm)nǞpФ{HJ yg$}{lk)tl 3J79݌v~|YII]Ю+-Ě<@zX k` E OJ&[Ɔܡ(bqc(~RP&^w٬A#?8uR۲8!l3 #%F"3F`;gC5[v{,;w'yn },hZ:|9H%|H%2J*'eyq:AEbe JM%ak;>硹הu!Yئ1N'N%#-» %Im$is=WDx2휳o6gc`$_YєB B߻2/+!6]_?cti++ !=AM,jZ vS HjA( C,HA9AǨ̥YR0FΗad$čBĔa =[]5>j-nK,J<45gle] (BZpB#gtI&aԳa-H;&L(0^F: %JI@[j\bVQCS_CЈfj̾/0?"Ssքtf~,p7|B톄 I̒Y)' JRJ] ZPV))Ngms(ys9/JodsF%xlN:{~0J0e47qR>dXІQϽRmloVde!dldf$(7'Ϸ!pzL(,I"*Q`Sv.Y\bFۏi]9XUGERF!%k%%tSlˉh TiFd>-BT`"(]V%ܷ`!%3"ln\v-O`#ώ^q{pᄎ-ss2Xg$w];d^r֎ }u[?#tY\,,1@w's ;uXgPGXI*iE}:{\@ѡI3h(W_ SJ?+c^ C:~0V36my?Ç V BJợ~w H tR2?*iJG ݳ7[|s7ηcåxD]Ra0GB2v ,zvʃ F,ƇwR d#WWn(]ENj!eqχm0 dVW9F~OzfrY#p9(Y+ ie\_u'u­D{8 w^FBr$9{wme5q$8gH>&JI| IL0'$4!Ϸ0H4bz{ongEQnY@g,"Cyݱ۹f 5&o%t)DY %G@idaҷ xNbPBYK24G'sErB:7Nܾ0 HΖ@1 Kc7[˷^ ]d mf Z]K4;˲LF]d!vLJn+9mu@L7=G|!4;n-@ %5QGBX4ߒC05C^u)!&,Q'wC*ޅCǻpR<#-VNVP,؇UV$IHkt'f@̤仍$) `pҾIGЮ,%st;–6+!#)q6= SfE46*)`s-:,w;8L!4Z'% ۡPa )(ІHjCBS#%?!ܔFl7.aQhۆ_X@}`vp>:[u_1 `z\ōc,%WYv;8⟭݃bzD*A5 - `*<Et36 @~""` vS$   $k1DZ8\@dj9`?& /~rb8hk&AJpo^w)jOd,o .V, ZJRpgrH?Y;,)P>7%%wT9Ab̶JR"fgZ7fasP:Cq_SS$WWQnMr'e3Ζ7Plz|zХ'b:Ov~_;e#.\ݮ2KgJx!)̌duχg GLp]upay=)BÔx00܄L r@ (` TJ‘݀g/@:00$"A$ҤBQμ^h}07tX M01n B=n0z6 C@(%v,RJAH)ք};?p 1{$7a(vvs{]t O`B,  - `?8!|0Ykt3=4 JD@GH!4jJ=dƌXSs9l+O?KB;ːb%;|;Ax9yWd`0 nJ Bp03!=;cg=ǩtهٶ;ˉ%|xQ9Ɯ@c}5 Ax:Jl L C*Qt\c-pHd"Ye$W=(͘Ťh " @+-R$TQ-8wS|P jB @i 2*t$oI1l6$CV!; p,Œx o @h`j@,FS`nI,h I+׶.t4M!~ə=%)Ն\%ԂҔ-J}RJ p) @{p璔: hACCX0ԥ }( -dTtJD@D#?y;/}2>:Wz2\s0 {#6V͌viSn[,;t~!߳, BR (3Mg'|GnEӾ2G} ]PfZѶCh?Kp, lTRVĠ&X NX䔩gH)! #)v~:I EL!0$.M A $6p,3DĔBۆrJ /qy-MaXRX‰``zc:]DB))e!{ sgV<M0$Xn=e3Z3ܮ\XY]=Q@,^HHGBKGB8bMZ<Ӆ2a5my]\ˉE_ š8#qs2H19 MY^삱F;lv=TyVI+ # V [sx[ Vc,@tCqDx04Q| !eIAAa)N% RY# HČ`  7%﹋ƛ% $ nd L0o (3xo'-@P4[+LHk S-܆ܾ5cOqjr @CzI@ S% 咑8OV0Z2ꬁb> s$.pERy :vLpp%~Yew)8ВJ1;F Qq۟;XIPKg<p@:7BK/Ә+%ݓYyp9~J/I\n;٥CΈ,ɑx{BXZ?Ҕ '8Ԡf 22ndPNG`6E/,ssv^l'zBr1+278 Fo 17@*M\Qaae~:a4sz6p@o;ޢf<>!63x_oqxStEҀ._Ē'YJI$v$./ {|HBEa ͏ri %(5 !2 cFPN*i\|^ny8DrQhBBP),`7/mZ}vY="|zQ[p&/%FKx ɉ&9XY] L1}:f)HFyX}Cnn TPX8v6;e\cJR"Q4O)X\b勹$lFLIDeněLx8X\f4߻291n+ݳ|3qq3(<BbfEdC9;)LlWeՙI$rJ\4r^,j J X J1XВRIghƧ6ǃfe'~€߉RM|kHK>P|Y<9"XNAZXILKp0͒'Y'SIŏwy=U}bSOn5#|<ͭQW:2qJDYx1'v p5ӧ(;h ub7򔸤Ѩc(PFUZP`I`3/n/+:dtgƝ& GmϮ%.,P[U:N\]-G"+`.MXjSVO`f͚AD%`<|`Gqf.d4"=љ2%2~V[[";w[$1X.91)pa]Ơ[cvϔ,.ΗK+E+9 (X7V9lE.(<5A,}wm{F=̯ 7c=5Ə3v!Μ⢟'8pU u F؅ňa9Sys⮕Q|5 {w!&g#)o=!?~ ggsxƷݔvl9Bic-9\ 4I{:k5҆,$rî٧7`>pPgcAâ #xE3ñCfa_\t?GCͪNoV?n6^'|LvDe:lILe\ E'w|.we&f,X0 fj_ 3"3ԱàXl4 lagr:Ef(> '?RQsWj`7\ʔTv<~@T XP`hGV/,՛bၽxD$*Y   &%CǼ#3-H, f8K1lR pe&o"t:)L%41>ʜmYaf%>2 FP0cDoIo0s4Gp9#hP +IfI,bfsgf>%A}BCN/.pLu>$e8#pBc_7w3 T&a4 NJI;q)L!Ҭph(YO HP΁gJ2X?@nb0к?"'xB VD.@!(Y(N|+15sWm3`'ߌXqT PNv|糭, .٘M5퍜il=at FJ7tB1!Sْ{>vuks͜EYIFO(njj­ =G2Y0KX]/`0ĵ,!" G$A0|=4Ѭ8q(6 a>~~Vvw_rFJu؄/Q)G)JDL^rts WlyƏ>_=|3M`B/Ra4 A$>mNpEV 0H|`(, 0y1G읆%f'6p0esOТxZf0Ը!^YvAEhSc\}, ub̸_a ?݉m1lJDAD%ؔguV ~0L16Fd3X*dx_8j?}^}O"0THpJ?G}%C9lOea6_O?htcuSf5ַ-n[B󎦆|n [31}C ua;<Ƅ:Fa],gJ(ŖXl!g+ Nb[ !apbl!;p#-#+’_K06V,bJpݏVH:?81)Ks1x (p 97u0JdXЁі1#JR"-$$hxVw6eH,ܔYEϷqOGRRw''2v~1(K'__~|d!w~q!MX{0?Ҕb3?J(蕉It wwQE d"Q(Y4ieLؗoe ci5|^KJPtITġ;(EwǾ^)f)͛ls0QR/OKGxs:RFpI8%ꃏ)HJDQR4|7'HhJBxtѿ?KN҉ņ%J>J|*% 60T).DZ7ߌ Cו/, ~|S|r ];$jx 0wJR" VlXj6(@y!"+H+|dgt1b%C2G'WQ?d% ndd< %n vw,n (RC(w+D##*?nŽ)\Z%[dbU;kIPjlN1IJU|-j 0ijX[A37llcJ!! R08~G=c H_Ċ)֫LG8:wK\rsn_0X~HF+ cP85,s&, [#_POu7lj!bfC?"'նSgۈ``bPXjRMIx0`Fv|4'z6` :ZV Qb) n7~0M!] bx.c.ОZХ4,Oao϶7 ϻgq jg5ƋXAċWBFм=(Uɾ;} JOKPɏ)Ht)(Jt+ỹ#qD%'ogPGDVn#%c32Z@lX OOŧ-?o8ZKu,!y- Cmغq$ȵt2qĩo$}W48Y1#nn8ka(~N݅;˻bd[u(R5 GM SxP;!g9}O!'@ v(L@nlKwC9M O} |9$/YBIj=Ň@!(q,wLD PBs!33#)g-d^( |K@/HٺBRJGO;gVep-$)Nai;s1NJd}cIridQ}[ RXcb4A 3Tɸ[qVeld2Xc1XČAdCU ný &l79ǹ=XF,L4J)(z܉!c~G]?哒O4g0Hl͛9:|D0#8 956D=ILxg?8羸 a:Q) 41M&ɞ4 %8K; 9l4vg0%1j-&d&ОHpg%(4Kz3.0 ȆٗP$YXQ/?|&I@Q8aA/`^ı۫@\L` tptՂpiHAy @cР(^K!2a$Qn`ͷa Aiᄦeǜcʀ`_ T4 %pYD_qo;©i?ҔYeK၉J I5;(1V%!S,cLGevOO5 8ᴣs v$q 5#8C`ܶOYi8QՉΩJ֟(L-|.&A 4t94 p߅)R]U=vFL;# I <>(ϑ|+p$0]$,* 9AnrشJO%̮jJ3ۤY,gt? Xq9ۺS$/v;] V3ue|-c@<iXgthb_$bsu7 A,:oTy8:!#d T c{aI);;= 2h|S~ ``ĥOQ$1?f|ˉD a_ bzwe2oo!9#)DI}h ?0, JI}fHj7}\Z -iޝ( `X0 kJR"Rngt3^e(D˥geúKc~eֳ)Ep|"`A4H q~ۄ> $TL3 ;wzF$8T/b7,{P p K 5.Sl;! L-N7lMJDQR1(^yRdQU6Jl#2H9k4Ö@Ҵg`7I0R 1l,ڏ~[:;fiѧI@2­2b?gc1}4= D">E$ARJDDZ)LGJDR42rFqm䜳ed>jR/(-b\F6$ 1/QGNOƇZ( 7Hb9cK,4Yea)h&PCIGVPM-Ca"BaR*r ,HhnJĤ `@ƤFƦcj?"!>ϹrJu =؏UXCneqc$1fA=wC)kcA|5Ꮁ+I<Q̆`%7H(Hޡa : IlK-b*I~ªQ?s[X.;`s Amsc?6Hp)G9Q;Z@|XU{X`g%*)HQ>Y@bˊ& syqTjm-"(+#?߉f-~?@a7) %rQmK-]8O tJDAcJR"o'q] Ԥj⏵W0VatS 9:(ê: _9oUoZ:Dvw:EvfOz@ ^8hs@+#3}jż@xxO[l!(jۗoۤf!=y9y>(4(@o>sH͠{rB26BmAld*vY Ƕ2 /횊H! Ona3O%i(X$G5wnDz2yԶ͜W|sc>>8h3 xУvHkpa?~}3)E~/`aY_ N G}Υɢ7JHKΥu󲏙cP!Ck?5F+KX1%o`[FX!Ԛ@%M %'J2r?ı(x:>5-K氩_mD~{pFcC$zNNF_CQ+\U1 l25)K/OǓp)mS/d$CVQn~V̴ FTب)FbbJ|{V$ Oؐ,&cHV$3wnOT2lj=}nyDSǶ  `=ØXW%3#EpzZ\k7|3 nSǘ"O FpjZ RƩxKK쮙ZՖ* e] <8A%-h_%/Q^3kMu8={yk8S4Xlzc)[E) ^H% q yUXԍ &: oPqiʀL2JACdm@:07`iDһJZۓpؼt$$'taܤfvؒ1;Xh3 FT9~/ls;۰e,<TB(j 80CQl;mveK+u,sj1xyږ ]Џ+;sVv_~>Vj ~ttD a5tm?3;vݭ># #3HıdG^xqHHՒ0 w,a)p@__f]ѡ gí0 ԠUN8k7'@0X@ON4')[ fI5B NJP4.0Sպ)H$u$,ah)#Y|>@ /8%0@?h[NБhNp7ƭP sEtn3=' JoIE,Ual&?-]:y} !!FF~O\VBT2]K2KͲdd_Wę!=gs-(>XNRgK6akݖlu,1ZNPƍ\p ɸ8 8$|?03I17vO|EIE|/@03HWCet!1 Z Qa%`ACwwIɑ00 `7vR"8#m+#>Wp"o>h3刣]â T5uBGHw"@.59; 7+ Fw .ؒ0h1K$BA cuNφƵ .cbY?z?")f65XbBx,ٟuIHYy9ebsqJ2Vr@xA>B;Lc!3&0b\j[$9zW9&/ibA7p>TxhA@b7(## X3 7øQT\BЗ440a$Y$1yl^ > NC:Ď+B @ (n7uE  e U;1+ /J7W<䍏;ѻː0c0/ S^n3k|Nfgն U]} $c4m콣>-;k nD=9pSx%sosZFa `=sEŴMuvnwo8hQ<WAyMzkuBM haX%et JR5^M ( bb`MO!nIx#=C( 5LηNYpL!)NIe(*G,oN4'& 4ier(%`!L̀#)1e,a/ rL &i`7)),$cPQ;p1gd *3pEaя)HY^?"- [ S`sIj$x+|;q:؜@[`8vVbeZws.lt[@U},8sQ 3A` @+-(3bMI]d`~^e/*,WZphc+=!7ec@`PE+?ղ 01~'t((Y4a e"`%''!(-ܬov߯3i`JR"ʈq@|EOѣ_am#bmtxՖ|ci|ZcL p0!Ck8 캃 `?%$ҝc?=P(K K(45K)$1Fc*`; !mN~~*Ƿ9:ɏvM,3FJ@n_X-Nw~G C&0Nؗ%ѸĨ e~6_ H:sԲB}$8a 渎Xz(XiǞ.Mf Xbo BI%%LXO~nrs( )K({[GNxa0A`QI<[$##gɉ1#q5PԆyNl2"t`$A!#@ ; ,aD Aa%tlى=Y$^&e)8i´1he2EVb4TtBNX\MNNW!0n ؆> 2ɠU@ QaU d0T=ybvsD/k:Sh'6))NfZądQXI%)x @`p&ư.€(5%YI%04j kJVԾI.5lbpHlo?{nrTys,R:m6S;'gm= (#$)]lk|laA7^exP(?ҔPPl(b_}pU @:@ ? \71dY,hD#*VTpGV|_ fԤ@-1!Vo ; #JAx[Iðs*8} K@xa?x^9²Vt6& E$7'5j\i8Pv~7#2ICQn9WBBKA'nìb$}[z?" E|_ϳ$%_n>IASK^~ac[ѡL=b~P`op祄?ҔhRFR#m֢H_ ^ga_ 0S,"lEpLcGH0G\IeHJn”t,եҏѱWnDA& 0 LBP AHB_I#@P  7t]Bkt3@W#9l|BC KfVeӅrLbƧ9!#H67tnț{o 8\%ME(:"3n[F© ZiiɐBTd}X{H%(P;G|O)AGQ+:j xͷWg)9jdd'±kq> boC@eAGD?hi=5Sqs5/6f({p(7RKt1[) bFSF3VSfy_\vE*D|h jBjv'֏D} ^Y&Tѓ!S3#)vLJV%#21 3N7O=s3MGj\zN8ȋ% np֖lSijo/oA]R2CǬ3̰&/~% ,sd)[zި%1j9{*|A?5h'Ceޯ؃8 >7q s1vڜ{ $q#E8,OR\`C8cWaABCSR^-.q# Cm,'JV0b}g%fOs#:PhL}bAC=3UE !Ma+9lz¸Cs|<âorz#;#gI[?  3 Q)mmy9O?"./we'3q]tC@C3t|ExkoW/CÝwgC]{n4!kwC.e٫#Pxtccl:03:TΑsxY 2!~HaF מE# Q'a69=0{R݅~8I?`-?NP9-MǹƺCX< P|y> 78RwG'~}%ݺ>|uOO ؂(u @&WG|7I[t ,ZqYEo~AY_LUmyt:bHs{{yK1[n#Tֳ<8u7+e i~v! 9祌c>F/ cHsGJR"^Y")-ДGOVBm#`%PMA M+ 5ax+/0FVFVͶmmϗ#!Y#)HainNs?|fygbB ?R_;RFrP2g-0rpO!#Se pOpq1sa!Bo9<7NdHz0Q$ȋW>}v__-BVW~4b7r^Sm  Re=BS²}BHh#P7a cִvXKe-BD fu! e}]T+pe48tn@ A 0Y h`,{ p&kZ0y}j ( !Ðll!AK+ GK,j1)`GRKY!2wal $|7d5jP} 5=^;  7腅v;Gr B:F! #g, jy?# 010̧|!{Q00401K!#bF %ldIae`Ӑch9rx*gf !1@lvZ,ot-[ v+|'^e:& XЃε-cpS(CR\<;y³;|krЃ% )Ŕ^BQ G^}VBEo8f-SnB5J$f_6 C~b۫ZV%$j9L5ȍXK `݆+MYrzzFo?'H @iE'~W[rB[%v6)!jsZ|Is,ź$k1BvZ{/`f?-)m-n+*ѲG=hI\),ur+2x݂dNS?Ťỡ:t0bK[! "4(Bw䄌 B )p͛IH;H8SNJ [5 .)N,?S|hA), { o5>*>Z_f#l:jݘϖĞ3=A;}g1gcw?FV%Y7 &d=@aAr)e fj%sL+_J_~(Z߇FrE,T(YW./FsxѨ}$e/0bF8qTRrE)l)ff)j4sq$po 4R׃9yscA{1Ž8hSt $+E`)W̄P†y/tٱ+xE{,!٤t#zJf ɀ7P3N)zn1Z`l/$)d~} 6%'ȗG|?_H%8s;d# ݗw@ @pblB.G+hNnk +np2U tM!$Ē6,-( qCr9Df!lwm[<Ϳ@ (H`b0bp.N^p%אg-@41)/b9\ѐG8w%+o̎X bo&i? @<; -]$1#F{b(3u!`#) N0 9=FYF`6p XyE k@7P "66j'_߉o6Z5 uutƿ;M{C'aqD3Y E.3E|nr̠+Ә ?~dv cTp @i rjJr`ѻۭES ,X^%ƄPagJR:@PZ Xh҆mJG$akkU?#tV2x?"()_mb 0P"a4X4^ܢ Wi}j}U\ܔv}>Íʴ804ul<>bK 31){cU#K;6)q0J#Gv;!)Œ8Uu0u-8 l ФEtc2++*)JRll33fQYcA1ŋSe q98%F+km,?*ޏ@jun %~3! ɥ`,, !fg#)17;8 $d`Tm;-AIRq0_#/7 n[x62[O&Cხ_#_gu1wb,N'8Hxafams0 g$bWƳJd?_T!XG]{P̺N:{$l1LG`̷ ۝ Àn4je=h3yBYt 0V,%k(k'Q%{ŰhFI՞I]([15M28 bi jSp(h!р$ąl+(-cY9Fr0K`$ qbrJMy dq$0PGm4jcpy01#- ;v?&ᜮ4f/ GNfA e` 1f&nl?}QlqStyzٔl PH}8Ex# +wdvX*K[eJyl=a _3f[_w ;-16 T#9Z 1ŰPРQ;ܝXZv=Ž>ϥzvPն汆^BԄCFfXHt;|w.|X̞/>-?l! *+s0H%F7͉H'DW clp$NٞRrDU4[}l\HCa.JB@z1OMb~%,xg⟅VUǝɅ#Hqx>.[ZPz:h5(t ?8ٙGb=N*UJ!rC1s1Zrk20(='rqmA0/lULn Ŗ1p ćN@2)_2 *ad OJLNe{NyB 8s_Yaf9t-HXAlt(xKD?}ٳq#3ƪO%6E@c,:9J> ghdu<JDA_μxXk9{\q<PwaoC{Јi-#u7l9yHCw!l̀#)z?#lHnsO["FtL-i|Yh-rPcf̌O%*w &R߳_gOD`o ,Ŗ,c!?bĤ d BV?œ=b#O@WWHc|3:ݹ;-=ҤgFJxe]T_P7o,X5h0sX]P fsT)DO?U< ׹x{ߖ87ÉΡߨ`)Gn++#8sdIyg=@>XnhO@ī#1.5Yn`[[ 1y)J$p1[] XK #[r J4m#Π-8Z95/F!^Bu38KJY:=P{'u  XW64*^V+v<{ҎZCXKI=(;sw˻ dlmltS[ KC8'vO^̌cCtov F:8NfPf 9W@c^ݜĠ)%|% ;!?hzqF=k)ﵜr՗ۥXooH$zpay7jv% 2 ~>(wrCsF泪9Y\'`JĴ8]IIwa5s5'&Qa,|7fw{C:mV#taYXv5wKfI,-$9Oϳvb1čX )xX"l y{M^: _98@! nv|+C)ÿ?wܜdd,5'8Hq[aRePGe!9̅}7a9Hy|:pwzPi i3*/<<w2^;^ifݔo@30ŏS|y.'oN|rw^~{Ѯw@,G;_l?OvÏl;g=ßha#J>J>|^=떄Z[E) X{ g76d$k8; h1U8l3HB $jw"b4΃cD~pàvej-f7!s3#);2уWCK$̂fAeЌBFvB~O1{glZ7BRH@d=? %`yP$[Nrw娔䥿~0o R3lf q_nw73btsf \h FHű3ĢFZNYU `>BRo1Bŝli[W(zEZK 9 g%7%p-[ ~@GI%y{N9tX;1)9 +-8gu3$!(d P{EbPJ1C?F+3F),_f1xWn ONWvepI J Ƕ}ݳ쑝+=d_c5㓲p'q8愖0ߐ%aF%Irݖqbے }м;Ӝ#wvn'uŋ Ͼ|z\ f0VvZ2Fr8İ |+i[psזc!D ¤\BKܾ_Ӱq3r~3p69]n{aj&B^5fm!ܵ2z: [H-OΟ?#_Ф!.WݾJ<-.'0+ F^H,=`8qLT$ӌ{|a@f̣1cӰ;IN3Ayg'7\#*g;,ЉQR;ainn8H\Ct+2 B )ՏO.6^qp:DzNH)?JI@* 8Sl!fh1lö_>괓3 `n#?`@*P_! Ġ[Ԓ奊AYaeFNBFۡO$q_s۞rG(ũK_&G?nr2B2! 9,x1Bw 6d%sq-~{ X|KҔ <+݄y䢂+ ct3%$zS<9gݜ^h 9jlm0Đn-0$f' HihAh;W%8t99 ōRB39OPQBHGIfȖgɾO_rl 5"OYZ|:đ.aKŹ8<*3:1fƟO&=c堔}s㛫4!b\í-ƅ7;F0~;uZ I_Ϗ^}{T3d8a$7 +d;8I5!Fkh0ac9O%Ͱ@qY—،Fd2rVcȳЋA949g 2򉧜N # I~1HҔ쾃pH"@VN"4_K! Kp %Klnb ZWaH%rIAkIi|,X@ 1 )vKΩ +%spͺ yT-0 q>:6D$MglGh> bt*➬``Ė ZQF( !) ̌ ߺxOLp@~d0>t $ 9vpv?w_="A ㈫"_G up7%̀uPb9a_iMt/r5vDa?Lp%d0g7r\S;wxaQAzA41!1G!y#)&VA$~M|^m G 1 yL$n Ε?Q偕A @SWh!>8فL*KSV 7k8.F\Id%enœ|gG|g+gڎXh0Kov)YӝwCKHb;ƹcP13bK񤳰Ї dJ,ZC1kG-o'?CQNϟSo[Ĵd g?;alzfoK~yl~l3|Εmc4;tۀ6R!=;=MZxr"t H2h+c/ ( #Є,,vuhP_nT@ʔ49}~} })ֳt9BH9}Cր?zyj"NO4uR(Kck5vo=S]1‰E{1h-\-l݌W_NuHqћNe/3W.`R0abG()[8sp4ɄsieAZ[(XJa឵԰6G JR"I!R?4SQZ4$HΔ8GшF '(I]OGQ{qH- Y_X[vb?ߒRԂB3!#m1>I!_wr)͆OͲܑ|bJ/3@t@ `Q#M^+_[02A* ( H h@!)]:ߒ>N Գb3u<~ւ5l-Oqjyۡ1? ^l` )%6wI(gΕ)=@ nBH(nXM,b@`M+e'4tay y-$$@vM$5"̂gIEPDҒHq{lI0hElv`P"#f;6@:%=my∢`x$V( 7NYk;&Nº*3  (80۳bzBYѻ$nnû'Mu\ZN7u5V|J8>m 'mhG kj]*@a繘vV% (J@([ {ng1 ql|8d@U3aG)JDCy?7'1im&rv$ϝQ8׶> ʹ0$K,ĥ4!#)ÛcяJҽ7d8ڠk󰤟_,$,y`Fq!\n:9O((]aiB908NWWհp`&wSQQ7v;[(tumjwBsǟ'H@m딏 +t>~i=7@އ ۻ~%W2ҶZb{`:mFyM*L9lxt!Hb+ɼYHo6?~g@؆Y o (S,{"Æsí Y۠qԀIIbILܼ/\7;IL' K@QF7JMO8A6gellzX +,Q+ %|xAy+]Bᔳ3NvlGTێC텿^E x|Öxя1;`kUƛZ zS={+r䠔g?)l:Žw=jZ8b^aՉ/a]!Ft%?;-c'ωCsshf: OIBPG%)Qe n?Ҕ?Y|dPŔ1 <0(o[jXXVf_PkgDsCNk$yoW (ߠۍ~1.$T(&ǔA3n[;)#0R_32pQc:ۻd,nN?DqϘW, X3ps ZF`O\.\?WPǍ:81C v;vV1̳$jW%>.F7pygZ D\۞[l@KnvP-bhDzHQ& pQy)8j>% F_S-ǎRB,5NNn{sUxaWJаы~;% GHjRRV1I qM$BymC \nXGwA 0]񏗼c~%GiCgoή~xXK8S\P]assH͑ b6'RmŒY?a mo7wFu'ݗIφ~5<,xf7ALhJS5  $7aφft fϒ3 ϲ~sbnq:侂Wm%gqc] ѰNHt'gt6?":1й.ogW =ABsf"4;k 4~<^`!g#)}gl4@;Sdxv0&eǯfjǓ-vpH`=tD]ߑXY8Ly zꐔ98Q s;?rx.~!{֤ Ք#kByoy(>pNWaM=If@P\4hp% 0hHa T2~KH,3V}d>ݤ++eÑ:ScEHBF:;'[(l>]`I]K>:'w5O9u 8Y}R @@xy?"'a4QIRF_>Tg<>FG%Zœ69t73ۜoٌZFN>>yPe^ېoWǘ(zcc:ԣ gwMsQ-Ğk[ 1]߄sYGvY `-Yjˁl144@`Cv@t@5$4aarh` A/[qw#'ARPb )òk͏B*+Em}(9ϜC:Scd PCodbx 7:{K;; ncŞ">hÃ{u:O5޽U,uo'9Σ;hVέ[++k1a4 j{'aAVb w^XO=w "̂8px68nΎWaߡ=;~n~w$ۚHK}$|nw흷Fs[tyS1%]p=  1b7Qߣǡ*bnjؙkkJy c]kvue90#ZoagAҐv-;LqN2Xe՜N˜֣ |Nb1gmjm)WN-`<a HHB !)G)^\"()[ߨ8-)(ݻùh<^ lm@CJc ~a:qXJٖaatD[ i8YR/)bamo Bp򓒀]BfkOpI{ej؋c<E &bL^(`߁5cґЄd+~d7JߙMu¯/vliA0lr{-0ƒ8]НW̐ pN-pfDeah~v^xA|:)^l-6V5'N1 ;g~8J@BqdGh%|!̀#)PZb>1y$E#$ҍ/O]Ԥkc[?$C$9yKQcFόOǁH0|g : `F8?r_cm.4z++6m R"6^1!47dWZQ䱧r@m4j]Bbm1g­}Ԡ܁O&f/mۀv2%:0Y9g4R߬.fqv`-kl.% p= RnۅHtKb!c Ya>{ BJKAqXL &Dߎe< S^[ (5 t F @NԆ`[qeh Ihܘ), :ٰeajT2KF{ R"Rf/ĭΰ0>5ǀc0s.XEc>1߿Vg08,Q 0ЁndXԎ@FHKl7#$HΝ?)#K[@b ut,Snis)%֝5cd`Cl'e{z= < $ @ܗ+(j{e 0JRY@-%ۖ0 rKN|ܬ́(3q#[l&LAC9T2ΤP@. glϾ:S`g0ɁI7ؖ[bJFd o?6m%ы+BrrQG|g:trVe(q(8l!j5v^Go8uĖ֖sOB+;ecs} r~`~~*iXZ'+v}ێ|.Eٕ7%XH \@[ːJG_(o@dlF;h]*Pe(7$[$hp?E+A3I,Q,PP~ @;IJa,'d~K; &l̄)?_=C,d,V+:r<{|<Ϲبg&?"()H3^^{hA: & % -pam=D-fW~ sDG’Z1KgRc:TMQℎApia:n{u 6r-fqic@ ~~B@>( C fI+_Z,a8z̟'1)tv¼TP*i,LA|Y| آ`^II ][fIX I8LL%BC >r0Zm 'YcS0,7D^|gPZ:xEM &In$4y1S^qc)ޤv{++: ZqFq[8[g"8| q$h( `Ґ^|Z1h(^p5PMHa:u0f2e #%jl33'eHCI+ⲳ̨>XԠ-A( 8O,)l#)%rJ0pIkRa=Ü'S`E|`-1c_ PXZ7{R6p~#ˎI HP0s[-aBv{hN1bpEGң^x?Ҕrǫ`r nhp7Ѳz K~u,wOI<;w ~(3NKn3;).q -y4.Mѝ N|܍PB& ϔ?ٰmhJQS} %dNKµa _t,n- /P#a[de8V#C/q'ulUՎqZYP+70Yaq50_X-4'`Fٷ`*ŏ elGUcw-|j&H{Wnn۟' "K;JR" R 2w!݆f#5y>uS^}T~$9zcb%^p{>,1*;n-۶4cϏ3:LC3g9^\nϝIH ʂ~Y/ `ns0%8.0{ 1 HI$c!cW 9l!JδO|IIB @sǸQb!ps2wU,1N[}HRKK1(pv;9X7 @v"ޝ-|C! (g3wJl0zv+PKjJ%(AjXb\%'G!7ea54PYHe6#l>Hsd6KƯmj|vG8ݯ!#)S|r% :F߾e`߿lde2fwi~k㕛(f؞q8Ыe90=]): \h̓NO-gRTgP;9cp<!oIS%i1: rByIHt'tt8԰(Sa u&?QxGsX='uS*?b dHQ#݌ e nz,a?hE/PZ9  Al8HbqaJ9Jr9LPD@bajo~𩺏 p?!\(:.,x}d,Rc74̾(7!E?drA#I2ƬR÷ZK'ou*IJ\RņrRF|)!7'=tY.#pK<)C܈Pp/:۝}6l?mõcrg|䩒0I~,al$bP7;$9Ltwu}1x?)@7`lK%ohଝ-iEcsQ ,: YIQG7+2O9p X!D; vbIY8St֌[vYKS `muB ̍==_L & 4`JKi#"kBK|eRWcN6ncCO~v.u냌f8;eaO²V{?#w }=C{wu68 ]@s[ N#/ _t0pQ+mB6ߧch &J@(ӃR,F3mI/ #Ka<[.NȃS(?Ҕr)&sTO"b4Pb/%CԜGH1C?ftP p?-]'Ru?K(K)i5BDzpHUH1kD@ 0x)-ewI䀀!RCs Vݙ9iG{L;ӴC Bp I!004MZC%T3:Xi/L1x=ƑM?ҔfryI`Y!}fwr{E kk4S ,Մq#>G;S"+).́(J~C #(H·++n 7Ě(pZt =l+ aI$M!P`yK͙`%F@}A ?o\PM VdPIt_"U 2d*rY 5X Btp\7@€,@#PQȇ(tlaa)fвu8$KC,4`K+|7!ز"~ɑE$ X , e4'ᇎ枡Afqly/> e^vQcg8:'V@u [.M7ΒX 3}9{Qۮn`M@Q A'qrhрAdjP`)=ƌe!g#)= vV0 H@Q4$!K@BXbОo3X-A8hPH|8Hsi\SEB~BF:bf7jX%l,e2Xvg:#v͗?Ή'(iTOW|9B#`(Z3ՆAx-ƒâ,0CQ~Bx IE&ue@;| 8Er v,iJS+-*Ϡy0.`(Q1$>CA 0#+@ 2K0Ōtp'bT߯¼M%S6j eOR:Q/sr74cÞ bxnIYGư{7ٔ{֙g'R nXݲ 7bJҦԤKBP4䣝ït?흔<[Ig1)2'@E VۥBooϥd2nܞ d8 _A}ӓf6CAx40 weBz-@ (3d/IQ) Y;:Fa@D$4%o7#/j[  fX(-(bQZ:14aLNC7pϟ@SXe9XLf7؝<vY]P2(C!1)!#L[$2ꯋY?eF< 䴤bJؠԒ0WH6hicjs9|3'ѷJ{%qaIڏWnrD00Ē6f._;^`:!PYEgKwo}wn`ZN 48Cl3v֞!sv?]@elZQegmIǝ@ VΞ{9nܡ0T`}JllR۱)G)JDZ~LM!pԆrXjd+-_ ,z?j3)-P8 R"tIǮO'f"?5 ORp1!(V"@R 8%Jg% eJԀoj8LXr7tyqےrt^պ]Rh/E6J˶bNoRy%V0(Ȑ~QCF~J?")\/sC,CA/}7n7xye;,: g7l30I+l_X{Pu>J+lT=}u"5'd%q8JM2,ImGoG†;>O0^LZ?iԡ_n20@d(5 0! )7vZk wဆ 5R8«D<P5 CZW a NP_j` &!JcOAR“ UɅrPK1h\[SG)(nKa \)b%d! ;q|L9Ph;2?̦=4'Y49m| 6X)G)l:&:JHq!_ pX.MB> AHfzrPi%k 'j(tsblsKKOR$d;:0vF*FLp)[@zà Ćk@Kx! -*Q[ϋێcN.!̀#)hfaE 8xh?Ҕau2tqVD-߈3sAGDg٫({P`g%QDT X79q<Har=ø\@9Dt\3YӔiʎ/yoMy@9cyjZ/<JDA9CoNjZRﲀ `ak%9;`&(bt~37XC(1 @@`2` % % $00h4h?Ҕ9@n!tȠ*?u& .4xHY:n3?uPW7ZE|7(b9[ vKQiXq›#Y^lmLR??" W3QS^^>؉m3шvۤ!@d_ Mt,a6O*KrRqrEL|x W^J3v$Fu;98]ŒSutt2[;9Q-s7bF%_Xj9ΎgH0{0Hmᤜ1h|w$A`> ˢxZsG"@IL% ϋ̕=qxs |K ~5)XEWIsÏkh͖p[ޛ%vG Qa _vH3p4j~b!#R;`Yѧ0NYƊ; }\ W~Ƅ !Sw:Ԥ;bmLWݾwv;u: IF瓻= cͿJ N^.:K(,? ,pc19BLh( O HoھuXf];w'Ni&$:F̤?$a!ZN1_8MiߏgwS1.ߍJ{fhhԁ&a?XX:e;<W9],9ϾlVR6O}ЀT@b<̄nKgK|5jqY`s\ H$lk!(w Y__nRq,aLKG_I↣%''vy@M i@O?drKm>YV~ G|/c+6/jgs!JDR[;喀e>YhFa t%(a!#C7"^@yB_>dtz708hQDRHO#CYKTTIl5=cRIty>|8^k8I9@h~]_2r &-El9l&]2QI%'$CuS,ٝ^F}7G** ꬆO[ f=Y~[ pYJD=߇em3el+ &DKl -M3;;fٔG6Wv$|6fPq'=S?{#g?Gg\,Djl؍^wRP!;|r3 OB7J/4 ' ,!3#)nP.ح/ St7ɰbHc3pvjeNpбWji٠ Rp$J6,$l3/nO=Ex,~4sS8fBeaΒl~3mmcDNXݝ%%z3HU%X Gݾlс('}oKѸa>^|2!_?Tr;,'7O0q?1`%rBP7l= BFY]@TxG}X ltwf'6<+xjpnݒ-L0U,S`Y펭l7bBI5 SjO임4g癈ı1Dw9cC#.K4Y6@0}#-pq)=._eWR"z!R$8ac~Nb%n3 tiV98#chNB`CF*ߺVĎՁHē"[g>UKQll)j Vh%6L2obv~5Vn$8h͆.H~5(;$j:۰vv)n(gq] ٓO2;/;SPd4N(kc;|s c@Àa,Q(II^Xi,/f^A32]f S-+| {9X87Җ70c8wgΐEY4R߱?10.[;mV lm?Ҕ$ "p>^#PII%30rTMˠ"۷<lؓҴu#1[BoJ]>Tp_?(bb'{+Bw>Ak"v± v3$kp0! 7!%bfO%(q#oź6좊f/=fG Xo,6s8A# lMJw|Q0Ӕ1D}}w\L(HͰOcRxm̠ml?nWًlpT#G8Fږ^/,Z H|9OevNbPԿԇ!l:4ӻqJ܍[1-Ĺǘq/=V|>UvR!#)|O_պԦl8T"/1 F8s,]-S@F,$0X<4lBR@^N0o IPc~/m L,Q0ZTv %FbZxH݋ wCKy1lOCvC8ՍlPa\dی@G%8 BR E(i,"V K!)-V0H@aB I>>8::m s0,11, .C*4Qǀ){b25vO,gk^Q{ERv [ƒοݏә PJ.p;b- *JQ9(CgY$+r@y4r2"1=nV8iƹ9gG[{#:!D%Ktq5 I' Y0pBw ϐHJP5djb̴=%dr^9 ē OKc &d?y#:!1/~@( fҬh`n&C_0ttIB|Kgdͧb4䔤ԌF_J-8IiBeJR"U.fnpS$$9Uܬ7+Fyu ~W*I`@ Cw%8H1_>Z+< x̴ @AX `,l.3S[wK+;w:2: vVI䅧|sve`Y2ќ9 [ɫܔ//exd;#/ Hw$1)@;=;oӠ1ZDᯒ^paHI['ct3R=bDP4JK2Y,L,X`I-?s#?D2`aE -`_d Nt2*ԓI\hFCY2џ=a%sua @wRYH0`항aBje!#i"tV%K\cƨΦwiYOFx+JS9;tooҠdJv}5K%p055յF$ +& t,7[)YcbЂ lM gl^$$# +Zc Z9C7$(@rQYYiq;qh @tK ,PjP4Z7W,05G ̖-#HW2@9(%bF摲rNٔGD-=(Yܔ GGu:e߅#BÔsUWw^^Zv{u;8?ݔ[ aZv흇sB6̈?Ҕ zsG"A vQ <0X+/o~Ǩ@q(;#Xߎ`L~4`'i7`07 v@iŸ@'Y5%( trI*̻5m)+畫[e`AB@wfk$*ּgspĜhĿR:%IAF)O-rTČ G偀X,aOY:ؔ5*cǿ ~SYRS}'7I+DVc@xfYX"JA'Dj?"#,*RkJ yDdY(F!itJN^}G7ٶ8avh2?hԺφߍ; ]<!Rar[17bQ1HKԇԑh/+JID0NsGGy)-)%?):'!#)vHN)$tċh%d| c)v֘3$V RM7jہeHWrRQߟx7`;!in7&suDџ#ƤR]HZ R[Q, ֓X9rN>2?" Yrsԑa.-:B>xS$ qIaI )ۜ&PVǏ顕.I9ʹp-#s5 χļV研{ 9 03} `KYD=l=\rG>yi(19$X x'$yL?:۷`;Gj^3Il1L$~kVmvʑ}݇@ @\@dP!/%`E5D" [[/YNui%eq4믈C>Jr d޹u-X,C@P4& ax?Ҕ(h,^Bs%>7Qf)ra,ƨb !/6L;fs;!A6pՙ!#MY=rĀIX 7 IҋS:JHA.Adi|J;v8fkvTvAi)frノS[Ұ:D :8uVt}>CJR"!) s`MF5k0.tF!GxәS{73kvyd'c!! ';Qcdr N3-;rO)7=#tgRq6;I{P`pw;.0Kqp$I%=uC_ؽAJ;{#)c8, {GHJնє3 tjh!g#):V1, S())NY3b8۶ e[:._FN yU$N|CZA3$q ŒJ?;f)#` 7``E ;4ߎ9\n{}Ʒg%>Qrqh8JIXWozV1a\nؔqf?".]|w|d" <9bLx GDP;QSY)T&PWHlmODcĝ|@6=c[\_)ƬvdJA(?K?XvǗ,̃V+uqIWx , nA_,`*LC22^lgf{:Tv׌"!HPPY Zِx#[3_3̠GiBrvN;2Tz;l(5C яP8ATD`T # @^0(ՆvPMW|?Nf@y?yH .Ζ$ 0N4'+K_wǞw|?jX 0F83#mVOo<8Xv~2&Hjѫ8FZ؍Ď>߇RՖ^ޖ/` 4)"2Ol_RgOfSʣ@#w?>c{o:{3:Ea~pO֍2 S̐JaTmc?dg⑰bA^PDJ3{؞h + P? H$^<@~ $R@V{ By,|5{u3xnJ޺Q77˿Y/K}%H}uyoiy(b\F/GrZ Y n\rаs~': H:NQh1ÇacVM3 ?ɱ[(rP[66 6+KZzRΒm{?}؋}: HrQpwz3̇lIߩݳ_v| _Gݎ?1K:5RZ)|0y[̶϶g. 7-eMX1)r)p1?P ΔRIy9U$oG&8Y :I8 +cn[1Cx0/g❻ n"Cw;(Wp~ud;XrCvJXbQ=EZ:XS>KG;np:¾9Fs^}y[6죅B17۟ZDR#Kf5Xj_c̑ ֧sbJ,c(VBw8 u.l pua) $`m&,Lg`ea?ArwЂ'`;Rgo#/rCCC`0ƀH_A(d{J܀&ڃ8V7`p3 9mͲrI}GeQ;>jZ~G$v|Ğn;X^cC Sp2K̊(Q| ᅷq$rquuCwur?̾#1j𫽉&`ͰB @Fe*B3CBz&'OutK)BěNʈ.1;jF3~6v3;$"rS`,cť)SOBGB'IN;߫+>~#ä?".SFrs|~|ۺ6X4 % ,&s &3)N쳢 7)N.vf}A1pIhKg c[Ep(n!lr2QHV vP(AR"_7OsHUp;x#;23|nuIZ0gxk7xR䲋W; , %PYk?!ƒ(_ua:@`[bK~ nM%DLQ )@a 4 >@0kJ% c E6 S~PЃؔ?*k` X uh2OU6؋~h Nۏ?V34lB,N2_XV,@/ >R:I_ $ p tKJ䫡Y(X~v> 0$j!3-k1?hqaY (`Hu}ͤQDo~߲՟lhF[.0߀ 7c7(!DQ߄@O}bUnHP3o [1# HfA\?t O%S!݆d2?(JAeRM `|38057K0H_Y1(2`3A)(QdPD.:a|J, dae04ݤ;jmP4n,|Q45 +?mҟzJR" XLXD&e'3q:Y؊<ȟ"' /h]@+E: ,PSmaeĠr8OC #urx·Txb3p C@J%  CI4ؖWtJl@@iH /BU))#R'Q&! |: P /I8G JR"ܲtZelD~Ӗq%At0LA7 -Ԕe''-s+Z=wNQod a߇Atp&LRs9bJkCیs cQd $IW2]8%R9~ݏN $~@rÎ6|ᇙgw~Y Np}$cJR"#*?"&dR<'ۧ$gVdJ|4P' C֏yk|PNH*W߀Dـ󣐉/bKö_0a>YC6%edcx nOfq~(N7 n5N3d/=Ғc gFP{Μx#os4RBYLQƝmـGDSqKqBoGNţ: Cg9~xxšGFNb3\l. 6^XN lJ;&ǚD"vpw2NR1@2 @!3#)@{Zĝӹv9+?J)%$bQԽŝE{K xH?C;na7ܔHKB$\c8ЁD`Ç2̬*JG۰OTP8FPrRILe$*jín#i %ȈD &8PQЯkVX(ZR3ى њYc&5௞|c@nQC?vWSok#3`oN@@M 04oB(߄q_{q_\⑆,; 5ql3]Ay)j Jǹw_nw^;fk>&zXKjKSaCFhg.,w#Z3K,!X゘sw`v HbT~B* ߄g9XU](Ja`_a9N8wϥ*?*:XDDa?Ҕ8O"뎂lG=O @A{n A$ӖGgNfx $ su xOGB:-Sz(&,c%8m:%t^`r, F&7ct|nǬ ZOoԮcn$M 0h`Œe!n@+eɈQd7XRw`; 93rkX"(%MEZHi,8 F bi,IId PjNL0s|v1PcEzWo-nL:K d=@nC1'; {uR/NWnl3f[?FHks\|Ep`vY #+`cct!>ͫl:)X +v\_}C #ʚ!@R"W|~~9]M"#t !?tK|E !^m3GK+%9onj@0|Qe-)F ;` 6$`UXI:dĖ:5NhqX/%[SCVȄWGE T;I@?+q!si!(5 qlCR4 cF}=bD 滘 /L4dweqRt* ~GRX=q 9+kOIw{yH]1+n41u`ֳ[,l;t!#|N|h!`&5'c2}yfb84p=@C92e` I%c`~y۪4mA+ /'DLvm䐻a3؎G^=wI'x\A)z~.V-e:l H#7X~K2;&dKuY|> Eaٝ?m+YoZe6c_̦U{G?^"Y<˷|^̱K:Զ>2aۚVvqCjm艗q;fc(NThQ8!M廤7P盻|Y P`gJ fqvq0 RRnwnn||*X\a,0ؔKp ąvX_gl=[ xCE!(dQJ2P!9;ŗ gWϏ*Ø,70"ɤRpȟ^R9C0basG:>C5/fvHz* UZ1ٙ??WIW}yӍǨp@Y@!aOhd)l0`!OMaL<(<*m{VVb8lHlARt;>nvF ns(K:]4vPe[}a@դbX$bC?v>eJlx' fwSa  gØSƹɺ(@ 329:;'yƎ$~C̠zײ0FaXhwnv);8?!l%Dj'b&wI#3~Ƴ5[jh1,kl{Դ3&yS8~:̙{QlS8Nݺqz>f7 MvOcҭ BymR3l7hY`5+HVocR]t~98=u{Fֆܒ3f@L^#7aN,'92;̠(RK H {e+dq u0a 44R%&;~珲iev1?γ$@jF,,oCw mXi1$4Rwǩg=dH^BIt)MuC/c5o֡ۧDF0hD!#)fu'+csVn_sntyX9ͭ,bμҮk؟'eYZݿCυ( q#?Nc sۺxѰNH@&!4:BVbp v$K((1weB`ᥒI%>Y8?ćdPV.^J>N8gePJ`g$_/K_X'tu-L Ii& +$fJX`hB4Y($gc'Y=Y[.eF 1׶K۰1"F$tXQ.R2Q#lb 6l؍ō(qVkbՏLaN+ ٷH\ T."#>؉07 {824Z윳ű߃6 6yQYagw ( 6(B-P'!.,3%! ۍfw (i040Rrv$t{/{R &! NNJ8Cn 90 Yrd:ư@$i@4i(IiID1ge1-71'O|c+`<;Jaf R"M CF%AI + OFto5^;pJp ļ?)$R{IP! 9''~f{ sDD\^G96l` ,!G`c,fP !^-&8Cs8gm#^", RR!g#)s'қyEK;S^I @B Hb Eɿ70-%` Ve8 `1I _lXin! , @!=dYi@(*B56sX?҇+gfC?#09)>t㏓C̓tԎ5'n!fݭ%nkA@|/CǏ_ehVTjw1L$y<:pJn`BW $ԧ̍Aϖpy__` jF[ Om>b<6t3®%*,Y9f6 [NslE0/]fL' %uWS.L!%?c:8҂P)V)J|{leHs%!e!䣁ӊK%o!h_C,18 GBR7#,%<8IK(d,`n1`]Fb:{u! ` /-!fĮ1I _ |Ʊ{G*̾Q vXI7{K=> `XД?s~rrZtr>y4ºM:FKk2Hoň QrB? Q; x Ai졽v;x ;:0\$bbHHRPHJĴY+A@Ri Qa""PϙG 6_`hhe'P4fwO3/͛mYTx"~:T= %mV:-1(Cﻏp.r2R5ǘt@1A ?aqy4}40nvfg\B!$15Ŏlծ8t#b8_P5F ,g^DҒ};Ý< &PL)$1-< $Ы!k{.'7Ϲ+!K Cj1(BSHIYq[fmtiszCZ@DE#_MY۰>(hF%8C)G&1${eAst6,SwGD 2l:G|D=0feC?x2~j3P8^ۅ}GDp<=A dٶcX|T_q4ގܝ* IxZPZ]d3GS9v"TiR" P.?"#bW (B.g`:/%v^I"+(t vFͰvDSkbhbSţצ?$ֻ"s7ztQcRҒnǝČ;/gK'5r:t[ލFT>nzqc^L)(u'QaG)JDQB&p;AMBƕp~QN̮잒%=RIS~1D/.3wd[cF!8U 91dce^4SeS:{Y'y KXcy3#sU;ˈR!/YS=t';?98lz9畯u~àpŒ w睇!%vR:vCK?v9kk~r>3Z25p &K|۷asPP&E S,Ng[[Feϡn,Q;?6~o7NjMOcpr99C0?;`GE2^#]9+ dQhn8%j:rTmC"y=ӆW̽R,))%C;(B62@*p"ZZR"7fϓF}驙}1G SGaeu ƣ%CP& p =cc۲1?^ՄĬr?)2KPѪH'~:us?v;1{ /9x~6a[/"끄"XaEɉJ7W{P1=UadJ2")7gӠ3Kt?KaCR>8wze03Sd)Y͑SlbldH Ɯcq[6d>Cp10 v#Cp@D܏%1qo^$60r-|/MGh9ۃ[ RR#lV},l>XIĞ̎߄fYD7 Ay=;8y8䄡+Gl)aB;?V_u9n#񲰫QJzn1"4{|Yc)7p3!C&ݏSw?e[kS%nFJN秜V%xB0]2#Nm{lo県7(/o*vw8%Μ5c$p'Y9zxi:FMB8q\Fb8zpY?%?+rR͆?b)\ jfc}p<*<ٍgVt{ï nOS:Aȋ¥u9{!W񤁙I  !2G̝/o(j6O(dؖ1iv5Ct³]; *Ֆ*ΝbZTpO|+cp@JnЎ,c; pIX%,h$`>ꍳPY]|)'Zӱ;1l4'S~lMFYi#;Z]x|͕pm; 3H*8ǾKgc>ѣߓ+ Zߘ{vn'K )m'}m; ܢ+9(WAy Nt~#<ғy4ćXOg_vg |J˓9t'@<na[wD3+ <0+\,@ĸC,W|k9;@~.ƿjxr[̓A7B ŁN%% Q5ahK NIJK|w-R7H`) Zc߭̑AIZ [Bn$<ƀRrԌg6u[Q<l2M fHgs\C-J/'f%swwGWǁtPsZf\q!3#)|;ϖ}w0,rm;퐥$q]WP}9 x :v&KQe 3b\3l|wPvx0 C/h;-p>l:I d1)(5!$1!ceg_V_lЄl6rj?J3hBq%x'섂@Kޭ,nwnnvjH~*'kaݱI|pKFD&#MrS1)G# D[ ӈHkT40Co! ”$xxD+0gi@;r`XIem@:|LB: vmǴY3|0hуtDҀ@@a l†#44 GAb.۳>f=PqJ·Z]>|>GmR;g S!nc7;-E"£ nCdg$Fw"Ra_8[p00kcg+˱oa@BA/cQ$ذW~Ğ#` 1.MV}(SsMBE3a}PnZq/';)8^L@G~YZZս,#9\gSׇǒ oi-#kFL+?|E"Ӽ^$ymN<{Sxva4{% ngVc&I/33NJ݅VZԻC-V7&GFK X(ß҂M4ovŹ?vI<`jmɹạTmC&%pЂy%#P~ĈC %*sO9ʠA]-[+3X%oc};7n.N-)Z{=BT1`m ITfґ2 "g^~{vO!d05={+{?>7% `apHC/$ :(i,'~bj3~ tXR10$  , P_NX$1rM1$J*ҔL,/|0i7|~a-)IO`9%0`JFnB%Q] %|1I2U\P l7XC( ld$"`bRhlsM,:1UvȬ'{c4^é[6a8 #nX%IGϟ9\ 41HA)Tmm0hd_5%^ ;$>&NC (a]CTܽ j=Oy ` ';3V15[X"Z5XH "|z; I48 -Iך05vo &rQX`ؠC-A40 1@cKt @U80),M$KǨ0?&dЌ"%!(J]}ҝ]KG;>̲a(4 pb HhZLBǺCKd!K X#kP ;<h̹PE+!H?ɾ2TɗRG#Rz0x,<@܎0B9#I: };AeQ !} ';6G변 $ԁdR?xCf$11El`R5#{J@X8Ȅ&50c KvfCSY#_,)ȁDKlPs8uʴ# ^Gl!#)d($ X.6@(}Eđ|H^_f;|眗ALoR1+P! )xtPf =OԠ f  Hg&'$̒jCPYzDr]-왈"hi߲8ҘaxczGtBBzI8ge 8Ȇ!Y4aW~11m (bhiݝ^/Xpߤ`2=$|G HCƣ9Oܜ4␂RL? Ƒ0}Phi{[l,GufQ-J/6 ~0[cHD  KMB+I Q!d`)&_a<@`bIdܖlKopGs|C(tbIf|4tai&Ԓx@b,o;e/PӅ|Ehi4mlԹ/[p'hA} j-\]uK%vu!cX4 %@R"jF.ϧ99 3[tȲb7=D? ,ϟ8 B@3430pcÚR`k)?aV!nL axלYEu3+FֳUfw0*X!X{>E!7'>x/]#҄#%PDL%!'졯WLQ`T0JB%oPB >4j3`#YIG,9c\ HAhhjH| K,%=,xڭig;>VBPiݧ@8,@`:&D`C/C-$-)Ac14! $+%l7<-8k C`$?" E]#ol4k&%CE@02@b_GIXC'Hc|pc " %$c[2<>)H@ =3lY-q8|>H Ԇģ wKaVU~׭?ґ"B>yݖ\<=f;*p=⏖.:. GGAL 'X` w;'-lYY> K:C`cu- ]Q`Uo )>Z':?'1 K/廖 Ow'ť.c UC6;W0U`!̋Br̷PUpL9I#y3S7}ݰ9&5H҄$"lQΊMÝ3M-7i7xR6^QmT֑AJDRYK8`?qs3*i1ФDؐȑ] =3(:ZVH"b^ <퟇^T ?4 m Gt{&uPyE˴y-tP6jF'rE GWB?n~gϷVu C3@q?Ҕ\8[>ƶm9>t9L#k[:[}n9K$`Ig\EҔ 1x{>v9oqDFI>Ɉ nJBxfdP{)Gb5`cLJDVAC:{!#)vl*6$8߸t씱zX8?e” @pn2`;,;+nc [14 ?i@kdo)Ol\FgjQܢP7! Fǻҙ76b?r<=y+{VKN|Jr928OČzy䃠R8NO8Y42V?B:2/19vk9y쥒7,?")`CA(^yy<-[mu32ǚgĄ fWnz (l;-H ĎRU9'-]]aYgtvǜ*K@kN!nyRRbpq| R-ΎKܤd,.[qC < Q҂&@nlg V`AQ zl}?)HevvSq?[ Aa`q=DNFøѯqւ a 5̛n BqI|~Q=gC0#~IKwhalyxJ@v9HjQbgI%ηnaB+2SLb얳ݟSla.Y];>sR#X:(JD@JDZl Qa2Q,k)ϓۿR3(zK/nnGcw:p;GEZλؖ8 T>%g <$#Æ,oNa…)e4XsuĆl[~8K(lhd,FCߝ i)HY+:tC Hh bО0bPHK2[%p{$/4!(YBoGIIe$`n6JOcY[n4nl8s9iƨzv+ :el" Υ̴U)/p?R"+\L(ߞ×ëG|O2nY`-9jĎ-AЕ3< y5 H*gq@5#>q^No=*b=ka Zt=7,gο;jlE4~"B׫c{ \NBK7FDqJDB-CanGaƞǜ;/:u{ӂMDPV-ƓqeQI<2\٠$ q l8ovXw:7Vjf8%YyC $=oWg킧s{'qÛ+%{79,h,x?f "Kی'2Az[oanmk @hJP|4Itsu5"]~b*zj9wK6P>`axvJұ!h1;E84n]G.՗aW'liPhf g̔> A!9НbxK:,8kQvǎe1K)mVCgtԧ#7F&$1?c[ec^8c^{ZBKO@C#~?S3F0LčN! #=P,=f~㮖r w| Pda 0 ݳÂϔ$,+jٙ s|/NC Ⱈ0iPHE#%:lFgm̲fx - .e!Bn)6Y, `Q0PH | Rkm1c,O1#Ɲh#|Nߖ oBzᛷ/ (:cJR"m"g p2S%7rWJnLR fFփ}_<(c3êjaUmX; {bfPxpcTfO* xwTX|P~WF%+<5 T5K0_H#&@NM&QN`8M ×ɠ`'mY:#e1%r~stb۴0 igHW_ R]5+H΀` ɘ00$J~J$%#Ire\ ~0[wϿlmcĪf [HJc|_8-nWod;|{(4 N%ĒI%JaB]!%##_ !q1 o/?BQ43O8n}[onj")pœ`K%6$4a|5'J WbY䕺𡣠bY`\e(@A dؠ$Aa(bFKJ%x0`Ϻ5JZVo> ( (00 PYgZtvNo(=g(hRV>r4e(eܜtBճ[ Mq.SWz-Ёy@fL9۳JNi@$ eeJ!`BIdMtÖN[D45pciE|RtfGn1Qa! HQnt-p%5],2u uz}?0 7ƍYŰB!PqEvFA+srC0kgNd! $w[|z:GD̜n@(CgR~̝n /R_A(}<k a<[Q` CH|7?pe%8fQDb C!C +x]酠 O}?}޶h,-[(1 - A0ؕw:I>K $! 2A]Y`7 >JH%pl%ۇU!Na4I /(㶮! |,]NRjP'0qxI,MG+7|5}p8?Ҕ@tɡԐ#š(YG dADݭLIA)X޳Qa;&XHB$X s`HA7)9dc 'tPQ),`I! [# M GvGB? r87p l]EGs-S_ddB@AEYh塟 Ŕz`uXg]VґE!F5Kp$ ئLSNn[5@SF'b+2?P0  I04f(%(/ %d4 <`::pAIb_G@ I @Je$LJ_#/$@1([B"&^YHB= ،±*%Ͷ1Var7hB1HFd#6ö2`xGnǨcב9Ff^h}B`NgvLe"sE$PK,s*#0͝)gOPCr2(9gk@҂7Bw9<%l=ïLŔVBI+6 N=BS^o!6˺oADdh4 Lq 'R‰RIInHN=XP/?") $y$r[볞-=vR?SR xI: RCrBC@<)\脒+O!0%d5LPA^ & ήδ⸨ : = ~c9J:Ƨe"aa$EC@bTBѤҐ4P&rHn}HE=л_I;A 2+9-+2;4E s?w2PCy,`Twap'" +:{g:(4 nRK?J7}/7VK8'o.]%9LPB,$ t`qd ;~lxxNXJw7:%G~?v8I5e?")!C7[!Wn )ϰtJDCvuJFDu,j8b_TkbYM;oBO@$h~>!5ݐ01y93s5q(a:A m~lLƧ Nd)mQߛ3]}vU0lB@?b(+&r=yRic!NWu'c80D @n ?1-,b*|y%yg~H0H|Qn)Rb=Cvcop)!3#)x)TL(5 9;4̄@`C &$Ye%Hʀ 0CH Ԃb$1 {&!?OSH-)",9TC)ݸ݄{9q<fRI!] 1@O,( N)ԄgVNbvCg npK~3jAh- BrJNBrw;#HO"}܉] /` _ѡ8J73l3M JT%/  pBePLJ,`'JpN ;޺hT-^"`L& aEaF;lvJF"tL.8Q)5 桔z'Brp't'oۃvv_|b(X~+]0!@:ꦇ4)f_?:2~@y;Pwj?N}LE-tu9D;ߨOn_B7JV%f ‡ R*v@"t`/1̵-[}g7SfYyc% r A, >%ŌuONBXw7#*g?szfjbُfL1C )Q0 Be9B(|x{vT4igA+-jSe(|#1vj^$Z7S ?e;?6oÅ)xw8xX >Xlx=.y0 P]d 2Pc?t g;I7ۇK })HjeɶZ5ʟb-+fS͎Ğkk l/7}o8Ͼ_|ʗZ2zjy/Âcⲟ~̮VvJ]#1QݝG?4Q?e7/ k/cKP+IJ[B"8^o8W;w\ 4 $nZ:v3sR2YCF3W 0!u2gvohaǶ~FmoͳXΐ!u_r~Hcy)g;SPލt3|)VE n!#)եE%hx qUOCMŐ&npU62~ ϗp[ ?L,ЎY@`4by|90`Y?, Z7+8n=])f,B5rn"iM!ѭ~gSceGEm핵d2§2pFdϡx8qSa-_7}hCwß{.58NCuݸ19֬jZ3%NK3])iQSV K`kfO8XshEZxoŲV`gn #jlљ$cX{' 6U4\8ց|/nN'pG[ {{Sxš }wܐ?}[yvu~qy`P043C 儕-l1OOPgOnqwCց>y 0_dk)Cȗ2@e(d&y,ŚeYuk|={[ `j;vBüz cIFY\%$a㬣xP izTJOfÉ@y '|i#gHǏeRM-dlc}KXU9Տ45>qݳàTdZG-NJeX?f S~{uRxhvni@9)+$|+1V$8yDb V^WKnT !9Bs75*㻬٬XsK$B9#$ O1Qj5$yAI\RKHq,|Xmg&) ;Η[!oȱc߀v>U4l [SJn,]gptf'[Q727tDtqmb$^#;Ő^Z8~?YC,nti-|mA7;c= 0k_qbspuri47F?@7E"-!:h//|P΀I3v~ۄc?^_$9ΔHEw l7__㆜ VlvҢ`aHHrKzĄ*Q]ӊCtf?0&C,1$ұ`6 A4J@")\NĴl*3+3]M q,%)n KF0'1ghœR%8@ċ0 @cՖ쾓mR$> W#f邏 0f:>y4TfM[`S773vfր80M&fxunl8;>!ah#ROv~fCm';2Ui(@RF^e'V_HhTJn` d,t_ X@Ѱ`bL!4` 'vl=u< bR9*4 |{kTDLB߆%t4bb.Ha4`ġt߿_lqXK,ԡ/Z6S pm`/2_>j@0400AhtqGGnjpﷀ< i p CL!FWXnyE]Na;0=`h8 r/di( ,hQI-S)x2\@2 +%;09v n!L@s7䐁ZɥrahG?;c]yx9Q}|n P1e&:p,+2JJ )?sUhܼ ?$]( ˘R8j2۶vI vQ/F+=R#c ~-kzlxq=J#ZlvNt}suϾ>eg)j֧|8P/jȃbt0ؘ_ &YD! #)$`)8`@ F c%*Ce ,4l&)'?ujPϺΈa!;,K8S%ݱGJQ%9PB7HC?=l(?Ҕr}M[n߫5W۞i4g{)s>lDK(҉I;/vJG{J҉RAfC'6?r*Lw`pNKI e 8p%Q0 p=6KGP `]#(hReX4 :eQzEI,JFt;V9&yZIt!zPԕȄ{Rm?ӕ.!/\~[&:Ftw}Z);ivaM (W9{݂q΄?aW@:4he~S[rOqB+Rpg%%$pboX E:- J$+:<0JFVP" ?{\0h T005K% F )#[_;)K&-Y\Z BZ 0@0& Y/9XDPb0f> A+4_io604JfO%`B?].$ePΑ[;6uc&YX'qT(ĕaa4d] 5l܎E%GcM& ?hhG nbNsc/=d\U z[,;YԾϏ)H PKo))=S@Y5%$ )/ g q¬$_9iCoՅ!9of?Z>>QFͮ7(twsvtflDŽ\co `̆1֍o=0{40!褓IaEg5$No BbW,7rф;90`aHЖYnKFL"U`ѐb'8C01ƍ[ HЉyK|6Wk}gے[>! r ǥy|-8p԰ny9; 1JDO+Ike43w7|KgԩSNǭ̅ ݂jARxf-'&n39bXw:85I6VH%倧:@d%JHjPaWp'Fr|E4s=?ǻf쿖ήYV`Z ܶy5}ú/ Hϐf^v_q *|vL#3$kp<:"N~]ǘjۯ`S܇%z>V0|*|-=Zݎߪ 2{3wf$Gw̸;`lP%[ 7ᇞ+gDVnk‰$41%mC^c7:crXA9 9⴩Ï#Mvþ=6,0@@mуFrWNtd7o~ դ4f%MaD eϱ4Rk}Ju=|V¬>gμ5n=9+oݹ:>9cy??X]+(R1UŠ, C'$\aT^vP,9ZYXFp! aЍRĆ$8Ll23ߍ I% DM}.)VRǨt#ǩ?F^VRYe _[mua%G۫w%|ߔ{?`߳'u2R qHG4c$ru;IFV ud`(*v'2Q'>P-s<|4μq -#fbà.A oUxVream8|,bzg8'0ot[}|7t>?>٣}w̎7t|j\!,̀#)tK $0p2qc] 9[Lfl}D찫T,@ xW9GqGۓ@>Ƈu[S4,Z7|9IX@&)bi8Ve)!poSߡ#t=sw: u^0mǶg5t۠m7ad>UR;3p68mx1s7jOpQ|%=+jsdGhut)@[2 %||X!^G:z^HNAIXKG^e~|'}}Y'`4}'glc0P2櫀AJaQ)K:5^}6XlWt %#3 JMJOJGۿL@h pB&-/cl(r/|IZƊx7Ad_5f)DK/X <V47g(E =!LF- %Z6R+D! e $4;* i4*pT0Ej}O 7ARpT賂đcGiSP\탢'1o7>xNQCA e#R)@$:7[=(>Z3J!@h8 ~CY+>Fl|(wSC2fx8=R:u(4 ;Bu>_ƭohZKİ8iCGɡ @o|Sɠ'HYfN $]A/;n G0g/ !<$gVu1K# <@"v9 g܏'3xp %™G;M݊vc)gpp7iZVtvƩ2u(=y%LA;roQOLu*B_Y@1G+r3˜`!(`sM $@c~)NyY C-Q30Ņ"` ^ М0TZ4}x `p*% d; C@ *& 3Jroҕ>n4}aF|W!}X| NB N@ $&},!`1*=tC@1$З-# it Bc B/9A|C%k; @r~zP(@ 9jp; X~nRՉD;a,TB!117OΞҒJzxI~C#mi(5aYz?5cНsý9kV YZl8;ceGZR"B/~pc rӶ0 )/b:|7PJ0AnJ Vs3g`Dp.Lq! F5 -a$5dB t FwF?FiK?+ %8@,_(V nQE,`Y$rF0SR`= M.|XƧ%e- =گS']]8"bB-tS('."ZOfOwd/75Xj;m99ybFxzƙ~ 1dbvW#qQV:{c*VVmSP_8xa_C:I/šQ +b2뇻wqpq>vƫm3};|brO{vY78O"-H{N-Z̏q0BN3}Ԡ [776\FvFGE-ve)J f듘Պ-`,2XXRGfbۍ`v~GG2w8kKC7$nv7mv5, -Vp75a_WX!@ṇe10!ؤdaJ{e-))F՜*'l-7? NbnS[a*bYա=X}pyc,պL%֥+z՘|&g*?aR3,i^tpYK,`iA9\gZ1UlN͙n{@ˮZ)Hec<9f޿ Mq3<DVX[ƜhCC1qsj)G6U0?>̝МrNqK$|T8>s\ qA%#kun5Pĸt1?/ZR' /`&u; ~#1Sc(1~r_va# Z|0W?*Ą ^ u er`KFJ{%qa8e{M=I[w[+uuZ `Yg~չ!UFL(R)fB6;mhJd22xS͵xN Ƈ1=LlByؒf-DPuvםxtE^-8S~LJD[ ``6ݟ =c#QJDNڽVuqqՖ4>w lqklׂ[''9r,7n1$ /dn>1)ǿݘl9Q/]﭅M_[d! 8~[170YsݏCsp0q%ewTS)ZX lbw(O'瓕sݾn; Ӑ0K1!k1K-`#3wRUٺtqhsR+m&^ݾni5LZqC9lAIe n  e%)!Nݿ=> r?QfF~dl;kIxy;)~5o}҃aO:lg/R22 GG%I 1Knk{yXZa:REb3>hA8 zp9}# m"lmd;.eefQOAgOe\0&t 찎8[h #fG0L9Vr]bҟOqwKl7買ZYx$ POy땅hM}}e?VO^ @ɄΔ (xJDZ7INfٸsg9eتl}O#HDSWeV u0Nlp[')NNQ{1ҋCjΥ-/hC)lu5vC5k GîΏp"$]0n&IK%GB|7f!@#)fc/WJx1#8ĥtd9j={'gѩ6`h;OV>:%SEǩb@]v-:ai'_p¦5AƂ Ъ?Ј ;cqfgAΣӰG(BP48n/$lps>5yvDr0Qjrg~!9;'שaKvv > |87t>Yb W!# ᥁_AY| [l;a+3I(%x Sppv/ N) /!|b9iB7Jxoݸ3բT~|Y'%rInSДe}Vbp5Z,shs:Q)+/!]1ϏXpJ_8x`?)|HBq$%kȽ>H󜔘'@In1P)Y'焻TaŹVPeUvVÅ_`8+mԽΑ! q@a%hiCIlM/Y,ܿ#ӲE"Dq9H|G >;*p%NJC9e}1}$CuabM<7HCΑ8@jWp$6nPP36Hޓ#B$NqCv`&A nNDŽf8LB2%d%{o6P/&(?=)/]!JDQRo"PH<0fV'Mi"~aYcCq!Fg#)ǐ L aCS]-HxJXX ,b40@ж3geA0(tLBҡ.{/ FTm5H%leR!JDAVv#A(a-dC %~P-ij͂AI@iH +^BrQ׾:Eu#df?ajX}9 0q/(ǣt$-h%lr|, 1K! 1L66fLݲndt!?5?8FRY0%duijp)H$!CHb+kIo"`Ҟ$'MscgX[nƲzv;$+h}䲱e|W΄rY- GG;l?9tf}& sH/e1ӾW83od8@OÜI VKی5q Xk8K-NY<:W@ ƌ$$c>Ė4\3Rìxa10`40Mi7L!9H('~DŽ8N>1xnc9$`~`=Cfd"Nt%ij/lؤIOn7 q4n#?鍶bK;glRvI'u(;Lg)L8ήƭi¥apd3'Ca*'%۲n1=wݕя;pۯ!-s?g'529.,0 >;% 3||Bq>ؐvuyX@^وʝ g@2\ serRtI,bKb0§–4y\lυG93._ӣXYcڟú/7[K3`rN % (nq8W=q`,{x1Ա?;;t|u{^ xZts330.Ln<[->B$j۩=?7[{n?o9Sv>@B|_n(} Ng_٥E#̂= IbSYCT1cԡ XŜ8竱9g_3<~xXJD'Ͼ3?ŹW^|~W:;gp.+?.VJ-(W^+3Bґ1.2 SpưxL, 8j2FZ;{t{ ħѦL ·bHp Cme|_%ض=z\p6MN<9d&;Rt-׌" nXu-O?/7 ˢw4l0cf `¬y9ݏ?򝆡aV$D8헩C ~^ w'0wpD&ύ~=K x_3"B=}ζpi:)].@b%0̢FqTnQd\\v"<0qڠt4baX #(r2aJҦPKFH/9BV?uVZ )ȾqMd]f[B pR@!G~TՒ 5vrQ$ck3eŭ#98a ݾ?9;Bvv+yHI|%JC𑤝 B!iz9[j=nS,#?Faj0`4q^UXRnyQ(tADQiwJ7It<2!"z>4#%3;yta};{y+$04g%$||5 ̏߭W3{Z|v8 X1!C0otђGJ a'q3!S3#)u4ZϖnqDJ-p0f PnC׍=|rB5N-al}(RqT @6p2_ƁXIuIV%|vuh܄@҆%vK nwn3>3[9W=g + <‹紌nN b(vP=Dӻ;v;t>)όMa:R?~j;>zRYJg),KKlR Hm%\ tb#t=22p=]nܡnHΡw(Mp,&krrS{ ˣX:&'_y?Y&Ř1'آR x!6 r)-KHō@4t#nj`J ",:B 7tc %M?fx,R1)Ic45A_7XO9Cvec `;)E~J ߖ03#[lI7V =îږdg(4PBp{%TwgD^k+" 3\RSb>,{no|>ޙ;(H܌7gRDNYUlt+(nsۘ揁 6q><՗p0`,VXH =iȲ#6lFnK58b@IyCy[u+γ8ѸpZb<ņ#drZ3j$p>j[41O ͝ϾSl4% ?[!wߚ@^:&!|KUd"ٮTh @ >p</*o&cqBvJ:95YhcDSEe噆@Ćm8f In]k$u/7:z`FC6[6=c|I `2bEt6Gnd#wwcgo`=ap2I;w6uQ%gSP,hkrXb$B,ҀIBׯ(QA4 a6͖XWil7~7OP԰}t rؼWgp;̴5G},Cpыp}$O`|7Ab69GX4ha .B?Xc"i[Pۋ3(S%!IGnm*AeIo[G V4%f_@$]XV1@v u#J~oP0\`` J!R FB\%6X!ՙwu[OQIB3_fPE~u>jp=,aLH + bLݱ9Nobۨ?", R(3T,apW1ZelIZ`$(?tu#5&RA`r[,p(Pg@V IxK, *I qC:V- ; RJ ݉d: HG(RR ;uAc<1(W5pi]s[!Y#)]5əZWRA?Mpиhu&e|?"%q:[▓3J0LhbpjP{%$56JLt 0'4b$a^ee5#,jǐIJȘnuKdIhK$0JX'1]nf)w]p-L;_bE1=9ŎU\Q*9@tLHj0߷l9Ҁ.Cv%vq5($.p(P7p(`-$% ﳷ@6/xLNMY\3wӀts2KziX&J !P*|  7,$=nsf5#(qRr- DXh>!JF hb@l^&$CϏP}/cc@deYy q+Cv.lp~R[lM,7y0!=e"o!bbZd7a;}; P(f-?]Cb,L6H dĴm/L0LnsrsK6uRh![R: B:xonZYړKж%p-d!,K"a)aQG*M%#bx H@ HCfN݌sj0ɉ Sw@ NnnaW8Y’P p 0&7`>qgtx@&&زٛFa q⑱H+26`!~9fD&?Xq1K,D Ry04j1e'% Ͼ2%]C,+\!C)!(Дu䣫HFG""WP|ݿT̰h:n09Yk*F-3'v?:uT&ڗP?nGE<JDV4/@PLi( %C0hBP0!cTj2S}M]Jπ >V6& jjj?t@&r/s1˶j|#`=SQ^GN,vCnM4kCr K8-D F$5!)$Yk=VC$S(ш 3ylx]k뱦HL+{ZzSħfM^@ 63 ^BLA[K/o-+E :=v(m<) ޺;X4d=#Ž;jWWi @`pP!YLqxg70!*BRJ1ߎ9: x6 Fl0z9Ôk7aK@E 4ab:G…כiI w>r 5;8XXw!]c̗-Lb5=cFA;՝̺^ԌٿSi-qׅvHHA{xY;7|/ |] ONz-:)jYR,:; 6/D$!:C:vXC)m!`#)dD8󃏾-bGuf - ;~T9Bv Klnێw4~dz4h1/wu[q](5G%bHZ173?s- ik%(ITJDJ_PMJА)HrlYlk'M92DR!b~:X;(P'``qVC ٸ0Ӏj::$u^o|$wXqr#[=4-2#HA~?>dVwBRo$~{-B2VFFm?Ҕv=cԠ -|/χ n$}ZvJ(~B_l=Zƣq|+e2Y8hQþ +ec 6U - 044^a|0J>sP 4+l$(v  }:w55s{qv~t?JHK,ӝ)#'hވEIe18 v~}[>5d1oIoэN(`߇%Pl-O֪_#{~r3v:FSsV 1LntF ^A0g _5<>gs:RR9h%'59a-)Hȟrf ^^`GBpb߲#3)k Sf_6vyb·4(H$A d;7sL@tvO+ݓgd>v%x#?EÒ` tP0RI4rKrlzK BIvO߭qzE)G!դ0NIpc K@Pga\ \w\-dRr> Ak9}=[e~O)J?>^|FٶͶ;lv$ ǮBCŻqSw1 XfY, /hҲWAccoJzX'Vv ~2T,n!#@i:݂sx?(E w4t8`B q[?=kW _5TUj (/q8.nvJP mt̙O(쥅mf˿C#6 ԤR5'`>( @@IT M,0YXM D-HV{Gg~t@LL!~J, 7n}dkOsbS+sSbh}gl~/ >&er `AzyB]3^=s]$1O9n$5BjmV @юƬ}l+@l1$KQOғH5(AIš84g.qMBsG0c;X'<ݕcGŦ,e~Ij P{ LqM]Oo~&Rvf۝m'.8ޕm"~!x_;3Ƭ^IJ m٣zݖ,qY=Y}ٲ0hK18jyC(tsY68  Icd!fg#)HbXFKfN 1Y׸gV8:O"A&TӛҒsqqU_JJ(19Br̴9bRvmjHxLADYI!Qlt7T-aT9x ;e'E?xa0 +l^[<VxiGvT*M͊ؾ߰rVYcL@{@bzĔ"r9J&#?8<r&Y3 pKظ Wdr+aDҊc!Ǒo Ēn Sncfe ^`o 8 K;^ec0GNB_qٸjB4`i4LB #0F0zX @dr)`h ,6!{>[:bǰ3JSbFF6ff%!~*-!h!vYls‡A!I6'Pt~Ag I:[7 7ea#JDR}H;a49H`f]AC[ DXb0 :[@&@y9@'Qb]r7"6&$0npIrPN1&0B % ZGR#^Q!P`W$ēh,Zvh2h 0 :b,jCΑ-k<"C0K%7g<bLF{16RJ % @;&PRzv(S@B3kAJDAzx4% p2r锗t*yx0=8 ɀ6 ~73wqR‘Wn2Ƀƌ72wNt=Pa}60b̎s ' &b@\F% #YEyq¦!@8HDy[R5Ga@MG)|fJVJHK@*A8g#0,4oIV:p vBA_$g`KV ?N@&% ik4# 4ڜ˺KZOU- $7, W0#^4P8#BwGC4~{Ed>9^W|EӀ&5 s1Ќ3Ƨ$`@M5adA1ƋY/on@[*DA9 3ـSK ke})G)JD@DX/@?㵱)?a`AJ!l̀#)-XfB[HD܃Վήxd 141(t?VJ䑆rQyfBa0Rf,5IO΀f&u$` @4&iᤲ ,K4 &!~LtL%wA[aOG,8J:Lie4#waq82 J7|i O۝y!VLl\4?JHB{ӏ@'; ԲJaߌ$x>iKu*%9 Ӡ^BwBP7qA 1l#26VP:.f|>rJFnö_OAE9){ftYFFJF"(4h,EsbB4ч 'Q)J\f) Ōy 1@-vw`hRj@tr݀C9/"/9 Gn}a\M10=.ORG)9,zŶ],z25`M":cl* R n9uS k1m`lٖzo νxG\gre7NũCr1|gtA!h _~7u lṇg{g "n!;'>Н}E)H(KΝ1Eh ev@E)G)JDAk)HAn+;p=?ق1?1)a6[g|> jƱl0ްN+awCKShI֪HP5(,18" N偒[ᆰ%ٍ?Ҕ/`oƓ}#R"i ;Ba #7ZÄKAQL 3wg`cazƾ,4:q)7CnQ/ Ŀp?ϜM1}X[PYIK, (~P)HHM3/| )HaVxPS7]6xu8y>Q=΃8nF5t_@z{ ǿcX 3 K&IRnj1h00'fo]~°~Q=x%+ 8g;/u{GR!fCmћv͜8?=Xf8oA20I#6bJ'C]'0Z6=vhß?-g'hFHVwΣJŽSe9Gfγ7 !s3#).Ѡh,|`K/ke<b*&p2P$i\ cė},<{QNG89ț9\υ}9-lVgsxo^Yes1)\)%3^Ja_fr_|{/2}TdoJ b?㲦?"&v3$5}Ytk YBH$cZ 3̱A=b'>Y1s9l-A,q9nu!Fd(oԳ(BŽxJj;1@\Ϗμ^2n5nǩ1ޮQVW"w˵eu-5q#3RʭGrpxFmՙYjXF-{F ff_OO}+8 ``8<&k0Ͱ|V @~U݉&p!E wg>c.KeiHYXinx]f8x>B0aZr]nASsΎ,!9+Y=w(vIx\)4ٝ4uQNfd$A9ma_ 7`?S.j}yyXA@: H3Q\ƀ=?% % ot3,$xjlq |0MJPb nIJIVF.yaOyμL@`n%?p Y%bl j,g߱ |u$'ӟq,_m[mH.901 JzS/aK Xh(RrPJ;swC@gPGI+f$ H9tD׻`i3B@n_Kr$W%<$3'z.Әgv}}h(|*ZΙGk#^~}!$c1؞85™cxY=a1 XIА=g%N$'d>'\YO?ާCFM`+zCXisXF:Bz qI#ݹi%H i3soJ~KC>%r,xJ|Z6F H,11 [e3}ֱc?i1Eɐӎ4 "|=ƾWu͏?>:2NB:I($,x {+ UMAG<5N` D !y#)K R2rق˃2P·ev0 eyJvNP/C.ց6j io=PC0 TxW($nA:4uvoy/K^sR{<]xh l9JTk`ūQ|s T&p ~PYG:٭@MQxcecK0a,&j(^dJȇnt=MAYh%a1$ kIX!!raDB/g;>B.+!5 n>y1$"Z $ Wa4`p-AuvN;xb@& nN~7aגn?(n5 kS-̻RD&VdoՕ{# ֢b'1 m@~[l,L `/e $td7l a|0 @,_%cQ%$P/q˅sqЍӲNHšCG \&',v<5ۭҤt0n+h8)a1TvI3{$-gg2@zXHьYbH=L"  e+ڗLt !$Q!Æ:('&n:yv"נ@,NL̔V! 4e=x+`20+XIz엃lA@ Rs:ܚ3{s3uPP$0o|ZS*~pԅhDBaEQXjRZJxXV}(搻k%(b)Q8B n(jW۲Bd:ACJR"tj@Zj R!Ķ0gb՛ZەmcOm̠ HX7gI~vV $0o&K!|3ܿ~3\ @5I4^&VY1WOJ-ӲM?!p,Z1,a *Kas!}qLFj҆Ʊ}.`?ΦB%Gv? #Tg>(lp$|0m4.I`0)/sI֮FYAB ==/8g/~$@@v` :&VS2b^ J@f=m:&'` 0hia BK(td9q>@@P@T˜4 ig#N*Cg%X( oĴ CiŹ%CΕc2==D ?f0aW!&5|R. G t 1B|.6bf&! lad>@QOŀ d)`@;h)rBN`&`~s!#)4 7I {anD uX@5 teD#d&7#扱PptK~4ʣR"&8pB9P!a00K JFhO$ p>hR(ƀuDĀ*:JݗFc~vSGT$L4Tj=\)H;I+:÷jR"8FLZFo`n&vN;u d?vBYKFϝ`<&CP0 ջYAi nӊB :C(JNNtɥĔ5 ̝XV)m+\V⬠P#|$X(*pP8¹KF! j/7w̱c;9UMEbUCiQ8gOl? # R0C1ejN{1:OP?62l9_+tJDWu㠣 d[*FUB>"DҷB6_-Jh4g(dDāDV5J22z?$rF[>0ЁK !Y[j{B6[27?~ _FH-Jr6)e͏ +p^+GiCS6HSq7b-BFPy)Ew@v'a:nKشrS0!aߺV3qkaVrss^qx{Pp 5 ۺ۝n3n1+:8Z,YUx4|b70ۥf(a+f?aG9 8;n,V{l'e8/pNK>>YY)1#r|pV-I8!; 3$IߡZA @lL-%ҒJ#lԒNp;w`yB ʝbJ%{$qxw{Ȁh+D/5-Bgg|gkG9IC5Sln0#%8I h~ͬjerSOC,5m1ue79]Wl/Z-n7#BHs;d?d %N¢ƿcXז?'>]6~r֞?!g#)Q.cR-_;~Jc-)a ~ՙqE:Va(PU _S7v $0Ƿg:>^㹞&#alߝ.{c${ |% `ÙcIgaT5+^u aW^9[)nWcvG|jٙeMcv:fK2 l >=-/Sc'v; W|OۉmGJq+?va`n ; =bG<8e% KrTJY'G `s,+mS:[kݡ_?PR42A(X _̞RCGs姂1 `[nbg$NJsvgZ+i(_P V pS_e {IPRL&xpt36oJa.u*-^1X'Ӈ~M@jk\L =g-4f䤖0:LA $BF N(71t#K54 /U$2(,J:w{*lvzzNr_1<$xY!_OV(yb&b$\$l"g)H07:rRNgRؠ@ynv6NnSqb$%< < `n>҆X5+f~g &ErZ@ rCTRqHblw @7ߙOmA:IY8zwknDԆ咺XZ0u`r)0#}Xv]d͉eC qHA!RH$ t0R )_ ŀ@_+ l/$ C'cq7$#J(L9 : ->K\穳8qarF۬$90~8 A1.ҕJ)(Bz;0BKF`$0лUi"kebPpaa5'uxzuX A`QXqǪ!\5#sP~oTgJvXS)Rs A1e'`ƙOmI &p$`G+se)F(v) 1(lPB[7,cN)յ[p 5b$K(4|䞼?"!BJN:+`{,Dt V$۲Op bPgΎ^@n 7&%fqu, &1!$7r@C2jB & Hhiy8 ' C7%>4Z`@ CrgJcQ$Sl9>y!WB8AB 7虹[l@Rܵ&{y3uj2Њ`0 J(bIhnK%2]h3B.E6 [s'@t /z@ @-!a9 5AGS{ +sy9+%o>5 ֏4}(3v \uɠa%!i_B3Z.:JJNʂsMDSyK0ֱ泻n Qa7TXbx ?6P&X_nX6RrjCQyh,|V+3  &RH{1e8~|ūH% ֞7>GRs/,ǜ%OC4dWrg ON#=cpg杠-CFR1bE"ž WJ/#ԙg[U!W-8ԍJX̃NR2?vH"tRКP!3#) ,AcX 7HFBF=DH/% ےP%ύoBl?e{r88>U݀S\ (! gwnvu0\+S|YL- ̣tC&&qv'@˩AD K4ĺ{ nY%g ta@ Pi-;gY9]aR P-~S 65Σ:u 'RrE  1 Y0 $;䀜o@O?Vs@n)`:@tvM@bL&Ri18Q)G)JDLaX3 n_~;?a>#WCIR}7s¹bKSwY {. D<Nޗ<7v?3g5#JYMi+/N?VVgO,#- ebkAcy_-?Ϸ3>d?(X ΠRlӰ%i's=G:ߍVeDytE y9(l}?F8\Ԥ9(?%?scP{9MB -?"%!f@h|X%؆jJl10'$$o|1֑"DXWW; }K AVGZ(n"C[1[Q_Gހ@XP^Pa8B6þ}mԺS+s pfTßdvJ^sgY3,PW_gaO@o 60@HZKJRGb9PÇztk[v×~tRw=30~c#K(mG8eb ;Ln tmGwKPsɻI8\"Gy8"`df ^ y{8տd#8l;m3+F`N?`h<]߸Qd i҆`ߍK 3'@bbs(OAHJDA;?f]|F#~~T"a䄿C=lwaZ4NqЌ!O}AʑAR@䡤 e$!%2Qұ/K#wQ,7}Պ?qie7K|d0̳M0)kjlࣦdt]uwo}zuluu]l`CuN« '=gl^m#mlzM:<a粄!#)~RK@9AQX%ۏ}N};t͎D:  GJZBBIpC5r'Vgِr~=/w:rh=}[lDtwI/lp2D?ҔOM`Oig]4Eb<dΑ[')C1%F`t_Bx}x'0S"S?r0r4m,kI eۜsv9[fX' `>;q%8])phch %0.ō)!f dZ]J=?;Yd5y4]9{2UcL0faʙܐ\@ӓR ̻FtkazS!)fWflM ;2ǥy pd8in|EC9?|ڈx_RqNaҒ_3 V:؈c@rQnl۳#y槀.ޞZz;?ơ@^b5({awZPvrPWDjt c/Zt[cn93WbZG ?u3/usu{,v_{Njled0`ZR6=4i'dq>!xB'c8,7/fN(+VC&t A0jNR1yb08R8>(~ch݆D$Z>CRxՎa':"oP7$vXgVv + K g c1}(W M@A(1(F-'pEW,3 BL[ h @ ZR4 ZB@NV@WCl߾n7<LZhͳ! =[@TML(P9`!"ZB2B2R, &b|rc[vD8@:N/rZ>Q) s?d83ߥ#Eٺэ|h[[|PÒKgBF1:GQ0 d0`gt[}PJ!wKr~[pwR/e>~L&јd ue!t! K?4OOvVHPO;?S:Ks;AdQY(S) g%r7%(% $ڇ[3/U{-,͏Ş.<[OCEbnc Mr` !5a%//Yq{9Z nB~ܤFl^4|,Փ! ,8/)l8XgI0jSҌ Q))#+i0č/d'쐄ؒ7!'B(5),YX19)$!#JY $b% 1~TkfZq;Z1BH!Cɨ&Zv=Z" @@JAIIcR1)PPԜ@iQR\f s te 85Ib fY@m҇O9x/F8VP*l_^?6D% ^)Wpn 6qC m|OQ 8b ?%- p'%1`[0p˶_$ AǐkO# c@3 ~̰l&b$䝿v1R:[%8g7` ^ %< r#m 0q jpk?GS9 @+|79)\% D1yDRpO$m!~e`@*rb70J PT6BvfIPP*RC䴣 @ZIks$=GD: qPC1pR#)un<)NS`C %DL XMѝ|L nL o,I#TeR5lNpp2rQ{{|'͒}Ĥ IOgVكd")KyA \ >˜a޼*:WǨuي0hKd쑜nu@HO%r}91)ȱ:>\}2?" = am^| nSݿc Q R@İ=@P$X@ FXHdmRSҍ `(vL @1GHbrr. %P=WRn6N!{k2@$" a0Y1gBCtޗI_n"!#ۮ5JN9=!,LYv@dX0 R؋$mF/:uHd/촒Egl嗯guSl`\FX@@a bP͘;s ]^(ekoxZ!3Xȓ{.Gn9&M!C َ (3viӊGO;ge҂4~7-ǜ`( زP=В$٪=4T#9JR"C)H؜NBLȠk  GxR$cF0S`P F"Q`h+'`_1Brj:K)ݶŘ̦-ԄJ:I@?BfR ̜]b|e>(bmlI!? JPah&ɩJ9)7 ?ҕS,( Z<) ~!66RD.pb3G@c@7&)tea3nB_n#?t89 KX]݂ۅyUmif ?" N'},7vT; 8}!//GJ1>)H@o ٻ_:JDHB?")ÍTAtķWfNk[(!(jߍJV͵.AADW LN ?O@IE,ݲN|-\RHE$ino%`9Pb1Ad#6:[7 Gelmv(t:Jt;g{$;˰9l+~OϿEbs8~ޚ;IđBFuN%wguIJuw܍(Yū9~a(A%J =>eҠ#?~/8VF&b]z`0]=v8~j#) R!g#):@,>Q'Rˠqw1;V;lvb(8P5P[eS:K{q/䲑-P;Wy=J1Gm8QdQ u?uѻ~?|F18)]Sq,PX4$`5S ζ*G3zh)?mFHlݻ+|q\D,ĭW쵺s:|gyv "=䀸 .S!qw$0[p1B uݾovC8$ٳ~&nvPVכwaj5LJ:(R /w?-W2ILKe/uZbx|4?,E'^{O0!uO"Ux94~ݸcl.]e҂mfP!~{?~U8"2JR"t;+ǯ8eA[Ա:њ'[, nRN~ %|?%% ]a9@7 }vR:v刋(L!|RF36MtD1 7Xt95r^s$W0 @ rk”`BW #] ' [L#!jZlc?Ҕ]sfcV `ÀzK0Znv6N#4p`: " ~b:- `aD3 cH`YR ? = ddtMoVGD4 [du!Vr \{!̀#)a)=d;;n (M !MĮ;n˶ ĥ a Hpl~臃K,X'_H (1XgB󨔑5IׁI9Km$#]@\JOkpU၃@rX|z[qϰWB)F ?A((@f\[x%+dgz!r6F@00 PbnCGa!!nrbPq핗-=W| S !i ݒ4a/ y 0H@ I )Aˀ`B9?Zv@Q1 w-4s-c:F҄ p@H0iѣ0A40V&`0CEu<hU04#Б;wNXo mYs<*B=h5{6wQقVsd2|4^+5% "-5# HG8G3<\mG ᘢƔl^5KI+ C~PpUxX@|7, ǁ(rw*]ȇ0gg'@S\zֳ]#-:̒N5۪~ӵa߿`[,$ *B&W+Ra0 ̌%G@oKB>&d~sa-g8,` `a,}nXK n VOJRb A{cj@OB0݆ p:8ձ(cۭͰN d[&P}jF`FcCpffvHIV۷nm)bJC%b,>0;fN `;>߁6lKOdf̄4#` _[,(?C@N+tb,0=P4m,eQ{Q ݻS'2q<鐂&z9&5BM)(W}і$}BYpYgۘ9b1xpcJ%/s`a, d8ߟ򡜒v@4~L00]DKP"ӜR{f? R0t }50N* 's?P$bPA(b$@t%DH|t~&XaE-9?n7llƒb>qH{C@,<&n%:cR(l /$fM~d(K: 1$גH7|~! @ѿ3$qs񞺂p8ۅ7R@чop@`@Nқݗ Z !3#)Lr@dRr8ICJ ϟ0ܧ ~Obu; @OP  a PaHK, V+dEǘu-ϘsX#nY`8*yYZLJLJD@v"`d3!bHBFv-pV% rQHAHm#I%Mi΀MdД+W|{ɕH1 ߣqn=6: Q{a 1+/J5wpBF0ќcCem?3F" 0^,g?vǀ:n!EƌǬ30Hcq©t)R:V I-+^u1/fXD.YOA!+LwؑyPrDCJR"|2v&<0w 2"` !%'$_),axqz|&# ZuKpzݻE\ 5b(Xp3)]˰yE `F5)g!/bӒo~ZUf}tD7!dQ".Gcxh?Ҕ"o dts?a6jR"Jݕۏg'L2xCI ) BZδ~՜EfZYp^;64t&S}+ 8݄wE0n?qa)g 9?2EmΝb(guwWWH f; M'x4Š'xf--JR"O|'ć:&|PPoH@ϒ5k-8?7,Q:JR"u,RVo| 0M= @o/9Ǩ:q@> ︽d}L. $ndmܲB_;v}?ҔPQ3նH@$0B\QLJ>AhQSsi)ustE5'|Vö_QQ\Z:;s~rPG|ef AVH瓤ТHn).'u}JPHР$QԳ?i'ᝃ]Hrq<ޢھ"@~7|sz2 oN`\m<5(C7Bga;7Г"ۍGQ! s?@jJu/:+tOg'm­ȱbԷ4gacғnm! ZMlg'$n֠Յ1d+fn4- zΎ  D ?"()HXj%!?/_Ob~݃lC@p-ǜX:lsLJ:f8ֲ}|XÿP¸qRZR7ݘllrcmJl(-̎~,COώ 2(oGXGs.'g!!?"+7Ǒ @|/ZGfٟf]p`ohɠ6ׂҔlݒxcnI?m8_Ռ<{q?`'yǜIidn~V [#(NRAqLz@3fkÚ `M!l05(('$V$᣺xzDH"@c#8,s-ς [_l/K`oo̵,9D'~ó!#r>1 ,P} @jN0D1wB` QD ЋipsX#6fug7eAT_1z@u4"[hP[1vjKrݑ3jyz!#)N:R8Woڂd[ab?7~a2΄@kbC7$HT%Rʤ5BÀVpվ죡 0gǨQo҅LIv8;n hR0Pߌ>L;Agw{/]HsfxvWF;]42xb7CX\ŊXZu54!DCre )H<+Ғd32iDk OVoV+mbB9hY`xyE >@i,LQaB>!.j6lXCemaah-U;a$Q4kRpԔ{ Z=l$gRؐOS\~kGƳ?")%2WnŝӇ z{*no $JlCZYbO OӂћAcFrV-o~c텷!L,mUknDP5a1ԇ7wq?F&G=RR"3v9_YJCc뎐.;q4,).?N\krS 1qwg+c$ongrz/E5T=O, #YxZHk 䱇 Q32Tw링 PgFn{8 {f9b=eC80'd)@y,&A1 (/nI[8`frbI `Ԍv`&"x I#F(3w' h|'t7=!!% !60P >PA+$4$0ae 0N)cp;##CPu=RHF`@B$GIxHK$,rDt$jP,lO\79!@IKJKHaBFHs)8H@Y ,YL(44b eO:73_>1)JzZޝ0bHxKO|=9̈K;) ґ23$" @јFI?* Kt gYxgUeLBF I7`.)h%e.]) DAtÀ` p@͆l#?)(fAnfv4 yv:\0$@jS; S;>+biD"7 oK(5&9 Ї'[`n3I+Hb`MA 7`,)Hc;NgLX` Ƥ8]ak@0&  XJ2AsgkFoIy줕}VLC9/ofؔ$kefo/̣>9L'5a8b| O`#v"@.9r0 b[~kd%kvF Si`a $n8Yy!YQ1!PW?[xJɨ-$ŧ3{0a@g0SE%L! nMN I} APl^%te;ycC۝3INGRrD6BY;Wf|;Ga!HV,#(^l,CI $ P A~`'nÑP0 p ,$!2\$Ptœ@r܇H)&X &HF Pg0 r50@ dhÆHsQ Jn74#dm58xs XFԯ8zR vv5<:S8P.E9; L L䠜X 䟙%A۝^݋C|A,pLE!og(0d0nvuشSG%"`.˸QH%ft߯:V̾NoeR iGD q8u,rzJ?Ϸ1 QեOEqiOJIڐRt04YG,t݉Hh!B~OH,b"Ng[$gx.M S$hҌOVo Xf~J{9H߳RB iRlՄQEgcV+h?[(ΰZԫtPLG,J{mv3 .WcJR"A=}Z]t@nNs;R"}|%\#%m Ih 䒜baQ>Ğn麌4o^ٳ/un3 uS/QZ,Jan8J:8Bmt{RݍVPf7Qnx:CR,f(7|'ЏNf1r!g#)1 A !% RGDOWoā”?n72x/Kt |5cB]{ፆfn`lzL],y { ǩN@%<3Rn uv|bZ:n i( p2w$59|ǩSj=Ȃ5Ic<|' %#x`F`b @ns +'{uAw( 粜-@ K&@`,bRS%b?|5  Gs)hJ 0d>Hv|zj?a_(JD@ri# r) |Y;u o~FkGP)H@[mƟj7 8]#)r md : CrGJ+ 5DJ dB^=};/[.r Žq#pdA'<D["S ,>0il|(m|O%t|wt J>N1ws ;kH/)o*oslW#6'M^Pr4NrT!RYKO$(@`\ |` ._ h`?B Vug]ٽǬJ6"֤!a}7]ϳf^#_}mnaG)JDZܵqj71K3 P܅@b(xԾKcJR"/XG|yPƀ8.Qk5gwʆ2eB0=Chn^ = NFP(rY\ %#pʰ[6%2KO\'t`kw[l:y@mgcyiy SGqٟ7@퇄oo/yٲVԷdJ vh4Fu]RُYå")P<x @6& uciґ?2Q>B_n}ja- T{0BYcy%&NICX06V')%==} a)G=j{?8}/ߘg B>Ƀ&zM&C ,t'GWԐ!.~e*a)ᛗ[}%;3JR"eCtmgXт-)?a_J7 @aorlIfņIJ" b[}HAX26N+ g5E fPi8E::y E`Cp|֍b?;(!̀#)oӀtpi(3 w 1+9.*?e 0 SX_:&+> O,WG[80T BBo&@ WvT 2'_9I $1[=Q1U vuƒd,QxΑƍqFܔz  3I'3&@7!r@&,әh( ,j,rbi0I&Z g, !A1@a5eyDlKy8B ̔2UyMxTL|J) o?| ӋO C9R@W9Pg$IK8,c;(O_6֊)4 D -ǻg0WwBwJ!eDSi Kf۞9Z@d4$"cѽT9?fICR $岺˰{Dh!J28`h.IC07LP!ܖ_3U` vQx09+ nABN}V ?!B, &0T'7-p@!$0KN),jJb5@|lB (j $`Ռؽf4i4iyy`7J0O(5Cv^&bc=%3bx%(['ÚTxJfO4~|Y44P[2zn9/7h$(43J? 0~i#GD Dr| @hБa;t6y+ 2&@āP҃ $'Ty0rɜ%fX샬8BIhBQpܔۥ=   ѧ cK&bha+ ܙd`h2:3qX1c@J79 yIfqAV)ВFlRRĽ[4,`҉,krXnPs߈A#ƳvB;r }3ߏhɂQH`Bi|a@纟@CC@bJI I 1)GW7/6_Y 1A( aOXa URN@C`}u &ezuXj4 1X(hf=<͐k)@)^0 #7\` @0D45V3=8Wf4M%f{v9$+,`Dt|tR@b_?- Nƞӕ֏Bpi4t tVu#q:f!F#"4b@F$Way?5]뗂u{Ccb SdEE@_nvpg1ݟ[FQt2>R!}M존ٿM8 0# Op脐ֈA)aM aq3xl BX4ނax:m> &V,3 t =sfi;ՔrVit$M0f%Rq3 J8ɁBr1p4/p>آ|ZF$ Ꭽ2Ղ<7G[55>zxƌ2hX@d2N1:T|6RӲ:X'?FvKcSwв:V @<9 f4p" $ y<@ᡟ@ r2wBOhXd~1*=WN| ̲`hְ:p` ݏ!vacώŒ=gTC&DY_ktrX1πt2t$w))`/jvQ`T9k;&%L(N@XbtV!3#)pBe$[ uE}#lJSfu;-*V6 4)G)JDMҝ$2]ns.!^J{u~xs>!I!! CI x/&8 Hj ~#|t~;] @5ků*DxI( hPgd4Mx;xGTTM !Ia; DaJXE$ >Y'(I7rO*Բqk6)HeǶ$>YC9 @3e/cg02Y=2hk=AΧ 4!K&ВJ(3M !~3u *Y@@tad`,VteNTEN#!{a| hؠK-q{@{aoe:u.$n:)HJu҈8Kє) &CIf# ~c1!־jhP@,'&1444_#21͂ lQ&2 g~ջ WJ?m)bL")(oJPر3}RgHvNu{)?agvyq)A\8bBT5 <>G nvLG?9e u7WoóoÆ;p@|YhRß~vwF~eZse0ua#@.e|C,noLaSfH{pP߼ `$:D=q-ɵeH[30}†BǏ$)bن\+<ч @= HwbbN</^}CplV,Qm-ϔlfBDA⑃ nN'>(JPVt(5ђ|/RnCimx4~89C0g]DoK&1] X,x0rx)PpiXhzP>t-=Ղ ۨm`t)BπbXJ3!N!?)یKo9DzJ3(]Knz"\7 /1ߪ w0@+4scw,+ݸ*#2@ߡgsNJ?9p')#spWcP_Šok<7|'jnJDR<'B>"@؏gt45V>kฉmA< RKts qpҐΣ'Js $ hf}sRP؀/=~nDwc,J,5̐5H 7~c-.=gS1LrV:Q@?vAl#)H~c]L)qR?E7]Lk':\bּ#IQ!ٙ#)r YCǁqJ>DIfh&P)R7injFg1~mmϽi=Gpgcc֓X9sv< a&?p4wCl†3}N!t\.<ݯ▱lff9o;)ջ#0A ςOS37$jJl'Pƀ1:)B~u 'p8iV3S+mNUtAJ\ yp[8l .~ 4,zf>x5q?R1}ճ`m,:< 9C߹^p8p ~]?\k`|~.p¹P A,5#:A<`nKs/=AV7p )#nQfnZj`T .(j@mB86,aIҍV"gdγp~Ie)v (@3 m<(6rtM &(1 񝂏OpJ#5( ``>!h(1{y,, ?ðsmҵ YW;K2@ V#;y&l 9dw:rn\'P1]5_vB&|riD9iY`bH%i aF)JV{Edy\Pg?V)h0$0iA 0%7`3e+-8_{wtTa@7 I7$0VФ⳿Ĥ]Š!]#@̥N`bKg?%/Ir0ZbI\48ӠKW헆ߞL@; &S`22D,~y\gAkNB 40o,cVXz'E(dog,ӠӀ'q奁/'t#BF3 !h1~\A|L({,PHB?hJ(1,R @ @&2rN`nEPi+0߾S8=rh:@!0+XHh%FJJ@ҒŶKž& %$L)ORݸ BE-d=<-E@J?Hߑɽ,scXL0 I@6!B-6Ŕ7wbW3#! +&/909HfNs_N+4iD&`L& JwαlCbM 0P`u.jaւ $V Wv=\(!pFVC!#-`'#6͌?E @a0Bp0OtO_($ J 1Rv ɤ1'jx( IN%l?IE?/E:t y y%aP\FBQ@3KH9YK-O0!N@h%bcjrtL N @j\ܲ)@9mrFzV~cIax/O((ZJ@)8`QVbB_-~u89A N)>Q( &Q?I$손) e##7FyW(`:ރFv*wP +ݹ/I INɉ=| xzu#I9gA;pP )Yc)ĝ@0^p: 99,h M 4(XНǮ M/n%sH[!c!#)fj!CV#9R-phh{oSSj\%a; 5,rQ{'82 0aXwG Y=P=fi 5 #~|Ȱ'’G8,Qcc\P g~pQ8DQRhBgC_3$B:H=],0@ #|s•:!Dr5) -b_#20* ,cyEk9!k7I&p.XH`6!17)o!f<HdL + Q4VQNN/rJ R@1/^X` E05PJ hrB [=F)BA7L['$=̬6%"Hj٬$|o/8"4&@ڙvg{}wn,91 0Ti!rfcjI5 #tH@4 $6s s w4·(hp @CK!nn ZߩY)N=tcSC^AMS?QQ9$W,!@$"Ў~OI`vFtQPڼguj=:r;w B5JREC^[c #|V&$n1@2` y+a=^h"f 1 @IHEREPWņ씌G/ 6w7 2Ae2rKtOR+V>(RJ1YsOMM.nzp>W5,nE"S{3'7P6f f)chYP[w(䴠b]u|1/5C;}(YiBJخo߹ì0c/\0E)QgnINFeHq%A~1,݉JF2v HH@,3pҿ C$npFT(j %ԣ J'@@hnHvw8rR a \ {ҩЏH=r K8_DS a K#0iqϰUR=nǠūQ|GD!uեv?Hy絡ERl>D@]o FX3Ӳ:MlgBeDƇ,P8?Ҕ*5]7|/:yQ.XU8(҃pғPГ݉L5Pgǧyc*Gu, 0,3CbKsTJ0*i{\SKpGS $  G (ta\iX"W `o050Q0a$ pqt` Jv*p!'C2lO %5҆S<  J?",J<Ŭ@Y?F=@n<wѫ j(b@CFJ1c{ oԭHo1"ō4ӎS7?"-Ch_Qv7$H "P"7gi3+9nK1r5/D"NX} OR?|lc kJzY O,`lcXN|fL{ Ok' hů;by]zN[ n@|)4R0JRQΔWsu_̍:^ėЅ~3+Jfil ˹Ra*zftvKű7n++Qrжv4 hp9^Iz[#rvze p,@.o֡1 Q!g#)p ses[hYF8yϏG9)]yp|753jv_=]J MX`_Vۺ<H@l܎7YOsV` 7f>B;R)9t{ p'>g0ͯuLbrOb1ӌ<{Z+F2{ 9ƀ10#qz~g 5>0;3?zBĶv8Q>Q~a`]D]]fa'O5F>5/)*ĉfpf_D':6  H`#du85`PQ}"9:LX#xQ$@ZOv:[:n|L9ᬂ{,y2L@(ph51?#$d8YǥjR0i/)\jFIr6l@Pw̦= Ǿd$V?a˥;p rImtQ0 td,g{Z'+&EQ1 @О iDhB伔s?;V Kō݇}d5>ND@r M.{ md hJ$ J{)q⏕Ce"`7 SLQ{cU jN|j&d?}r π@{ b܍OƎ<{eLːM'pDQK2 #m)iC1_Z~g |0͂F=`2 4pXB7 S-ę``Q/-]A)_CbIgP`  N~A@@63k䱧0Ccu+lg|pC,i؞ u  Sel;d?s2n n^ƓL6Q M刜@R3ȁ+'nha=n0G"@PavWr6/Y}[x7m4?@>m?H( σwnsz3?<!3#)+ T'l8T xq LJHl䵄)[f Ot?7 J|Jm(<ߞ$@o t3⛭ݔsY{݌|{*ۧ[ÍX nyT)f 7e19'fMQ PH߻a;$sX^ 'g}6~s]- p X-u5u'~~@{㮔?1{BL{ ⿶iK/gQS`-*JG'4ݢCY>bD~ǓTO@mKJ1ٍw*`8N]مT͇lKSӱeBiacY|>,n#6fPlsM|isqXň1X :mk(lfh['|_!}?Zl1;eCnj gkak@>'dA~1ea})HryH-PP}-rȊ Nqoc?Q gFh&J8(<ʆCt88~mQθRaǫa@rrOm,?_By[eaFSJ.MM)kl[+,IyvZ-|ǎQisN7>A)ah|gl<-ǒ;1|csh?:0D)`:r_|laΥzR" % 4߀6(<@{pyd R`vog嬏Hba6@)R0[V͔lA.e\-C纙F7uY0 ;gXtl@ra 1rŌbWHyX=/@ ߁f⤁@ݸ?Sj:X=}1|Q`b  C;t3%*$2ġch2՝0Zp 1=d_=j:bU:d)ksO;w]-BRݯemda}?Chn<}-r.Cu'L# Ra6bwJF|ߏ@#貳 /!+ZVKǚY$,잌M5%n5[{r ,k1>@5$.[22N(Pwv1pP2BA0 - bJ/uMbB/ wnR{bQl! I-,-I i,9%$o@  `:Őn&۠5"ղP# M /} ܖ@h!4`cBx!!#)$  &)(cyVFGz? /xi`<ǻ%rRyh xh@$`ԙJҜ56?l0n i4{u<0i |/ =ĥ6OIbL+ h(#1;! F ~p&IfP*(4MҸ >p!Ms* 5E!;d)ゴ n@'vRϷbh¼L@!R` !N IaV0_$#^N&$7!#Qcf$aa K ݎQ6^@m(a(`3K8 !(焒2B11(@:HgqvKd@`T ,)%R`8Ad t~oZζ78CRR Celyh ] Q;4+1G'( a^PsZ>5?d6X%)wbX Q01,/Kr3_pL+4 @Z/t ܖ A |,㥍҂ScAL@$%=?T;+*yTR?")0RL6|Fஸ0 w:ӉH?qtnlU2x4X|C/4 # =]d=&픶{.(h inJ e0Zyϕ|P mB7&@+p.@<, J`R91z0a- !vg- -}~Cy(j0@jLs@@x@h K@` bo_lH<>|b5Rp0B&iE! HE ,p cL XdYaHfܯ8 ^<9  +!f;XQ+v=]`?,v>L(;-qbݳ񢮐o{_[>?>|la3c4%F?D &ҖJ8tְP*'`C piyohPXG 0p@2&P޾v(Ԥ{?@1 Y8ƒ$7+|I^^fP`rŁCb/@@b LGsy\ 9( qmH.s2x~hBJn/) ;} 8#6%(<&D }H,|.H5o5an``*XHRYä%У|sa2@vAbƲIC 6[>p&eF,d84>X&d_ h&brЀ,φ%!2 ^ -±1)B\hn01 ; 5C6 q‡&H` R %!.wG/t+/X, Nˉhd9vhg- ]q4Ɂ83K laddlp ΟOcLoCᥖKd?@p EWeewA xIj 䔑p'CXL2&P Kg& 4aI.[ZK=a&,ЂP(+ /?r'*:=tE KmD@4;3Jr:ޝpA}W~@4(MKpCt 2)h|n:.` B@`n` U@0&K,rĹ@ $3pD  cRZIhdCK6Pw HFf P!)1<86JP m"Q $D4rFJ9N8QFuH^cPEPe39!#)oOޚ##t#n _m[aPY6Gk1T L~5:YU+cW)47SʹBff+j]Vv@߽b]R" m)v͘J܈ߜ˟P"e)sg3.H"p_m,f~+ 8h#9hT[G`S*Y\О`̍."l-T͙@h`v R"L"5$H [, as=al3'a!@KqPixRKnH)C@RۥXoe+9펛wv'@IP$` 9UڐH./ݸ^\D$u& 5V:ֻ_ЫB-j(8ɠT45 Hb74D -Fp5€-&94y`1N&KkU<x%5.SC'㒽[@da4L,a7 7g J3tY՟li$R Е4%8LK$0jJK /2~줇|FHD#xX=G:4Is9}wc: 5 GI̜'.y鱘$~bPP5 >ؾCKņ4%8fkaE$(,r؉B1r2qy G o7%اcܜ@R<M䲟!9 CP$VZBP'dvW6ӁPRأh;aZh ĢS G49l,~d`tl N-J7Q9y fJ(Â=$q& Ye!;ļj>qϗM&tKGdgt6 veg߳ U3AtqÅUGۑcfCK|1Vg?<=B6'`7;!LB:5)U4EhAh/9_':P︹=8{)!)'IiuLbaM)noe9 5,=lx O<=ћ,(0::Ggنn rP<_#;gf],q>t`>=PQwKg Jك1-'p~;Ztl6H, cVf\FF=a=29 R=|a"N-#QA( ffHtyC(~Gy0PӜYy?U7elA]e 8>A„]OavHД8Ry햹XN` !| I- !ix9 뙆u*V`v?;b3!l(٘l;7gjuT26vFcVru )>f ƫ#0aš "߇smլ`??P$u3!g#)g?")XR *k]C0E?}:Ẅ+w!JDHJDAl-. @+ [NY`'^ Sc=f(=uq֐fAL+ֶd$"I(oloe?R_rjlM9kI -瘭HnWS8̰s cJR" -#Rw#5}ggl;~e= ׿2Pj 4o%gJ{Njσ6ȮnXqheXǏREOXG!g3n<(?Z{ @Vv1:20ImJ>͜hX$9vT0;d?!rQq߳m)?LpW%03'89&3{$ QjfƇyHS\Nj~j?")$7bH-ÁiM-%mW Fd Ϳۥ} A'[V@zV|Obu /|ۅR̮V$!(%+p䡾|eͺ߼4,ae(g BB ]%Fl3OtnF,6qrpwX2chϝ;!a~`> ~,=n,! X ,haǜǓ43i 7x W/.Љ(C:Ҝk1g8%$(͟8qS!i )(Jvs$7'xkpƎ6éðو|)tJR":rv{Rޛ56<_~/Cl#kC*`̘C I)ҁ)= j;#6~~Ƅ2*^DQ𣸺z2^@bL&-=!A?l纙2xon%d:NēpX PZK?m.^ZFD tC:oә9V{*h€1+Ba4)Ĥ0$!@-ls~ %%v[/Gw@1Bv6=< %2pԄ4hFӴpZZ w$!K+Hw4 _%!?=V4(%d-;0gavRI' m@X]{ S|N=r 1=`Мbsgr)n@ܼ7HHo$6VٺFd|&%H&Pŭln BNe҇ݑkt -/bg%8Rr6Nr_n$ [2Vbi'> [n/cN_@aHf8߹E1kl8Ddt;=4Ňndb|1߉-8z{[XP&H l\= M,?"-!Wes^uce1Js ]X &B7㶀 HA&?0V݆>]`'a|&$JxIB CRU<M(K ^ b1?? P! tJ--bgZL\PbJ,P֮!B IHgǷ Lbf@fHhg11czԓP&rY [K#(PtB &@h` x$ơFJR^J_+l6mj߬mΌKP8!c0*} Jmb'lb&YIsB +P4g0!vn1bΊnIY#,dcEXh0 Ôn @vX*5_C 9f0((5Kqbh: 0  K\pK2 }({/˼ (*Ʉ$C)8QWT A\.C K4fp<}| 0_S@Ch#|~u:+s:۝Ic!Jld @/ad B +kRůh`ZSń*ߗ% b %L&#jayH oA0f %1~h 3aCrr3(˛-!N_12 ->xh(5ew]AEfDҋĴtwZ __ͣJR"Rd6;&.H Fߒ{!bB&2[?Y$ baďD;`@؞s '&bi4V)`b8̴3XywdG @H)P#0X@3&O ߩƇ ̤U~K>xӰҜRIDU=6+[0]}ϲA`0&9V4`o J %|`=074|y@&$RhiI%nKNhx^?Ŗ|1w}֎(t&1) &1<Ԥش>W+>$8kq'<#@htY5tHBGA7'򀹬tQ,j?rђ5w  !\icJ/9~JXCJ1  h?>b+#JL5]xޏpȄKFJC;8] O Fwfj@ĤwAkܿ&p0Vc>P0x JJ"$g('xdgJp9@! !X+ d cDl:jD 5Ů_w{1Z\&#vFmLb`&%)Y|jyAJ KN@1F*NG~[Enݻ3DhkjznE@&! &Mr-Y3l;*)H`+ (WQSf>6%ĀxB%Vߵj EH‘!n~]JDF5 Ro~/)H( 8<7#d2 33;x|vVBjܔH<[:iM__u'eiWJIhA!\ -JO awe2HQrx7»t(INQ0456?m`ē %`͑maZC0:?"()HK q +f!3#)”o\!Zp(Ƨ3%@O,Q$7dĤrQQt}zya3! dt{n7d2IJIs!MX{RRq /L}`a:D2ؗFI`HR6-ެ( ${Rϋ%-1%p!t01)N%wJտn')PBc_ܜ`eB) d5ޞ?"!IPZٰE؁Bh(0ؖ^ @#@JM`j:B~,?u~7X;-EB[*BL&q1~OZ0B_ H߲F txj O&#XBRJߎ3ܼ,aHC!HAAxDZ>w;FL%d)NYO'y鐷 @́fHV)[)%te~_Ҷ$+: cNBnGxDĘh` 9KD%%IÀJ t04S1I-Ҍ1[ R <;1 &|DR (WJR"6죎!T3pi v>V AypGDtS)fL!ܤ5% GJ>=ҚMʣyAsUE& ͶjZi:CB (̄C?Ҕva D %%V+ἔrz WKH3ݓ^'v>k+;{yC)(BXnݻ?BNr.RsG<<:V(kM = ;, ! g,1 5(@k+1l0(qdat/<<B@ -l죱sO(cMJ 2XI40v$K<>IAyl0SP)/s,Գ$9P"xXR[vPn 䡝S5RPZ9Io:ef3_ aA3'ʁb\K"ґgrҌ'%*Vš҆O>V< Ync+22n! y/1݀RYĕ3u7^?ά{̎1K,kљHl-oߏhc%)[۩MŏPD@XgiO~N Y=P_nz!~?) g @u9pGSҐ{ё~][oﺙ+%`tn~tB ,IKd1H{abHX < v Β?)wvbٝ Ӌ 38~`@:Q)B29}}S刴[omKu11B(fl1F _wE]#@ݭ̷~xgS`R^7lk@m49C- n~DŲN}GR1Aǰ,Dp];B:xR7/~)cT$l980};/ZaalIm N6lI?ݣs_7ǁs2/hpQj) JŌfY*Kx GO$sM )J4Qs>Y)ǚ=f|=A38bBwA0gjxTmMi@w؞xzF"80OV'"^}-=U,*p#u=6G'ZIJusm*|Y'}bNC[ }?hcѻTP(hCIǤ|6XR#B@C6# a}gS13iFyOmE1pv CqltCϫM`RqT"B['W]GR-XN"TO|f[4n5=yRtll#m;inH^ֲF=J/: wrNe8cj߇ӑrHωRQ.лsUNϒ jI ~xt$r$7wcǝg!sN,'-8{%/ cw;:aBnN|LI'XM N(I$? >NJ(XW_l$ V*ƣ{ܗSC0a?S81mooPPOLB]=.$_$0Cd œpA)=fkC GJݜ"?%0[ЃQ7ĴNֆ`Q? ;[}0rh_qGK g8ՠHnHrϷ/4p5!䀁!-݀Vq@7@& ;$3>zrsR , #L؄MAHJTzv~*&손6!_$g0Wdep ɼɘ4WVŨK(m n72:g\<8x1Ƒkn[3[߿8` !i)Lj;$*bN7$Ё dœlW_-sOQPhb]%3(?>zh/%(PH<\DO+M!Pdd`'ā!P@TQ%≅t%`kP7 driae?8;0$37r`RT?ea8=>NwX9`WtbqX KtksaBl ōp ,_rpbhi,q lx}(fr| [+:5|,nvv|([y$ Ah@n^ϻ|ƣܝΕni$0$ IP3rPB+hۀf@!zQ5ev?p&NhG-+(4 Otttm'!>)& };ɈQ?r10 b砖6m CJBR5)c?=#aQ Lq+g%@4#`` j@ԆvĢIKfo`\` @4@`х8߷z4X-#<޾0Ohha M,Ld9I%dؽw<6ê@p8&P݀'xDn<7PH;Hx0@B8ބ18֊ZV+@Б+ ( o5)?`P / [$XGƒ,&B! #)F;r^U2@@|6-.J u ɉJ>Ju  4h BJZ:':0Q\Gۗؐ?G|RGR# 6q1 r9ٖH̶XP:0axo%c??CB:et=q8,}k' L˧ ڏ)Qz aJ)Q6ҒZ3%\SqK]hrv@@6Jz|q yd_^G^X*Xu-L=_|e F;>PL7ŰKqF3g\hBa3`X|zar𘴆;oԌ#`iDd־?PItYeb~ +3BJ?K g=41)k.a|3Oʶ";lwj B{7]TD ku2U)<9S+J6_ -(;vB1!K(naT#6$0\ӛ7>eň眦YMG-#3I5 oP3҇KDnNRXxlACF `,h @s`S- ۅ{8tס8[(~YήFZοV)b_w;?"-lO,*?"+Әb͍ʁ1# `0hY(B+qWtP7;h (qe᧰H9Vm_zSX5<>|%-C.R@`48eH iG aiS,& rxf=,SfYXVkEzBԈ,9H$qeR~@: 5!(S;#BRNj?" hcuL|fwqԣ)RƎy/ۡ̐E]`o`FG4JDL)pQDXJy-#B{d$(kvݏ2sͦ+*;c X5RF)lRc*!!#jØ3t˜<Y7%\0`B]#K0~z#}X?t(N5[7#“}H`& ܘo,19i3!PX0 [Y=E8vy0]׈nSl4n[1bv!&g#)SLbR06H]<iM%Zc| [x?@5@;;!XВ ,J(z悕7J,`Vs@nY0 0 dH Q h?IC\[(y,6fɒɍ v v=]=;8cB-񙔬d[Uv KH |x gщA? ?lebG5b?4ƺ$of(mҕ!-=No;Y5t!@da KJ1۱Ƿco>dH?ZzORR٥w{wX;"ȢCkg>5l2KS=Nz:w50 _O2)1)h8rY ?c<'Pخ!fld S #I t~cT"R!' sy&3Kh8S9ʝ[q=[v H{C2"!ƣ֔+o[$!kmPtlA+_';)L'uf8T q~K>B2X ?m1v!aSDP М^WJDHŅ, :ڏaHeDߡncqՓ+e 0=NF%sF$fHNqBYJ|Qp9<I!t&) cp,Ǡ`BOѬ lM$;c*}`idzcO:ْs8u#~3<=lhbxF SW}]l~u:g[s#O'){>< j~~n;?>w I52=nT8AY`8IX09s3}]T!I`[;}ՎwP.=Ks40i/ ͎[x?y)HeDl|k=M4W[oa<xr젪Ql7E,Z k0u2Ƭ?4A/@,*[7;8ŷtu3'3/2=Λ으;^飾}[~r"v'w'Ceth `N{%7z9QPY`eRKp( U#\VON,PFQ lfLߓ2xA)`jI(WgǏMv`(fN%0RR9&G/Vd}5'f vg:@dēFrZIa16xw$ $ЀarF_w!,̀#);ZH -,!3,'ܖ?bBqؔ% ɤ$d_b@yA|HJvv׹0ъap9YII0+#,0 23S/hg䆱7t1~`g / 즊!9d/@Px"~2;~b0 @I_mpc@k`w ۔KOJͻ8\`R=tс3=XZNV8Jy ԡf4vXk/uٹ,@)AeR{: -jo@!Nx z' V< p|Xm . ` КCId,3:Yqcҋ/9OerC8Jn! +17$ia0is09CWQAHװ@V?jPmG =5^khF"iCs~!c;K\6I2MbxGI-+[(0%j9"}OG(C0nۺ~N]PbLKAC]F ;)n쿳e<&?A\1;pR]LJ\@\  jL14ttpՀzà058j7/0ЌL@B&jJ~`P#fĆMD#PPHOCY'95-(I#g-|a  ,gd'ߣ]Ua47bRv(;-8fلbpnIa%o5X 0{2)Ac#aXgsy NpĶ+,9Lx[%xGB+4~(9 (ń95imvSj%p](P  ݷd>X9֕Pr`-F G` Jn0S$ P 1RP KS i~/ nj=[5e/0 Bb7^!֔|b6\b>JK$̆s !RJHj058dK7Gc_8ō!R B I(fC6t#dOej~M, C|eF%$ *CJ{`_G I RF 2:xߍͬHP4e {b90ZC])R0#BHAoM A }]l٩x@̅ɨ0nh0A喂X`ђ fWb4twes~W|jbha ]A`9fV%9g͗vXIs*-%Nu({w2A5$`v H19f&PRƤgXI8+xMdL`s RO~_s&`L-]? G%H%x43vwxA~"q|hDҜ9_q ƶ)(JJ)3̶de _ev}c5*K;Y,8?b)@bBp @tK~s%[|a[*&!33#)C@vOZl %Dޘol׉8 X pQP->+]RΡǷn;yAlWK5 jq40Zqc\Ġ$6=-``h ܐ>۬ݸ"ʄO!JDN5 U"=mϥ,qG4B1srCN֧qc'&3#[~;sveXޠyO̥㓝 } ;%˻(.vi'n'7ϩXI" jDØ(q! 'GD^4;?Ѧ;Fׇnݎab'nTGیmy8^ቝ}"0GKJ ah%! et;$nG@ 7u0q*nE6' ~R:ҿV1?}@@2,H ̖'Vbu8( Ħ=Ǹtn 0$ z{\IJ-e?>C}| D, (.7I,7PSF#ፘ5 YM_:%"q0GH,œZrO%  %g~H㺖|cJR"xw0`?d!h*DE%?4%r^l)o_+/r{b4R%vO!Eֵ713PlE>:??7X1O68 0 @-FIK=C1XmE>r#JR"#sb0024VG@f@HWƌ?g"0P=`L$ V{biԹ,#('0Tv*e!ä_oxX aD҃VRrs+8N d䅣`j}(E(tJDA0_aDƒR23Ot?| bcJR"kt*(Y4#9tנ,4@U; (ܠd> 9wi` ^@"hhi(:!?̓m''dX4>|wu?F?I `3Iw'@D KH>CV]A;:Q9;|.T¯ăXYMrbvS?"GGZ> O}ƾ[Nn)7{QFJ[P2+h&8bru3lęXN!Ioֶ;ʣJR"مgCvs0G0E!LFw+ce(Gk^~;~#yWAڑy~oGv|)OHQ5 ^:X3lzl="  gG0E˷!?3amN7oq)#ppl`(w?wS/{}g>hGl78ŷ}@x`?~QXL:N;&x0,gq'>nH;!9#)d|؍9 /7ΚT ,٠Jr9}RjXa!nsL c 9;Ĝ-xkϐjU#oå_Vcمq{1@8)TvWI+;1ï; { Cn׺,3\Cga{:]ݘ̽MtbS *@쬏F:m3 "70 865k;,&v  zLHGjN$ H%ьtWWt)=Mr0P !v"1} S-Aߩ_bO{(ӠSRn&7) Kr ґtg[lz--MmhN6:EQ (Cklt?̰8O y!ы31=9̇Al ;ԡ[z6;0r_.v;?6w4@u(da3)HϡaCF!­ぇ g}BF,HY"R1H$Qۏ<햖!sfY}bMc~3R ]OvhSPЊӐNqeIs򖼯n:}ǯwe2@<2slT9x 4grRF%KdϸG&4pޔw" % 1=Rƈ3"y~p_Ҷ$eR5(޺)/1Ÿ gkiVqfgpq"?H,`3uE:G ݡ j 6+t$[W@B,{YݔƳc`hx[t@?D,KpXV1j֍ۊz(Q+v~#ÔMqkKY?D܌n7w\@e;~k; eؓg?' -((=4L &bOs?㽃ŔK@"hn+K!݆~hd’+{ȃ  f~'AiB`h2nϵ2 ?Υ-}Nh; σ>=(Wey}|`&(#8a,)FLV+|=p3d,#d/ٖc~!$5  3l>W9v,hs4PbvJFܙ?Ϻz;HB?(EZR~SXWc gJBI';mɡ + vgRԶKI,jL!Բ4+P @h`O@b@F-e7CuY8A +iaryK$gY??`4a4!_vbF 'u' WsD1QpKI}rw8$#!auBF)D@P07ZT;߄V=hKACISQqLĀottbl%f 4[0͖>Cr0?,K1 MXgF58LyA lD{rra4$CKBSxi? }@bbi(*'sdRPw:: k/BQAaF@:, !BjP7`̀#yM`R}h@A]! -|?pna%l@ H? b䧒kQH,d6+#Y8p;AM!@#)9I2W`;@a$7%<抈E%`|B!~Y:X?q0D  ̌L|S)!,_q>) 1@0B%)7:0 hK81`ԓ `1~vg$=;xL+#5*3ύcn7HKh> {ep' o1aA} %{_c3 u!X)ƿaV)n-<gΟ0o͜7aM @P'ݔ}1cAt1J/ d`3OeHkG͌3FTC,A)#]08˴u(Pb(HD"4)Z3d8 W&@i-ۺ>}m٣NXJR"H)B:`2KD/X(\lAbIb)h^4eA IIHĤ% 3|\_ _ 9)@dY4`bCr_.x8DRw%%q`.sunxDhfKn{>QHCk1(bhO?/szw9HGByC_s `ՎvWl7. %! c+'F%[;31P P3۾%lgm8!E7^3~wD xvgq W&!^MňAƙ2Y4 wa~yăՍ-$&k biDxp>-bWYa[( MFH %Z~0#d8gmH*/cٸv)v \D>a$ebV &!$F|\^+ݸtߙY-K\(LHzEJ%qp[&bvqC(0bMJ?~GD] ؖ@xE Z:)qʴ5  FN!*JlyiICx0iF<#dJx 11mؔ%* fV_nWHܔu#7vN괤j҅I1'CVvNj|ʷpZw l͇ߏqS)`iwO1 e41u'r2 bJR"X%(d! $z?YdY-JD5= 7F7?Øq-_8#u/n5x1M6@-,p``n );|5cН);|lݐjSE"\6=€]NCV(:8Iym7x041r(Nd}[H,Ax{ Ue ٤ӁQ#YaӰAi%aQ["6T?ҔH WfAztHD[P? 0zOtǫmSHx?H,!Fg#)#Nv?" q* ;a3=1ڹN6;Pb41D B<7%̫B^ˮGAHkxx䇞Njm &"0"&? $rQ~bWNs> nk0ip@tJ,A3G}ՓP|)٠]C8@;w.f-5Sn{Q$q!I& ijϰիB ⋺К9"CѬ҃pĥ%wĀVO/g/m+mG2BJ[v 8:l!C+d:}da*0*Z Ҵq\!E)]AaP-;Z7t>={nGDc'C˴\ KHОe:vS| vUp f@h'!=~ K@>v/HU(uF)|gJAFNt QfqG(,-)"hq#m+l#m<)K[sUiJnY>^pYka8ՠa|4HgE :P?b G}0~-@g;glqþ} 2GsK-x"E08]4i1ggQ];s#!ea[(3{2ζV?~Kc1s7߰NW~)h, @jbw ~9FU~njMnnao⏻f?r6[ei,csh rqeK X0αIoܗ[ l^ đ8l6+m8[erY bpa'a :F1X=R*a-o5H)\ΥKVv汆::U  n50xѧ8jLDzK / XY5n79ݖ{Dny XR9݄~Nr9֥Ôrrr0#ŚF0쩏->@cF a8q-"Pن)a\A[Vh 8o(fN8 BˇL FvWwԥ-Kw1L2nJ(i\ZaJ ] V:wP56_V%6n#VcsqZ.Mus_۸a1`SN)hbH횰#%`\or#v>=j|~Q=ldW∔AAB qퟰJڃ!gO{FQm0B+Y;cF L<{|7r+Lx/tg+#"l;lZ H?5kff[ǘԧ {;czf%6aa=18㲍>CX?6Svl 'akv<ߘwkeo{͛ؓߍ_BC(o/9W0)hֳ̓ +uS'ɬ1}B9R'͑e^Cb8iacՂ!L̀#)@1 ( %+s ǀ褡X̰3t "B9Ng9NYɅr̝ɉSpHJX{Q.;=C@bB&3񆻶_Q@OxXߒr, xMN!c5 ոfm,&,+ (P c9İ`r9Y͚ )#Q\80SE)bxa9lY4kv_cҫ&n&%(' G^}i~rjq|qj~zgatad0%ǯbΫDw Ҡ<9G?.&d햔9(ke𓕟 B]ܕ$jxw*LY}[-$FA$h9% ;*t@r00rW @| gWs`B&K nL%JXr0V|@;J&pHGp?'g;8"7s`b&%)&NΟH4a0jCBU &7igؑ'n#MdRz{{;, V8P`Qo=+n;3/j@/i&$1 ==֥6|L|3NG5d3/)h544d+ C1{apZzl)d%P,gy!b "tL,4`JinlOnJ$IJ v/IђSbݖV ùMnKcA}2[9by.7=I;(y*3N5/;NHxǧ?%ZsDhɄԐ@#u_s05`䣄pf!X(d=.ijO & _Ǜ*ÚI~1\{3i+l#)!d@8H>uXcFОQ-ALzFsXҋI@ah7x)ַEܾ`C>,R4MqyH`X1a?o–`'! &?oCBc8 0`y-,#\F'EGҶۿ5XKf) FN''|gOHfXw xi&Eo?66|aP?8a#eh f-ܤg`?>4bGPiNc;4M /Jo~5vu :msjڏv`0hjI: IodζV?h RZzo7~x)J]mo"@f`)OOf-X̭sx@6y@4%N1!gC vcxz>%04:(@ohCWʧďKs!Fi-( K#9';81x\Ia p3|t7vQd!"/"Bd 0D1kB '[%(ADcvR!|?2QPj?Je-[ ͌tPԲRsO- JV{lqxo|g,kC: CFaQI`0@풂Z;㩚DoL03jvQHEnߨ?ΞJD\A%rیK @ƷwTY( 0cѦP} p WR?"'HS?7Pw^φ|p_D %JA),p;>_& YdaE$5efGiHpBI ;ZnK/l4kI|cJR"cJGWn3HHbK u^6r]# Fv%8̞77mؓw|?iw3< :V- JQIL7s@Uq pCqv_wiNG}׾;5C3kfXc1)?ҔbT'bClD>ntlcp78<{0{2֍f"'Ҏi)Wy -erʂ4?q ?Z{6vFjAc?> cm#6=+N}vo'9 ß_x^p!s=/B5Xih `G3ƍ ^?/-4_sk)3 l ;Lf bY. UTd^׭$D0]]C2]IqQ<[*сQ:D{oZ?!#)"()HaOX`a>v6SSe]ö ǘhzFJD\)5O<(Ob:۴@r٢0 QzS`qJICs:;ݠۏFVx_vyI Y`)!r$tYqc6eZ$oAL˜ R"Ms>f<F$=b` N 0hT$刴2gc@P4LJ1e8}}^l:{#\cm݂8els" &$J\[^IDwX$oR8BFpva 8jL) YM^}!^XGI̞L%JlLJ@1R)IavBt`* /pi];'^lp jД190LG<^`z77䐃1 jLdr^8px El-c[ nyHd (Z@c0F ^6Jt8c 9e@vB /`+_ 䴒@19X4f9Q06 (L潖_} #Z@ 9`go&ے5Vnn:x` qL&IQ+ L\IT45oٟ`v +%MGUo4)&uv"`-֐? acԵ0H Ƥ w=|zqF[!lZP@T̕n1)?>ZY r݈KJIrtű/g$5>ƅ`@ tM% IH 7p8}ɩ hJ[7IYE! Rt83n9kCŊ F-iMHqzJ~&QDnap=/&C=?o&$W,fbjE!pWٜ?"(1Hj 1Lha/ѥĤsQ>>>@!\gMXF%/V7kODQ)H``@5sB 2юZ2Ր dԤ ! 9# LActL ̞^FK\# bFgV,K IO<`ѵs$լVea|RRC?8>Pr!BJ⺿w0`e7>A{<6J)15{uoò>BAGE#d`ۃą>0},crWwWaWWe#fvp:)?Ҕi&̂ @F)A ֆ=pT* 1 sl5}rǛGE*Jc6ô1'+vQJ0|M,1 !ؿJ4g7+2Hfm)H?h5_7?-Pf Bߋ%*?tBw&`tsڀ`!#6~/D?ҔGE0o$i QAũ2uK-Eb۪th( upvd pKhga̷A@B>[Âq)H9R" !JDR bn{fN' @jI 1@;GAhgBFB6ҢRlIP7 & 07j~iSr R"VJDHq)Ш# _>NζB}}4E!X2Jİ2xw$[=NB v3}.VqDSzlkr?F) Vt$N-(~S/`?t-!g#)T۩XA4ju^ 0ICpZHP9-$՞L1RX0 >Z0#%W?5l?"&a\ܶcY`谪ۇoR A)+c_aXm$1(BwJ*,Lf4T^ cX!7}:`][VGDCJR" C ,`š=8cwRM;.!A,D$#nY _5B`˭v5~2yӷu0 Ԩd?CnuqRB1cY Cp[v?ϗTQE 1fB2DŽ3 O)8Xa5j?"()HAnM&C8j_v 2INM\CQ)+yEbF/gtiCtfX7[,8?Ҕ2/Y %$7^,{h?: z"-o@h j0oκB9 Rw@1ޞai$ &1!9ζQ}Ci#R^^bPhk$Krg$rQD61gZ`u |@wq`pV̞NRYUѝ@3cEX#>V@uQ[1Bsǩ8q -iiċK[(;1?;d ~;)F"W~36l٤wZ4~1Ϧ,Zg=(ap"ec <9(p"nq`{c:i╃ j/~A8N`qiB#R""䝰Q<bMn w,59J~؟ڏ#1`,Qn㈻=_$b87兓gńZN~GZhgPu96OQ.؈D>z@︎/[=gKZaE2Z`5fh,A,3O`z\]WwHlh >ņY?sG /x#!jI8p~  ,0P3$ '^B&ɡ&-){1sBJah ǀV&CSҍ0q`DҋwC[7Ćn(P|1jFtM cʵ @b(`!FIHN-)@D< n+IXL& HNRBB$KB%FO?7(`dc(87V  |C#Xjf-Kv`b%)ǟv<r|'jK9#B`;!!{cݴ/ EVbHQ(#&&1,3d` 1&L)@lVJP?`MJw R>!w|@)jΗQ(o{vt焸PmؑkZ$~L2aj H܏Yhx44%#*܉ PQ伔H ?t`h S%+Y,7Dr6Q) k{@0 `o-X$1͐bRJ!&Ÿ,I"@`38W'v +o$M@?%qO'W-]0yJtbCx;A:`PV/'N}2@P!Pn{1vGH!8n|m [u٭$f-_J&p"bx X;h;o! vҫߴa`'L D C3!jB2JVyzo{<f&r-= u$cRpHXn(Vl<0Cq 7z\!Ajq.0)kRG?OQ>!^[ F~AnPޮZXi7,4-@/-'0$4<[/}OaomF`F])@PDI-Cu);}ÅOJa$B~i7ҁֆ9xdԅJ݇9՝6V٧JR"3A"Y2^P̓ki @wŌA0}EXɁd8Vv_H󏷓ʻA@kI2B7a/w>ޖlHeAa$XsΥ̥[RKt*TJDQ. XLIL4nf~Dm9B[94$+١XUva0QTJDRqA&°#d#[Hx(`]xjNWkZ;>A7F w*W4Swui'I㝷v4Hgu]!3#))huJc>¦?vC[Vg'V/tndQ0RMĴZrf~P?Ҕlb߇fZÓωT8g4Űq#.vGd\_ ͙־:?뱧Z.hh`ai&K/#sYeRCPJ/~SnsZT 2u.[7`5Bt#/'($_S&*dNbكg |0[FAZB(Z3g|*2T>02Gq&Ii%Ӻu(`}|:)Hsb$ $YJR~.!l/318`znezDMbcRK,'# fu? Q)8B %! "d#';Zv Q0ucK Oh, 5 r'2ߧ4?"&`tK%qFfٛ6WuS-X#WWnKr%zv5$buf"xE=GGzh&Cu Jż CK+035,`CgR6=F[8 O,j#tٸՋ@P*d 03 ` C@jșK֪sf(L$l[wC[a i|n0Վ1Z0i0 RL&(n$`~ξvv})HC:ǁR(D N!cf:2pcN߳,e@h> ֦9Gƥ< Ay'HICs@0A bl߭?-^ ibCts:Y_jDIHIX5 ZAHe@%N ),nҬ3|*nm`I$qp$|;O?a3xԳfp^ͿmwBS7x041r(Jy@ȠɄ4_R`GNB,cz?g"$(5R_FsfBR96}2jC1I-҄0COzY!L&F39--*SwX`dd,+8= ;gWYtJDA akݻ Z얖״Z`30y"_pY/d;:?!!W @Սc ZuDN Jwl:p3BҐhbC:& Oر)_?(RBN?Mc´1<+M!#s?}ºtT13#k6#J t' 7; C Y9Ζ7J8Y=|/ ƾ9UJD@ij S콃lawmrHcI9 ֘8%D\Ok*p$nvKr}. ԅkw V{ex4f%Iv|gq)WfqJ|toG5q۷\>og8N#Ν$HޚvpX=cOÖDm_~c)Mjyʴc% C3FyaFZVmwcs$OS@5S)|ߋ?cݱ$6B:ؔ]1uXs q|+W? cn%I ZP*Vv ?2H aDx>Xm2b p$g1 G\S,J>{4(.ۖp?7fehIu#m32޸'JBh%2ca GhFr}4\ e$adz %4㡔 HI 4jvgq;coyYu_7VaelL $ r,hoOۜQI/fSspSB\eZ@}h?CkcEM0C !a!tΞ1c9E|ɯXV`Y^c*s4ڹzYԶÙkn1;|#:W.Owp.p۰ѭ;-N߄_~9W1-Kt yy(8{>m-_xbsd(qpAp6.Vw7)P(vQqHa0f;7ʷ1q[ P R8`#@ݬ)@PBmc+犾Kfg1dYP)%+o+u3=_olv۳W|+;ݙ]gw[fQ꡴|naaOJc_!{d>kw"< HRb)fX ˰劖`GO91k9n,CJ.3c+y-ζ#;;* @/ɈH ׾b8r&h+]o1xB&yoҝ?}b7\,~ƀomle! <',RJF0%g:OPcDU YXjJvw9lY)w@v~zPpx}M7%e+,h7(JY[K͙e W@4 8lOug?0۷@( )a-^vV9FaCyy=}%~gB)DdҰ ;c\pѹJ F;!i.0A0X;Ki}wgݸش@#Y%40%}ärܖY|JRNN "Dtd#\ ʌ0. n8\ ?G `\ @t"Rf=[@ľdqE3 .5h` ̅ŖX8D<ف1GhLē\쑮<,P gؔ4[0pӔ%)hxha Д|W|`^C?vwĄf[#8cR>:-!HDkWecy?lZO0Oipú?+dh1!<㔢*IJzgQ OB:r93XoF /ĀͬB9t_uHbtA\t.H$oB. ̄l¯#H?rCpL!) vPAYEEd|Q,a}+0guw!;3xqG­YFCGe:- oJFcJa#v~,禼y4@nt#,, D0Թ31cP7g0`pd ;2!0O-؞*Š$sqtW%r?psC^9 (`JHޕ𬃾GQX{W.ǟɌ)+HW(n7[a`X[9aQRE9d2?& Mz%*V%Н(]fT-n8`V ~% # )"Mn#?[lu*鎯aUj PrĪ=C &%'$RX[m:toϹn9yNv@ XGvM-?B w}M4´ v|NN<+SG@?8Ґ)g$'4c 1ݕGg4Gn?>ζK7Inkۉ}R‘uv_4H*Gp2j5:xξeWgjf?d(/ 3ؖ#PvJF" 0a^ƘG@6-Cܟ(OG_¶5ta8!#fB6lcm+!N#<ƒ x~Ilц#H, o+$-)sTN15@a'> $plk)n̹&+ O߲tGnt*6ZWJD ÉX%- qNrs~ӡ8d}U"pm HŒ3' |͛O}(AB5"Y{ÝÞZF`4@-!24=SҹA){'쐏Ԝn_i;ltKq( &C(vZYI$g$G(u8aAYٟSH0(HK UKa;`r!S0?vEʀCV @=#o iGz pmҰSAIHA(NlOtAD,VwI;Ւ4S@@A`GHMN2 cDF.x? (ٝo^%20#!p9~#x !UNC{ghbݽ6:%H0vzGyYRuȉѺy)~b~ ckՓJ׀V!m> QW!j0C !Z +%'+^RL Vsg~!g#)Ͷ(=@ =O g0 J,40_ JQ |L(4#dܿ<KG-!a/nNϞ0ܟ)#Su2ZCQJ Im1aC~[qfYf[&xLD &J&g/gB2Ӑ%)a~;H b,ݬxy\ڼc[G& JJ1Nmơe?" [ <ef 1K`:fr󛇩[)kgvSvcG)݃V~}/13:'*vߤ*GRq)l38쁃w/-JB:uh´4ֆ8paY 9f-¯`Iq2X,p5n`Uu7eun 'E` Ah|<$ `<(Xs0Wȓ`rZ*%`%,k `sĻw~N^'GEl{ҺQE >rls>q{쒜=]ϲh~4@8 <9,*:F8t6~es̰S\e*)nAUEYs|!]xG 띂AYvGB/}gߧ t7,ZY;-c#qvMfh9wS-RÐ?bJ[la[q>P󭃍5~of~!`y|fՂũbmFT/DF$1j(#pj bc NC [2L-5x4a`!̀#)2B@Gl5p+a 56g%hx!\Q~n[|wh7ab?XR6_k}Ynyacjl㝆4x 0bCzxX_\fn59{II I[΍px4PnB<:) q%gF'-j;^WGZN @ӒJ qQx`nDcnĢJT3?fO␵)!nJq͎i s̃K \J,3 NZGPH;̑(8 JtJRscUqp%8$'23?@B?&*0`h0l(q~4h %#݆7ijӃT 07hƤܲ|R1! / 8$7ħjvqe;cX$0$' ߠ~q#yk!Vh;I0E~gf}8!J-9M|%­%KݘťC:A+|0=`5HXN❸JJ ?$] ,~ƺK^vK,LQCCrJ HJo־-jxDX'77dVPmG'@;&Ґ)L-?8€E'$H?i1U7(X%XlT+@ROVbP p73-cZ:l}ra]ila";Iy;8J'vp,>Hƍ7 L,8*NCc8b7 A'g  bHO/3ԳQ/0ޅϻ/u$oB+S߲IE3xJQ$`G ߔ;v@77$? @ĘXhhaIܲgetq#WG1F") {v 2+rwqyx:l)G)JDRea~]fiO0CJB4(.#/K'?Ge5K/$ n%|[{G'aCR=lRsI "r*Pم, p [`qGƃ X3#O0+.G+r' c8v'MJ$>0C !a:{-Ͼ`B}̵еb{E`Y{}8RO5gxCC,ۡ2)a,9U=O5akcC(% 읓BvJ87S\;°ӰVeh  e%'1 wK$wO;l~pOn+}jEK 3sv_swv' ?n? ai=}+cwnAF7 / XJ3oۥlH<<+`?TӰQfӐRvg v$w5-.l>²_7[5el3 I~vgc9wl7;%9fu] c){=}1%}J8Qn6rKCf.ĂXS)/l(1<[eVFԱ(nA?y)H.B-w@hrFrR1|RVy8;9R0qh cLg' fr")%a,~tŏ[aRPO뛡i։GSKv_P2u5ff; A ~,f!ٙ#)Y=W @ nYb =S!;9WHlxV`,S)% Jǭ楙)p )±;qdA1}lۿRxfs )Mπ a/3P>+,r1õ(a2 0h1g,r7rKt OC0)h!{n;q-Z?")7"_nqZvX :‹/Є0 S8'aJº6`f~ߟȁ[Y|F]ԫ$DS=;ej v~c/~ߠ/b67[b~7kV; 'Iw,ݏOI!G_h R"R x vǨ\t:X_;3Oπ [~+k '9R&Xaf/= K--R ûm"qO[Sgp"q.vaa Kdf^-h;v;i,W9𵵂)wml>сH&pK`8h HadH0jJP.U=X2lcLv{'$^JH֌K֌c7Ppr ` e54ogĎre lJ+|oBARdф;C HJZ|5;0s`}8(gFGB1[nrsea?9wU[J&Wے[' Ic ſ_Pt.H&uL ;%H]ws)Jui PJd~'},}b1N")z(O-#%і(=i35){8j+GDш䢘t9< Gķqt?Y G[fC+' oC$jfoH2_d $*$Z4&9Ҷp{0H.Ni2i۸ KoϗJ7 #~YlTw-d 4A=яnݖ >4SalphX 4]M3?ID+T0Ol>wYy6]. (Gqi)(? sO!*}%4}_נiDӆbIJ\* ASP5BICYt 1Cxtq>>҂ % .&ɩOwFg K')Ήט AK-#8C W> |?u}q)4و٘>c ӕݻ6Ɓ#1;ŧҕCB #Z̀3&~QE0g+HId K7dv$S9< y1-qf0 0_ K'eG%$B: x( mYD߲s;* JwK>7՟)m'Iu _u sH h 2=YkR]!<%1t>Nd܎I@|%`;JzFkŏdu7 8ZTx((rߑ>gCtukbJ 0X!}Su?vRڛ)a ku10BF9F338S$ mEfὍ1bs8tlndNGhCpр|@@73fJ_l(NK !"!Ms2rǫ8={C@%F$n㫡;u bHZOoiZGm7',fj:0 Io$5\a8>NK? }J[p> sŰPy%gRo{l{ +fszD!#)%r2BY` %S[v#& C9obp +J^i}itK5 3005*HnI3WnHI0'KX+0`t&x#CH/~0XZPa,7`7:!bh"~I 8?sw x"ZP @Żn,uEw xiQX~(`5&5<^a: -=,{X J-9eq#:JR5/4G5>!bQ;#17ܥ8]Q~sWcJcGZ(44} `m8z()Ӊ ηz؂O (VJR{7:; De`D eq/:%e$>&AI9j$!XoB2 agރ `Oa)0P<`d`-ѩI_+1GO) m}bXG<չ=aJDD?"(aH9JR"ťE , 4[ e8j6@K6ZIE1L\]0]FvvU2;šX>P~|;f ~>¡ q csq٘ (-%1|44J+ba'iqGg<JR"J e%x:3 k21ȜZ]n6EZ? iypJc[»5;i$lZe™X:vz7OA };0iy[9ԣNACJR"t ٧}u|υaTcnZ;?:B0Ͱ6v?" Vή'0DM-(x*xRmNxRA@JD[kZPs> GB8n+2DYd)H I͉γ]"oK27:B9{Br$;d@@];# ̈́t+&un_;(TR0PAeQwcܜ)a]s'GG3P:bWG g̸-^}VrX\₽n(&wQx/@} B_FlkZǎRF?N:o71)$6hu,)IuR(`c6%cf̷[2( \!+tM/,2 }Gos9FLr[1^%dZAdaX'{>յ#٘ekeX ٰӡ(ѷ f,J I)-/[YV@eXz~QNJ~-m2=R)Q bKcbr|4Ivj",iI>/tB& JvY)])oJ Ԏ0 hFq,7UPt^czpBN1Dpe!JD@ШCUcƋs)@.4堡$ c|W}VhJPR9iFtm^7=RB A%_wVpEvV@g[d"  RqcJsJnX:#gw{F}⁞D0 l@`K^X.sjHX :aS\ΰ3 nKHW 8w$c nwE5Ps8"nF.'z9Dc2P'@O<P-BAcด ITn V F cB;y2oD| -wDgD\@5 !u88Ix)2|BwĔ|p圸a|, ,| RYP4ROwbP %hONP/>J-Eݒ7sLœM[i#V>*xVN!$5(,btR%Ӻ2V)\̘6Fx:ZT4RyHV/V.\&R%e{ ÉbPBI|w^RhbK]PȌW^9xAu?a5L` ǜO3Y ܗJŬx X0'RE y Q1 rE7t9,ls[բ/8V3t '1+$%YÎ ,?(ŨcN}igIJvr[lͻ4Cq4xVO:$ˬa ϝE[; @0C+V4TL@Y4@9 ƝVÄ%a=CRt@T%% | ӑ@BtD|*K- ; =]o  %P3A+#eP `aо$ˎ$"Xc|=CHX5>}϶@ aY^y!$oJ:u*"z6@W"x3,hZ;%zV:ύ=ȄkJ @ƚ8Ej N8zdd0$h_xrhK1FbPc\0Fܑn{ws׳hRPW|&7 B Ǐdo `Xdh W (Iz)H3HR" Vq?1vowp uO<՛rw5!=6$@ R4l5g,wtD3f7pDb@NL!PSh@4!CGN2`(7F 9nܒs)8H@Ȉ"S4Xbm6ɹ"HoF Ὤ`@ Ta L+t-',箤 ސʹs)H$)=V @bL IEZ0'@!r,XH @(p(q#VGE#)COyvKa(V F(r`B! ?JO+w= Ka 硾}[# bfvJDHD@r=g3+~c ?_;\ݳ-B@Kn50whrϏ<e?/aGŖxm 3!sH `pLN- ^9]nhLR20Gy<0RII% n@.CSدed%^teR}DB23ϲM ~`piQ@C ձTAE1?JR"2JVUCR"7Pnpv_3]A+v-ώ%g]=v`}h]x}.!JDBRR aiH9R"RNy@B(Z1쁬RwhG}>bp`;rL  AH͑4)4;w9g[; }6 Ҳg犀!3#)%~Z7Jna`I5oQ|Ҵ%`tiRRح>]/ݸEܒINF;~vD :ɥVmh!{ĝ)!#{!Lq[B @aM8;L'<)FA |u; 4&͈@n4V@)!yHHѧv^S~QL'6R x4f%ђhne<阤܏)HKq)1Ykx1Yj,zC-Ĩbˀè\<#~`7sVcj5ڢ2PI-&À=)H&^wJsS jV10]DBaL49ٟ~vԦƊ2u@/58"!aؐ)z@k@8p=qt7wîBS=[`vꥡII m9 +E\ÅvCp]b?"!Ip`ߐ bJIGi-Is~M8%b_;N|0 jzxzSxgo2 q:@2Jr;TIw!K)vexy5Rrn)b"B>7Ϲ7ٺ'Y:xLSKAa:61ajC3!!uRCIJa 7%!€Ic @@7IΈrD,+/eٜhFyGDlVa4I KNnߣNXO[5kD(MiA*EJu?V31FN00PgO)نXoeQ" (|NY#?d$HpXC%?Ҕ") moh!sxQ)aQ ^)G)JDAw`@@!3 o&zK?X1PAxj>݅ l5,m!o(!]cc,XPcyۋ!پRw= v 8 BYgC*i)H.FZ,4xBȋ(*KsTڂ_1L="JS 1‰-'qLEj>ߠ@6WRn EeRg %d%18`1/!cYabe`@Z㈷6,02B0V >E8gceKJR" ٢Ʉ @x0`|wfor?ϲhyN(%b`r̷ ^כS/q:QͿkqNn2ݜEs|>m9ޕRvǰ´"anNbabGINwNGƷdz-Ա6 @Ep' Eݎ!#)bE E#19/ >+ jL+&o_"`s:qK4L` sq Y(`X^X_A-a;Cbxd.Ox8@bB pVA =q Bo;0 N@0 rW=$ Ѐ^P4a t}h J 6 Gŝa;u[0V-Z,`K 7 0͗4 E2 eKC`|KB<00QӘ 8;^ bZ/aj`<T(9$𑸲5.#0+R0Jzl<#FX, :It14'$j_4@+ `8>S'q4B8TZ Uy kLXt?P>tnNb.@jx631at\t*7K@ !ϊ~ۭ0Dp[B:1(78=0 I'|5ͳ`|`9q4I Hb~׃aM)Nߩ@n%a]aaX)B mj7C<4`O(4VOpǝ;쮄0 @!%rQC: =FO7b!9 kf!0H;%v@@AYEBuDnIŽIz] t{3y쨔R~Ne[3rtƧ-3 䤆fX/,ϝnH$ngIhNVXZc0 ~ /|$g{J Z7-bܐJsTX\c,ưwvrۓ$ P%?!نo1PA+'$w^cLd@S$c;<nPa n ΃ e1q4KeG:O'Yϋ: g(F~Q|7Pii!R  <*QT 0Yu HEز-H@87w-5!H9JR"tcḱV#/]%e W,8 'n- 9(?Ҕ Q\OZ6autZ e p- Agn+٧f! #)BJ dsyD$9q}w AagU5Q1az@I2h @ ZEpbV]c!HdYSu5($ #3ص#IVpur} HDQ(7*j BqwJ4Pgt'99S;"xɚ"lÃI7kuYrqZlQ,o8Ġ7 0})4jIQa=vTf@40( aվˍG)7c;:̒N5>a0$K8B~u~ ۪n;qxK+`2b9p-(dK( _Ks0Z D{##wR80K~-+dVbXaJ#`vxwI-9.11f)~8Rgx 3?Illobl40sRPP bB&P"h F Sd||B )2KBFc8V& *[ROfboIcp s1 zaiӯӔ 0Z?" [ 3{ 6ewli#1\ *MBC0 p2䐀<08%p tL#;)! p,)n=T.Pf?}Kӑ~1 5"audP ; o(`6pÝ u#Ke7.d vN߰p_z/|yQ)): &Pv?KJNKlIytۍ=C)1)>B!z{);(6^$j1.8PPQ=Ș(ß+b? I@#a~~ #+9QI4!(d@2@ RgaHKwQ s^͛Mg 4?@[M#*\+<&va.ALnX(H]y 4tbFaLղ7w2.?Bi⢒{S\#CqM]) n- kU: &hB5]әc4(qN^4hCRuX7~-۾$|~JDQɳퟸ)7R H$D a[J`h`)%?s:?BV99{X,D Pi,ض?Ϸ1Ÿ 0>O JK }3wwSa㬴!c k`ؠ4} ;6'A`$7st06"'0a TD& 7', vPN\CJbh 78G)(؁oKߛv<JR"CJR"Lၩ,hg%K.'  R`f/n~jY8F=+md81)G)JDS+&R^i;l8F9DE/hJo֥e\Nƀa9W,=GvI7 "V \^~[vʾF1;w fIǩlj0BbP^te:<+a|)`?|Q3x78hZ7 k=U"$X)SHΟq>ӢD;#*Cql! g#) Wr65یY;Ė$;WbSN=\4 :S؞ f(M$ga 1٘<-?lgvt؜`ӮG~|7rH {`MW 2˞xphjXi眭%,5`xW9wk4K-#\HkdbOFQwHX@rpto1‹ & )g?.>!n% 7u c4΁9؃/p E)/6kS3IbQ\k d% i̎pL)9?9%: c_ L@IS/u fY-:AnrBԧ>/03,G1LAd@}× w=(so9N]/wNΨ_ 6p9#/tpRr{ yv!'Pi@6.Jy1`;%Ɔİ 2N8wւ`,ըsB9< XH:)qH&js45*2HYa<<*lX@ĚuDH3[ Y5{̭ߜ`j Bqw ݵha${?",̘MJJQ\7Fl];tFt~͟NOݛ):3T?"$?")oz#tB 0z=blYl)@}#XqN >PŎp#aM#2P51( +ƜIe;pL!CJI]LW`p` 7[u 1o3ewUf4X$4@Ԋ|@=c DQRC`VuF?V LG }΃ J{4OY<>բ]g}FRz bFp 5:VZkp_K{lP77pX̭w̸S_8 6%=@?"$?")X?ҔhI)W*d$k`kK”v=DhE=np2ա;lX\7HFbf^\a5 Ds+<n:HX +-8.ώ<eOXs0 δM Hra ϼob)V/pu='eA_oJ?Gg@>PJH0+8YR0lpf8nnwHQTw B,fHٱ/ée z$(dcHF>qm_,f߲gP$?%0GK`jDQR7 &O+vJqŘlc^>"Z N+?sVffE aqAYξ* b - X\Чb',VpzD߅3x??,۪/vG% ZeܿljX<D"%` na)?b$s$cN k4~.݉,[L!aR ̥_".cX]\b)p4%ۻvv cÜ 3JDRKt,"@T0) !bGHu2`7,Gth740f=O%ptlxC!8o*d<l8Co|ٰlcuCM“h*GZIWW` 5 i?f= a0fpr7#A]1>톓RrXGaoʟDX\+ àp4;|G:khc*&$w1xH.T3nk=613 O~()-D$"PQf<=Dyٲ{Yb1#H@`9#/ÅdƒpJ Jcіi? Chބ#2\f x䠁[>ƹo%#7ݖx:u$%Vf,8जWl Z?{]ѡ(Do@nᄃ>@4 og/ (4b6%_%#fdl8՘+I/@fK+wN(bPYAw>A NIJnfǺJ0jP1DGeX#A5!% /RďGPRC{66+I%(4L竰6="__ ?g=~UVt$=PI lh<``1eidSFM,aES~I߰9Q> ,PhZWq93/SX,ˊN48E%t,'u9O9C:׌:r8<9Cl@ae᭶;!#а>o\JW?u(L &dJٿR(?&Ӳ],pWmA  RcGmÄGV:H/mex,8Iİ?Fd8ThC ~OXm^lbҐ^脔~ZԦ׬CĢfbmYݐXr1t ƭD> ($$jQcM `/PZs`~av I/󒑃F1.0h!}+? ',Y*&#b%́a1Hu{}!j-C:Ltt^‚ٌ-% /nldv%$9c0Ig!/؆'7I( ~%$uh< ubƕ`5?'0 }% Xp;RRҤah~f9%}喆4ܗⓎ8Ky5Va)| %G9ϙl,HwU9kc{ O/bZ-L̥g7𜧀5/z @u8 #QTZ[c;QDEXA Sc9Y#RF'π5 %>E`8Zc$#6h`6bC8 NQB1˰V5v=͎O=@yk A%>^{ 0q00 g fI+|nֺ7C _f9BűNF+nr7Jf )nZ,mY`HBKܜKG)+BTgø9]WNp؈1mm6))C ,#s~! 3#)1  {a".3 h '@dw꫕+_f̧Ql6H \ H̷fgu-K̹X!bNu0ݨD30!&@YYyU3¹#u~>TstCD,D0xR*%t]'.apՏ"$冭)`Pax4PNG}} D#nuQf8GНn ӗ!)!) @)nkl0 ,GYDYlٟ~M'D@Ii})ld R/SdjR?ςA V}p7p.x渦[ W;3-a(17a#i]uX"X≄ˆE l#;aZ;u0;vT&ٶPҟKrx|! j֥2P`R\zm惘/m(AD |spyA?Ҕ eBC@B$R?"&YdB>!C6N%Н'UŠNtgZ~|r˙n9"Ίm~C)%3'rbZ @Cf@}Š䴤nPF5omH/Ay'T!ULܻy1%!et‚:8?`0 I7FOg^ƄgAcRau @"bz@0 ;sҥ0X^+Mt7P2{k88  -8uIĖ2@#, ue'<~^8aYaȞN= OmM̲`9E%C Ģa0`7(3*43ZZPw//"&J9G?v18 $8{)bǏT`$zJmٹA`jY_dQ4Na(T6i &gd`5Fc#۸~1շnw-~rΊ~ApUvtj1(9+E/}t(9"OG0 ,@6a`<03Ix>9\ fN;LOklǏcdej;KP'Ǒi/q{:/⇐@1`sx/K$S*L-ŬE%Z" uv5}`;H}=/<G0fkf318Q4 iXk O,- ' 0qp((3! #)I" qc;F9HdBu 3^G[#)8~ 2RI?BSFx9uBWrԔ >B8ξV04!Wq"u`*%,d.4Jąmg7`P(+ut W]-I/#xhb}JI%ϟ~߲Ff-L}nsE?)zf0l>]VLGϗĺ1 H یe,Xmt PPAiJG = s:QEdJghIXcb|I>8H?*ߏw&@xIQ#3@N;?Tk ͐sC'5#{0=x.v1D&?g~8RZ@X'00;}ȷrR%sBq0y" M H`<`3BNgƇxv։JχjmR@$3czyhe2s7ǮS 6Ғ-8ƌAĶgfm()<_ 1[@7f<@\B)ƫVB\*<ȚL G`25K+k1 bOZ_bawj%ܐaF4,0HԷy9VOlB}s0Ej" KYœ.OM o۝]2Q+^#C /Ƨ5 #VRU%HbX51sL!JDR?q?}¾ ,-J0N` Q, .[1`IHCIv~7|DcJR"J s|fqoo8#YR@Lh1 ĦZ pGEwd~ㆭ?7VR_? oÇ]=?ȏaJ\L1V_:( Mq#P*%Ƀ[ , 1tRqh%&M~nPv.%_lrNwrŠ5(ݾwxl1+vCk)IALF e^ +|zq_>6BFs;;J6;h c]j!rX %1s[XmҒ^Jﻶ?*%GЉcJR"hW nٷfg) (tq'F%􄒐V8zk(3ž2`DQkS峲fY,-)i(1󳱬= >0n/ [!9g?y;gqac^`3岜p81% hsWNP1@ lq( 7 ` zlُ~9hՈPFy݂6 h|`@\ ퟨv*)fͰ<0A&CJR"n10B1OsÀ>X?Ҕpjf AP gu[᝙) ҺQi(|U|P>R`Bo2xћpHAOZ}:(") 6Ul/l'oe9c杫(mPY"1݀),jBWFo5+ٳS) ,v?".ILPCӄau%7b {Z/7i!}`ćpSIȄD͜k/)s*etB܈04F#*#~AG3tP#!` }׸U6,Dry)HE?̆Jz{1[2e>7@MI1cQ2F%9FUa52Wsp_%8u|ZeJ(bԝ3a~n8-9[B‘~L@4VrcFfLd@ы/  &(1B#6XA Rah~!;\(tI$s[} fqUґb_|{*f[lf`ihZ2Fq|n()H[bY4bRB( ) ㆘Pgj?"i@1Od8 Bt2G' 3dS=@Pr9O[l₺Kt>CJč`deL"ɬܘLPIA#yP`CVXvXYuGD*b#҆ԍ`U"$?",!&5C>[QaHhR;g 9];}mF Nj$M1Mp, 'xU291P>)H_3"`bC cCR44` fq89+S R"Fh!*L\4 f%gJ͇HkV`jja3xB rx0{4C1;0-g(bx`9ss. .Xg }*W]#!%` 侁qnzw̵2~ʙ0*2vME!)a!?nӜc᭒1q{c$q'v5;J r|crru$#Isvsfᄓ׹!)Ogf‘e-4깬O)ϳB,9Gl`$)1CS33!~~uKul۫ `PF$$4wHzx I;Xaf7vq(yD e l7I#d `N0erX2QNyŸ-@|?Is%^|RKȰP.V2mG! g#)@fٮB_lZ?F였rSqx 1Q4 3+S |3tx}ݵ 0ыOΜp1x5v^kl4<= `L@bA44!-?~is:p@Q \ =c蕉 WQЎ7;sv70TRI )Įy'}8zXt0LC(i))J݆̊{lfٰb`i(01 eY@\Ph ۤCvHrKs Qhߖ2\7& 2}gp $Δ a ; !NQNg <<> 2!܇Y$ !q,%xDp e   |XCvsK!l-''x3u.v^SG[F200ga*Q<.8`?_ lJuZacFq|@ R1E NNnH8i$hە(:NPc1ӲX  ߥqHs3 C5 4|ԣH@x-=9gg>SfNJxK=jcF+9@l[~3uny "Š3) 0SɄ.BnZA-cQPM$cXn.I--) ,r4Yh!#@&[+?Y+$сZW3;)HK(oqA5M#cCL&rV(%$8[8V'X(BN`T`p %j KJRw̷t$kmţ(Ivb|vo*K&p1E)gpNC%4%0 01=AKWdCu-oRd;iN"#ڲ%`0Hnfٸ@c5גQ IEpx*8HC&HC0s B &SV Cy9̷j-()8?$D ݮ!!! ̀#))K}8y+SfO'vx[2җ5D‰pތIn9#PxH``39.L߄ [ 7rnjP))ֿ n?ݓH,^K}9khcx.s.OnCLhΚ;)IN;/CBX(V(PFH 7TO]]A}f;n ?")idYJn{>V Ks2%`щ X=r =1RVbqƟ#-%H(NSNtZƥ[uo`ۤ 3xxw$4ǺmqFq9KHCA t#2[罚͙Ktz%$–E0{Sh $j7s/\dxW>L!YhpLK#sۄ('s20vX $?f~vu)c6~ @ͳC8?K'R)HB0  uxJR4^+ƀ r ޲<廹q|vy\ ݟ9 lPFGmoDplgpfVe-@N}< xQA2W[0(q杬$'$a0H + B6ö;Y\vRPI7YFTnpCB)lvUm= rV|e;+ly!1BS @j1e|':}yFFleΓ଒=taLJDALj1x!0P͖J4UjiʶNl)hWK)Vnb7:`V F/7w$!un䜲NS?zh :WP7,kö|j!/0Բ9rxW>9iJЪi0!PW8yidDP,J6ԄJł#'$8~p^+ܖ(|6 0tn_r669B-L !!3l4SypGG (/)HE7}ͬ- &B)f(;em)H h8<2 0@`,A\3 0A+7f[dE)  kO˴޹g4N0(@2]*q JD@@C@Ђn} P͠Y🱆-|̾?G-",AA3 쎔c%e7l{YG bWk@e CXx1ŠNFrԋ;l#kFC8JD"hgN^Zԝ<٠JR"Ns~^#sw珉 (ac7H4!? k0*mMJZ7d)HMLX! 3#)3=׳ ȋn)H¶L XL!8i)IC4!@xp R04r׳f7AQը?ҔRIa'p݃F`S8 )AE#~u8X2?"# 35?N0MA5>;ݼG) OF(C9JeDu3r F7B_)83-7ngsdb_tC2 <jj,8erJG2 * 7Jy`(@˜xXBC еm$ԽSK& r ^ώsCTQ\1cAXJDLJDLCJR"Q@ANn;2`R}¶`x88 _4GxakY1 (1F66n!>:݅ LJDQRla!)!/>B֤[~[G Gw۹R]Sl8`vnc8{`b<;vdgA}U <*_OqҶF0gmi6cq@T,Ja>3,\JF)?r\Eq#Yb,eŸ9k-ðj簧:cE<?^}5QY#r>8İqݾ>@Ti[Vg#d`!Ƴe厤;.xR:K:=bf#b54ٴ<ƾ q[h -GK_0WgFqv9/p_Cm?`|λ0EC p (ieNd Pk>7' D;I8##Ȳ&';,xwyJѥ(s8]0*N `Íuv0JMH@d ['vSێu  mgR?AXZd3)(p2b88=΀]#S(mƉ1@54- /5ojćTL@k1d@: f,(=[/\ t% a7s,#TKFҌ#0Gjk' z:$@S|RY/(aˠfl$-I XF#ٻ,Z>gOp(:0wi1d`"C$1c @i C c䞿Li$o7fhh2dex]hn -y,bKrb@ ]$|Y03~;rgg@"*p<%7?Cg Ӕ$Nbq @-oWb7n1[0ﱑ ێ0$VxmC D'jTRBJ/H9}llY+ j7vxi :gA%N<:ɠTbcVp-q Qj ђC10h8 dw8xջF K0 NI!#%XqL3d$Vq'̲I k.|| %,7x7 aPnvxPO߰SlJ  7ND Cna/pÄ{)&Pi5i9= " '|;-7PO=R `wk`wB2wy"ėCXgg4Wn2R[B5 \ ̧vyok*l+v2?Z@E ! #)bJ uC^->d`:BiǠrq , 3 Koa]żxڢC W1[fന!=W>J0^W @x5ax\m7y}b Aoб?@KI1^ۥr[KKpx Š!NpXtcV{2B߲WPW,ބue aDP3Ya ~ؐ?/ЋYyD`ЄtĠ 0[>qN9036A]=nn; hXJPJCgnlvGC瑶_w톡N[1( BAƒk([aFu`*f4ŰvO@81J5Sb )8X>  2>}Ӏ`9j29 eY|I%n4 ҂8 cImW@m!d9cWf$ 0w1 faC+]_0̣wdߚ3#hna"R`w0(,v?I4Iʰ?-` s}FeΦ8%7}[6l/_~st IDq{Xa@=pHi( ~R1 !?::(hKa*)H9\7U]h #F $Hq-%!O#U")bKysl4i20%4o&qƑT-Wmk  H7%a# {줩8݌NXUX`XCj%(xf-xB~b%1JfA'%#0 _[;+a+>MNu'e.ݦzx,BA (xޜ,ht@ZCḠ ,K%ǒ?Ҕ GpM:Ƶנ РdY)_=n~@w D݂wd@a;*pT0yvᧀiu3}3'e$ܜm|1Iyg$3 r @;d1D@&GkxpH-A:^Hx ` p%$)|{%H's3 (nU~5۪ƨ$؈`C2.Ξ&Mr))PK2 )!?Ӭ>Ѩr5C y5=)B#>ߺJlkaZsnCA2hQ'4;v:@uuv nK =m 8s CB37 t I"K)R4/.(gg&%~T.`!( Ɨ!g gv3iD١=#r΅=t 0LVvBJCWfa3oIa(̆aH$ݷ'gaiE`$h9xnr8/E= 2Y,t 5N~` R"2u 8a~x @- \PACzA'C|5a؉<- ~K (7ƍ%K쩻~te0Z?0 v0 eS@2 )/tQ4'1{@@K>81-E ~5S.I pWRydCJR"Rfs~"w bgc5SEpǚ꾬泊̓`99<-DR En7oZNlt eLId†?&c hÓo ?)ۘ*)=O8g`8q=9~+z}L)'[3,,+uVG5&ny=Dbys.B"Ɵ}0t,@^G(7c-A#>knO7|5>:I9g0]Էr d8wM8:ež.oi:O5^awsm`X˜7ǡVBds G,Mķval^ b}7?e߭bTSC(aw!Y;1.Pيs3{ Lh4×knpdRX@{m#lrul!| R=¢ЄJ AJ''hgp@g^aY '0ç+_ɡ)*sÒkX] sg9b.Kgۑ2,i`cHq%0`H8ox3o$)0YMoX͔1ĕ/!MOv XPΡ8hŲIA fM[4Or4<-- rs X` GV,[es8@b*"6.BƘ1" $JÀix:;c;;`qr2bI!yaUDN1ѐhVk"IdS af=+aPč= Č(,@gz~BkVA *a- a|~gA+WZ9;Nþ<̢ӺF(S-; |Ą;+KI}@=C8lj K|8՜i:!$1<4vCX`ݖ 0bqM9QEj18h@xqFKOQlvFqSXr9퇊4=Wg`7]R Qe\ &R B^G )hh%հ@'6晝X̭!JDMb9$w)iπpmm;V ~Gg}82uT"Y:1#bf~_Z9y/sn $p|+҄rB0e"М;>^IAO( ~/ќ wXt >pv<R-eӺWФ~ `4*k\H! ̀#)5'iӈţ}҆s)⃇ ttLVapqȘ4ܡN s8tBhBǨ@S0kD >e`5|84* VOcEP ,7)AJGJ=ڑXAԎPNaHg ?"$`ٜ,, !& h Ԯq9#x !}h_w c+V*n`NeqK\ς `;M:J /:Va]lm)T!$YF)ηc!ԦpJ%Ŀr}; Cx|JA`c3-oƾlrsLgX깢-®6sX r(1`vΘ؄C!Z]HBKHF9GW-va}''9r %)T}QvPĆ#?m rn FN9;|>Δ< :`JF"QD'^ t~lvtPf-Nri4@dc$idWqra@0j[~F$$̓F;S ~zi3v7n ddh⻭gݐRklif?gw 8 @d'nH@$ \ ns0Ar\.{4%8ҕlZQ+9М;nRř[ @l*lgwAJ/%sȠ@೅rT[9< Gē -(JQJWh΁"@4M(ܿXaGFI}#xZ)3#68)F6h-#7㖬+/lA9)(|[0ߩ`p @+&P K8 Y%Q8^Q_ H I{U/z LriaI]!FU,}'KaDtm}/ö(0 I4\`2}|)8Rw`pK"]g~vZ-‡-9pgg PC˅{cl0xzu#L p|!n,0 37^ƭ>WwSxBF?9N8]'FWH Ĵғ6='E4W}BˠP}wMƒ?G_v>w ṽ?MGs}\BRFJY!FkMgu GSgṕ8p~}t=J XK3,٩xDsaߙ%8XF;u O3|(O<9?G'RrrB`Stp.KHt!8̥ol;Wِ glKm{3նY !ds"hxg+3ᇶP̐7,#CtYw\ZG"wnh~0぀ K`Q,%ΐ`**Yy] )ٍ7yZ.Vc4nkJrN00vRYi;#W!idxMhj:Nrz AZ=|ƃA4Ri`!!bj+ds70LN1Jr6Co ^87d8pF_(t1;~b9CA)]c8f3eu;|N5KǛ }gn8|r:r ,;U(Ō y-÷ZNC3n2FUűˊGuic;W<~#D zSd >kl]ncr ?2PpBdt#VΧBpľc@:&9e @KO) Jx'䒏Fae d8G@T (nS_lٝL`! 3#)AJﱐK ">I _}> &DǒhY:_XqtCT1r{Sד s55I(<7<8#Phķϸ|磁#HaV̄1Bm}މHC ȶpI:bqвg_X{0Jb,O#y#TM‰<S(<%މ$O<tkS; gP ICv/C::@[*u2tb!j7N0ؤܓ 1=$ kÌX H"%sR0<VRs,Q+lWwS{ $﹜ճ[1`9)_e :GoJ7_5~Ǒok흻 Y$̲1!?Kw}ӸslLcp!+͔0b?cDpo_P D?18#U@Rwp +c۲f-`"9l݃%vq7Qwoݸq"]2L_o`W?eovF\7KLגMQag-9_eVXaAFN|֎5N|;&SSeնPs[(x?" |#eH`K)} gMsO0sOcQFz2F_q sƉjSI,|+;rr/yzB;廸Stm:nKIJR4Nw+8Sc~-Yĭ]呰l*X_>1qR u9Bm ǎsgZ3(߄c_PkHsLawʲ1%( >@jz=J0RG$콒>Y| dlT Y&P(/9eؘ ~jp;/I*_am>[ϕi:weQ`ѻw}JkZ1јnu:lpW{1=9y-#~K;<90a%<%vafsxJ3<* :0`L&KC Mr|R|G! #)acy'&ERq Xhfь!gēK( 1ǯE} L&$Ơv=x$YAO%IE7*; sl#0nۏc$kv" q(l$`BPACA3H-HƤ s̝̓ 7X DT Ɏ; '@Z D!ZqYu(Hvpq41?yX"D0G=}= !KrN3F1nl؃6p-gS$:y+?gfÿ Fw`D_7fr!˃r <Gp7h W5`e08brx5. eRQ)+w5KφZma$PH;+yKvwZ3!_ su5$X'~>d0CD"hae`3[牗q. z ^A-ƚ8m/I`!Pe,M88ZgY$I4(g&g nWS@1RT#H%:GܒU^a3%$f(9Čyr4SM30@h y J @`1DA=J?1ghEjL\}plY*g|챪n-z`~]=NʀtJ!e/2:B"g_rpC' sT)op]B ( @-?~R]yâ@ϐ/ $t`ɘ%%su~>;"(F?")0SN,iPdNs͖+鋰vfvS9h1w%(XQ/K}%gs~\+W8CŨp7::[ PP?e,P*J&(R ƺ0KaߙIݥC o(z:/|jB߯u,s a2A. a֮̾f3ȁpo%#t 1,v~{ VWp$&v#RAYW Jps)a8bbC~4p^f_4^b7:ӃAl q+x`ǭ"uq[%nt`#}-{3r3 J<9חK-;p$y:`I@|Z]cu{Nb2ג!+sZ 3 P9RL;+EpT/ƀkqr볞zi33L@(`L$:Fq?"3ݺ>|i 6 >A7ߎqB\c=[c3𻧃9MlZ H̥lR?/}r Iⅎ,H\)i$p_vD Md \m!jVۏNƧ~., %,<#~@Q9)&pø1D䲶P"fpIIY9^K9!II A$L]iJ! BK`ܣn6턬@6q7AD !%! g#)1%%%W};l | }l1Ԝ2Ikm k_]X+A`8R`gH<1'{!'>vA; = [I܊.wJxv@`)j; #[uetRr zC4Nv ~}r<(Pχ9pf-xJڎr%vem1Mxȑ76a]p@.HҲThGcΆonj^ nn-#N'1B1b>CJDS(>jtL,ӆf1񥺒vciK.?.*VV!\1GE)Z<|S%{`2cV:t2(RǨaHGlLJ M% ıbx"Acֆ#Fg.H=H-jmᅕ}ha16!ϖ͒(*@NYˋ(۝%9|q6<6,0y]ƀ/' KTV Ryt'T᭐0 8 ;&.RQi_@ϘEm/Ȓ5|xV3+c?ݾWw}3Z%Gjn~z g?oWLFAHAH#mE"(#[!)`$#[Zj!1T;(oD{Gv'YCN ge'7縃-'k83#(ߟg}s[+k&+/B%rc9)_fpի~dut  ,Ĵn>|7b*F B?7狁8bK~ݙBN~*)=D.< B +򘴔1#~C| KSwl-.;!+Wp<<@tP=SۃWHm1vu;6=9;zz4 C (t Q8nC(,X`.:#q"94*0: $1bI3( Kg-&pj h! ̀#)jKma@B?PY< ni<:&lL/@ Id| 0HI8b>ٌgiRJAۥ,- v}0FoՉJY|xMG -%Hʢ2F3.e ?Aѓu{xu[w^ZQ ^Ky@m݂{qh9405!i]Lp(B&aBCf9QmYy\`0R[3\o`ɗ!~sV%{Sjë?";R AA`xj1qv%#bHDtm[et5n_qן躤0̜82> :atud$:*`7>bS+qhWvc^C=%v:aiJ3`30lXȯlK/Sg04(z@Td H@P5$@ @'a X5@5SuA(EZ ؔ t,sU2B8czV{ uNRKVu`i0$$o%RD58vY@/*)deƠ;sHXO_0Ə2e[ &Sa …Ԕ2q? ONu"'% ;"U &#ll%rN86JT`pukt0184>NL @f/`kO^:v'K8S(E]sP$X}K7"drRߤGJ΀vRP0r !Ɠe~gieFe>3g{;lٰ/ACM^8q y qB7}`/䍶k3l5iOJGevcē*N=Ѻl5F%;С)CNԯ4,$GwU}YY9c`+9 R Y? A*w?"!PL/XMREGP`FB|R~t@ CI +=y+xL-9'/,?oIXq<[â+"Vtvn $HO1ݵ9P3 ·D1f X?",ছ))GWG类鑁'ja.J']-w< s>]k"D'4_5 [m;d KHb@aA,qǍO\f&3ϱ&BP6IXiDH4jq\e ~vlQ|Y(P_#I'x3!ùIHnI3EɣN94FxY_!aH:pd'Vۄ\x .#y7*[ 㭎fUaJC3f,PK j@n1.B\'?X P϶IP >I'0rb%Q~(pP'?҂۬5A}^$x{hK0Y?k. ~Jr7O;% d0WPHxM`QRZ%9FGdowc5pL~48$Rpџ8w rBuԥL h ~{gjEgeƎ0DRrGWk^.4o^ R)p}˩}aa14g%v#zBa7IC%( GA# ]@R6 rJ/I+0p8bw8c`P @P19ӛ 1Ðwa8EKdpS"t0+RCJR"%dxMF[)>qlVJ2@o^$a\FR"T @4|Ӹ SG6Ca|Fa`?]e?m`>RO;n$lLFŸ\1#gbie/lx.pSS -3fF/Z_\:r:2{fߙG AD?w2ZDR`PP\M,BSv9"܀`4 B_`M;{ 'Pގ(:@6ej7'%C31JW~Tp2bX 0fAmǖ.5#l83:w5-$h#9622͡- 0l@> kB>BJ@n8%VBzs @[67F 1dV,*47ђ}ݕB(B$q?Ф8JR"D07W9wn=@7%8f J|[vNq;>cJR"f .cR1Cu`nxL&bfl7<'ՎYP'P73 Ǔv@9ޕ%~w#ԧ?Ix ĄCHh%HgW̔8*"#RrDVa|=؍))HV,`a6Y䱡 bXY!Iʮ1/ 6V~t+Bws a! #)` PH ŝh[MBR̯߲tL0K[- ƌ4P|ϛJp0&CFŧm PcRkJ9J<" ($˺$ag0X?owho%s@ @A>@끞8ѹQXeg)y{ ZvB7)qa3hБCf2 2X3NWlٕNap7KxlIlcHq-kM`#'CprW||>d A2J788?{Q GCI*OLXV{UX=|0`ȆXRiZ:sd :8WR, !0aAĆYc d0V{s m􁚺| @C@-B66$s3.(9 4i9ٲ`v$)G)Jѹ؊\+<ٹ>?jD@.@Ս2a`>Kt$7!g ̇vVTH.ph)n8qvD5T쿳 jvtmDU77\;GEV?4F1G?<=Wl=d"aj[_Y♇qLk31cLdn+E|P=+-8 EQ /*HoI5s"IB$g\I Y0ᤦyz9rk0;=`pL,y'!^ ,pjiIjF˜֙gX@f:lGNjRvG] VKqc7f}ݐ?g~=zo[c H0i)pe9YX9$cH&~<=]#(@W':%X@jW䟳;aO>P̌f8t4X&¥-=V> &Y00?!Y8y{ǬIgc#Ocn[r+&@KIsŗJ~Ij - Hc2~oE9`7&cĺP;=UX> Jr8og J S%8#G/.plPKsIJB!aIKH4*廘`|Kqv]yNUg9j-΋(fNrIl&ʯSPKje13W?5k"A[侕Y)Bԍݔ L+qnpRRD^`C4Ôa¢.9nd䔊>J67] "N?K;sq9y LJ˻ F?#8ރi3;qꉥr?G9J %8hbQBqbRzwI"U6#'x,(.g4lw PͲ͵B#6VӨG2Ct0x &?"-˜vG|qRrE"[xȐbWF;wwy3 sܝ< !FO>Hy:%n3tվq0%OpDqĜ8ƝVn~Q(Cr vMhv%CT۞ٙshv0+tf؉ٓQps]"IqߎaH?J|1 ēLQF:(zСsG0b;Ǭ _GpeSGFKDšda.?f5 %ē^'p ,LR gߡ[(ֵknAq]cr_&r,3p~G1 :- L΁H}ruRJC%<lhY~v=]䈞7!foH 4W''cQT__ _\)XP[ 1](wQj [)(F)cMaJzN$nH03Yn݀Ju$-Ol4j;|v flZN::Jvg)jps+KίfhcP?ҔKqAcVRhΙp[P18/ ~g䭆CXj[sq:/nq%r ֖cYt#?Pu0#Юd )aba,jkF|y#GLNΥVg ߧz{ H%k,\)VX`8KhN9= ݗw5 0T ]ϋ,JخgOxOH9q-~>r^KvN%C!`"0}f[­TC(sQdv7~nǚ۵uMM/|,A {DA?>A0ah `P߻(a΀~g)>1Z%Bl%;1zPrPM$|w@ܞf`@K:Cg2fNCӳ>qK|‡C` 9s $Q^ n8p~5aj  4{1$hfH8Ja& 9B4R fkqԏ0fyi2@B\ l<Žm |YqO , x(I\6+'9^"?(R]Ä+JZ6!MOH,H(3ffW hN%=Dlܸ9@0np3:Q|!]K> 'Pۯ4c)HB(%WFGm1jߨ}$qF| d<8cNa:??=x`f @ODbB 0J \JPE(F) 2Ҝga?ثVI(90UQAJ' BwwUU-!f PhDjH>oʼnPU2ޝ/eA'B! g#){rv!b6~7mf ۻ)mvih .Dqd0䜾R8ݻt8IW=q)H`s=lpGܓ AZg~?W <ծR" >^Z`͝<+l".n|I]- ;/l 8a)njeyaHgw?(۶8pp56PE)d4D"f&` Fr)qL``#t en?D?t'o;MȪR]0wy iBAO1p0? ONٻ2"d~Bae'tCqZ̀tP ,XkӲyWK'f4&; ^#Ǒ]º\+5yζÅ3ݩ\qQin3ڐY O)DݻA&t8gBzKs @FV`u RV| ivu_OMXTJ0 eJbN7uپdF̺}>t)"X7har C=ʼnq>|Pi &Go򇣷7϶(QWa?&dE)ySh`sci6}H+ڝ D@J2wp+36wtڧ!:xۡ 0͍ajۜw ha>v,8L]5w6RJ/!;䄶K$w%slLwSg FӲR hta~f#V ߇88Q>Ad 09Vx 7 `'[#0Ѯop/`G1>]cŊD;9bcxr2g+>w$-DUW(;1̵ҍ/PJR"1-aƐ W%̣MHRǰ@(*Z2?4.ȃhf<-Isy`` ІnFoO##`E Y-AV:团o3n;*9`Q!M%I::4V00ἘW>1,gmjp$j9Ac;0Ş71+n'}>jY&"lQ0 / FY\V9-XQd6ۀYtYiC{ =#-anN 7@`@aa,tS({uOu  >Nlqw"lAo Q)2{^Fv P#A1nO:]Nـeh,(őh` R1#BD~m (QRA ` K~vg:wIh$3 ƔbGv HBCHՋuut71Z~w쫡[d' أ gfUb!K⇇NOJVq0徐GXGvJKղ:sgЭci/fBun^vu1 jFkd86@RzPA+Wc:< 1iGXIp44RKSt!@Y]k7RWGI b\}Ġc9'W_Ǐ IzAlrVt `H͇NQqM7ApFK II %rbX!.qZ2K-}stZ%B9IyN<XXx\#' vq9.ȽYb{&+\ )%xRsp{ bFp7PGK~/a]ld mSm`4 p15dy !K-HBGwe*5d3,[V[s9[tsWWn3P|]PalMr@RY]hᄱİBr,M 8Gܜ]ҭhe^.d _*݊0?$0໻cOPN v , Ѯ7o٢OCI?C 0dB?LVn{'۪` ` ~q-cIÌxCJF"W @Pq?e“ep1q%øJFCB~nLҤ 퇫~#F?")pH779$kCqOMbIpq7#Ma*W GLş1,F c)HM"Ԯ`nJFO-~~OO [$'rwJ YI]|&yb)pp57W3tsugm67#G2Y޹F`\)K+)5Q ,>b\: 0 Uk:GRCfs<> @#}}#ml:i21 2q))3wlvp0s̜ۻvq\4$) DAw iDŽs-Nz5Y_WKCX6g+ZB0ݽ,0`qCσm҃IA)̖^쐏ԒN58-:u^ޔFikRqIOwp”yC ŚR` Xl/]jf37ZF/_"|uKő#2mVrv4njzcSjuS & 0E)M0ǀ "8([ @LAhZVV{(RI)y=t?p%(Qe!)tccfX(e¢Rkw<]W:EgUr4qP 44"`i 7 fY|%4bI ۷֐?Ҕ R[C Yf vF?s`lٺx E[;;uvFNY?z̢J bZr!FS|@l2h!\ r@A)6ҹ[AhBwp 1UBRvvZ(<=1?4ʖX.3 %*~x*0St<푟cAIzA\j"`)JDL`t5R @4 j I}AGoj%7c1\=ZNHr|L!XP`%# hoZXԤy[;vAfqOB,"Ĕ65oة UJ`g= tmQ[G ) pR?fS SG)JDRz_9n%OUv$bq!:/|6SfcXtw D{l<8:qn+3nfHфS;NfIONq@3Y:ffmasnQ,*tP|nϗRϐ3IvЯvqvwUe!LPs*R=ٜ$ bhϲkUYN'=ay,}uV <쳇OvVa0og? YJ4~GW-f 9(un^e;vݝc]<`S`G a掃9!+1r} V~Xz|+)gA 'o0#P:?XHtFgaG taq:}D"!EYv17(3!9P xH 0J x1%^GBG0{9?g`?$ITV dB|F-a61"iE< $e,t+FX8αcPVts8Yd2iE 3%! 3#)BL0hOeXQ.Z,\L,0ibaD҃\g}q7 B(A=D TL!q@_LQ |vBb/ev0:8y -;t  $ F-- <bKBfteZR5 E);f,_0N%G K$)!}*wi_ĕvPGS89N>hRsx-qI#axߐt$#qAΰ1)=g$DJrxȿ߸ 93pf'6Ƨ0\JY$'@@\RcQEHO;ttYdAf%ѝL5܏wɅp2ٳ4 2Sʮ[ 0[$r?|c9ՋB];%㼿O !l7F G>:DJ+NV-7c_C3/5 }&qh~?nDݤY⢑6c[S2 h *rStdZu`eYvcQ*ep󜝂W76ݤnn<}0T"QH%k_c)p _Qƺ'j*pwUWX~iٸo[Ŵp;- nQ)!(2cLzqZRw"wi n<~R7wq$z@{Zp{ad<8bKT i3fNB@nyofA~~a@xJhOaH.?;e>v] Jq(@n,w,M|c,ؔ13ÅَzuW`bw"pHn*7Sxj 3L Iq4Ge\`u,d%=aLy)'<\Fn/vv0۴qBG+”O1 ,eF6OoèIG\GfVEaf=q>, -bEDA4b ׋!8g&n8V?UvQabiy&S~ 0ݍ e5ٝ? Zi8!y*<ĚGD2`k7:N?->## XH(%Ƭt ޝ4:,sX-(k a$zGG^?,ørb)e5zNڱV(' _?Ũ$h/WZ@1r$td 5PMZO.g ?=ñֶkګaŇ4֜ˆ1rV=bc:g3E2݌Ss !xuO€fy˜=:dґ8Mb)bvNp7 3OQiKe~Y5fNuO;[rX}<ï.)f(qFA> jGR& ~" CPVL|q<_sxNf£oHp ]DX\ Ҁt&tI_x8 t$ Mup&X)`>Q|3-aNr gw (&G`3Lj6Lֈ,t RS1(XƯbbw~?$ m KBvYy/r?/1# 'ij_bKc>J 9 nf~;/5d! }J#.3\lr= xrM`u{滑%$wS5ؒq[-k?Ls G/7Yi$#Yv+)G{rc8m5Hr#CwV?" q! #)CÜ#~7nd^͹>(,6" ト2zq]u:yB ,+oګNXvsO8~0'eWRPbQ۰ӯǣB'Xge%$3d>w ' PFjw')%nK ٸĥ;%t %Ok0w&Yۍٔn![FI fN!1XT3-Fz41Ɠ”v?NjVXU6pƀz|(ln|weD? w~͏Kgd?ҔdXK8![VP")b-@ߨrY;9wa?" O ,_C B:r8M}ǥNzSKNyO& J0&a(6i56hW hrpNߖs`,  P "2N )aF9:ǡ]t mƷfvԳXq'{mߎQT;W-w Yȁtѻnمsu,q>Vo<\40s,OlA#ܬc! PcJ3nm nx)lfxvv;AN0߄$c8$۪gF2܈OC;PLaIe~( [ c)(8 A \7PZIH=/ۆ厛S<*ݬ@b([s'`8 6vG6K}hAe`rrsv|'LQ,8)aЬ:p4MK 7mW8; nF9]䁜13:"9_8+` /RL /(6hoPJ`x XQ?0W˖TE`^[+ACJNuǨ(0Ro|N?q|ך*p[ ͬ1#TxHV W+,9N0H Pxjlq?I`Ϛa0*i'30 Ćp2>Jv5ѓ$hnŝeҜ_G N8 Kw@žyZ0hWM&Gy|D3A( %#{ fj_(`CNS?וpuaC?b俓ߝN;+OT6C)|W̞"4\Y+Xk[ؒ~YVAC_p f/rUN`8xu#uNH@h$=àhqV&y񰅇^&Qn3R:(1҅﹨p6-mgW$%D H3e@1H Etߕa/AdYʀ@Y$:ROc05:6a@!kn:}#n3]>5M?G[ieaGl[aPЍ{ Xcu N+tfW/)yAFEL0_º:-05cr7 Ril4[###luG`(7 $0UaE*gsd':)=w`+˔Orut@H! #)bCJI)7A@c%,uܞQNN&G-A"x We Zat,rRPPa8.X̔7HV ).^+aHN CAKb `NJoCaE3SGpc,a`{DeTے2L{Mv0yt$[:O҈5dsTgF$#;FXQ+LKP1fnKYChDK1.VJ( AY`9h T@@pUiCJYD Z5J0SEK@amh>['p̥;uf$1ocN9X;1p,+,ΠT(! -[+A؝MPCIJs\$X 8Bunj NI%dIr? Rp-~Ԭ!R A4zE?p8\PY{!(g&n/uu: %f.8/1l.V0|K ;I,eŸ ?8Hݖ>)`а44'1=aYdN`_>4w;Z\Mgm زpV`\DGu7C<K khC ^XNpۀpә1c&H@*n&e-4Z~NH0}P\%־rC)5ƸC}lmGO8s,‘eЮp,WfK;j̿wT=Ǟ/l&w ms/So쮍*d#Am܈FY ࣀ"J6m8F%Cv#!S( !H' ۣ{cl -XBpt1 !!$g0|` 3jx sУpDC,n+c- ?"_"Dƨp[a OIF92HŢ)0P ;9e[wgg paA))SoC;Bvd7 $nr;V%-xА֒lk^bAu0u݆sD +J W;|7$ w:|h*S3 S1ݷCؒ,snYܾ̌[%R mо)?Wh)\6(@b4C;}-Cu6##&Um|Q< Gh7w8-xau%x;Pg qZ E 0I-<|uv,JDLKncJR"D®xvtɃ4Ll` |DiRb R05!K~Znve'%J42Ɲ+qAA[5)S R1fӝHe`]h>++Pr^ p.JΑYspjnv1@~F´5B84H]?Y/:θ;<. 1D_B $#q;y4 d 1f)SQǟ05w@tXRXŹRF|IYPK# 岙ҐK %$!qhSóL)k{ELFQ4hoX%|hI d2:{:Е" xvN#Z`yH (7@Ld 2S%#2n&$D0D FܚQm@Ia))~@xB&*Q43A7ap:O֥SZxh (nӎcDq7x$Ű"8pR7[/g`P7s+@kB )!N4`'vgYŽF(o w^vcW!:9-|e`!% {,}?qsZhnas3v"y)D$vlߘW Oγ:۝~]Rb Ԓ9p{ƶmM SxkVo=ҋ ADX`.2`N݆o5 da+g%psA&8]&sn$ Gs>J`8 9zٟm:R>SsNL 1BG4@f%߻ȅ12;v߭LBbX]9ŰiNfcK+,Rn8WS>َB;|{61s~ݨ\bwR le9죞cJR"f.2aH(a,-il! !V`sS-RNvY|sx?"#0Jwm p+G.[VsCH& hg7?‡԰Q7Y߹fw}ߜ-ی?\>?"$\6ydyF}NF"+Cp8'sW' vAl$j77d vY԰Q v X\"IdU`P̎T0Z`ܳB< ?,`~7ڦg1z"\LGt+Nr;u|fs?(SRX)+iK#@ t9/u 97u6u7^Rٔ=K{Ip~bF?Ҕ5W ܗlZJÎ˧GpHK$dO c< -`0 .oÍ n 7\ [8,* .M&l  plPS1KJ(#-l#t9|bRx s%;d%I;}!S_~f8ZdJ$@01d94dN7$#'%dq I &ёS}7O픳k\HjGWR?:ZDUMA,(Y)0{:(bI}#B)]oǭ(<1i(*b59ڭwH cv.$$Pm{icZ"qp ,זGEb7M0U,iY96zTJgL[2C:KȷzzJB{1Wz>J! ̀#)͡ꦏP\y1 -c9Nua)e uڼ0-`bK 2&0CsujWCv%x'  % /@TfsТJ e9p[ 1HF!Wszܜ`E@rydnsґ2N&P j.K ('z.f391c)H8?Ҕp[w3\+`[~Pz8-agcF"e$c u;0u^8aJ9a4_Cj3:!.EյA3;wƨq>?{5<47w,8<\&%,W Bу2C N8r۾X*ͿrsH>}:eW})2 J[xd0¶%'@~QtBR,ڸ0 N rNlZ28Ǐ۝`ٮf E tX*[Np[bܜWQm}iWbJSdl~d w|?)nLJD q,X?§F"ABws~ºGNp}<|u}}b/"[%Znc{1Mx{Y̬ɄԤ#+;e+Z@ Ӌప">c)nzYa.W0fGrV sx|:Ĭ4-g)0EynQD ʙ?Ҕ s?ҔD>@I$I0\B Hnp0r=07nR]J=ItpTfu Fz <S1CJDK[ _#+N0-9KaRN y׿rL$е}z IGA8g0, ŀ3P|fyÀFM؊Ҋ䃡@t !ӶJY!o?a"u"&=!ԝ(l'b&E JRKv?(0rRY'ڀ i,߸ܗXy rY̦&QG⎩BC1y,D P7ա%$3%}nvø_[LIfqZ,| Gsy3zlXܱd S8&XT| J&hbqh^twׇ}!9StF Od5©cO;cD'c;6x?ҔcĤ a ΂МyˬDB)$`;~p`QcvgA~z[0e)\W0S L4:p6w7`( AE7a /(_Jv3yӪ"`S{AA :L(}]"'8-`P3McUpcɠ4Y_CjY> ̾0lЖ<ϸz;஽.m!a (R ņ7$FmYls@K|GDる-nD7xBqr0['ڑn+ (E (Naγ!><ͧwC5ye՜WˀbY-.Ħ2pQjF9S 1æ`\ 7@ wƍ|wfaX3C &nI@cownA ~oRIe!,ϝv! #)\:nw?Ҕp[W\4D0D#<+d#O {࠼Ea)Y ZYf+?`&&94J6Ս|cjYyˀ?lo晗Dmhr3i@dwΏМ9{5,*YN06v^ uʂEB A}v ql;a M䬯#Y#F gF gN\>%V;R a D&M-BjX蚂ƔZ9a XaD-F䰎IՋŻ9nr/$omBwe;S|wSYM!*,Hv\lJDA_$RQ/d9?|n"p M,_9YٷXn 8/k:!$VB2@Qƹ- -,G𿮞 a=L2l22ґf`R`Ԍn WY|*#RFӜp"23-4NӸm( ǀk0coJJD>w8#?ΰ:,Fι=1B3GtCݿ?R7+kT]u;9L8?'x.ՌqJ9]4/4pxVǁШ Z1Y,#݀,X`:|8Hj/-ÈIn9*Y|>'B$xDi|Rv`9!$$K=(.6ZΕŎs&N"xǰ jypݴfv~ >s/6X[ٓϯ{"85 Ǻ]Ǻ,@ߜv"N-=H[ m0K%sz18H7۟BeDKI'>PBWn(5JRXx\ZR7eOXT洗VHZ($Y-pp,N7ۺ:X#9)=nw8[AHDŽIΗÅQ-̶hZ̳,GpS qsB52DM> C;QLG~#/r+i杁V{Dg_8I {X)+Qud<ҧU6ܣ,f,`͝lk~ƶgp^2< 'D21#L7\jGXh Odd&_RJJ"1l#TyPH`9'7> ̢C@%K/ jNPZUtnܟ/cJ/>,04%(J:QыBQ+qyX(Hnw^afnmt+h~v:1kƳ!NjɃBIv#tNOJt/!F{XWqu@6 %ZNQ#,d,f1ȣb&&ӐFVw=V+ƛ8x[i#O aE/,#MH R,@쟭h )hY?2h XQ6<:H G&|o["Wm)6JKzźćHAw(b'7  +:n~ێ|nnQ{mu t4audbXփW3}B՘ÙnMf`ݝv}#i@ ?>~8!"f*X1[0`E ctvSw"5(E9!%|fω_)|d㧂6wp t!=~WW|;GNbqἬtdnBy{ELkh#/Zwl8(^2XCO~F'7A{t#'wz+qF8Bcֵ6e?n)cD-u"8U?c1|ψVfE:q2Ճ|k6OI-A-[fRݪg,1@D=|M &rw}`mlEH,o/ NVKa;(JDI#۷@~Ϡ GHqI ̂~Ab~z0pNhqiիv{1GˣJR" )Lsuw^ppi"ai-Ɔ$JpK/ns~cD"E(C|Ǥv "^y xZ?Y+;|%MrȂ Rƞ6AS-`d8%`8%1LK%Ur)x Or$|K[ JPU{d{))bmc9@g1gLtn5)j0F1̬`c~pY1% h 8` vwHOK R|M60ܪ?s+`ou=2G:x@tM6fTͿ+2(@_tvUd nLJ+ߐ@P#1Dll$ _;! 5 ~h0 e@\!p2>!ښ 4L(K%t CcI_~4jԦ̧.@|Ab<8J~02 0e~^#'x( & (@7"۹E0 Rm8iD2OG;Yղǫh ۂڐ|ulx"Ŋ~'[&}mѺ{w f -G|WnX\FN|nsC1g! g#)ҿ/); =0lEеnEtsor@Ԧtb̧p4Q+ Rv;M$L"/XChI79lX38éa& #)H +3>KayahgZFF/' ,acVc)g;>vvum(qχ̘6ԃ7,ۆ `[d$ 1;a ~$;6L3n+s9+a/XaDr(WճE N H ;&)!A j ~7$I:' ~Y@鼭Uٛ,n%▟9bՉL" ڷqJ‹F4Ąχv8~[l_遭V?Iؖ&Ԕdws "N-c( "`(F d1% ی-ICuWbltf+X)!R:Rkl!t5#DĖJ(5$Π.P(YA> u7%pm.Ѩ:Q_?G@NlY^;$3ƍ16)!tfC8Od;n3v~ /ef)C <$=ud [+BfAV,K`(tfoeߎa-GD2|2i)يGD=x> &~18 @:n;{ 8¯>p>@0 (Y#FN1=Zbe}XџLOPјKnkvυdg(a/Z7$@[m\SۏG,1ن`#u_=[?}YN\"N-8X` <|V}ƥJK.C4L`LMDX`6qn@je 4j Cw:Knc3-"*uk &Z?G<^Q'W?vRF/Yc#wQE wsY43GNg_;)?v4QYyPbC O/%}hf#?p"`9K,Ŵc?fFwAE34L %g? `Bi'$o;eF``ȇ +kD2- P MJW?@;@JF -= \90׶Sq6+_ _~_bFPr$<:`ð%.ta䀤qb|@Xvewq0nFt (?[)yTݨNǸ>A7 9s U- `ڜT}ⳒΠy[\MF JSk ݩYϹ]QlHٶ},_qaS*)H Ivg1qv![ۥFujJ8 .؄D  HhfCDIj~>PLtyV ~Kq`q쐐!@F $4JV6#cNaƯi;g4 ~XCή̕v6 I4V-km'#Ψ)C8H~8DSKLhxr0 % 6ilZ3Ť7VD.!QE?3v`JFIKH%c r?Rx0qI…sq"B;v~G.ۚij.صu]*d`0ZN/7q0[ j^KjdG[A ~Zk6|Ax5IhY''1 [;(FHc,Z"` s ?:졻4O7 q9p?( qe6'$|4C`$;t{(?[$7e%lĘp~_0A$cm SF~l-aW]~ 4rcڙ/8pNb)ņƇ,5\al'wS⮚ns~c# Z^ 3'gO1XhqgWh%Հ9۸7ķ,o3v̓K,ÌReBqܔpf·S)HD$=pFa|x O8Qԇ c}=1&0Fs&CJr+,c[3͉ POmE2=cF0CN`ٙW?7cJF" ` p2gS!R R6Fš LGL"e‘E; z8\> ,cV s[CPB&dZBN3g%4AOg0@'>Dnl]\ӂTU;--@4^ HľO l%\X{SϷ3##;`'0~mNmflm*aG@jJ y XVnl5vjR"qѝlP/q9',%!Pb dy tX1 YLnFG&[(,}I\ se](]lO"&A?lu])7*X-aḚo=p`e;>q] 9WXAŖo[buћ񽕕"Ua`7)pݻ't'8u?u,݅X#VB6FV3hBRv o?fVT ]$aG(*(3'fI=sR抂XrԵ"a0h'*j?}A唄W|+;J[:v< nF#X8mW130`F+y K&Ĭ7 $h#΁LHIw:1Ev bw'Pgsţ /*Q0n-^1Fp+e‘aLč 9 B_7=dC`ǁ|ö靫`k]9 hqhn}1 XtI`` |YNAu2Y٩ѬJPh;>!]{aF5&HPRM3I4~B佁$$mjO7#KK?dE,ƴ$bLLşbBwSSLaF8,` IM{! Xů1S͜/9fD//"R1P}+®2, Yth0N>!wJ=%oadzI{,tgԨ5\҅L}w?yAׁRY];,N"oHbw+H 21/~#70EϚNDb,"{笈\1fl&$8[@?vn.md2:hK3,^,3ohdځ_:?:WuREcnY+}HpF tZ79X;5$rw)'؛8Ol;/GZˀ;1*ǝi +) f IH/,2uC2 QF~NJ;T0gd>N<0 Fod9K KbsV7$ngAw r,E^ F֌_(-ǝ.Yep; ;|lPs4 Z%LD'uǭǩtQ=wǩm8ef` N<Ϗ9KXϼbT ! ٙ#)җ҉_pvʴ`Ұj@Fc.g?|!ApH{n\εDBB$SJi9?~HPYw0h'uDxՅ"[uS4cqbI\l*9YxY]K`R0j9FDe&]_<*YHx N|0_=0IC_Oh5.yC"[G0?\ޕsK)1 HW#(pxWNN dd=/8ܤCG(o & $ R;p?[oc%=;p=usntqd XsN3}Ͼq)J dKŧ7d#HI=?s,tC  l 3s@偔#?apwϸXŽsPJ_vǪ "+ I쐻f4qET*h'[cy֥eaJ+=U~}>ZO"`GmppN-вXXNٶcpЗٶVy@q4,\$ݻݘ% Ha# a/85(l~Ycr a>o} 4ud/;fsnN,`Ĝ@!4`x{6#@7'}~ g5q簶<> R|ytP I,ĉ"J,%]#=шH_,ؐ:KejZSq$JQ-Au!/;x}r\`l?s90b?pb3-L)C_6K?1K=)8AK'gj?,pטeErPI%eҷIn&lVw,(![g9|uF,>Y;+wařp 8wl )4qgqf`찎^9rQ}žBi%aLK@_#s}% qT9Oœ(3L[ cF 9qSL&/%Pk-f:~P{>%F|K3-$.eTF u;3X_9MO!fQNJ9̵~#-ya2Fwdn{7Gϝ%\eRg+8tHC5 "1pɅ( 1WS?JSs`>pqaCr#SφE4hA,~z#]Mp. 38q^(B& )k$9οŀ)8㹧-Sm62as!b0`m*Z\V)tp NX:S]ǁU6xNX,3t[ w慛R0Ar|lSng18ێ&^0jr>5`>gs6XX,;|8tJ%ww<[x}4#X`_5yҬvNtR ml4$8B <b5)vaN8=5n:8D;f8rRƶ_FW C &tbPC$;cΉD4ZW$$ =8vmkTg$# 7# ~)-`7GQQOjͩn* RPP #&jQ ٟ(@Xv''>n3ym+N<}r!X_ \Slo!D|0)#JJ[>PJ;}XDtP1UJ {OL`H[w>2 `jmվPf[ 5V[}!E3۱ [8B\Ne˺|"?4qÌ'hs՜Lp=:)%tҖtZba;/|El.O{F7{`cvzcӵrH/bKb=[mV؝wM^?x3$=\j7*(fP)lfW@3; a,Pܖ-cxԆRfX c6&lJ6Q#(c?e7+9)W[);uywu+О. 8C2 rϾ;"G4Ba@}."XޠKZl>kh Bdޡ':@|;s\ƋƁ? ! KOw˹(#iRgs[mZL>ACPYhf ΕX5[*4#79tM 8P IG8 (j@Ágѻ$ %wXrq_<-3BRK)K _ZF h^ qS k(k-GKN$ Z=Daq(3 1M(7J Av/s\Й0gA1N0sY.BkK..qmJAF(XZtv[+PP{”G0E& L7D9Xځ!/G٢s0{É MTzp8ߎcRA~/B){ oIf#-ɠ[c@;@5}x8Qu2w7@v`@# 5J .YJRxJLcN8ovJJl5kQU@1JK)60UYlr0Hߌ Jy(jA|aIT)xؼRxK ,%]|^!'nl>! n;r/a0+,̲*,ht%<ܾΑ|f~+l;J0kZ ҙ)H0~1|xv1;  ! g#)Չֽ;~/ na Ğ Ȥ(UN%[B !Zy}eAs ~F(qDh '|E&߸CxA娽Fw!Fv  yT)JDJ`b?"0#gxA#llwu:9R%)?Ҕ"-[v#7JpLmXܧ@FBЦ֡WNsoAt' S; "2 E=j8|kQ@q$s4ճs?ryƋ-qǏ<(#0gchV>-:6FNYԧ22 h0n%ۛY$f0X;י;q JJ!q%x-k?@/9J`{ֶ^ IeJ158W;sH\ l<盖K` \41$X惺%;v; kV2ꂘ<[҉޵pZVRuy1 Y{+q  *wsK)նB"7V[1o^LJ P(ZxV]ed(ܾA«=$ӔV~rSM-8+tR4Í=b ( );e]c̰( @\jht!8g5<e7%FD AfX9'3 уJ8$5#*7^8#Ȋ:;.kT oah,ՌpؒCJx΃UqpҞ oNOr4Dg-N)Jv j +;u%kVOqcPsEIpv1C 8N8ABh"V/H;lB 0ِZթQ ۲۷a>R 2î(hHn@JFI/NOXs-0Ll76UtLF<0l#uZ;w^7] =cfS0XKғRF9c͇0.P@n+!! ̀#)iJqKY~ %5+~h$(uڂu!%vFADgwńh R>"CF9 +aF yvS.a v8HP?Ҕ- ;#;~1A9/)#K(j9 #ѕsC8{u5Qc #us65fl[v[3]2d?\sjLJV?ґ)H$k[k fIH=;nOB)|kbCI" &?1f@ @bK1 Ơ=G$لS[`cI h'pc:V|&d>a,=ߝt!e9N/+0jfe2~72PUP,Np67?? `L~ُ_;,:DҞ_@ omgKt:38>DX0  ϣIDѶ7YiHԠ,hH0L?"$흗6Q3t=e?VQVJD:|g3(Pcf R?/K-:W?\'&vQ5! 3pɁBbQߧlfu"(”B"RxVR@Dп?gE*ҺW3yzV AHγDb+3wS)xR Y8j9υ"ShJx=!v\%tT4JܦDu p @;IBd2PJ7;-]k:N pAcJKn.tn wG( T #vI#څyO ;H’~.ӿ(}ڏa"()Hŋc{);_SDA3Lku\EД HՂp%)jqS2w! p RdtQe%!?I@SgcX{\@@ѭ,b7f{)Br7Tgٳ@5CL+ g CoR)[2Cww:`6vll@e#ʿJrqp0`vzL! 3#)( aaH/1 =)L+$Dv"} 'SvE<~B4p,&8fd._~R@l 9n@'2V JYH2?g8'73^!BgaiWaPK=]i5(RpI&YDz;):3FBb H3tRT%ȒP1cC"Լ1iHЖsO9^frŀ{c9}bRq|jgi84dt4wQpH1昕qkY4afs@ʺRI1 #9͋(z,PŜ3Fc1l :enZR4ğI00t[/#ė7\$,5 W7w|݂arj@y7!ُjIgi= Rz3Yh b_ajS/|3֎@`d)vݻZ%>uPE@Oi`lŎ?9DmaBxХ" ,RS{cš=?uaPa|8g>5F]: rI5iC?ZT{:ahH|1泜y>!5cVKv;N`7Wﰧ~5cS|ǁ$siXt?"(#86k[rtE)L Gnxtp `2#hs2pn $ec2Jq@:h4VJYvwϹ  LBA4",fQ4n܎zeD2n+en>(BἬt`n7#[8#tX hsLn;S(rF/sy`LR hv$ݻ>qݳb YK%Їc-GqςZIUk0 i(j_Ʈa Û,a!U' Np2g7 a15[--\B,Y (ns|A)*b(y>  ~8S 8P7>8kG6("edЇD`r.NjǸYI/f4O5 7~Gp/VAQx8fv ADΞ99X t#|n h/b xqE +, Mf,,aqSk4! l, hYaydGaKD P4f p,7#Zw$r8TbIs&Iċ@3 ^nCQ1)!,J3-90?"()HD% n~q7W?0Qa1$b:8wi_X I#,S~rXu2!J;Ow0,ic~Ii9#0@z{Fgz??OaD)N$x3Fc\L6pH/(9M[/cU|:aHQ@v`rbz3RV^Y!;φpG$ FNM%$+\d\'33k*@p7 ְ.JC!Opc I(3vܰ r(/NϜ?|N0a.c9_Pvc]4F g3T|ד $CD,cdbJ ľ9)H> P/%0g: !2PBIB1$h d5*7m_wp=xQ!)Hp-QSYHd 4jRvf\/%*N{kG}ývQZ[^ Rp1Z]~:6xi3?f4ܔt2K~26;9,b7gـ  &~72̵w)4 ?Ҕ05f-x7yagA BJ!%tOVXQ@%|haj0H y kdKgm~ml#lCqݏa mc)^Vmg @P!%-MG-ы++\EdkĆ̠^GG^{wԌ  C# GcHښ-ݾ^|):&7TRhdDSon 晱@/Yn?z0@aiN|5<@  3ZPuW|P3W aJ Ylpv،YsrN`3d /;HJ }{&rɥ_lR6'Ca0g0dԔL=!}j\-K,.2a5)G99{esp,71h 0M# ]*tGHk1B01ADbF?r= A`Gߡ@v`Wt)*wB_mx ` QEG7OGx@<KFARt0E!72 ~5$EFA> pJ9]ۺ B98%W\Baoٟ[ f+:d8FAL&e)ŐZ h:Y;١^8@hE?<Q!\=gN{Neo0D0N5`]0B >lpaG n jԬ˩PE-1PXVTȣ+oZ #0-62 QvJ r9$)bÀM x.0hǩ}(b!߂ $zR͠BC@U^ wqpk/A4oO07ƩanbPPY7@B! g#)͋v15(Ȁ3<Itg 2xN!9.nwRۺc_G6TJD@b΁ud!=NG0Y8sԁ J }1 ttC=L{2l*kghs>kD!)Q9XHQ9R :R3OJt~,K9Vc_cуY \%yT7vա$o8c+Vcra07:"ʀ`o% &n7bGN8x(p8F``BIe D#;ܜ0~y,jOR,Ӿmуj?`Yq,?΂-!i38aAh$;u%P_ %o{HЛ41(zH hܖZzĉ? ᝗3u9',a~9gun.}O~:HR"qmNqF@Dp$TɁἛҀ0tsv+ji@1}0Nd%gdԌEta" !͟!=N32_ [3K%'{wƟHz:hT¥vT>(ȈAKQIF$>v[Bcvn^@%'|SvߌO%?tJ€`MI5!B+Xk%!]H@GbBFU$N R1H̄fvӂڶ[  oV^o;sTC)HɄ7-ApQbhp&uylHTQے|aY@;H-I?KMkmٶH $#iq)`? xIyFl(qR7 ܌S|YKėfVrN?[XqB)b~3lcgo+w9laF̆€*|]`@AE|_ W~y1 ݷ^vc8@a,[D>?B8F\OlTr]`k.ܐP$Rl㍃JR@V3W şViXbw FG(ì"d,*@j1e|u:AJ+6m9HŶIsۋl,iFLd'!@sL#N9ߛ\F4H@bt>WWY> !aB4| w cQa5pW7HG@C?F )? ->Δ X@H"LXf_ײJs[n~S2 (Xjr ?ْoZXg~VJR"qk-tup F ˃! ̀#)1uMO:#lo 4`?RDfXclv3^UԁPbT}G1EFw'J(vCvƊv0] 20mXQlN͢+!#]_7e0(.F 0RS-K {TcNĴwbQz2i DQ(K7<! ^]WVaB/,Pch4(FfDcݝ_,=Yk(x~;3?P8; ~y0k bT0D" 3%v l"D1u B?+'98Bt _Q)je幋RxMA7dQ~T?>Ba)8[05bϜ'앍o@PM|<{%y8RX[0:XC1F {79gptJ" K!$#vO9\_֝=@e'E0}b-[\ )AJ@xj:g;$TgNe)}@^>+pic3MpI3َ(1t$?1ǟ sJWK9\Y@?ɀ!&$ ߠ{GLk̤b2]sz>J8wʻ]ŚqF)alP԰>CydkʶXc0 a$I|0d¬vڒGMb5:x )ƋcL(d!q2B.wSnyƑQdǘd܂aj[.$%hf7|Y.5!%g ` .8>WOːKϻZbd@u<ԻJ&]7JHrhY{|7!ɽ(0rZI`c02OG$"s ^  Fa>93(ȇ?Ҕh ͏RݗįZO،1B})p\05(_Gv](2KI)Fb$@TJCeL4D2CPͱ&0uބ!X>(HuaA;8HgbR03 %݀e9rĆ;. }b"˄/pU}?`6@ t CpsIǨS e=MV904`, wX;_ ՝Vd~„ajxClQGGbL@ Pr9Hi uDQY0`ڭ,z""8/ >s)?"%5vYF4~Eopb]a+ hI->^"hg 9gR:kph\`0ӀXt0%H}4gҼ )좌0<8h`dG.%#G6 8DF [4F K#F'D,YEũwvUWYeR݌`=Tj?ͣD橎P܄!oô-6efD<|iY[w|eSm,aXr(z1TFD<9ܪr)0it32p㲠,:kЄv;`wpGPjJKB|[o+fF콍BL#RiPY8ZpM.͌c6ACŎO]NViGv5#W:M-h G h p,r~GTWtf! 3#) p#p@D0̂Ҿ3,yY8(۱i, bbq,.js5T`G _c+ O1t<)0k3;y"s0,(Jo{~9n9Vى? [u|'SN;1QlO;<`_("(\5v* *d`V  R9ʹv هs>|ev$@CFa=֦c)HL#jF KVgi4Jxa)8q)(F <_xm! 89AdМ( )k,b`rLv5vQ'/[Y=C q:CH"h ga\ M˹0jal J7.3cNN1{%cVvq_nHAǬR lǁSai3*1F'sE8(&9if36 % PNf7C?vn-s^YMƔWve83I (3 ) Tve/hC,ar{q.'5@ *<۴1T_B:g8$-Xؼx;+(*N>r~<'r7794+B‘L`> 0W1>V-$%jX,69ÅAoQ ȂX 0Qz6NjhK0h~PR}=rjq5yşe;a<H`N a0' ;qh쭕Ə 'a?;'JS(k{ h0QiQ,= F=BJJ 9zW[w1(>)NŻf'5V u፱A 2]ޔ%6ۭcDD w=-O(z9/ٿV )$D,9ZglHBR1, /)T1_`NQ40t}MBT&ry(Y+e[$7tn‘@ۤZ[g՗1?KftOra*)H6ueYW_Y¤KAc %&*aZ':HEcurV)%Üe0: &~FlxXh ,$ J A0EPt22Д9N;q5$!BHGOݱk\1)afi)H vۜO$[S<BZ7rR2N1l퀚T4)pjJAIŠjvMlmIuiZ\V8K_XF/2۸H[)0/pz;PaŠ_f_虃0bK-a =ΐ49VpBQKX F֏%nB&&=}dHO8ps WlxpfF d`˜F9OWL!K0 ߣe'8{}$bPV@u=bs9M<:<{(e)Fdk6Dq2gi1)c /\=X\LNJK3$>Q+y!p bSPRpG|-c0fSHJroq9[,Gb 6?"h(+xO;= B0a)H`& 7<澑:i5(:rm\줤gk$3dJ@kqd <5R8; !,?=&,B`I)R5a5{Z vz-f%@2BOPr-Oob!9RE@PnI;X!_Q19CBO-vC@6Xy2I݃?[c(K&29D)G@26e1o mGj2,TD1Yﲘ׃C] 3:RҞaZ߸+lnۊ& Ga@;tL9|`pȢfRkM*1FbC1# ơ I#͑ gV àłrݔƭ",,P:1k}*,!8K46R7g_#_B3նjBrvN^iߐ4$b՜sN0 sֳAC?_uœ='(Sy"zT3|0?,H톍I;O5dVͶ= Br3+v.pWZ?lurMcbqGȌWw)cwc۰0ydoʡHmy΄:;(&Ɨߺ]lGeM٪i ! _b0r)d֕cfꀩ =E2~@U?Q0ᮌ:oPF jN4&Yx샔}Y*X/g: r$ X,*?3αrϠ`mX44# 8Hv]?vR<_gd c^vY)H mamgG~h'2řeݥ;ec;6wp ]~ؐ͏D2qQ`,嫓(B1{wTs+/#`P1~!d|jx9$|9vX++\5ӒWnjY߳|G4jxX_J=҃? z#$`P9A!<w_%g*W1$C8] !b<'W@jssw`eG1iL /wIfed?(p~c]#Ec8p!Iԣ}uĴsХzv/5"جwY!Bst >:(##p63\V"R Ȳ! #)0kLnDݭs2ǫ2CR"#?PL ,l@4p;#F!̱c'X*uӆqbi43`ЇYۡ}hpBmhh5rE Lj<_V!(8 HҒWB HGžq-s6H(f-i~/X6Qh_wϻQD(>'"1mI e/+R% 1v?5c6b @OtuK6;&옂&qgHIQ1-*iRE<5x .?SaRugg'efK;FYK寄ԬeR},f;yj j~/|cxjL#vsMB }RR0I`;BMW8t~> rEP`a1/-XεNm 'xPP{aY7My)۟.0Q~ Υƀޞqۧ?߯`|DaX 1A5,1M̻sĐq ϰ1-?]A& vgB(Q6QCIl143C #@-ֵ>d`=s)ǭĈc(4!zG=j`bI9 ơ XS-_[rHo'2g2?]GpQP uʑ3!'QY)KR5Ш9;p٘iF8_ /VGc<T3ƣuYr>r߁Hpl%`S鶑[vÜ0r% x ҋOA^c{:V?oFg/%{k0I̖ ︡Nw2 -n  2SdQ416V#$3{H'v 59>CJR"D`،"CQ@e 7#m<:)Aj RhԔ+-M$։Y $$zȍjT`8\yKH ~@O#iϜ sϜ~e5BR㕎IapX$Xv}ŷaiŲ9$@= l$9v45Bwn':6Ih/3H㔁%ăoD}R0mxc+pT=YcF)JpE4?c{qa=Ÿ*Z @3m8‘r0E"^1%gN0XwsӔ8@:W b HaV|s `(9n43Œ0A gcF)\! g#)Gy 6O eհλ{JΑa+0ߏ0kXVeTaZDg Ecyx|4s#`00?g JFvpI8d[0t]ǯ40n!NS 6T_4`YL&u,K3B`>$ [;_I bJ %%1/8R\hՉ텨h&4z^ p)j]2|'bGPJF "C!b y\jK% RֵmMJϾ%(gu7u PӋ+ `XA:fۀ 6E\Q`/6=i|ag g  M{1XQyoZ)l`e R9A/4:nL4'۹sC?ҔoşveyfSI,"1)bLd2CI-/>̭M' _=O0C;%ID nQ[ p10[hpY6a+ *Qk2 78 l;/;>[gb/! /lwx? ,E)AΒuIh JR"^?iފ  o8E57  )P$bB>̑_u0|̗qV^8K~0gL HoN\iN<} pKC@wؠIA$ ̓}n L&Zt|rF bт! ̀#)9BNQ놚:&`+p'`@P\w wi{3`ap7㻘!xzRw)sJ?PDƑ,eV-a F$!5JAG*$Յ4g&`ܝD"iH&8E!##fe8݆+9V[t'K#2\́člH@f%-XpVa = Hǎh^ _ynD؝LC@zˆ\~<?b)[]*xoΥt 9N},})KJKGP 8#~o+[s0C@?̐ӂ0$u)와R;1$!kȑ('ì5Y`A >A 71KAaVxy'O([I]}P~B2kF g s 2XO0+9{M~nF i7yak3?nsnPQe[Zah¢r3)B B@D(ZZղ&0! ^x"sC=gQvf&cϵ =N$v  |A`b'g1)ACzۘI>/g8vy I(H8iONcr8r!*{$!q)1"cbJ An|s,p8Nn¹Tݖ<٘%#.8[n-lf-AS)wdf4XJ_7I_KO^nqF7B !CBoqُqjMG{6.IHAc)HF , ;V}=1c'E8wG&ks0N Ò<L ݙB{UZ9\PU8gdϳ-_amSKuy9O cW-n dK(SKVjÂp7h'>5'?,(?;{A`%[lHV i)GxvJ TL@`ėƥ#Rp<5~ũJ1! 3#)nē_sugcӖrOh\QX<Қ#d`ȌRdt܌Bї1S|baQۏ PaNoqAgSqd |R?ƹ?dh<`v4]:# Cp¬-J`uh!=$„/r΋9D[53R1 Ri0 b L! B@с;咒 P4LJEw n*J,jŽ3: @\yO'W-20>uܵ>d`a X飓Vuq|sbJ|i, 3z CqXJP?) 51Q0nKs[ַՐ5= 2\UEdd1Y[fhNta+H0F hd V KK+ B"X9UL*bqV 0L:I{l'L:6O$s2gv0{Y(06֞0zoH%sy/x3pn܊M&PjA ߁B%@%8lw[fR20fL-L0Ej~ћg<7k0Qgc<;8"=PB ]%lsq&Il &ÆBHA:9,fą86vU)c}m!1[9oVeJDX Ғ*Cd$G;"a]M,9U?1)2LJ (ԎkW@GlH;G8R- R?|C쾞ďNķϐQYUT> qfVM^ F20+F=/_)!&e"O4  ̄8[8N J:c)?i$gluL| ~:308Ͱ~=byd(%¹@_q b9yay"Ne=  !!Ͷ;lf>ICQѓ!-3t;,=VbsgDe sH !8W {!HJN6/1a %WsOx*1Z fva^{ ´9Wz~[X?5 F4,a1 bP|s7ĜW; f08[K^cvebL唐ܔ G ! #)?D\t!)JO6,(LXgʳ*Te l5'~_%bbY% j2vvl^ё4< MF,D5`lrQ (B?c)h &8ԐA;Xhe Kd|V47# _à:vh - 3$@`pi-a$(jg|脐fw8=}v`0 5$F|ٰ~JGsca+i­A.f`67Px1RKIY; ל̲V ۻDLRGKļG"ɩ[pѿ.0`7|-`j6w{x}gaaEu1ctEi+Tp ,I OJRKؐΞ?Ҕ& ĆY,3G}yJ[TFQazЌ 1<cz`N&PKƥ=# `cmq}eaThaa[ } 1(W pd;W ZKLX@:F[_1[ lɹx`= )BF"p )I?] x&̏- <7l80Q(ygByiy*%vx(*tNS:@2@O-]>QN Ģ6?fV~@|09=?8 &ZrJl{>~,?#>XW4^{yh / 6[QOL̍_]fE#_sA矶{S_|t ?Xx}:Yb9 L%mw6_͆e;1?hoJZםj{hޏ^(n] 4-> ^vIg]VM{G8dvB (f%`^qκjdd TlJx ssͱ>Yζ?ǻ|+/T@,WJ;r[np?ą,~IKo5@Z2/_lD`Nܜ{G<)ہ81`%ͱlwNoKQX%b5)(%u0'C!Xc텩q_JsG|M$gl&L|LrQY{f1%Sl(X c.U'Zc1 T̴cV9s7nA'l_>cF n⏰[ d1Hs[×>8A,0`Bܜ:/gTh@*ѝߜ(}4OΜbn*a Q/j8s])ZvߟHqR>U <|ǃ$ge:[`.͸rS0(!bDѤlaKR pAK4rK†wA~' /Fx n?\5ٱd q<*# Sc0Wrldp]r#|F8R'd&;sWm`LdXvY` @`g*`I%qFR?siXlj@0jTョ:&Sv+rzY8>] BwHH4 IJQn 7 `&@\ωJA(/rK881nRCo7)[QS+n%%7_oenqEJD@.8s^7eJ;xbnݿ%vZ~(iP@V@ɠ0IlLJۻcXΧ͔?"$GOoJ#0h(AͩL- QOPQ,.c@Vv)(fu0?Ҕ,nrVBQv=̾ԷQ} ,ZC2CgtN9Е=(RKY,MfB JF`@h yKv@ @ J&Fr^A1Wnq0_:jbٝj9*t7K?aK$я矌72o0JAӇ5ݔc/>|)坖}) DAE Bw]Pl7:+O?-qDRT%|fr5%nŨё̔a'I)1qʯ_@?1)NJ6G+DŽ)?J? }v:dL RT=n0  ~P'wjM-!3Pe-9 "4Mk$qqҚ,k?iot,h1YNΗcDJ* 6iy ;^['ԏ%(rξ;&49%%y_7+!`cM@œN"pD<ڄ.L&Bs``YLw;}W!ˀ3:nLnо~4"RZ[II! g#)h$kļ8P/ qbL0%=jvD} 9yN?%g SgXcJR"f .^Oau:i:53 r0=0 G-)cgIp'L0D.n7ӄ8cnnҎqQY{AEыAxw\##?M"'k#996GsD(~r+d9H{GraEW$wؿa i!%8F$<>J;qjq)# u vQŠsv^=6aH ݕI ,Ɂ/HCA(7, ? ݵu2REpBka0[cS 6(5))}A(7"X<9LǨc?l&y,i(Lg< ؾ6I4g%nwIu#K,s;9,$$<0BZ5M 2 #b9R# U %-870`jRٻ$QL78k*p C Wr䠡CAeq bnΟ>%Cu5P3cȓ : &dRil1űF ~Xd JDX˛;ٜ"dB)EOAqCvp'X`KA4XK-=:. ")TPnM:`Ik="`UF@4 qQ  շsbu:ك̕7ض\`_Ϳ3lqcn1 ),f;[ ;#m HK >ᑂɢITN)BE'хɃOeGݣR3 edK`/#:?)6RLL,=TX bVw8= !9w[W{<57WLod+X6 *I@$ ɡ #p;ZS@n5ge2{-?u77KmbĞGKt&CzcC ћ}}(+-Z %rHed/ox[ DrjCR4hjx u,P@109[dk>[EiK&ɀ!%d$j Ph3 0e|On[qi#JęqfQ `BNٛdw[Ud pjTl임XU !sP><ͤ4b tOٷt7#|}05 g vf8?0QkMp -ASzfS=pj5w92^]%lSݖZF& 1pM+wII;01”0LNEaqV0&EsØ>BQ $ cG[RKGR H2QG JYP%m^b6 q3nY'| a($pZPHQa 6($!a_ΰe۩ǜp/-N~[u?ȬzyӌVb0D0& RN#ífm!!!(ygN(e*Lva1Dijt{K-gn[(pu,t40I5|.A,ߧwu$j0 />^hHJy%M')Y"Uԑ:ʉdf=؎kaDD˒;n],Xjͳ eP$ĤPqOS 8u:y1ta! 3#) R$jYl1[##;cD''&Jv+)H0f(ZT.I'n'8ts n4S?)\ѯ1T%HA'ϖډx8ZGxdzegs5lO;X7|4VRՍ3\Yds 10Y8o%0Ւ^"azT M]tQv-og7* -khwuG9en%Z+@/汇~[?Ҕqr4rP:F c9ca4А0,J)9 hh%#S+mG, 4vQ3 ,h3M/3X(1;AGBb7KEݽԌr9e!n>܈Q6Ikam|!l~[%D UOǚ)7 NpN:g9hf$< ÌB4L. a0/UjLفǍu6OpxZIDXXU3hU($C2,k44g-K 3}>J{$KDv:8q.,u/s?fŁlᙔŇ=-Fȁ{EgOY\V7Oap>"#s.w(Զ[g[w"Xѩ쭔aeCRR\(w•+CO#Oi0[ıZNby>43{r#yq Hg ack ĖPJ/54g7 5E@1dnpO8!@t^Ύ)fI"sc9u/K7e<,x+8.FM¹Of}˰ qY0bf7! أ3RX5J{:38O!Rb%gFXa7%(ߎpJ J /H))gCqHa_[elS!ز%xHOn#!jOKQ|'}η{"lo>e5 cU% [F%6RxߓWٔlƸ?"'0eS9nU,e"x9} h%Bz-|3#XA"h ?H=Ǐ _%IJ_pF0 "a|{υs ljPh^ 0lK%n#X؆CO- mpLM[-n%LQξ5%^Py@hPa4I\ǘ9%5E]ؕ?."̆&! ٙ#);!-OĴ-0hhn,ɝ! 3#R4%Cl%s-ַ1@>94k 4:9cc!; 8VgP։!i:L 'j+̳PRǩ^皬{4ŝG=mlo3MXՒb2;ߒ|8Rݏεj"V)xEH& O%> OOt?;!OܔYNp}g[XX|!lWЙ۸tQiIA =3/e uc"M'jЁ3܆@5:]H7Խh00Pn#G)(;Iݖ:BD_8dCC:3vG82I.Atn1#{/Xr_;$(x0_/Ml1)L 6qUf't>c}dgҔžbMcP0ܾݼpg0e7'ݝSa6fH(WBsqҘ]'M y$e;:8GB[΄nh&,V7|t+ C6`NSne DB!*1 πDudA dŰOi~Zy۝BvS) SI@\YbqDa\`~NsI TȂJO,f ڪ >}֡!ŖSrsq( M`3 `3w⎲5\) tXAe J3e~ ,E.K%.j8\7ᄢ#rX ;F[eɅ7mϗ--),\wWHir|`_qOlou^H`^HЖĔc 7Dҋ BɨO  o<tɉN~p@Ĕ(=K9FE9p *CR\ v %[;P|ɅL5-#3dH wQOVL4Q-ش$0%ZFX{jv%yJ(Ix,ǬI!lY)+J^3+ql XDbbK]DdR{/YL9ُ)P&Â[ =< #~֎&e9n`8L5z Hß1I-ך(ka+1ǻxǥ<ٶday >,9.۷VF^J:q4 H"ax5(IbjC)Ũ44Q1=р9)W[~r|Hjǟqh Q44Dҷ&T,g!, Ş,6jޱҌl.[8Ͼ-)-=)' ڳ]N H >w0Of](F H)Q+bKBԛ`~K Vb!"z9z, @tC,5V9 zOE@6G(żƵW:ӧ͝vyEEN- OP0pJƍ̧j21$*?}$DBUH8PCX-%NJ9yka(CZt4o/¤tn? 8ov )~R5hC)0-F1m#hRv~GpAC[|[/, a|gXVJ Ꮯ,bȇW?Jy|Е$n>,I2W~xa|igX0iH58i1p?> sqt c;`Җb:SE` ZRRsg'ߚC1E%}׹(yMڀ8v#8*et-#WGj?$Hhϐ=;3S8Ú_êa,oqyKx5.ɡHı)=̎61sSkCE.L 59N5S3INd Bb %-Z&7p?lef#RߎKad'-~6jXO><wayl 9đgGg}fw!3sSn`s>)(gney >0()V} ~e㳶yœXnBqkB`b0X |C & 8Ht7= "'!F!+9ӭ?"j[!)2]\B& ?VujE MSkH(kd:{!ے@xT y(5\i_ ||ԇeƒm*B&$7r*[e 1S/b"Ҹ1ƥՇ0oĤ0s cR;PDw}tbY"Õ'>Xb%N AS2_SႳ9:!JDR"cv9AWa+D !!gd` R7!q֒ [2o+InbC!o擤?v2͠ :.HˉQims OPe[R1'W-# cJR"9lW@[͠۾x,+)c9gzP6;igr$^4(NM,44` /ޣv$hbCR3cY}ymݾy9v'~k5470=ֵGҜؾ='sLhnn.A~^P= wY:CG@9N  G`YQ3FZ8-~YF!G\Ra5֝PX R"ÅX 4wrae xn#'p鑃w@qZ P(` VW4Y17tZ<|Wr:uP0ieqx5#K ,kh4N=s-'vR63cFY~z+80(܊ÅmpӅ*QJrr D/% bN߁,nbCT0 (xS1l>  \A vԞCyc=bN"kIT`C52Zǹן'vD XjpVBpǎpuul@BL"AbvGX%qSVa,sS,g h!}H&Y_r1> Jz\:Қ&%! g#)͘oWfqm9x]Qb *E08 )AZc\SCJP J#8Gϖώ3OjWSؔG1Ŀy ?q#B!bIji Jlq +!+N~8GAfBfbC; pn)Z"i`(_a K!Wэ7{gIrV)֣V$Ta Ii#aIa _qՠx}d:U00DKI,ot1#= w䕄f^ΎַѐFQ>(Hmr0 A5Ed;9IW3Qrhc3'΁w!=p\Y]$koHc9y{1$d Dϗl6.l[9fr^0f/m#>Fl;%,>[325hXiu hp &PR2ǥH^[;eu;W"0‘r! y0l209.<|/cտ>$7q_4Ք2`Ɓn FXKNXbL< D ̂m%J$> [p㎴8Sb`n@yǎCmfôº%nvSa2)nvL"fs P@yۄd Ŀ1Р<|@1 2Blq(F$zxվhn,5)/HN t`!F$gI!Xj\(TP1P1m:ˤiɠa |aFoQnω4y ĂPdXCTw^^{oz)߉e+Y+;'![0ůC# 5>|A~HrZ`& A=8`^% >b]svkug邈==iI8@R$tp';$R0Ze v;Ƶ.8y'wά??`N_l/퇫~7 DD?")T$SP %GEXKF#mJҬNsbiHMϹ)80 ;.5jPB|˶F &$WrK ZN5+47SPn^l#%6?D·AYŀ]mPDlfq` 1=oIB=v"eB9΋#]t6@sۯo1t <-u!!RTF8a2V,bT 4TN4(! ̀#)`J]ꮸhbKI_ fJ8ET aCdxN ~8@5J[PUq?#<4=fyaHBCahdRW97Ft Ahqۇ̔oF1l@f u%p|KX,a0inͰx0Fd'c~bH/?`Um ZhϏfw=?F9L4DO6R?̈́78_^ƶ<)^,D)D5` |X vY+(Kc1嵄-1t`I(쁘i$i){)!΄% Ku)̵-=E%]20 j)2$FdH.DC Ss=Bj5V ^ˇ !-vكP NIY;/0k(^OCsz.0')M22q8=OPR)wXgYƄy[[XQH̍B^%rĹHJϻHR2?s͉S;˜?7s3{r K?u @xj}g]$9Q,,젻UHAJĬAЦ}KvC @:Rry M>xLL-"h:IF`a,5.e!)HrK$T300p͝%#Y^ àM! ~_*a b ơ㆏}1cE4 $ 0a 8<ݕ#-J3dH t7q~hCm$,k |D-n-VaZ jy֣)ڱEl -pC@R=̊&f,5Rs[,$xz7랂k^ lsՏu@ryLh&F Cդ f[*D~A$sm|$<ݕHՐl!)LY0! 3#)% bh8 k#?eH4ޜW\.݀w:M!oӰ;\H-ԩVup0)K[a=g.Y߶r2V_>P*uqpц ̧Qi: FM ](}Ot~r@S7y`dNGKs daqyJd)QaqsuCrGEoALā[r|KgRƐ~Y"Q R)8Y ee;Eap, Lܯ sh,8|R2vRn(y(dQ{󇄋 Cใ.lǵ,QapXrN_ցN;xCK&0`繛@;( L 0dAM;b!#R4 3#l. #u\ # ' fa+#Yvt~5_pFPJ4ZkTF0_!dg? 5`>Ռ`ᛧlR vXJ77$9H$aa0R C48|d?",PnC"8fK=lw):Ў<`bZ5{@"d:xjP1*rCŖ7C+TsADe)~)Ds4ant\j] scF Û5󰹓 j,?b,wJ?e F#GxdA Q(ǎjo$ B/CG_7_>}BIn|/ٳuwRo1Jr39ňr'vBmpsYS`1JZBHOnlV[6Y? 1__OR(u*"Х>Z]JA/;hW%47J/]_2]MYYztoP|83xD$)b"x^9n M)sk|?}zY5L8X0e={e̓Iuw~s1Itpr! #) Kr@/FC3 !kB0(Iit7rWdq%k9DDxɃ>ƬXQǼY0S-.IfƏp8aėYDbJ#R#!cPd:Jܢ! WGa-t`+đ)(E!)glD7 1:%9Fa=)##@> Wj  rWdnq\Dى2B#d5+BĄ%x)urzT , jk R'| 0ZɃ0fH2.(lg㾟l K?WY&/oW{$n7 h[0 ,SD0˜Y3a/od|0g,j^fNwL3.B3eH?Ł&1wu' :`<8}Xl8|eYœg_ tRgX] p[|AO3})d\QI{2A믆K~"Bn5&@5 %ab( i 3f8@  iu(?#"P:!bvDG;Uݟzg%$ '4 ^DZ_Vjv(ĉ9?80c+)N|S)(1znc/\NURT xWlag,I&&g@`jVߤ!-UؤY_ܘ3$f-gO0q=PoQ]aEd σ1HFJQOW$.FHh{b>zj{SB,IdpaZ*q5H`g&b%Gc@i Ć~-q׌pT.ݥX2_` wƬKG+t A<4ܤ))̲CsIG uU %»9[#\McF|!PĘ=[4xve;p[+f-cdf̅-V&`&& K5#ի+'\1$Vm|Uw4 JJ+p/Ю)p@Pc?j$"o ;oJbM&k)9ͅߜc7R8 wi(XH{{< 0h BHu4~=13pf%o͙y{vW ߽LP|?zFG4"Fc`Z:FHMyk`n2$"Y=t܇I s<|VLj&(0`!}Hć|&&&N;>`= ;0h{n?0z[u#$~79ǎL/9A/ =lq*T&R4:P≀e0l[p}D|I!ݺ@{6V6DĀ%ҎƄ%$ Bx?毞}}0*D,ŻniӝDi fh?("x6,Qwa˸Pk?ͶaCnq*0Ϗ:8O]G'(d"%}}L#S DQRljIi)".u/neƆ:@PfN0eVB( 6醖v{YK}g^WX &p`fqi[ a*ܞ|pR5n%L &" !"ɼ$b0dh"=./y |0PҾ){<ٻ0ΡhN?ϾI6tE!>4nqѻ'g3N, ?GE7`)X4rݯ?@;YC2mpb0fXF# uD,?)^s|&C@΁@}抻RS ba4ر]isݩ7.*f,prYYDeFqY&=eД%ssrC#?n:~p(@Ey J[G~Jfrr:Cxq}rx!=+/'t.p.AnFYӁ4L@.:NG"Ruo `Ӳ|;][|0{ Ų|Es\$"0ݓᄟw5tWP}-f iV۾׸"Xԋ8&C|a~3>?C]4j~A@c ׸ywJ9$ԥHQRE>;c+kAjBlF p(~4Z5xtD@@Ad')WK@SksWh8ɶ~y;gܜ+p]S/@tn⍛:1՗n<].ڨذuXaDZ2Lv‘'ԅdPSl)BOZSeQ#"03T!qp¸hlKaYc:qϲDBBqD \ƄurJ~p0?vYx+̡)H]6RbYYo)HA3l3!:1;- U7uat(¨-<[t v@bHHO j7@`.Jag,O0Ru!a)YoOH¥2) 7+bB{{ZhCKQ%05npB:FǍtC h ֓-pki(B\n}08LLFb#+leуkY?RD,) D8GO>GjO; ) DH ;(a}gX[cF)%Núz d[ٳKs<p|cSiA$ayN۷c[#{|y <b_~s/?1l܍)XY9'.BTDanu(:f6LHJDX8npqlɊ,$!rļrqEFFX=;Iz0Xy#TjjS L&CF,1#Q;LJDB"ˆ#l362 ႶJy jah= '8ax0ܝ14Q-gQ82L!ߤ0g%,7# 7o K^7^6?C$nfεavc|nYx @>1f-mKaa4/V'%} —6pОs#mƁξ|p C!3dg0j~r2݉*]:_}ez95yDX݉z\rjiaQ"XB,+jE&*mHl8_ a|?[t'"+(J 9Ry!0B9{ 4K "47;YAB`º!6Ii%)9-Op8.VFlp3'3|30JJs!?;+ 4 ɠ1e/@1ACTpt!¨a](>(3$b]Ez}ZXb0[cݐ-p PX)7)K%0qx&`(姠4hzPHd#*Ȁ'() m3{֔)߁SJ>@ 3R1=iIHO ofJ1#gc䟌1 fx<\|Dž@TԖĴjy(b?".m_`!qnt'7gEmlb+lO#a6$9X;)bEXhӜή9aqE(IDḴ$xtbA6&GPhXÛ~CFtNv ܬ%RP+8LK nw8p41x nvjpaln 497)%8Ҟ%! ̀#)68f8,s9JHJb1ЄffsLZ `` G@sҏHO)G\sp] GXaEsl~؆Wp.=z$0*YnX]\w@;!mS~S K>}#H9o#n|҉~YU#H/P?Ҕ64ô RWKDdki_d_S,)rZJ?lV(XaH&BxI3`ne5u8 1Gf=p@@vB @HP%wǨ~@vu/-7T5I$bĒ<${K1XYs}A~.Rz" `=A /lҜd~N,FZPOֆFnB 1Nd:bTJ#ņXPh` %켳n\_XQw`4?N;㳀4G"(w~:2 F"ڐ2 !~JB& mߋõz ϨV.IE)8;\^}i U3FnTit /N}VyeNp0#1"^ҏFC (T=kwXH@4H%(͸%$AW4 &cGEܑIF0dхUl܀"&!eYcЍpŬt2KCP Yί8ʻ8Cd9>);a̲|JCZG U ˛-Pց@1]r3enH”*&\#41pc9c_펲3r h[uR 7kflg߱ GCyS @?) I00J2~JԜrO*jpdnL(inhC&P Sl,l+!G cV; ()n9Gnt~XoJ=[q7Vp.,Ox-C% _ %I-#RPס=qzә,nj9>7suJ'J3R4j݅IfE9A"Ҝ|ۼj'l|M!vˉN۪-Wk@ .V-=:,/2Yk#JCbhG l~L˶CRI#$XLBPڪl& EP- ,׶z/vxL;>$Ԍf Kݠv / g CǛ-.z{ dm-2qor੃405)+ $5 ~vV?oIˢ[cq1 xNjDO(b[҉>Z⒖>C9AY䵏ZB3E'< ?7}R>b+fQs)uжY  !ϥQ%MœWiwb DcR"r 㾛lm?~$)(k,Y|oTc t7"ng;%d=d_FJR"+G]jl b}i(A!}Ggj97ZDa#ۊ{|FR/ 炇DWpX-1nrNK۾S hF4y#R.Q?NY4Z@,J 0[9pdCK>]jv:v?K4UY->@ScCfZF {$0R?֌[=AUT"()H [GB}41e80| @l({(^BJ_ov-1e%*Y: TL(1ܕ03, g;zs/3#!3#)GE#CfNx6>uW-4?",jKHivԶyV.e;Jp;Nܔ?1K/ybn珅^g^W?0 rsn:D8!hLIiCWO?BH90ε<^Gq)HP v{t:y0 qD ZR"o +<*.}'@; ~F} BK`."G92f,J$>[MAcro`*,7)HHG?fٶ[1)HGX{,X2Y n*nI|vpAP[0II[q\`iv\CJR"Y(L-<ᡅ8 ̓INlY\'g1@EP @wEc;0<\% 8bGM $Ȁn?Ҕ,,9B:rN,xT-8Vp\00KL|B _ [SCQuF?Q.NNK`̾9+͜eHˍ²_:-F $8 )`rrW.ٌeĞ/0 OW `9|D?HvHnl1#^-k ҋ!cXޅpf4~>L & 3 R5+m+eeN Ǒ?",8!yRޑ%_+(D6A3 Je`A֧Lc؅B3 Ωfa\Bh/ .}F 02+26Č;JDR05+Ws; q|aw `ava]3$dĝ)/4\@߃N,9~~ֳJC g;ϒ~M& 'vgKZ scՄyT{SYНBr9'n?/y>fq0Ɩ#yAl'}*& 4ie18#拑 E#aH;Uґ'$͆@߂OR?e($79x >0ġ |Fz*MNIiIAd %9qxMs "`\%;iHe:KHi0рPIw%ڏ"!#1;lROwQ؎8|S+(YTnhe?l 1gy!!7K|Ҋ,18v5# K6d[bW-QՌ2Gb5?av8 B94^ |77ß8ra\[a6g-a-"$?")``i,hBP$!̀#)1r7 ) <=F2Qhy){0Zς` B L",K=&l4;[T;K0a݃zr=:NU-(I[ӓ?0Q!-tVFܷ|ZDF?b()HC[c^(JDR _x r»Ch ydP:c4w,c-g 'H!$$h,*yA4-CqÇqЬX @orfa",ϰ7B.Nl$ۧ!̃N7 5L pLhJzR HZ/|OJR"l, H@Yv ٴ(0C;.+kҰ7s?")c7HC>HwqRM7@ ř Bi&,ThGH͒Hji^ieڴZ tqTCJ@j:{H ` +3r mQI07=N˻z~D<&-*h60ZO,](k]}qvO4LA|N %GęQ(P 3kn89wJg Ui>{Zi/lP>e44ϳQHg¢-eaxalV-w @p K1P)SN։AR *PF,w?(3m:i༡R& dD43g$n"hd1~d$HD4RQ!;%9ԆWZ|4Y}_Vm;ju(yz R15Iu]-rcn(Osֆ3'XVs-DGa⍆/c2EGUx0':AntRK%n4Jme3\18X |c ACr15b $Pŧv=v@ $i JKN89  d /ҶdϏV0 O,+$;,.qa#lfc"\P!Hv'b ZdP+aØb6^>spg; 򎨈?:|CYrKgW f&5_>qcҽۥ#1,ag10VHfYcCOv4%$ۄ$!| -g9οߒX|8ǚx^K/|m@il˟?mŽg5M@!((ɩJ7) <G#WX7JxH89Nmm)8o~8lI(r>HH+&8>˩>H?d $8E '(Xe2FN6'W-z! bû~Y8,Y=2JLJ{4ʖ2~{5S^璘rGY̡L֐13xx]DӪ%{CTp!($ct F[ߔ)dD2%Ga G''ٚ\ӳO{8t:$L'JRqx20fJ[A@pd沋~S`YE`6U ͻهJeE#g|ޔ Ta4j\\,YN9<>xgRtmHqk]sBX̆+ް#Su~^aVjINs[]-=Cg_rQ@A,ǯz¾H7Py=D!v7َC`H{RdbZƌlΩ9]8~d[lI8̥8bY29tpvP]@ (( !"|zNY .r8 o#14Y)F|:S L+pr``n%цvqyj_ehl?jHiN+bG=Y=7,&جmRj)--_J [t}#NY|AcJR"%*cJR"ZPT,£87]{x%KPW8O|7w?E?W-UDlt9.׈+>xGNC 8o%-W| #0_%$dBP}<!aR(7dn"0yX@XM|L$P2/T"ē0kFW '%Q'Zl Hұ-ֶqm Kt N]c-Db,(>"`͚GjpE Z C ,4  + 3eP(pK̀ 7ܾ6Q(mq>c|xdbJ$dĆ,'ϳxM? E&(ь7^ c0SRYcF 5hk WóPPq`䤚Mؕ Yqmȱ3nQ/xZzPߟJzNfXhJ풅BM9r8ha p}& Tivu~~uAD|kp/'b|䁝>󲀅8kupYEx~;8?",q k1:ՏcM>k9{J"'$- Da?",,`8 =LA(ලh2Kt0FR@8bV(?<(^ pv?ap|˜P(-Kr14I%Y;BB?}PBrvN^0E1JWȪ><4\[Lrƻƒr7SQ) 'C KJDYhLF—0l/n(ϟ3l78\5//{ 6C JVOO OIfld263}%8u0ξ{e5oF77 |Vه&m3E,{1LBƿqL&ƋB)x~w~U>zz{ϋ,8î.&(a=SvQ4 bs¥~ i$RXfI-C!#)|ˎ`;z8þ0L!ş@I,.dwNu|3з8w0e߀"v|?7ј%a,n͡C~c_Zds)+:ņ@md T'qIX8pP:(,H}W= [u3,""rLp Rs&Wvܞ ]!wHp./G<74L!+ @Iy8V7pŅyiAX7ȇ!$nYaǥ=Oi( ZzHIyÍ|voۡwj80TOD£.Q" lM&t>3=$(8׀ $A#sHDM%`n'GD ϻ(7t+]B@0cvٖ}{ ;q)[P 69GܗzPآH((?!$ ?r|M&}sˋeaPh,,*lQC.>UXq}& .(*`vJyEd & %vbRs%CaJZx?ҳU\DZx~{8KN?Hn+kE,[,J΋F3$@C8Ўl:cfǛHkD=IpXj{ - cu֨v#pHA,4f”e(Ȱ,XØ&sXXPüS [ cс $/6gǟĺ׏$6G ۾%psâr? Dp{N B -(o_F`#0`.#:wHGjc p2P^`НD'P-cǸR@ {QuoPܷп}p׆2 f$$q?~<!#)V'@~ :s:)Cp^(+بnt8p_)G}(F| ytퟝucLO9oH%쎓v}BH/"{@X0#7;>[N g }+!^&KGCJР>ʺ<<иBq%q͂ު Ξ۳(q8vY+Ϸ )B0{*Y$7~HegC{B8NxwJJV+;!N%v֝[wcﮐQ>nq<u~](4@/1)^4Ăӄ _VE4H Ie[br6+jw2Lh iE)igJ %~Dg@}* d ph pYALPr~ORՖr 0 e=t.2i(13l(˛hY |t1Ggy! 43 Jrf-Ĝ%1 5,` @`:q-#P+4($ YM偔b_a81(ӿq#ږ>;x>.,Iˆ+A$)Y ij\㈶G:e(d$0jNAW`Ͱ̣ZS8HBq'@UC\\ٸwQ#ch+'`71HF8<#ȌRv}j}c*@H?cB]%Y-9s'1_,1#c"Sjԣ%_njUDN)>"Bu H~c b]ok󊣿)8Nƴ%7vpYd0$kaX# 0E1쑀 ٝa_8HKTG}JbT25&R0" 5JwH\ cXě&feJHy,ϞZ!aHX8.[zTp*=g m[u>92r|&C{ewDfxh堥lE## C!aRew zFu #L qPZOPgAD?bco8Ho}*1ŷ!qha &~0ԱQ5?LBF!g#)ĐJx st(,8U"aV ZQapI 1|2bvJGN:Sr`h槟Șx]-Z5Өp . # ,$d,6El">̌"?",aZ# F*y;A0#l+AI5phTj`=Q, ݾ9am:Q:,i%uc,I#6(λj:(T"k,@ $)HN-{ݹ>fsgxcJR"q¸k屰!C ))ԗe*t`|!ؖ;~,XM20# aXO QFH*8A;YS?D_?yHR"Y|kabgjqLmv@ef[;0 DR0`JR"O!`ߜ)L{`F@0I.Bxsą?2}*,PmZ,"%ٛ2dPƘK<'+yUHPa2,H`<#B+8~;L2S# h#ҿ0!p|~9  wbr'f5hO|l CH#ㅱHNQNȅ'a)X,0CDQ) OZ{gvFdem*֘<`!CJR"1)aXp~?;s:۝ ]DM}[ޕ!IAjRPaΈD>-%eŮS}3BY@ 1؆j 51L790&ێv1)BŁ5-^|e1Rƥ#1]HB6@;3]zRy# ̀v;efhaRv EY8Pin ߥ+lzMa0kSby]w[)J~ow79m@s쑸ݰ>Z{ YdksAdЎ->x!̀#)HZ2H$`K;qC$zeZ#J `;qz|$OM Hԧ P_mzmq8;`@ -%#d |2#'nǧOgݷow@yRLj0loNl,R 4ķW c nNIƇ]y!-l5u@l%~|䩏%`7H@Sr W| Q3B?scǪɮR[7~8Dܟ$C{篇Xݎ9'N%`Wb=q%dcB:efm$CbGV P=͜`dY#㔼7S j|N^unF)b!@w?Q+ꑺ;N/.BN[ 8iyo^s80hI|*WU2wEpoCtFQSR9}\ V?Y_q{FeF/}q43a\}=pCvPhS ;(YRò8[0\C) YR1 ;`r>̀AEŭg̣\%wtPVK[sowe^--H(_22RX&׋d$ 0d fQGU_?p 0=^p ␌,A'rxcw=9hxrD2~[)D~@(o]q8|_7_ó0Yy]}mtO\Y4p 䣎B;dO̡WF + .Xa(Cs0f)_f/l p5'zѓJdP>;mCԠ B;cjH(0ดRժ&M &Ƅ1̇[7%ﶀt%8{/jxw[uN?\6/yEzE8i>´z͇w& 01 al0Njw20aҽkc91?}!¼/`XD}}Eq{rX$x 3%\>kt ;#A6ю~#Fn}qI0k']p0DX4)` Hp0Xui0nSfē;0@(rR-X cfBrA  DRa!2-ΛJ^ba)G vU?U;?:(v:rHCoÅFC"0f?6~7U",a)gwoF uKW%CtF0.3物\WonL7` HM0xd\2VPA9$'mYT*ns)08hiI)Dw̡[SM&j0(0ܜECD"Fm\>!3#)7lݟjA<yr al/&?``^ĢGla> wgv|tNԇl5qFf$`szD`D'iRg]CZ=͵_7"g5nikBp?cʰA9y B9+c3å6PSdia,j@q"RL,Kۼx].N]3eC!bKc##ŀ#H}p#Bݘvs'⏐~:Kp:f6itF^@j1e|'>{wFʕݻXu) UK tra3`GPtM O@@-b9֠R G+l4i&o!:A+V!p>pw6FFBôQX =nzCf8* e#a牲Z29LƇmcgZ\-GCgL"G1,IN')Iµ[2)HB#^Us Y1d0@47{)]R v'Xq )67Z;|w.8 5]zBn"4:̌DSQPQ%9g9I(` &p7-  AHA!^q6)94A&y(Z (%|0ύG62#qi/ rkTDaQ1} " Y a$brs^L& i[b!enesGW' ^A͘p+9ͳsR"$dC4ifё 󁌷O(L-Q~TlkY>'$'':;D,*NN'VaUB'nE ;lIs,{/lpKf?VzUDWQ8vq `l qP aHT7a}Ȍ(1> x}]Y3QTI8#wP7`aYT8Xks #q\q85N4iKr]*w+ B3 aZv$qA^DJ xIb ؁2vl>!bݺyʖ8qV">2`6}֔۝l͌"8,21s؂GOm8Z:FaȌ!&ΎR~c RVdCxq|ֲKI)$V;vY4FtsM`jFK(F`颅r~/|*/8~hs }1 F"2!ax@,y)K%Y>aķ?v WC&c@F5!Ʌ 3)ߊ\TCH`7W |~_3 IFV3OKCfdI&7  Zv^HnZ[AX7^B}aDT<|1Y8[nrweOo 2q@n!@18^i7ؘ?Ũi>lv``n7'mje AcFq)gۑV,C-߈33fuhDQY`ߊP8U Yuf_~8:$HTvI1L~𸬁<wXIE!Źnv<̙1*Ouf|" #9[`ql0FS{ˍ5s3n 2JSv 3h8?R:3t?"cJR"̷P9݌Rۚs,+Jzqld(۝0aH,P=Q7(s KH!#)lsK N3f0:r5P)jq Q 17m΁kQY9"`7d W/)Q8+̆0x}dħ O qu}tsKݲBHU3őh4E΀2[%hѿ^2T'H"߬0nmK݀KlH, ϛr՝L1O)Xi0 aҀ`BjwP W0 $ԒԐ>.HÀF4=/<ʺ(JGBzߣ(zY8i$[ƛeG"q,q^k䃎'٠Ōa`  ?c I8HAv -.xN|+#f bqqۭ4 9āe 'RNnǏ5B>ͷb9\X Hcw$8NjӝAαG/ΧSuG5i׎<фHs?zM7K יĭc#Kf[0}žeo |fIZI]jYC#'x(HR9IX$,M'KcбZ;]x@AO#~fI7,Z(g.g8GO΢?yY| K|psdz(J? ԧ'bR@ep%vU 5!`/a燚 "Qa $qc/8Px: Mo0$knn-?܂HzJ5<}٩ [EkfԳȭhJ|v &'fZ[ f[f4,r;Pm(M&sx@dҘ 9W x3??dCHB/l+~ x!=pmx݀<hLlٟDQx䈺T#H_iK®NHF~gqAx+nF>@F;u%Cc6}ĘaX'  qZ<!E3 )ہN^C@'I)k@D"](e¯B0hCrB}ΐ|LSRVIe#WH G8sb 6{Oj]1 Ƕ2?fu`tcN3U"ZR"fqtlFy49nDI) Jv嵬}(}PxXJa_wq"6E,?λJ?[5K&BV`y?",$(!?ixXJDA0f 0 g&FYJJQ}Kmc#r?jLNYRZQ|0hi4$E)i9>JF".)8s?>N-f.pn;w Sc=b [)atl:p ke* (6dm5+l(_>"U:%IáJ(3f#|7cSsηp Us ߁S !#)ΠuꨮNyELqFAD>O2bHAaMHllsL Ef~ }8 0r}r)qew]ژ&AH-!J`Zi- E[0aH!ɻnVa˨χ} qaWq+!f\&.*:>zU qÇI [T8alsjv]cy,][,~#x1)ṕ)H(PB{ luajј-dN/РᦩcntBy>4rG6- GN 4T EF;SHc.2n>K1r2yO9ᬜyCh0#6gt5蕀;WRNjDj#D3IE`g&e=#]{/ $@O8$G#2S8 &C(3:]#wtB!$5r f%0GIK2ZBޔw2>eX?Ҕ"&L'J'|D'$O*`F Zmӷ:HDP0+}:R;WG"0;bb dYֹ9NƟwuRq;?Ï恻v^^_>W^׎n(81ՕOmd`7mƞM%f=eo?cXՠEpikFX)> ϒW|ϜqVX}R‘!)gp; /Bkq1E]#m$g?Ҕ0tP'0Q架;bhxus#@( 4ae/ Ncn# 6}saIt0#3!JU5Ϧ[8ȇ @bR@JzfE!PX3,%cGx6#N]: ? ռ70't'+IBPPf(8WR7qCRh8munhLE|qJ9Oa,x@#Rٌdx ( $tmlZ =CguZy].ٍd znwes:n"0fpt^?Fr{b5<\IaME$ }|+ء*<*13=\E#NW[2ٟKg8'ٙ?di|Z0R%E~')!/gC0_*[aKxC2&Rɣ0gĥ$bBp荭(6#r I-+^p= of?=$욵R{b\/D20jq!֠_ 0t1h!ߟjaQv%=YW b!g#)&^ٟSgô0e 'WQ:E&# 2~}_;?[up."TH(aFs7cPu˜n@fd,A'/7Wq`/hBR1`@wߓ1&op j٥ۘ`L’ci8Dy%Oo 1x`[e8@0[P CCqiY#8/|7C[sF g}Nn|%do xј-^LAlmZFt1 oxngl8L7'): <~Gxx&C0a_ & G`q& wSmAwLj-}Ti0_ +ˢ FțBRsݎ{d[XX9c1pb'C8H":2% z V \*7QrEAdq #:ći2bBaGF,f2̼ϟ4bBBm#6,mCiKohj;k/,niҳ1n}=NJŠKK!0Ƴp[x[bVwc1)A?b,.׹F]D 0Yk<.:ɵo`ᐶ/tssc}wy=huw $v\ &WnPȈ_X_ݟ ,a#cm3?e@ܠ%n! `a00Sn1?,WLnyƒWbx?ґ~* DԓP37r}*fb|˕J?+o?~7Eݡm\w/ -CۡH @:RY(옆p(%#3|(oF:j'~)P޼D{lrtLZoB2?wÂcX ܷǘ:BASջL`B%SpA\^Wc߰g-ܔFy*z$]L,j %`8n@AD09_,z-u6"C@E'S[PCa f {ga0"( iqcGeݐB@T%t|퓇"lI _뷉 \^a gC-,@տ5 1 Rn O;E]ZPG۠q"%IN4@`_Y ]?;'V !,` jJb}`Y< RN6K"9*9r-cQ0u#gBs0ԉwyEG y9gIъш]V*'`2bPIm1|xsvO)n#αϥH!9=a]Dh.~oS~.`1yBa.5A@@LH 7<`фz  vi%5I5C?>0䗿!_\R> pam!X p&1J)%opw: B iݘ*2&050 I̩\if8Xl_|,Y ٤ْh5@v)y|%xB" ̲<|{JB2߰_ap*.Z{,CcDb_uA^)@C;4W~`5KMf YD-5P&ˀ@ZCJ!p`PǨx` F;ndBi_^Tp7yEwVxi]W?m uS+O]jbX@8Zlg% 5%!̀#)~ +;\5Nn:RǬդþhqmc ?+G102p |B!Z}'@CNLtnY{&԰p!#Ž'Z8#XI8{<\`ji0hPX _C<IT%OزNq"iF^Pf>S)Y| X5iPY,mi H?LX I{a n8_3" @G` 0&CԄmEEe"()H?@;G~۲dEMb t:V^%;I7s@݊ !}*R(,x}J B6 ԣlҍ8OM $o8cfLq̱̹#1 ;ʈQ,b(ĥ'T7oUYV =lG ps0ΖIkqabdO)LT?"()H9H"۞)jFx5Uf.po@ >BTǭOsX3%cl>9H)8X!P4C:)H v`N?KHԄ'#')jϞ"wFiʊtrxdJDSP x度ADRCS)hF\2 z5"{lu= X/c nJDQRrrF3cgk]B(  ^!vF: {G >FذEbrad߉gFxJ,)BDJDXZpp.;dd_E 2ә_:\iiGzULvYʎMKNQEFniG|JVJq &80ͱkr~osC{|>HJ2s| Qv}i@?ҔGʲQ!bG;ڃG$6+ K)P'jqX 'uϢU1)`f8bKR{8{Q+m*kQEU)`i18/`tC8yiP7SM01!.0P5 =88?Ҕp[8wJPI X %u1 Glh!﮴3߹:LUD[RŮ\V 5F;p0eGJDC u<GY!0M՚~ޏM,čΝ.ԠGWtal:d?0nf;6*p29~ȐL%2H3 A3tm+efQ|5F?(]#/\E'R 87rؼSwn1LzNj߿[:w"82$L-HK#Yr+X#όJDVY>)HکcJR"˕qt% .ߎq&.a9~0j J)-}鶆?",±QKuZc[J(!2(a) w0 ^QqkIRE#Q W 9=u 79|;@!3#)PK:o7Y͏BBptc*N"&hh f .1fXM>) $^/q;BY E:SGEHc!HG7GrNKcXJN ى\$u0ތXiM! 8nk!HcOhX1@f&8ghk8摬8ast;`@] N4c!rhvDD`c0?RpZ?~+>) lp܃~)4斑r J<vՏ)a{MM c$X C0d%g[[abh3а 2;>|9]g* d& 8.I eԱSQy|Me3Npg`?8p5J|F<'yխNr'x" #J(%Ķ09tEDvaOǥv?")d82?b,W:vW$7p' 2ksCFrE 8w|+qPa/r8id,ˢID Qn!@a8E 7 a45% Clws,}(\y}p.8\=Yn3l\Zr I4-! py8Qԇa)"02L'In*)HB\P!AƪPf?"!oDzP! rD؎ ɛrS%_OOy'?֭ `~+%$SLʰ2Cj=L9H !x2_@4JDS)H<+'hj'BR0$e>r\{*H<*\@}MK<8QƁAVYƥ'fqtJDXԷ=`D?r@Y 04 5Ă0H hq?0rbc(4h\=2`J13 }As4H13o?H?!i͢AYfg;0|9co, =b'XǺ}]]p}uYhz|͆:k`BKr6>NPcm;dav\N8%8tuoex/ۣvs-]cy?"$`w)lfў)(.GϺ?{Q: %?90+k N̈́tgVN`饙쮯##ҧzo:t106<#fda)Fc-"$?")xGz?M^js,slħ)/( 4؜"z%W*}Qx32{ӷJ,S9 ?‘`Qoe4* ْ݂.)(x!.`/ Kn؍|Z䑀}Ǐ~7^!rF@Nwԍ߱a4j -9z(2~DLdfOs4+?e,2"Jט$Ǡ w"8jf0UaEd҆+䣌v+Qe¹c~)χ<?Imv/N:T@{kh@a HNDn g*/#іƶKqfP- 6gOo|U1iE_k-GXpGB!G,nO@j $Pj ǿ p3:y0'қ6~B@x,:BF- aJwl\6þPq<)H<l{tCqE%Գ G=A%(7b7m <\Rq`{iZ?IYl/b0!ٙ#)csG4cBji+>[ rHjoaƜc <)g[ٿ % 50I܉KhC񬾣Xx,XHGu}!|n0@Ü=[+0%΅۠0 vpc(1cDi )پ<9@yْQr?Bsmrs< !(ON },+sq+$qpemb\1e!e@"C|W0Ō=f>Й5 Ѝ)B5ҩd@ԭH8^[C2>aPJV &fi?Il3-n ]B?|H"v6,nP@e3(`v4K,cc;3[+;u ecw$t` ðO(Y;a׃ij9Q XaJ-?`|cV<ԗtZzY <:a3;/D :V lj[- ~,Ǟ($j7 |!?O G<rN1Å]~hDiƒZGzf?≄SiIxv~;7;|y@,3?YHgWQ_bfnuSj0u khʈB1_"B⇋ h[C)H@##P\",M)gOR_r<5,xuy:Ȅe m9c‹B<(@Tp7r/@(;,u#(;0y1BN-_rv|ϝyq2,(DOqW;8x-c%2$j8ްs(tX8q'I:&H[,%/Fc*59j~)HmҰvPR7У(ׅg,̄2H00a@w^9(u0nOsD,4xrD˰F-㏃IkQ7Rl6s1(*8A' j?e;ڄZa cw}ߍcOMR1l.  &w9AbDA3nun=At|n5%-Hί$I>2xNL0`"#p`vf60<]P`Бvs!]ݠj. .&RvJ"z=. Wp WRt25P D %:1\h?qg"CajӖgOt1t<q}ё6qc|g( ɏ:"6b(M?|R`/i%;B,afD 9c: @,9GB r_%7`4q:L.jXpt2]L22A:p9+ K+~3~;%̄OM`:5< gX0JAM%eܞX# xj B8 @ߏfZ?G䈓0͑Yz/peXk\rz8oBH-!g#)t=!x5arF' IweyYVa0{>9cęHO|ľ% [LJTTpKt}(3|qJƹm)q㏨*`Ў1] Nnx?={Zǹ~s̫EI,pog $?cljv 5t 4Oݥ|bǑ Ǐ0hu('Yjd|Ql$8](ta.7-a8hG`G~>I3DY~9Cv͔?") gr\P.ÈANrçݷRbpy(858|z,h v04b::ƀy7\|CAܬ̿p&$bl/]2Q| gW==*ؖ} =\eDaq͢_Hoc!cҟײ3l0auxQGMvd/?'VglCrs9hsoa /D=sӈУX*'vd)uBØ{? ^bn!)2`E 3G 1{9pQd%;2o:hh0!-#G]a43Ct՜pPsm,vsJ&$#%-HK\gEˡCQ)7'LM,0^% bƀIcH2Q4L<楐(JDF>yÕ֦xXl%8R󖁉X=DN*i~_=?9iYƶvlg'L&JR"xrjnnq3%ԇl777eJԌ&=_%}\;Plwuf[99@ꯞP EJK>B:8ĒђsF-R{2~)J?~!ccwa8d?Z f_?dDݐ!̀#)#'FKQF?"(ͽ(W%)DU? ?Z,6ƀu-;& nq`g5BSSNGD !<;QCJR"ɃGEUhbWqOJ@ ŰNnnݟ8a4 g\EXcN5X;Lr|p#llW2'( jLS0:2 bH=F}51>rŘi\%tJ74<ȘQ-d4%,ȌNF:2<~[g)_n8\S(-rYH-I9Z֎5N|; 5bft"VutP+HCus`M0QbezTl> KT‘al{ i0N6n!)AH/#/G-9 @4&q0 KM%kG ؄J; "q 9§_8}'uGhchBLO}ѻ|wϸyxɉ0͈UNJb#Gs֫=S,F|:zQ0tIaH85Xp}5Lö3e4ddw8y"a^h+9$|>aȁ=e)s?ҔM/sCr W?͊?¸nD?h%fO4ūf -Q)H&[PQ. 4E<vG6ˉPeqm)JOژyXU;qd^ Vݳ:l0) ,$l(=a73c`CJR"m%]U#g`?L|;&4BR1_eg0g1ni>HIF RvK Y!tkIZRG3k|FT/e}:EiNA$0e%Ssw_uf9" cxz\A|f@ ᑲkn|q)4E't9s!h2HmI//ð̓wH10b3@}] sSikJ. G{o!TB_3.3f~a ::_ 38aRKYcr0fH!Y4=a )#v=lƼqKKNv@?~4T#pр'g{~vRvGpc2vfͮf^?Xm:+ b KnIp<-BG%0eL$F 2f̚Z9RD%$`OfǸvTvQ-oq};PteYN0D0!v[@sɰs)>vZ2s4O)l mH@Ͳ?_)fպ…R0_‘QJ9[m-ZN˂sΛ `k(A 9B {fÃ_&MI'mR` `&4 ` ].L JPRRӷbas,ZG爃8cJR"!)aqd:ln=e1EX??ke%v[ԴXL= cmܑ!3#)IԤujk=y`=K?#ibL(01(* vw?1r/*P 01ŠƲ3`UZ?fPDH_IH!ux8h c5p&u-OYfe!?,@1AE$ _?sDt]pIO3,%cDZ¹MJ2NaCn4~9'WÕ|Ivin3;_Ost+i0 v߳8G=cD,ҭMIL9kes &ӆmR[1X? pC0JE4A;85WA/8K4%0u BpFݖ08y ֺژ$@p1Œ8$ldX,2w)[8OZ(Pxv0`LR̷~l1aή` !) úTq9aOXØf'$˴c0ԳqM'$$H2Jͳc(>vVu;M] =gql&*8e7p]:愒" v`;52dCO̠=؎FĠ-JJ9'=~_9K 1PAgպ Qx[2|>A N4Nj".<}2228<< \Tν'$q^[=L܄%ur1uJN5(vԨ1n5ȌrO`9No ;5 -Cٟ#PvtL(r,dLō9 =QA<8ٹ9{xyu `~Ksml@ 1>>,Ѻxp9'Fσ@Wh;w=S<:). 4 NvbQƄ8݀8\Yx $H&:2rKO-ezK6%-k$:+PW bF}s*|v Z~{kK:]lX I< d2 AV%h-g0HI^VOv8qiw0f~|'3'<<Cy)Ҽr_Rrvq̀&>(`BMd*eZ{~|y!JDC!a  .Hٵ_naܾP񜃭M@SAFQ ͱ(PN/!`&/Hp23zbÄB!k5[AJDQ‘q`&?pN~D)Hp; 0xQM2x 5֩T(pNY;ۑ?ҔauQr772bl;w7;`~)HU C✬u^|ZwKcML>R!cjm`yMo ±{(X@Xwm@[1 Nx* |01H'. &RڰXծ% )Y 0ް7(p6V?<7!dnqc: H­!X$qX`õ)gJk*iԸ8R?8c,58O8vx,7;44TٌSJ#R1ua p.qaߏf ct8)xWsG~(pB1M w/8>AmZ8p{JpDqi2HG€XVtNPPEcB^bװ8VFi=-*`>qDtp#*8pZ f>H8{p¶%N8p՝|l{XcCD`?WDIa^ӓB=YqAyXh4a(-]AmäL D>PWlܐvF"x7%ۅMlFqژs p%3BE\Q+lfZYdȁn~ aY_Jv3>‘!2hS&=˒šk2#wK[[v ?"$u8"`քm"!_;6l$0 aCq=Nsl?Q"'M8 (p:Ӟv yN3 aj q*e̸D"XDkQH/Ov ǑivYǎ+wP=<URvB]pqLGa!~{@`f& fv/JR"n0 #/K DBu8@/ 8 d[g+GFJë,E/RA(Al+yX* 4U@/]0wl7QmA~]؄LIaQ!#)cs+c{Չ@`H F_nsճ_W[bĨD  הvM\b Eb^)%nUddP^LJE|=p} ;v*t!O0'vK\glCGםFI:h J@haE ߇ykw0r1iP B0 gpq ɧ;m?cuնl簚y-PBgG5(ĥ:09az(/m.܂dWǀwP*og8H<ݜ] t*Z IO5@cdOiKacۭ%#$F!% 0R- zwPԨӧ)_p# WbY;9-`I&$KWu8 Rچ2Fb_<Cs -'{? qZH*: qd)H3:sXD[)%- C%8=~a[S'1mFbSl-nn/7xPn]0DN \>Zִ@9df2!`2 hܽ7e sI> N~ @V?i`OhӀvR7HNKpuᡡF6…H5o} ]RJNJzY.kHPAJP ̜c/ cO"[C7fDJo֣0鶬AzȽvgs;#|Y- %DCDt-MSf0 &f-nRO%7v8.zG 8H,g$cJ#ӏaD@7785zԢz@Xi{>Ĝ^ GvӠ`;/ ΠX|kgW'E)w:8[Wѝl GH$[7c@^|P5\s"@`_‰]ϒLOJ~ 1r\ +u1<<lQ BC%r'pTZKIl{6P s7|υS. ?"!hDGߌQ$q{(G|Gf{qK?<@() p0_Bes<7!o/$0 z&P B`0U`g'4_44Øth_3ÀɃ>*sj[ur7>q. !>?(?L ҕ~y@@|PbzuN0Hg+wz n )A,71ҊBHhVڏ)HCn-%7J~FO6rxICrww΃ļJ wiiKl%BrvSv ^C&L)N%|k( DRIdcJR"? Bкf!'L9Ekgl_`Y񑉩`aq_ XK @2H\([֙Ǽj̗sg;~ҍo{HY|\J[geshxyY,DjNg5Of1:?[)}vcy!J;:)H9F",o>}R1I(ۭ<kkA/>OG6AΐӨIc6G s0Y .dw(~w]`AP -o[a-*9 Zz-Aäa0=KO2apvDGE (p1If 0|."F2D?"$ -i#TrH}py㱭\D`x~U0u4KV@wXc&AZR[0$RM‡`'rs|Tb .`³Yqn&Q4{w2F{U2̯þoAHKmqV5!><5TI-{;D h;vw2w@2hO4*8`d78Xl'd߷SМ~we1j"`̵|u-ld.}#m"(|#Օf5|aL}aL)J |6R s]KV9Y?0?Ҕ,-f=d9 `6  Xq-xff-<:\5G4~͵ѶjB qF)Y`v͠JR"EėOnx?dp}?z?")1%F Q.ی4cc1!g#)1o᳊1aE=;o%Yyr"' e ?B/0ċ-?ґ&M^΃c 0 !YaX@FYoN`,Keˍ3j#ۋ:n&(gVhbt_ ۬ 5)QCya(\Z?hHs2D{eX%pg$Еr\axBogn=g}6:!x4Ml tai52ƀ`W`U &`1 ~vnm㶸Mb^OXtZ&-!On; yMljKZ` @׻n4IS LҮ<<84RF~-~y:IE?<3|0_( $B@,++~r(`ba`1İ'۩=?d %T L;==Z>!$VO(*hŧR`@W@8'ǧ:B BCz8-S(geB\H_CWӄun.`*X89I5 `=2ZK!GJxj2F~<a6Sa5#]Gy^ǬksA@hhrv0bÇ %qi0N9|81{WbFj[MvM(`D1VQ1,Pw팈h-5k4oS Gmu τjҌVľ-8Ո9䐐a%ۣ䰒%(H*_OO=5gXr =đV[rRܔ 7w0ܯO 0B0Oφ /ia,$ l1xYA@Qehět6+v650B@SͥͰv a"pCDix lx`t<Gn^Hb 1;Հ; oy1Y Z}a扻gn=WFy6B^c̅?"(aHCЂ(?Wmt۞,`nӆ#~$z̑%)t/! ⟑ewhC7(r=(drܐ,{x'$/cKBUa^ &bYiXSTt\SK6ͅlIRRX vR1a_KFM.el ]7$>qKP8 vWi/ܐEJ@%&Z:F\ca.8)gƑ00~XuFm8xr&0R`g/!ţIdnHЪ[ɉ7 I,쎢XyȚCWŁ8BP5ay<TQ( %ZgnNU>b0;ݲMn)a^ YB v2'1尐*Ahk$dO?>LlS;.Cq:TklCKA&ueϞc >& bv6Ľ(P%9(倣d0‡q\_ 7@ fƍ~vff=wC8؄h01, )Di NwD*@nMU(LN w̱E bQV ـdGUN$ԗ1!HLMHXY ^;(xFCx`%%t$, ?Ind?phf?ùo9yO'8c:Na ÙJӉs, w`O==Ա)fl9\y-78=ٟX_s+2xgkџPu*?"+V 8?Ҕ3?b*'jդ?Sy9 xTH"ƸuхQ߈SpxqT^[SC@"D JR"K1Rp~d%[a;qoGuqGEt= [,JDQȝ DQCDTt.G04' %CvzBD x(JDRxVs'am =Ǹ6 )HP8L(PkNH%N?qzDi9fJBaec衒S1vԆ J 3uq8ؕ'di=1L)n -9'eٓϺنgfA@P,ytL%! 4 gr'36CJR"ƓB oP @& 7O=*M M;<?") u,L/jg` \qc,JDRhfx iL戙<:%bАvN9m

R6?&3tlsCX:5+GDb՘[لcvΘ¶;J (7+:Ñe /K Dxf?"&aX0E+[rj~NJu߁̷H_t ҦUX:=z/͙85%",pdF5N̵41j4oc0BjМ!p2s  1f%3"Zz8Mϟ@R>?1-X:6dJ,FPnj KoVxgFJX̑* 00Q31Y*5}[yflV]Ța1.4)_{6PN ~`2oL \{qm2 P.ζhv(b~/KlJDAxS_*#Zʏ^B26VX2MSO !3#)'arL_m%b]Ֆo^g[N!^z٩v`1rR9;)Ȳ>HF(!Rj a1-5*_z 3ѼI)df[c2?Ҕ"܃{#Zfa[>8~9; N`M&!^x0̓# #6>d2?l˫B ̫/p Z[(rIHTqaF D}^C~3,;JAy\9~n^ ֧X<*`bݔ?\h:GsO#La41 C F1_(vR"PQ)O_$1j#++Hkih[eӢoLH% nu 9NAst0҄]#{ +37/ 3+~(%=a&$T*쫅jF4z7_P{ى}D\)H)H8?Ҕ  ABPj](~[FX:)Y7^`;JVFR"}GP1e٬Z?g<&hoc8<6(H3,J+eh KnkvυaW&PVIx9F~< naWq.SJyi, @9X |B8!@: ˓!ɤqXXJ+?YY۞Re* nn^ǚ:'HW ap[0 CVϻU .{YT0vOs!\EFQjKI|,5AC_Ƙ`x_@>bKؚW&m91p밐  .0=|^- QS.nAKq F/@/tr[$瀸cSw'qtx{ǑLqerJgwPC,c3:h zٌK#[glcq&%/m :ہ%:630'Q>Z699!C@IH gʷto]Gێ"ԁ_Ѝ-Aojխ M5Dwvth3yOgc(JAMruz!riX7!?iC*BD$J!jI-867:N6\?[9.&SOYt0gy;u2!#)Md=l$n#1?m` JDA$H PX8N0>/rȭh4d̝Ke(oq1{ȅJN0E#HvdH(7)CJR"]Ƒ-)〸#Ġ0؛ؾ3ΜR3"C-!JDRqY1.,9D 7~u2KRU"‘HڹC3!W'vd;mi>)\RH!TSu\FbSp[1c^d'‰up`mWG8|:L$N<+oUZ 4 1%fߗߎ>\ ͂:2]gb$M͇0e9VKx r?ҔeE rI (4q4SwZF pí[F Ǔ@LɅ" p[j?kOUHOm(}QRUH7mf:s\FDp )~x-]#Y!6<[s@1  0H0Bޏ)H BSSMÑOU Tf;sZDDG&] ِ-QINv唄|·˴o=!)cJR" 'O%"WlBߝNo[lt0fYO00_DE[ @\]p,?",w#qgH@<)FC3e~kc`wnͻ>#Bl;L2]o2`1F,HY@tdjjحZJ& (ߣHWo1pwjGpLpuFPn,#ʮYf @w`lKHA_`+nǟw`5I{<>4@8󃏮Z MS6_gPvqɵrx1u2LJDW"xFUӶ~czE88p90b&,nSK_SgZ8;Ґ$0]:c2EQD.K)1־euУX)7g7$AЦ B ,'U6D2 OVqN gqh3`Ax%vrZwuo'7i "6PI $X0?Ҕ׻v)`u5B:Y5.b01Cr10 Ttb@h-I9!Y&XFg-s@O| |e M f:qЖ]tVO-#]&z`}p퉆K$-Kz(}zG, F.#Y>+OhK9ahٺZ(sS]C`y:Qd%?IG1êD->ߜewbI ~rDyH_7)<s( B8 JAum' Pt195% j<|}D;mr2\zn  ~䳑ڒ^)& @}oSʼ[0|QyíT×y9i)CJjV=w9G.1݄$H@B-|!څIn0Z̏8GvZp5Q 1,.Z0")JDB2υY+ ? źrƠ&"zkZRpF1$WH=|s$H,q$՛:®݀?Q,aC#nD>J4WF2, z. {3X;, Qt>$sϟ GjqWseï1 oFrX홇๝B%߼Y73JPVmҴ 睏v2Ё99Cb%f2H/ X |$:|4eat4) 2Y2c7ݘ>0|QL ++pJ%#gu)c6xcF%#1|M&S3,aDPAdKXrZEa&0o(o̱R=ЫD8f -цtShk+ed785s -!s#6xMH̞hogUhn,k9]`9O$tvDgk#@)B@qi+|"o +g#_NS*L %cqKftbO 8$FYF݆|9Aaq+]kdÇ8-xu; Xq㮗8x{*r!g#)uSHtL2prG i&rcnBc!ovQ0?"-Հy 0a.X\sjZ)H*rXr,')]Q9AFݬCzȀo@LĖ3܀8tSKIN+.Yy>Z;sۃ ¯?,xFB`?QX4 85Jl/JvBT;uK6d4,d! eSc:ݘ7_j}K2ڐ9sI핕LTou3h0?-D'uۤScoypx9ax-pS: CPY0gеO)W82  m݃@_ǝ,`>+Nn|A#&3L{ fF='dkD(e7ls r8%eS %s>cJR"RӴzjЉMg[Zl}F;w3{__sY8^u۰=D JDASR |v'?UYZiW0m(rx{]H4[ ̏lut0#r_ mLk "#b8n5#6Cve"U0Dr#5A' oJ:ו*{QӃu tAE5^"7JGOt6#'6X&9=b,Wj!Z³8SJ z( <cemcߥ!9PCcJR"d;. d)98!i$Fa:E`b0Rr `q?.ޒ&fc8r?a vaaI g5QcdL&Ygɲ;KFA[(og?|>yi-#3٫`[<8QrH0ܺvm%X_gPv:)-KsGQw^? k ­-?URx"{+ۮϒL,,} ~8mHvO5"JP?RFAԺ:>XR""`Й-5YJٶ2B 0/ԦS1% 40<S4=B& @?|0~?saz vF,1aG!̀#)b8B h.2?8 72UzC6Z f)\>d (DF$E0<@4" JCEKZڦ[a j8W`PbzJBRW~΁](WtKCwn$h^ƓyQ'33nk.d$7x>eMdbIlUo]<2쭲a7XI^ai,cZ:l4' 7/-<)H /nV߄v 8%4\(H+]ו!14N: hu{ p$p3KV!vjpߗJ4 DMnWR?"'F:f-[x%obRROsc2F&y#Iw~l<:nhLj?/kO PXweJ2CIslP,*;>a1/_dqrh\ xv~8íf+I̽.q6 @B4SedX*j[rS?+m  ` ^>ʀD<Qe'JOW4 rEž&I I+aB =(hԻ y]每q>ii}:[8kvۏOmJض}d BNOC3ϯ.÷gzՌ9x?Ğx!1c4_+(W4HiYI@ygmo0:J s rb[$3-Cv=kV֎ iFcqcHDс3tAQY{ Ia۩^^/2xq'π4< nŚrDF115! 9T>I,Ő#"֤iGC^kL I}9%t Kg98~=ugnmt#!lG 4j:~g> } VՒǏ1[cM, đ"f)}z̠ ?šHBSe5֒Qe9)Vc:tʴd 5 säჸr܍^P.<dA R1%wspD00GP׋3:ZH Xv ֔Np5RP`уP~燽8Dgj]B) Je Xbڰ}Cl/HX;Rų,((5Y B0`)]|8uA`9?Q+d:O'@ pաNJnѠԔ!#EܣĨUϨ] hI)nw`SFrυ /q,. 9Е9/1!k>߿/q:, 5N 'ݳ $ߊ`:87f3N=lDnoaBpOqCN>Bʒ>fq,bY |c9*¥0B(XOO?NJ!'DQWv+Q{sA/s*8 XvQa Ү cgsle,$%Xch[47g 7^" #-?uYP5cJ9'r}R[!Qx|wj+ KA/1X,XiYKI[ BaIG9/wa`<X͟񄁬]d<r]tFn5Kl  !Z6ˆB:`XеP  %0ѩƾ߬;)R\ p!3#)pbnBl-cR4[!hOR/NZ d(3_{;k8]bBu3, ÇgZ>v|°)Hb ?Ծy ЉK٥HPs T5 q8 10RÂrB926Ypߊ0!߁01ḺFܺB$Ewxs?",PF ;R/5/PX.5%sۿ|~3f9CᶖSf20t!V7es%RŐy pē ӐUZllqfQiC_YG0e>}|AGۋN6 !0`_^NPw̉}lj|Ha(7/ܱ :IYr>$,?" qfSX @Vcf~ &t 1 #~/ z07f?( fż00fDHGĹE0c'?{a.­%y}-Yh'|JDR8j2VĄS"84[܌$ 4iW;;8/6ٱ [a9Qs1gnνGCt0ƍge/ a)G)HS QMo,\^s>}Kc(Spx>iYݳhD1),bjθl}<ۆL (3( o+h䁄@RF7x0ؾe󟈌JDRpS8hS׃^"yUGW'?ͳKH 1㇊s{uA%ŚfkeGwKSܠe2 㬢O.C \xW`[SLL./2ձ|ǀY2#SN9Ì/us> fP:#!#)?6Yi>5Qp`蝷w[7 }5ViUja!~NRCcNe]"&G PJDASf3>l`qٷg)Hn섋H [`[wLJhz JImq %P)PC {K+t9,Yp8x`}tgo 3lԆ#/~if$fc ].i??Qb&uU' t^%;)Pl@~, Rc(rvx(&% ByOaq{oA`H#/ԓp`ݿ;;|'7-E? %una -gOlcUHC!!Xdd e?CRаB7Pl0A(;8x!@l>8. + 8i-<̭pCR"b2xf#2F*auWwQ^4} pV[J¾FE0_`Bh1hRiC a>HX`h7qozu4Yf󅈤8qGK2~n,UE)CmMʳ6 )!D0R5 #(D ,_<:P{<|vVPX~XH_B9kOr ≄€`D82 7OF)9nlM4K%nhX`=%-RF~nH{1?=cwj^?",8-m.쯂7Å3'^q8Ap|BN┫5(%4{ߥ B2\c%Yױ¤^J1z+uOLFf ,ҵX}]%O'd8b$g4A7>{ _]T(3%ϱU9 ꐬe!9nrya!'/#fq20f?"+H+FG~Ʃv?7ßcs-* @U3Kw3I L0;/f9`a`RVSlȕk2rqcB_.T&Wʐ685p/`[{߈t,rݜy 8BOɀ:,_(0`B7hr5<Y\;n{A!AOԵ+K1{9lG|ng&RZЂgYQ0@sMt Td,+J %(h.rK#‡d ;[1:(@mPn1,!#)wA)yQ~evv:B0[g]h}a rinJAoHv Pj8(BFF @#9`NYK)%㸈<,6t !%=:G =ArRq14 uni`Jʼn:-  `~s'# _4XPE@ ,c5Ty"GF l0I=Ż`xXU߉GEj1`1]1uIӝ %|-4X<ü+ Ĵ' q:6擇8)kF0`O뗜bX՜6>^I{+ @NP`dg%- [P vē$+)`CtqJH&p4Qov=B[A KqPq(4z7wZC<~jN}}kJ߬PzGE'n$mC~2B̍}pA? K+_)4DcJR"pǯQLg$ NJwfo":BѢi*R~rB36NcI`<ӍFqSDrX͝ǎ0uƬl8bu5[joeEVh"7fB +C;씔2А渚D$ D҄1 FÐc޾sFe( L0!!kGzHrR=; 4W t+;߂!GYuYr0m'6?ҔPG֩"̧a§0Zq} D,Υ9_wSC+=g8p]hXF H.?")N@@մE R|G ,#Go!Q7vCKߡFcD8-3 !… c>?"!+nxe%5~yޏaHdjX +R}<*E@#8p[ } $0}vFlvٍp!k Zb*qv|ҕ @!#!d#6[lvvIPAaԽLar\)xwac0_/w)%2S,5_$kua-WOFmc2"VO% TYn`߄, qG"r:v~gl?FH?",)f ^q5GlJlVԡ; (ɐa2&?"!~1O8"|e'ÆOd~P?㑙||[z1gT} t% (k #JR""0og9{FVq`f0{u0`aRd$9x5nzꢹ<20Xq< & ;jmu"0B^2q_mOQ.5iᦵ*#kw "U Y<; Xp!g#)S_2!oep5aHaB!5]?Ҕ:W\;>N53Hi0cc+Cd?Gj*`8Zv?"#!aZi%eq0 G- Y(9,{+Tghy:Ε%GғKe~e y)J1>䮔 *i/qgRMMdX|M$C (F-(h)PΤ66B9F8YX?MZj?",>M?")'dgùqg0Vل4|)BGD0 p76߰KsTYEn,.u&Q>8aKa1K0@i,܌5`1cq$ P~ -#ef5lO ynp3Q[vmn:Fh7~3LRvfHk͏4%)!ҹШLŤE"`a7?t(2ߎ0|:buvX'vc:|75_lì`cG '.]o<@7 b*#|N Ƹ1 #)HCqҹ~;83B9BhІdv `cI8vhXe' wBz\ٿKj4 wc8[@&! y1%}Ip >lcaDToZb@r(CCWǭ 繨?f;06{Hq^9Cis!~`FO-~?a0E !ul0,PHsDjx(sBO驯P M >sBÄۏ3>(pZ(ۚфyՕlf:e~i펆?"+Q R̐XOo6(dwk F %Ф7fKw3wgnabq=$zb\Ӝc-LNJ|33$ .\C)Z&60}^gPo` w |yAE I`+HGe$J$Pf FONHk-:#YL^M2Mƺ |3 !̀#)()|lC  K`1ŲڸR}%4?ֈɩ(ԤG=Ox F|hp:#۸#e5JDR47<) 3vVŤv}cYi#435hFKqP6Borӻa&<dFexZS݉k$-ƓO6XBঔy1!@P3ugY i_$;/,`Z;[B }Rv|/ PL8@\!)&w3w, p,;U&1<G_J [3n5sW ΡNs N`,Y#yvP<[PI (y0*Z9'| Ɉ7]<b6lvٴEx`0C8O$tR#ftM@IF0er#KfB&RpbIE%vS]!svzL K<JR"APYyA;%#ZT8|W톭`B.KA ؤ V>wYGÇh 0Dm)46z#v[} h>YksU<)Zȉ=B&cL&'t7i6A|^Yxc<,r`9a( 8 S|-F1 X\э&&f+2ҞGDw ‹ϯ5x rvJ:ٻ9Z[Qa(Pb6sN*QZKr`PCBHI d''z& u9JADGzbY ?Ҕݫ+l*?}?0p/1ùƤC,j:DFSYB )(5/`-a~١6"q~d݆gnSg l=d>CoBS|N ђ3IW=r#DΝGNtj JINHg}I]~γrm}À?R S g?I&Nϻ|W]}"$2wR"n۾szN "hej'!疑ҍ M | 8 j}@w !-rjZ9%;qR4#0V‘ }m83(`Px9SRii3 HT?"&a2 0ICO|]}@?C PvC&$ # -Nq骴|2`U,pJk.G-~v"GB?Pt*Zm4NFD?",Т8]Ƹa|x!)e28LNK@Spp݋t2NĜgn4)2r~ߵ,DE' dw@&@`ِ0 1!6͋%Jx{[\)HFet ̾5,D zFu̷ DVbCJR"R0[vD"D4bNJ9,! &lvٶ?9(!3#)aaG8ufwp0{B R"  ZR5.݂6Sm?ޮ!eJzvn5m2fi9,^aj_e_KpRH`A҉ZRӮ(f+daGw q)?f&aXDlN +6Sʹ GBי]wJ )0A}_ *:,42X KI^#,v|dJ$Qne>: mj了{C~NYm#J ~YVvuB,I I]nǩJ7'ˆKib|K }+C( D>ZX}qCUɉ) JIh11tL tᬔsP=&bg8L15 v3WXم;uyc% T B}VSD`(o+paivqGw;U8} g7=̉u?ސQhF#xO~?xDC!bX4$fl$\auftKӣZZ nQxdo{흗 7`/bs[1",LH e ,aYh`K1-‚aH)JS 8a{;:;{cgD$`ߌuqn# toax>&s&&T6( !^Q1<1},c}ud*M+;5lFwF ;ߟ;eQDLĠL߲PG NaS +l冥 HJ\ PS2TWa}ǎ'Ζg]MvNKptp400TylrL`䛔*M/r; MGB,9I%m ~0 !#6/<(Z ʓS\``#)%n$Z A*V,`1KۨVѿa`֮XL+RŔYxvY0K@IN@xvy9$̸ @DJ,7 $q@3?ܼI`7ks:?hPkH&4? <3HvX I`H c*)Lӷ-YZ@j1I"DTZRq. ) R2#6ö }Ka7]f W?KIgNN3rG *KܼR-\\wEG?~Q>A9/0`<&ZK(.Y#fաG R'$@}[:K;sI{f dȜ4 HXM 検9}Cuۯ ;|ŻP@Q\xU7Ii!3 C Ic7/↸bՐXЕ Vo0jЄHęUH )~Nip`Jrd&Wm8k Fr bҒh?j2(Qa*f{Jr dyI@O a1рr[C(1=9\c;:RI8۾7FA _&ѰXW7JJ1r's(q_[A8£'oU%S>_W<j )67@P Jޔ%hp%iwJyi|pJ 07cEKl  "+eTxVH&dii!, XF)݆"d?0' J1eĹL1 IPf_gS:dnAerJ,m!!_"l F19}lճN0qWiHd1@N%B!<.`uM"& By,GFe;z52L$݀bX4юs8GB _}VHHDFY,gJK+IÔ!b_tq5LOL(/ܑo#J|]u@-%7 ᛁn[^$slg <-8ÌԠA-R`dJ@(nGpJm9 G[R:m[Z@#7;} YAf~ó[g8|/ [J̱vH$>; nY(l[%"$N ^\(o%$8ϿI;)6xMM'p[NA(X(9ȫ20nY)4Z G,gJzMp.L%zj0l0E~蕋*8LZdOjjL)Rf"anGpRg h'>1\WX]V(TͩG4: I'0#>@BRp'эF$ ҃;Y9R_w;)C6mL*fcH[f `7,oA)Dn7qL܆u<: 0 Xhn5+h n&[ݛ,=v);$! o~u0ORJlt 3dv'hcK,SR5b{ 1'y"$?",&ʵQftw߹dyva Ot` e(|RKOVߏPxRI_KPL 4#c|M&8 V=V5%\od>S :)%OK%"v4QVG,s $j,7@Gݳ*6ٰ*@ imm6B Y2q1B\1ҝ۴eiѥﲹtxf(Z WBޏG'jk`7#; ew4EeSwk2JF>FLAx|YC~s%g g=Z~cTiM)HC˘H@ѬSe/U Nl᜵YFId6:Jy/nKN<+#?䵭qslEn?q঵'W(Q$Rc9牡.BrOncLkK%%/ Qqv68}G}B6q4,:٨x Du `ݕ$|Ain! 1_*'%3/=pPt7/aRZc˥^)i1ˤu3K$+(ɃT Kf@?c#Z8> A~ʂK,C-/>F%o y :+?OQ!Fse:2X!#O!cnyۋvn%Ac¶aa9gSOs)l}\]G_۷LJ@TyX5f$x%b~n5td, hT8f$\j ÷'$3p6\ViyCCaٟMx$P7sDP>hu8Ǐ'(8 Lh?4nY ?w^b4qStu%<|@ 5c6yED+f79 w#?U!l^u"20exh(*9\q>]/R A2׵s <:S'S|41Ga!UO[cƂw|,{J"Ԓy{hעg%`LJ?:]J懠P ~q`t` y9GE̬fu?U ϱ$c$v !‡E 1g)l{ʖjFft 6 \.M)E &$XS̄b0G. I8O^_C .G[('{: @11&` -\jR̦ p%$Sd8 wl`Q@ NvҀRK IA8ZCRZ~j@ 3{|*9i4QHx 1@{w9asR1M;Kg0 cd/b-n9Gj ٱ%g3*cJR"58ԗPpx)c)1=GA$6Ae,Vn M jwtC𥮊If8A/aG ĵ w'=) p` R !NYh0jJ=0FC`掉h 3g/ŠI/ng?vR#ҐW`+$Ōs p .1A&ї>utG&E#&)Wd)k[Ư=je, CǠtaB! 3 1J.0 `<;YmOYgo>N#$ռms9oXBC3g,bKOA-_c?xS 7sP=BE`̂B A7ab=<:ia`Q04#A7q]lՠ8wQ9;d6s#vDَȸ`}i9_z[;c}`DrՙAR@ܶ߶ n#9NV pxB(?2kX‚]#S7QQ8sAW }yQCwSgA:#laBK:gϮnTIh )BGCfeS܈GDQSd/ 9}|:jۛvFD\0M8*f(X?ҔāC2|-cӢ +'ـΣJR"lJ,..ZXWXݳIF- )$️ѹ:ٹǩhL!1 ӷ`ήI] QճJqq!<mR:9n_HԾ݀le[6՜0_N1#ջ~Yޏ)HCJR"EDp79H'v[,,T +;xqup)a_ $U$[w74LP6&rrJF["'0WGML28t:S!))H !Y4mv!pj]3E)-E!e;Qg; -`0 Ǽ_4>yAIII19zg1]Tul֩}+MȬuf XN`hSa"9pH o8d/o?JG <@# `|2=(s9H174j B?¢[0g} >+GTYbZn0U3\cG$cI8 `2ID 3:¯;sZ~`G NP BPNPf|pD C0 QEl])w)\~b&{p>  iĦ XĖV/`"?gg㴧9jq)c DUT h( J;fs\Ff3aNC-hP}Co8p//q96BP4kVk?L n0G#0М#@> M- OaPN8 RiiIRvGd̬l+^EYvi"#0k)uR0lδYԺh wDF9ÿM(jtw?"#0!r}`K$7$`'ȑ3|vI`y#  aQ ?br[9Е|++ %!`' SG0R>dL󔽆4VP@6tG/~̨ٞ$tbGCs{ dfdR0w}ݨ5&(|Xٿ0d|DZ&  ,fikJXԜjY{s?v@f@UY@`(Mg'*$kw1(o.,NOOC1PGq!F:c 4d{&#Yyp*Xz2?F"9iBÇ(Joep0cqݔ|>7#'33)*KM.[@*X̞g X\ C hJ3>?QP-&JF֧@y|%}n?0$A`23sQG0"2_xVT [f8Kly]`?u7GĘGw[?`&k㳨FJ[`87SfuPyPmo`3Ḍ& X5nxMZ %A7r|&SE{RY¹Üqm92ëbKN*wVO#C%v4̖~c)4O gtnu`hUW{6V5~A"+P51426A(FŤjYif~=5,dAaHZ/!Ҟ?PGT<EYMi ĿX'[:[ nv_,y眧8SOz;p4\8XpclIxZh4{ !$nzN}CoEl;*"0yE{:lf8n@ ^sQۅ>rdDL40Տ[1Ld"0RHmIJDR`a84$k5ka 6\9 1'aHaY?#R?ґK@`dك1-hE2uHeS47S`t,J\9uVgiT "|PYupxtEr6Rqꈜ6(J `+7Pϝ Եs sl_%Ę"Ѩd}nOOcJR"6hK vkXD 0AØ[3Rs LÑA2WaP4s馰䃗!qDLJDM=.@6 3oٗo$Tga/pSlLlw|i_FR@HІaPQ?Ҕ~ߊAnJ6(Osho%  !R i۲s}2 3Z|̎P(CR%.!!3f*'0pszټB4 $ $kΣFC]8q@6~jfΠEl?$02l]ٲćXHjK5')G)JDR=_>quotöBIif0ѣ_1֐Tqeľ4ðUPbP jl$Ź 8۷s4vŗ߫63 e><~/p q4 9UŏLZD eX#fRR0kل&H,'G[K@|'M~tn˽\ZQx{-X:`ihCa#K4xEKy;)<-ȇg,لf%HwVXq~a]7\ B0Ժ7(0ѻRZ0A0P9WشJJ[qPV]#g Gtfґ/IlNgYau?0FoQ_E)LkA@ -'K2$de<0!Xs1%w$$G[a0,3rp1)ϙ)B>Pn< 0p ! X#81!ɜg%1)noߡ:0 $ñL?M4΁5aQ(">R`Bux\VZ"aA> ]G)8-Sḽ_b-|B]V۬j]߄78C;q:A0J(bK(zDj"yiw1qqldSIJV d$#a;[# tZ9/iasZ~2(j8-QOJ~Ư#te֦`(Z/q໴\wM"bYd-9h[htwC {~ͺV9(ǘbCPS ; a`{s % t xY5%t%bNK9 H͟_"T` ֡bs2GZ 7l5-ـW`[]э 8v gMZje!4~XWN& J4湟 qn1oIh lMa>,Ƿ*&Y+og[~=1yi PJ3:fssK姅cۅx4RZ{`8ZH{sMaN2j`~Bj$ÂJ[2]k VP$87nK||uEL,xN'VyLcQМ~ҿ,t87AK?<h{ۋe;OH|ӂ ` t''1cJ֜ ˉ%=qiG!3#)c߈])% unᙱ %E!C?}eHH:y!d셈IdJ\rXn+!Nqh _7po@#.&PK JsF-B<.: `L ( s71>Td;53]"@i u v`ߧB`]nqp(ru| qE5GbN:psTDɃ p'+֐ 4`P†iAe!F~ q$q:zjf6n7CW_ rYك; Ϲݕ^'1dM ᘷ&䤦^B!(/䎦uV9 ) j7ơ!+χvژ]a>qc.ԡJDQR`;]Q<\j`9GE' EcZ>G~hHBJ׏q[]PU )b]҅mo498t8D`a7K Be2Y0,E>cJR" Ѓ0\fH;|7>G- }#xFİS3,|'-Y/0;B(*y V(lmx哏 Փ[#}?\)<1Bh #fwҿ[)CA%d&Yb| X ݶݹwGR (k1!jlkw{s Pi Ү708 %{0Cc4 /3Ejou`22=?͝VN vzNY0R?",bId75K܏)/<). 񤲉LtcqgQX@CӑstrRP|헅[7(/Fa) & AiQN;i~+H/$! IY'(϶Vۺrs RV @NBEr;N4KJ[LeLq9d$c/,۫y6m8-RGm~1  6Qj ?~'aa-vN Ra(i+?`x]PQIGJf@I`dؖ BG:haC@mXSB@Ds55SCd(VgWYaw1.ǹnVԂ i!(x`cfkg])Lm-ex(26-:"QGC_f)$wq=__+fL, J[a`c*HvO5x^`XB³E|q4ǀ@` $|lrI|]{0?~(?8:iO^Cg#a1 OpeX4htmA?2Va iaKّ6:J7 pN9n) ONFp04`G !I[:v?4@p%bFH DQ?cY4j|gHĤt=-aUv{0G, :/kЖt!;?k 7 # Ta4v?`;L8۶vv2P ɸWol$(9HHLyrS^pyҊ>Ri7t |n3S 6Oa]W4q:&T~W)&7`;|&lk/]͌EX؄PY;0A2VRlaҋ+WZlʖ("d19#Kaa,_0O<8T+P0(q1If 4ܤ~hx/2rNYH)6C# Om` i9nX7c!ۘ"D?D dbp{HLX`g}BU(:mЄ$ F)Vٰ;|̲>B+g8vV8[<ُ 9>27BΣk h _F)lx¢a/w7=aӐ_[sd%`E2>!<%p.H9? n,?g?Y y6y] HOD!5Y w / /uڙn9r'?ҔAl~sɡ 1+`W; 4Si7p{8psQ״A>!Y+!.+s@!5CҜε(6JX`1CPmiIi/0 P PJ H@Gw_.! )ߠ  `a 7nY `<+)$'3N9UUw|Og0sPVnHC6fn8P! JIi,`$Y 3פEJI4ہq0H7B]3b()|Q> +BL@8е41~ 2*`f6(cHr͠@0M?% LfI{OyqpKĒђ=x=ϐMs-N0)fj?")8)8J ׆6luCf}Ip@0 @ @vZB d W44B,I$K 0G\r 7Z K1x>a9 ,n&ڭ%=0OV~:u3DRrD0`&l X]e,#‘! wĠp,+Չ˴sCPJ/,hЕ)g@ "RI~S8vz8DBc.)ȂFueg'-`̇߻]qQP_Qa ̝}ۭ{ я)H6nrmggpmC>^@#g?K?Z#\I_ qqυB1T֑005G}׾7E͐+lvJDX/q2 ӑ{3YG} `.۬ M %\yQ\<nj 9 Z[#P?,{p"XAD& )XhN&c0JiC qHoLQ _Ň 8,ӎ>O& \;0]op!<8FH=]x-w(l({Ds@YptC15=((R HnF-ZX洈?LpV8IB3VF Rr0ERZ0GwK9GTJDSޔeXTd@6 _)Ռ^vr%%)1+;mֵYF Xbv}K )li 2?T? u!b1YcJR"f )H9JR"ۯfPq$@)a#1Xp6O7jL%̻qX#!g#)K Q(6q$ǚH!L[!4c%pj> *pPW4 C-VaāxI&!,RKaOcD$ócjyIM`*3?-yKWQ8sXH.kLr[ recԇH!>)CR~&n0 |Ivg 8S.M¹l^)ݔZcE$1 ,5t$KGe K@$2 Hx[6@+o0 ^X& O :bHԣԿa"T9]* J;;c{Հ7 -*]|U01$2A4 -34.`55V)56 @Z147S' Vg-x  X`(B m f@?ߥJ#q|D`Q3$j _*cbHE$nbYhsۘJDQR*!=5oPPK71)L$XQ]KqK;Ӎ8aސh ,6w(*16 &~Y5 ٰ,8$Gu_,~Y8'0g@E).6-f89qi5g58l]bkt0C5uc[d`Yڕ`7Ȃ4n Vtٿϕ &p&0bBwX#3+=*tH?Ҕ/'-wZߴ9?I"1)HRD۝<bՙDa2!4J(X ~fSvg:cJR" nPĄĘ vZfh&dS\!~溄0+QQX?Ҕ)H0 ӵ]$%(O/qeXg(cZFWbr+̙&OE.l$a?[D bKHb G->t8e|0jHyR=4uTttE gt,o6nzXb5fZ(0*)|SLs A*)kI:WI⃠W(r-_iLP}rIwC?3m:>Kn" '{1=#\.bi)5wn`gq{O۽ۚ>]-j?:rgc19Zp7*TV̊=[QC*3<*Sm '*'M]I>ۡlb:7JG ~)biJ J $g0R[c!gRaD xhױ#,PY#=,Wt'd{ͿlD vy' eQa `LG0sNVR@Kp87S]@*,R^%Gp b0 9b941X{DRhi A-504=é8R?"+V!̀#) +u v_KOlⱳ/A$Ae>e fsƟȾWZ~@̯A03 J8ݸ^3a9 >ٱ9 )8ӊHXEd?8QE7:;C'}c B8}>6rXp07=p4zRP7Y?pW\_ ԓaO$~c F)(yWnX#{~-v~IaGHF'%uc@G5)Ɯ׷H)i3 <OjDұygXC%w!cgHߘv;47!Z o?uQ懓]F#Iު?R"p\Mor'" hp{$q$,'|32E~”8A?Zhľ+}2X;Bs߶x9heBzr>1"HlW$)۰p5qC' '%hG!0b:8H, cᅟ= $%ߌCϕWH~4%#:JP2[ÂU둗2u`}aD1 Ӳ ljh) `LݶH O/K^ Lxۧf6Zs'|֧[ݲ>d=J]%;=KÜ\6ݣSN%N 6n#VP0S@k@w 70 {uk̨$1`?1)Cgr tZ:0o5ȃ0;Sb[2Zw9D0j@n߭(ǎHJGs :V,Ő&aוx \]pL,HCyeH)!JDRpX"% IIFa{0q%@KH$حMG払ǀi0b@rwXZx 3݉M55c>À]•vI (jIj$5#8v¨S!'[0|8-RzQG@;>hIR$Fz<KAAoq8']yD=Ђ<=ts׹JRH26ö#^˞A/oOJ, r ς= Kvadl?'bOl#u XZ|; ǏngeԶQeKqF@:=0ҜzJ=?YչalQ~4c~{/3fbҎJ;(Q*4`"BIlHX [Y4K5Vt0a-& x` I!!$JJNiYuev &rd:` h Ls4)vB)n=APp1/byvs{BJ8,jQ?9I a'$AcJR"Lk$$bRH&>Ԕ;|*hb@)a&wy/NJ_+8pcgZI-,vCO1%^GNc$̣V-LffZQ{8cVKefC_6v~ )(f l~3N9g(0ټ7)P㰩5tv2aR0ǝ3S; D/qH z40I Ԁ J7hّg8 I}C2{?mYĀlVIBMCG$ 8`d;N#V,([*8U677; AYD__? :2 h,YdG| z h~0l ī>~8i 04` R(>hЄND2R^ϐjEbsg_yJ{vqgƞSAbJ+~yn?=_fwZr uǘaxqgAݙ q0hjݜxYDw|r)S[Ҳyǵ) o+A'όV3su,6L 0$4V:8QU(4oL庛g1XEl{l? gL=?gg9° d.r`1Z~z\ǖMQY 3> %>7voƩR]O '$?v]^ 1d,(!]'BiAǠrߎmB g?-" NN5@>]5`r*K|TY @'H3G SӶB2kaIxRΰE,]]|`ԤoVc?U$h=Y^>|눵8xI_W]{}X?-I)G)JDQZPJJ,j?=MpXZHmR zx0BHTA˻U$|Iѹu<],˷FgH9gbz"XllxU{EJ, Xp.,(yg鲽i#JM1)"`^8'\"NP+f $r`7* W?y:(sAAa))Ha6J/ t%G+=QiE/rG |p̪Rs-jd' u!Qî~Ծe֭J|H%4!aάyi@'1x q[$N.&1%4p=?YB1,$s &̜~zIDgSH|@vwqLdP3nJQAB>r}Cӱ p?:4B}ۨp]y0q  5 Q*P`aH(,U:-ğh 11 t[7sF=C ?͎;;, O2Zqp7!)2`l睶p5a.#@-rS%1Vִ/c\Zٸser[#ho'3!ltZnQA[JxQ9ݳHF` B0H{P`)-gZq}[!OW:tC)ߜ5lcύ!@ f3UY6 쁯ǜ$>G3!o ' aݾ4RI%xukVS`=0X`ofNo2?*-'>jxWt3d - $$c^71@H57)ZjIp[}۞>iҹ{}|b&0ge& $0X?93 o ?vuA\I6I(n,G!%-  -(;} 'q>[*pla3H0UKġIj3Qd-8*1o79Š3PR6? LCvdxh q>!P+6vc߉ꝯ,re(.-ȣ0S1Qt0RDHӸ+/?1aF % =DU,;_|w/0 w!YCwVq5¾b_ܾg(aw$3?s>> ,Ry-/Nft${7F68f5?͇h0Fe,]6d g8sGglsdddl9V!{' p ݳ2m{/-Q7%= Q%#ӄᛌvu ;w+)7HñoL` "(0'+ S|Yif9ל`MR?cv@k$~R8j+!Lk(\Y ۆ+@XP oX1.9I+:w|2cAݷ9KV:W^ٴ](Y!xj!n*dYJ'n#=Ƈ+qT^s,0Ӎx X\8-ȘM+%%/wC:⺚ByMrѢR,$5(]8f= O-'bLJA!$\ g9k͙ $(#hYu v33+`4O @9!/g9kMIJG- š),Z]ݐbII$le#cvq{۬ * DJ`O»{a)r(r[Ž`# = NwO`  9 Y]P^ ,Xb2q%L[f\4gloa-k d#2ncrVHjܾƲP|wve(Ss4^ izÄ((`gqr=/e[lp0uΜL$ǀ*FJzӑnAP0jF+d#ll;l:F,>JU0f+l 3pr}Ҁ!g#)WPƺ1Nmrؠ @Ѡ[r_FS?Y㭭^Qw3 ( &xa(\L¶ϲziujԍg|b2á:M, _eߤ;lF]p2Vpׄu|½-Ø8T"<|BFn 6' -#3t OB?B9| f~)m2q&dǘ:J9V37-Q+ad2'y(WBD6wkAܰ0X᝖/e0a(#:F05,8JEr!cl+ cY; =ߡbǏD!3IBr0ٹANErVt0#ᅶvSi)HwSXN< bIi%R%X8 ))H8QT-%9 `,|DH"~!");%_u١BgIݷψJDQ!Hbr!JDQERb(!6YȊ;1=9tEiLQ:n$O>H1bj vB񓹖mg-x p[t05$$gdgO`f=b'l)`88GD5/ ̼=+XX! z([s0lFL۰Qּ4CcLMϖs F{3 x`+9Hz|p(~' =_PT<oLfHBFz>LjT#8,?") Fo贆dHa,7NRa(q#Lw{n1d<`RAN38(y#rpcG@U:1* ]n<"w2Q A!̀#))H(gbIw#u 9BÇM.A e04eJ   !d#;/zنc].$X50Qޔi " 1(7ARr \c~KScx2&/ٌwRP'@1@`y Ӌ}E?FB)O+ _1ΧCz8 3<`@<$h;d(xRPysy{\us֖K`\ `OQppBY~HĚBׄ:Fx5ӑ*Kl1+w #Q-(X0̈́,v̅RB"h70_>&I %!eJ[] Z?g$_3lÄ3χtJ-W0-p&EZzK+# @I9[oIG/fNCuÉ7$7 ĵ-#IƏΰ2~+%#R9G,9cb  !3`bñb5ϛQGpA&䧶n+_!x?$7e@nrX8} .(d,s TBK1k:ō-eHW,lN{ŚO_Ǩ6:ful᎔c?X (|M(KR}өOǏ_ؓZdMEIFI{F\ѣVI&-8qֈY))fCl%CX#f?h^p@k W`BIql]`9,ÌKRY9ic\JZK @JIE,m,`p0|͗SlXp܄m0=-GIk,$#%X7BbF>fzNEz>v!8RU\9.Y RӘC_@?;vd7Jq)uqaH 9 _R t"x` #%%hwF5L40M=%JwpTRfVtwFD(t PJHߏu n[u ]\HRn{c@hOy>b8Y0pO5O93p쫫,Ӝ)vXx|.pkI\?Ҕ?f]”8 RkX)Bw $ `. v# 0n9Npnb0W%!g ؔfRFqOkB4CIeYJ;,ߘڌ[(>K9s֊^d0ѪN~@|rr*㝅{f 1'qA%$bPqbQ5V@%;=-HuuoRr.4F@2u $erZl7 %lZЇ1̢F4a?Ö7=L& @M!!3#)X*tpAi--V3!m0@ 4r? $ #xAc KqJ2 (5~6.X±k`cuB=`Q+4N~ep{Uw 4KSrcZZDAblGI0z9 =C[q!(HIKS㥬xAd <`$wv*B7`~Ƅ@ nf,@1N8aP VV/sP4cqL)Hc]0V8^2S'yy;'ݩhs6߀P)԰Đ4 I75a  % N GA,XfEo/GI^fdy#FfĬ̷|<81ϒ)9v)iFLyNZ\,Ϯi9l"pGlf;` loII``NE9}$d5@gN!嫆[w=kd?&,0Աjňڎª`x`?0>4`ǹ㯠S\ GS[LAЀ ,a#ٌphWA(ی9 9W4iPK!rC :vYKBqv{™GŁT[WI4%VÈv'Х|V86$60b^tv`ĥ -!%$1~8XtiA?")D?{a0]~r7`JD8)"k;wk0nIZ|BS$p -D \C+lQ/;3 e3$+3$8m_|toúUo0nG1͔#>vXHUxOYHٕ;a8SDO0r8cg%q+M!:)@?Khdtk샆M Ѻr^+ TcV9V=RRJţn X@,OICT_8~"YP͘Ǩ'SI&,(=qa8HČR]l8=| ,Q p>J3;V#? ?(j8|Dd@c `E'.kL@;S˃-F z ,I8 CvJJy$嘸 rad%C㕔8T M`̄/-!)uj̨i4`F#@@Pggp?u` !uju9sh&S į|dX r[ K8o  wƋ(" I{0|EhHG/#l0A0^H>MH1xќ,.ݐw;y#"S EV6K`Vˀ5!M(Xk8 - -߶ܷ;v%`tk!@R[~J5fZے\1e dg_Oq 0qj%n:jjw`QEb C%$X/swĖJΐ9j'cH 1|챮b"(kSỌ0% GAiW$>5ߏ9Mf#@󰿀 ƌj3@~Yc\M+,!,Ӳ7( ~d_/3lBgwYI91Wffc[S2$+A!ٙ#)RݦFԵD\(t; Oߒv5 hK CuqҾ?`;D`;g4?b&L{unPxѻRe庄XvB|LHfIq8wu=7݌ Hk+(CuR8wlٕNGRw7QN2B]|L&H,Kl4ch[9`8/u)HpUfJD@jvB3$)`N;9a - }\@М߸S)ǭA&} WWe(\O c [D bxjIM$ba64o kwC'9-nrrIDV@S=/tO9oV眭µޙ?9f~:r?a߰VR`hIMK93^ H&!kF_Zx\1ZW7r0{oAQ^`SS䣤&Rg" ߶%n8'4涫p@; &biCrY!$-NQݏoF~ym3,p,!$5Mv ͎#:/C=~Z2T@3(bz&CX_Գ q>Nc$?qvA} /cٳ 'Ĥb!y"gW[ yå8s$܌ya38#K$f&A b%xs{YDf RKI' 8p\Qk~`x>Wa]w CaF̐ۋS޼ |P7/eGk恅`27~VN#=MF?8K ǟڍ #1XIpqœD5y cZSbRαc\ØZnwYúnYK]$OCNJ'hS>Hby;wp|=cZ%$0qnRW%+u+M׳u8DN2`/ $S:C`!'c0?X!Q|K|Ϻ|Pc9MHD+#4:..9x*oAg`a:J~0p b[~[ qN}tw8y#a]) DYAe~0Iu+kB -f.Ѭe?-0=䒉?#݆2Kƅ]4%#(ʀ+#d6|uA@&#! e Il$0a~c] v4(qXZ\?w"Icc M cEWtL R)k*I-+%qNb.|9decydd} lJ={+n4sb@+ /c$0ر,H4@:0;Jm*B %d':?HiUº 풻fGw|=Fp79`4Nɂˆ#"X'1A 6p)cqj%IH<+6K=Ŭʶy*2 ſfPPG[~s[`Ź﹌vL*8\)hqFa f4O_# "!X).퐌&WM&p9p6O%Q5wq0`,ChK%FUֳ`1j s Hf/R=@6< ~%U+=ķ (_}2F7ѓN$^ 1wWC^G)NI3B@(hH%8a7˻L`!g#)"r,s=x+/y901G](b`Q= y"&p?.<Ǟ?xB5䑂1,9у2 E#rsLs[[7N%'!&W/a1%'[d)ΐJBű9z&7@0倾# `؋lIOQx tN#'s+fur4 t VsPN~ߊ^}%dGa",  bi+Xk%whaPޔ`?ƣ;n,"`~r geIe,&1Ia9\K/a&?`@+d۲G8B0 IY"FK-4SubPտBdR Odt6J6t݂(d_:P!t(e:! P05$/)đQ:44uJ(Y`=ξIǫX= aC'4x_,f1 E,ah;y+#8BP39.ݺZx|!n%Vطrƛn}_0scB -ѹ/΂@A- b, ZW74-Jz[2t-5n+>E#y#oCw㥋i cdYjcCA3Ɛd;|11cQ*pi&BtB &''K4QYI%<#%M*ae`M9=V_Hi'*@VmUx=b3vń^?>]ґJÖ0T D[l;w;[BXqpn2SNm*{ c\Op ׫H3;eյ%YN 2FhmqqZJ Z3}0(ZFٖ1q00Q0&즓3{){l#+#|}TA>٥61>xM8Sjy)HS t2 ))CJR"FFUA'PWFGg»H?Ҕ"#1f\w YU;hp7D\)

?"()H6}:;aLu,kq}MPadԲ: o3FK eT8Se`ZJ߸)6OCu2]sEr5C&Ft# < Ip, )!ZJ9ك)b 0y#%aXq8MM#CFc@tՆ4LmLfů$`ͿSXL$9g5"e.2?|X  1 8Kq_>򷈣C!P%쯺9YI:_c9s~c&{I\p@`M(BG=FXP] q)`A*I6~s]̂4&[A d,LrG19Y7^ŭ  ~>N8)q&6AY>/'E{HaHXXM?0A [;00i-.ׂjPIhHĈXt>H<͖pR9/$f|aJJ ?'FU:1[-98Onv;^b@V5)GF͹v0jIǴ4Y40OB~'0X`b_J3~sR,c5we\@hF#yBbx|J)#st38 fɀ5!7(5%N;0R~؊D &~O# o%r7,lNz HE%,Scv1.&&+c"Q-)=+Ɗ'3c%zȌNjE'~oqRgK%f:~B?" \JDQMJ1h^}e.a- eB4mz9)!$Ftc1:NNh!A9^F2;i,K FB~BFhe{|Dg))( 2Uk$(`e)$-5$> wt0W YFZJXÁErNG;ZJBRfBa>}É"X<~WUn?vk.$K7 P; Q}mx(j_+A!3#) )tXJ9cId@:&7w2?цTZtMBd3by(eXJ>Nn!|PG>u52? =/[bV0KGD?&Y/ew4Eqpюưb7<$ ׶m, L`ftw>/:&O7BW-He>K7FRYHH`[V֦9Aaƚ+떺L)!)G)6͚&d0#lRRloLYXF52N&)\50] s*f6(`( B^@b-ǜbP`HH %<Na.}aqOJ$z}5;IsM~3u D\A&!n(e9] lj20]S bex 1 P(CI0$kn5é?^G%3 -(\JI43* &#d ^ r}4è?ҔeCO tM! a>Dُ}XܿڸT:A~05!A :O; g փiJnGq<t#`OX'v(<_e|֡K%b+UhBv^l'as|xPi^~[+y YB`hB ^g#?:'Qu `I`,Q<9Nx;S$Qn+/"fu7unXYWM+o8޶{[.vDK&Z&ݢad$ P+A .k ˛usHB1[!;c$_)7J 5L { :#_`U}JIJZݘZ v_.7]p*~5=cݏ^Kﳨ V`&(tVM1Q$IOyyC5c hu(yHC -Kv s8oVF0`l|y]*sruTB*OGb^B00ԍYjNaJ:X<‘R0Aiᅔ`g/7~k屇,?83oQPI`=ߘ:5Hf?!;&hQXݱDco`KB8s2wKg}0H$g;Q|Aj{6 0 ɥCpOVV{`P nCo; TE``3XTiV߆ÜU۪dzVu NJeقέ@H1P?"()HB>UHĒKNG0% }^epN] X4?>3|h]j# ĘbOq`t h |. @hIl7ǎe#d8ԐSi%< ߽zGNDBlK=q047K'e-޸Qe ~@}_7 ę#h\nRe4J04pq`0bRG42Ž.< 4J uq!#)}à4.$n r= Al1"(̇Z;Nw %$8.hq,Ax+28bpY<07rP@@N? %M,d8B@eKd;pqrZt'#E(CSlKۺ!wFpg,,90$ 3Xvd0 4!| MaP$z-DZ! W='!ӂP3ηȋaPŤHNk3$y=X' yr`ӿ<fҲ[88].Mē 4fWCOy A-*Fw| :̦d2Ɋ^ńd$qGh&Q)Lx%d6:,j%fRr窤Dr|6EMͶ~7}mS 1  ;nē? mJ@THB@r;pݽF0F'T{w=d$6S; Ps;D(F #\#*7r$'|$u53oRJ%#etRw#?mg%[s;vV-?%t?y(Vv)HD?")8%2fqk?P'0eXt0[RE:g' ;{NzQJc?KHR<<,lRϜg|+ZZ Z{/`?я)H( 4K'o\& 5 qv:P5 cs8’80[!RrEpK䱃;3S=e)HS;҉/J=2&Ĥ D0>0,T JF@ԍK1#H,sDӐ|CJR"”Sgqr?")IH-;}w?Ҕ&TeM@ђςO(:x@U;> 8²[ <0S4%Мw[ ͥ#nnsu!$Z' ̈́?"$?")B?!D3\eGw;ٖ9Vg6!)ez +%c#\ 7;$ 4xt6iiJDAcZUH1r}19hnKC$q1'Ynmש Z:c9T?k`a|wg_}ϝ O‚ M5Z fA]sȔ3C hQ)5esPRMِr׸o-IZgskVq0f):!'P9? Q)3#%v;tBBQ>`̥S0O}|t\L!z̙ a @Xhɝ?lCf61L#<zKHޕX𗶺Jg+1ThJwi2DI*Wwl%k|+-1屌mr@KRK% +Y2ax$J v o$%nnnp(st[n0g| E wvO'-ؐRE|gKu[%R+tsNf+9=Üi @fdfVOO ,s 8L}'8* |é`2NY f=݅X/&k>٤8|YI7q|%!X }dw^8sg &9=j[yZΘ9>KO(B>Doh`Nق{A7bw2Yu8_ E奆 P:&;u+0p :PjKmǨcQiF~jv-.d C¢+-J8|bNJ.w ]P[@Wŵ)CXf @4݌ TJC7<:5%x8( V;n&; |=;aʯDidUlr;77?ܣ@/}Z@b\ . J&!;߉SdMLEa\񧓯]\Ȉ  DX]Tl=iђwcjB|Gx(gxi([89a`HCu9j6ѣS9ւv3[R}2muw! 0ww,\>3Q)9/`B\M)(ߍ#*Gf ~kmz9 6Ğx؏lDgQxTbA=ǹXڦO?1ڇGohK԰ٶ[ Y[Zh' 3͙¹{|֓(73%5qm'-d?J̆@(400_.B xW&b%[-m.*o$ 0M/G\; OE'L DR0SUP-plr)"34)`|XM`-bT^y۲Dc%-/|ۄ8@ 饪",pQ@eqNkf~/P"V@1\L!!h 5F x -l|:`/p60Tw><}Nu:n+CdqԜAl%a/s=ߺg?",`75,/-3Pg''cdn43ʣXw} $p圅fVʽ@ @#19㮤G&:]!(<wZ(0#!mcv7~LdAW&SryM0qI%nvcļ7~+ThB" `w HbQАJQAIXUnBF Ú,VqJyCVO|Cí܈u J`!g#)B9D$%Χ)~rD IOI]r{lݔ}:(ˆ16Ocfɜ9mq; <кq{pb )79{ŤĥofZD)H@`XjGdrV q9ϰ01rkve~([<I| @1:3xc%\{qϝ `84} & +)9plԤ ()B}+!nq9x+FLiM Mȅ1;,fr!cI"rtc/4PcQ>*+I1f -@\Ÿs(;u0ҋA(1MD7888K+AleY)OO?wC  [QGO?~ݘ!G0?~s?BsL1Y?KIcQH-p[t1u0 ,mÍ'sB- eiX7 eVxC߷QV1<G`[Ppb fHF'R=dU1tMdJ,mؖW#f7 1zqP= ŀXD>䤾Mda A :@n  ?)PZzzo_G cWߡ u O0$08ar.q2Xo~S + FA" sayycDNN<;Rŋf:.=tKz.P5ѥ[0Pᝆ  {I+{d~x }y_{tΧݰLKͷ3 KHaH+ s\VǬ3ؔc ^* ''Y#K)G pdIlh#^Ȗ䡮1u-<*jY}Rq\@LK / 8地&`X c\>1%'$a¶B偫sHp. {L/YLbuv0cƱ߭nS~;Ǯ_2 c~ؕ88C㵨f6aN| v T@<ӑ"vKLǸHi0,-pp;Ma ‚| T:{%#K.P 0n fWf8OCŃLG$XќgdϷW/؝eې+:ГGm~ywՕ#0 cBxH@cF@ah\5f+ llEܚ\#@]Yd-/򫁄%#ZvΖa8RrB_KݖVu{! ̀#)(`i22ґ6*`yC?| 7E0h58ަaV ))J7%sDas 31`enCg £u6>v١a. ud4q Cbf)< ;N!Otk4JR0D1hVNTft2HECQeθgjE3m5i3B{oc19OgHې,S^ON{ {4a2pXqP136x1$tWZslZC!Ɲ ~. ݘ-"+@riAclճ !qAF.R]؁K>eD0ħ%K=C3J)#BJ0Ǒp8a(aP]${m\JR"#g-g(7ҁJd%)[Pv0CKX f,RQ<:S[ GI-%.4)Bep7Pjqr/N|F& CcEƥBP\|ZDp޷$vற0Qˆ?ARč- 05ۚH[ap#2P3 gXlkG圫eaxRBNq8PjFb,Ü~,݇ώ`k$$q  [ _4TMBK톖0חf r0`4͔= t+1 <#==sOX|avq `9(߭L=ĬzցL9dKo;~fsQT7vy2;B`{J1*ƒ x۵I| &zt1po$xѫw1h M&J,d`ҿpHuqKŎu}hy<~As[ (c,1 ֬ 7gՐ(XX䆡׉(W@xY HL EI/7e E8J{s':a 1HܔH~vs[,kw^@V%݋ģ@I/K@ ? l3#v-I:1cCGB1( Xޞ,iT f I43HUoCBq)+@$#ce .d; p!#Hc*  F>|1!'Kvu݆뻣AceXb#6F`.8q8뷢+;8[n[} ?nB01d vݵA͍۸Ôvq(á.W[6`Mb ͝{ZLZTC@`2Zs815&t-FΒ:%wlh l$S߉g0BLcp}%k\Jf9xW:4@ao!u8y\0E0̳\5$e'y1xKߏs}a 84B:v XОKz)k7 `č=l3e{-xrϡ@ޣxDV+ 1 x @/p~;Z{ #fަZNV9u٭`rΧNT^;6#o BN`Z]ZL90 9 :j_Гx M vA$݉l| ."#QKd.k - R[ ?֭X/H1]-W@t dVay 81dVgDBE4K~{fVg@TR1+lGA=jh=r^hۯq\@~Z* ^;B,% flwM~JCA|/^Jh?fn)Y[ @!;4DByϝZ S`*&'`a"h{K)o0(d/1 )p?9a c%tJ(mZoՈ1$Q8-ɨ?u4dR!pK`P5~Iʂ 2diifC ( >V ݌|e? RH! '$ڰ0ln*")0@#4x/lͱZ|BFm_8vrv]Ӓ9(DIa1eSݘ# Hd9HƄ6d1oZ' @:/8S_IsaG]Ի88`Y408E@; 68%@qGr |"@r_%%Z nl=^ &?72I Ϭdw;Q)"\  875_,,^ƳF\!.lspj%1ΰ:S"plvͫ,T cUt:¡I)BVpƾc9wZ:?ݸdP15@Χ%8xm(0|; Ql\7h1R-YmaZ#ƟP-8Q5\,33l5Ԥ3c+;sN:&Rj 币V8RAݬ){q1tb(jn-,⎄L(@$2f)pѽ?9ق*i`ae[) se.xI@eC%X`,pbNRS.p'Į'qhN0]Jq.⤠`u¨!~u`j l=ʷ-L3 &()=%e 㟩pa1=%n -)BmT6oaf-<4_dZ u x<( Ԇ)? ?Ÿ쾂haI盜@J&bGipr 0z :5fJFc)ۭ>&Ի 0~@ete%cs)փ/_#vw"ge:E'9!XjnA4 <1pcN-)G+FUX"P /~ , BIjVB`X8c:8Z2j!cCD HTU10y{ ^9zߺڄ ۪4f~ALP\Mfļ3ZɀS%a+Fq@C-]RcV{5jjԌ326>5\`>r:B?F`*F+wl4AʻrI%fBBIQE5h9yCnOm6^8Rz e804 ,0s0| :[̂nzBnZ$s>Ec3`ȍdl\Fn S5 Htug/UphĒhCƏ{"S& u:'0`<:S~/B]Q ۹[|2'ϗb|&D j~wש8TXwSajDHJDQV~xn`LEc׏ L(cB]'͏0c8HzDnL$%(3=ى0|P27|1c95С!g#)節d'|(Rc_ ַTc89CXPL,-;1>9UۺZ ?LY#b||gO -k.,^5"[ ||H@Iq;cluYJDYf8TY0F!0\h A5$݀R^)#8X 5s(19*q$Һ\vNuJPϳ?_<:G!̀#)X7&e-#:A`E? c~6i57>dfٶVí +9[*|C)%`j $Q"8X1=xxpᅍY>@]!aHa`߱oa"(釷 @;@a- Hsc@c$g@Kt2x uOBpU<  6|ݗ? \b# @ǽa@[ta\2RH;yX8thbFܔ)= =;48|bBIAi/7t M8e5!*MK?;;;<R[m!یp` 7'Յ p8>-%7`)D؅"%ag//)C[2PN;ŒYI|ナݐ3ҡ?i[{4$Kkv r^d(f`K6`Bn$pÍG纟 F8hHA~TnC ?A@6OGGH kE^$1y`go)Gޭ+,'ws9ǁ+ /'ׂBm$5Í!3#)u܂+fy,w䍉8 PM QI-9@Gn ă&Oe(}[9$CtSR aVn$HX*]ʦ}#40R'dAh.`8yIL8XSjl\!6edⱢ.eJDFX0CZeDwcJ];|@JDDN.3q"nW/>*!)45Sv!u(өxb~)zY)FL"0SD:Ur]?l6P3 F-W7r B0 !?"&aɂF*WI5#kE3Z np=Cv=Oav[~A%!. pI0BLa..PKpx-dɥ1]{aI(@?utYiq}eB8Wr?"$HrNB+Ya`p@zb3+7DB]1΂>a"c;z> 'JPט˨E$4塹wli̸6tIl1ɂ0BRI8s@st_=8O~, DR+a Z3u. [5FL ܜ)BtkG"4w0,:߷U@4F% DY.y0(՝~1)LQ䤘c.qGǙw}E/(wcfT>相FgV;)'I)D( lHe }h\{ דK%(Hf,$y3 PLFY+ u-80aI^aju&,aY#Y߈ `?qjR5|c59sK5WGݺ\g?ڋ娑Ę (uCߖf¢GB0 a=ֶPF[ysi>uz*OZ,L"Ldte;Ve ÙDg]/zy-Z0 ϐv6%,,J58a Ѳ]e2p<,%8MǠ)aB{ 9a ;\9֣EрPǷX=fԌ2b, `HSݕiזy$Ҙ1qo6Z5p\MrQ#]#?ps:G+`1Mo{ŐLI i WVwd#)`>d`2Kd`غQ$|7y/!fajXu[m3l`o%{x|W1HF[wC4yGNl0эXS$2U@z1g;q汦#b㯠i$uf`dRXf4Ƹa.e&R$u˄&N^ef3nMF{,oa6Y'ʀnX~yjv4c,}(ؾMC~ƝOO||R" Nme]O mn0T2rI$3NCnsJ0;I^Gs(|9ww֌|I膒PBƤf P(!=^ a04<RGE7w=Fk9Q 5!p(Yd/iˋAe9ԭ08%ퟡ!h\S!)/9 I{TE0RL)n4q=`?In&ِ03Pӱ!#)?n,@! YCKBJVI-/ =8 0b&+#R"F=v44C 84 70-^9Kim `P+,~)9Q =A }ubf $g|u>|9Cg d0ƍ|ffsOjCf}(Ǐ<_d2]V@A%Cƚ%?9X<7bSnL$0|J,Vn ‘ȵ- e[,9)G5@Qlݹ`3t1V]#KJđ![2`0ȪVC$R5caÏ.0!^!Anx@ş ':,'>+ @&!16R&eX>]ZI1Ed!;ݰpjW /J \r(Gt$cퟋB;مHݷx0j)wqp*`(^BOIWⴡ@ @ x7f'TGQ^߁z籈?|M+lR(xTO(sm});߱`d -iݘd턷m$:‘KAhKnq0ERYV~1n) kɥǹ NOw7^ -$cwJFmcvbgiW]- D)7QU"Q@Hh%8S:h-Hoߋ5\M$º_,(tԱJ`r "S@Qi~%31#؃$Yx0HSOÍaBv_jS=5~1|/3'aNOpu28,QA=.sՃ'O)8pt(L-8$!4`&)@wǥi~AvUE8}(X LM?iL;zad/ "@3 ύ;9=LJ:#,{#[Di}? 4d%aX9b; QꛍۋqAFflj Uݻ_R{4A(]2FNR{D" x "& tv_p`F`j dM/YsLژ,|ԅ\lD-'P7)ޑ'wG^hǸj~@v}KSLY$?ro&gb;ݫ!2p?pq|guAWm?r,&z,q6Y0iNd3R!~ٶ=Bk8oñ(4 U'+N1nI1yG 858} ,x%Jw>d1k|vPciFG vNT#~"jC9D8X*RW?,seݸ@Hp}uY]/F, DY4cl8Yh,X6 cc!)SwSa"p>ԧ5ѷ0c`aQ /;/^`I1,1\y㻞rn<Crr6lPϛ'IZKfƞ| ')VȗD/tms޶tق79&(  8ا'|#3LH/K_a!#)Î4E& i-dY\3B($yLw,0 <=p@CJR"c37f<#HD+"[8=`?/_ga=ՃuGqlʻؗ~~$c!?e,Bdg(^(ǯ ^^\xx[Kk;&TD Jk#g>ǀXmƬ7t7pԐ3q9|]=AfR'D܄Jo;2߫[2hNGvq^ w(^)!;yU^-tlLj8Kp%ㆡZ>|zűVeN޲wStby̻M~`& [c-$bQԮ;\ #I$q)eS y@yg8,䠿ơ5n^,Vcvb)Y戮H6Ç}~ 0Jo;Ofr\ڲPS-ߨQpSv){8_J_rX̆ IN<8|Jd҆RRi`Y=;u, R7AHMSFGs[-I➲0ŤX,ס# w8HRzw$#SZ@ آBbP%ҌyK Jvۿ&,9K#[9!IIK$3)=9<%'h p f)dSۯ'<}o!Ǔ?0DG/[dі)HV/t~kqƟ4M6m  c[# s,q;Fb PS 9ߚVm2B0sMp;̉hCJR"9c;gû/9sgy VYN$rɖpr_D[ a}qQFsdSL,1HJDJ`w0|6c"$?"-xEh?" s !ȋK A ߄wWϖ?,ks v7Lxt,;$"ܟ#L! Ih_]*jsa,W}phB8ztC4?"+vs@YfPN 'PF~1+JB9?" E0[xa .BG/nzi:_ji/>[T2]) (vQ3&Bס8FL34[' ۅiG'xI`K/@P JFtvE<ˀ41`cYG8WltcA.IrF8zդ 3֘e0=얻c&<:U- 2 ŰNn;srH+J@b':FlCJR"7C@ʉL~wXAj? %|-~ I іW$c1h of}WY/T I6&3εlxC `W eveM&+ s7Nb|8QAh(1 ┥M P9ngRȶHY2.ځa"n ˶5 -_#U 7q h1Ӏh/N#?/?gz lz1ڻ# ,T^"9O'HIhd:!g#)eNAM“GCv[,^c( v|NUQE! ٰ tYue-`FЀ)enkRah< T演S8aͧ(ugW׀0Xy7$3:v8\c,!v{i}RO<pQ­9 OFZ+vԳsNt I-|w9Ju )Fbi!Ŝ@kNma t:JDld8o'y$:Ǐ52&p1998Ѯ#䖁K2i#쓀{,'p9Q5嵕 zEFYDSpquL+seoH;2Wv/p(Yd 繵^0Ub!s??A\ ȑ4@1?+4rZadgc !C_g0'@Jo 6郓’miZJE!:SpYXoI)e1˒Y[2:S3"ݿk uo8Xe1)InVltY %II/2 l8q-A ^"F- nqR0MC d 00d6@ɥ,N~w"G[R|b:E0fsb*X'*hi(1)X3F'fy7$ilLp2z61)!6xZRGO:Q0Êv9% np̅,F"Gs͑QYX\*M@]hetNLfcYPA/qOl~Ԝsq^wzX |NO5i7tROv4r_AfBC! ZP3VP?gǨ@[,,P?u(`B>Ge=w׻ ^|jQG~Vq_E@\f m"vLKw6[ta+ƯCJR"Vn Q߻j`oL2 &`ˌ `U9H/|+_ԩf58} |+c!̀#)JR"#)Hx1o(X E^qClxI].7cǩ` rtCq&Q)6pčV@|YxkLX |"<$qHp<30νIr u0R?? e~ s(YxvɁ$1>6wuJ܀YAvP(DC c.1||M~KNvmY{02W  RH0Ei<]!w-% RBPUnOXH|5;xnD` ?֧ ͪD2"=,Q#(o4 /$#%r=G|rgs䬗4%ȑD$5(=L<|C!x M9 V aGE&%.utt pqm,sHRkj}d2SI *bhq%(z(Ӯ؀Dj-mxi4˴) p[gٜ!g5J[j[Mpb l`(oIPn\,G^{1EhI&IhKܴIOח9F$gF;#RȾymiPnۿsQzZ Cv44S7+ <h))~Jt(] ~bWXCD-BpAqhZ9=Jew2̲^Խ8nqΰ^FJD#8kB@A35+|sӔ4yF\ƋCv1X![}B|::dgl.Nh`ݏDr63q׻Vlgo` (,)Hm]i: ,l@ 8## 19`0FJ5µ D#+pN7I0j7a,V)/=rC^H[/IÉ 1=ݬ)U0 ($E?,_Āe"qMMaH u9,G՝c`aH))#4gdR e /wA͜{b9Q^Ҁ!`) @y|8@Ks&b|0ް wp; VfAe@p -'ajRFv,pI@c78Sa:Ou☉fC@ɘgH@zA!vFpCy'P]5H^ٳΉ5FI (IN3|)%cVceRJ_>X?it""tB% ӡSKq/E3 s5%b!3#)П3n|`{)wl8:f1(XA0ٔKU# s`R>.%7 t8!ub{L?Ҕ?B DIҒHHӠ( 3/!OR"Gu(Dϋ D)H*cJR"Rv-D?""Ru H|+/m ZDL%)7s>\XKɗ D? jO4\I8*.-t~}Sv[ DXCngmJZ퐀b\nު+cR%F񒓊6M(M@ft?Wrq)H81nr!!(/d¦?XqgwiI)xnWh Jҷ]Vv?-#3zvd ~ oSH:Zjcn`?v T fc}B31:u5ߑUʑ !V2g gaQC3.b hb9Lc6J~56-DLAbD"HXu'n69io3ӓlVc2dIjDaf6>k# HS'c4M`` @'g?}?gXoJ (܋  E$!󵌋%:OWZD 2 Cy< bkS`0!|t>4pR,uy$ l)ggխt'R s*!KiwxcN#H{K G7SRSa _ewy)Q`#,HέZRELC9--IҒPԡ+2qg=vB2Rff nFāde8 W CF( .Aak v' |G;.<|S%YJyC8'v晶{t ş֎HvƒuEB-  N<4iK 4k˜+G&,sdߋm}ƹ=n88jAW~7CRaziu@_ƥЬMz]羳n-V1DX_FBŭ'.*BQ%|bܾx>Hn6Q8;t!8'> Xcv"RŒ !h3(ŬkJr [+-iYkArC0j:RւN!ݖ\O?Qb^;˟!C4L,4g+w`OJCLil0y bꆆ))hZ 5nx 76XX¼4b%;>ؔ(Oa+^:\yك<d-v ֖hά Rr!) "/3]YD?3^ H H`6 -&'߫6+ac` `H@:L#P}t6w JRKO;* l:M1\0jF`ٸ;0O\.ŬDX HЄH0#}Ãqi$졽\7ne,(Gu6')?e*H ( 婀J7sPU#/wPrVIa]-`y/hP$ǿh036b[qNsֶ2d 7b[k mv.2-mZSp &)̄,~PzZ7P1-Me`yV=rW_#圓NoN)L!wqӧw[GBCJR" NG. #5Ԥ8++y[+O R‡Rv5Ԓ'"1ru(j;sf{9Xai-8&;[M\2@Ra )[Z(wRd* 1?,!?Ҕ ۥlrDMw ƶ/lc6XZ܌dCC#ZXQ{͏l%n`V' y͂=˺#[E2Ÿ;,$up9H[t;t?䏖*gF0a_x!kc A7 N׸1|?ga2zI.2iV8\f? [z`fD3 a҄G),`|L!%҂3𿴐1h_^v, ?"'`c :xR4<:7p IwHOOrN8wn*a;SU_ffS.F.}B9Vz~ +,~9gf%P?̱L$JIs;vv46-⑔}V]SiX-|!:PY)8iN#v>pghEa D_7~ E ,cƳ~OO v˜(Ǘ\n8tfoege~;(퍇0o,j[a{3_v4ɽJ~pϾøy:T$c_膐0Q-Osr aVC>A,n[i: %Y=bL DX4L5}u'':;>( \ءs4g GsC&ق<`6$oS\[Q)Il@'n-rz(I_3b$d G$w &o``!Pn=Y44 qW1w/DeLL vQ?:I0CeJDNZr[%lZ Jn7s\{ (c[=GD40S#>H㔂x>ؒ7wY fp5M37%wd"-NlPT =/ENxO W1^9է1L~Pó8j 50>e?t% Wxo/n[%&A36cxHO0))W/%< 4tA' X4B!jyg:jio}怉L'HGA_XZӰ!ZPR_D}ځtC!f e\&P8S9CO `:i),R*Q"-Дf(7%Е>`{7}ȟEaG n t+mo m2 lwh3^_c1h=PZ(J7[-X1e8`.wB4p>x a3on˧߲vnƁGx0 FXH 0_da2nC" KR"s%ґ4p9DLB@MNb*9kL}%$L wx;>MU4TC#r*04ԩmb5XI; p̖n#(@ @bQ|KdZ7ӟf}=pŸF(8{ @U qԄᔓS*:`c)rZCIa.c>P.qh%r*O]j@k?(aA>b0yV:0)ҋGNH3KJDA>܋{A|Xl9L8t*BA-=Pb@`PP^tx$YC0<"@`P*PoJv)c7?'%E ]w %~ZCmj,ŶJH/ [-ӆdLGbK!-֎QE2Y{8|y u1]r @fW?Pj 唔C*!2W+ Pyp:҆x(7h"ւRP))8`p@Fj_1_s` 4nac: \.y>cJR"n1si=k":z?d 0 Sh9n (o@O;X[Hexy~Mµ#-XἐZq^wH͘p#i4 o<$_Bh!JDCtj Pqd[DPu'?B$ŊX[V2jaqA7 5L p<d"i5$ޔXSAEe :CPQ5 cGjv3'o; li,fJ_]B߹8!㌶"_/ #|‘Gz?yfls֝V0%`j(,f71Gi738z5؟L.SZ(QIXX@Z\r,?9[+RMs FZT``PHEp2hPPa0]<=2=cܝ::*3_#PQV} gp}Љ* @~sq KAIRJ k-_!l7w"E %0G;nqg<텐[*N2`;Z.,@v](j'~&Vآ-۠(G0X'%kexI^aݔ/QjYwe@'%y@pm0"IɈ +RU1փǰAQCni n@!g#)o!tBJ4w%#[Rew 8\ewsNzyLrU{a`f#%s~#dUX3щ3@uY/<#-d *,jr0 0q>%8jml#wfoN8lU5+ӯ0[FJ0wjLxB= PU%e5Ry׺}v2\cR"7q_/y/l%a#|䎅+45)7s)C,WAس_2b|x -Zݎ9ˆq ncϠCx~;2:&-a G)ۓ{'8T}-ZjY2.)$Ա,gw$if*3,jVIHFcJR?:Dؓ kLK6%Uzݘ*4N]Ù늝vQS[lLۏPu7smQXT_os~eNJ̕hEz[Ȥ5l@ (9L =M;`3#}c! B~o%0!XhdE0x2i@` *6W, 0]#Qpcޕ#rg^ƭ`Ô's"pYُۚՏ?uex wUrЗ…>LJN*ذ(&5%6-!'[n8vrNMO Z wOΒVd 032؆u#3-2xZѨ?7?aaCirÑNVe٤TubF-q܁f)opƑÃ&1{ ciVAAr`b2WVG씒gnb9|e|ݏ׈Zm\G |)pP%9BSbaHJK%Բ?5b7ڟ!7h{yDӒ Kr!Rq(󸣲Đ)!*Ưv/~FACk! R.kņaG"&~ Mk6W,DC6LNZ< ¹l^)N۲v=[;t^#lbHNÜj %uqs>gÿ x1Jgl'<.냔W)Ӓ7gq L IM3['zRriAl` a3+C؏쏍ZDClx n?QhQ\CC1Eݡ ώ R"w"# +~ acU9v|C `Č)Qn āqm~I7j@@NP^GK۩a[WS<Ӻ~FIѼc %bVRB =DẔ.h7emن3}<- & o1ˠiPJ#9NJP8 ^φ6WZYFvwAx#@BqPDQl:鼥=,LE*R{d0RG>Ot3*|s)L>)(#. Տ2_[dz۠l 0²0ĬF찁G"o*z{|;:KYw؏|0P̝؞.w0ZLQ"~'ؔ w;?f#YH̓K)֠.J6p%#!}rSb#y|~d,I7~DX0Qd7_ S,[] 3vnW vra) 0ϖ0GO0|uYNj-)F;@s 4 pVh0a Q<'Hc}5% H@!1Iak:MSbY$j E8t6I][j3mCw%)sE-x߀IHR  Is橇4\O"UmSrs{<Y3P q%$btuܔ=O+S0;cc0!3#) S4׏պV?[` s9E9, w,Pg YSR4nm8ZDlΈJD@,v;~М5C3vCA1XcΕF<WQӱ{EP.,?T`.$,᳹ʊ n^^ێu83 g[AELvPr qhnņ1anML\ `\/B(t Mah^hR~ @T {d'XBsvG0DDzo|B9 4! BH_ZFWgZLD4'Zvas (8g: JR"sq&`aa8aPr01;$y##Wjw`k&4unV ݘ@,hnC7%ݾ7nϜ[g JR"R" Yad#kl+ Nj^H0".cQ Зl,+mHnR1)g 1sCJR"V`Q,=Z8\moLM)`QQùjh):Qh9= Lgv^I;q%P`a`d$bP%I¸CȚu ilbJ&Gu2 x#Cܐuhi>hk^e:hd 5pPzIbäId4?  t|ĕz335; [^đ,.H[qmsa0|[`7 XeԌAHuVWqb= ldyTˈm1,ofbRI9U5ξv7>ݩPPWPb  !%A j? m4ʊ,D/-&! b9'+cX$š=9 J8]c-}{h3&F{ݐlYvw Yu3в4rQEZO 3@ v;2h,Pd)6q5RS%ʛ6a,rSpybΈ]LN%H0ObW(~}I䑎~qxxIJvwQI,a',R i/+2/ʭvGa Y:v<ߟa.N*0B7 Sgnq&cN^dδ1 1~p@Xqh>S;7^?)ĸipp?؋9 e:2KEg,:Ա h.EDbOUOi3ʉ(! '8u1~s,í)B|(? 7Z\hsBְr%}*iª.#0%? pþ}W6SZm 4k}5Gsr(LRAWIZJFiUfazPK1$FcنYvhgЂ䡝n4% O2 #IFZp;t9RRԼP{AJR"np},eh) [?! Imeg8ny:8PTzzvj> YeXpmG@|`%n+. S%Qе_𜸌8$񜘒c>alQأ@;&rn Y):'~q*0k뺄 @d@a}|٤x9w8 '~_6P/mqa+(8J|` Wl.^ddgp`95Zfrp}* Š l5#64bzSx'[+ps?s;}WdRnr+ ډQˬ֚ۙ_ :0D7w~L& {gU-MeAK$ݻ8VB_ gg}[b{ȱXxB rNjF24nESH'nԱf^,19ZRY5AE78PxՈP.N twGp#RO Ζh [CJ>t)#袉J,aҾsK0?6L5̫%Ŗ1hUjaoK3R|r"V#.9{ enpA<9=(79׾V<`/؎JV$` zւ\"[Np};t77zX"Q%VOG[YӉ nRxw83`JP+xH@ tb6&K(f#'6XcB#zdy^yE$ ѿ%ܝsipdб#Ћ`'u( a`g 5a(aaX'[ (@U5!Dzhu53lc?hf}rV`u:o=HQLJZK )kk3WnTpHG|-<(Q{7;d2o, spyD%6%X~ցzG6) C0a|ަK62wZ%1k~|K v}ׂZ̑wnflG!:A/?é couR3r `Yäd$'I=bOHo+8R;?{h`4;8x"d@` 8=ޭ0q)VFA7 CvYOAs [fGf33iw+ʶɼ4!Z9`2VR1p4jt18p*&5;ZXz@8PW+1k? E{)_2axewòwe@Dp"L16N!'g-NoY9_Lă u~f:r'e(u $"+Z&%)vh@Tmՙ1DSуIMU`<gN2C7zH8ߚ& jGD1&S4M3J!}%##$N-;°r˫KcŰ⑔G d.Ҵ36寚;98a`$E i)Hhj:۠t\*( Ϻo 쿛"+uJc"4HG?J$ C_-j@e)>OY=hhL+1[gQ-Y:zD`"`OHddbXj3( 9k1axyZ.4v5BCჅ?qU6MƤ%}ݛP $'(L)tg셻[ǿ]K{#ݑ30+8]$nysrqm 59J@b` Pd1't6$#N})-BA3Y<]| 3A`uc"lM婱Ç@BZ ʼP/ŝ8 aCa)Fnxs"&t:{>5NBqg'gwNWa=r3E(('H(W*G"?Lp[C6s{01HbS۝EP \k!Abv] AEha4P? -䬵Џz`Tfv5c6H?&RR1Iա7a74_=߀!8#>3(AD@4jBR^8Ɩ vf2݉g*P4yPјIwۊKa41to] )~MJh>9' 3 BJ,fY6 HImAw[~qBugH@pЁ[*J0 z0hG(,v( K4ATM>O( CR[RFInwL$pk`dH əD0̐3R3fc$,tqq:vVyjj/3-dY1Qs8z;xѪAVN$2X;)>d?,dp)gJ0;E^me_͊PVƀjH?a,U$c2@ΣϱTV%{ǘ=bc k%a;:ŏFRP FOB45 9,37t*0d# n 9g8;g+DrCXJH(%j3ʹ?H5љ}H @??V"OYξ=DatXg@wXq~!JTpM(Bo[ >a`JpI:rjVIt7^PxZ"RR%NkSDݖj5`.dO;:|d@]ۘnxwb93|R[5ci  իQ t )Űs8yٖm5%Ig0`hjZ߲euP#)HDV)+ `?"->#X\`c\87P8eEU)0MȀ@Б&:j*UM) D$4,FN# Fi")`ci(H2#k(~pAWtP i+ͽ\CIevJ>|wJ2su9E 3d#mtn$"@%wdþ3Iȷ#rw`n8\1Q?.JD@|F.Ed0ѿ~gD 0*qG_Q A8Fj1s#i"#I {p`*˭E8lԾ* &$kg"gD(Gu-dRI BK@hCFQ`o`¢RfEokLN=J5EvHϔoSД'a40+G. c-bXŽХ, 7|sEw88Ty8g4`a4%Ծ$z9x-x8xW@ia@k%8A)##$tN PR{J-0 X"hLiD -#L] Bo d92xaDq:22©o9x㈦!g#)s^kpui}Y:9.~q$ggr['C#jƉE2؊U) U?AcNM_*uڃ(Q؈%3>tP8W+TYI+$Y/ q%,t~8 :ӡ3z`͇EpfFޖ`kNssVuTC$kv'ζ7gmŨh|9  DQR}Cؚ kZfkYY 1LmOLiF CWiOΦ7Ɖ^=j6`Kh˖ $F.ݾpyAiE#i#?iѓxl_»8w TzM+p’1a߱z (%?I۬?ef>Y$@N҂W Bw>@ݕB@ͱrwA⠷}Kml|Q},z?GI}McրkBwn p;<80^R9AcsfF3PվsٖGc8̗PьͲ*C3%5'qA =d(1OK-'C. )}ɟ!̀#)^cVb8^OC/a?d0A,0K% L[`dujhjhv BIl2i@eIO9^5-熣W=VRH9nD`2,[~pŌsl IH(U҈|HT IOXtX42j! 3dF;emKZ++?"+sY+D@$¤_ƋN؟hcAVaœ š;~K8G -$>' h0Gie8P-6XVL SghO2оY)HJoW00I 0?rylЗeg㦈1)KC3ݳǩQ)?Ҕz@ <, JXxIg9rCjvÎV hRR7&1#ƤLeΧ[9!`-i4# K%~AV;\A, .h7>\A)TRckwsP`YĒZ0>S|<,?Ҕmw 9,$fʎP=² clՠq>蔅,,mj Iyña4045yC;!&Y>%33jQ*pd B)#JC?;N8x`"Ekv҇GRΔ;e҉0!|[{2ycA+#Pg/aHK p/-a& = aM@f/t 1c`9l'9gHxMjЌ67l_aC&t! .]J0PDӀJ~/a^%*g$,̅+ 6w#0i%{R"-F kLHM(`j&,{g9)J2IlL5g G),܍% J> J: bJƷt[@4~Ԥ)_\D<7}^J͛?obU]"&ahͻ9Œ#Dul!3#)$m $K +hѸfc<`3i4 &3`p;-$t3²AQX'?|xϰJDSv 0+h Q?""0 X;O"1`-80E(CUKa;Ã{(fB!) lJDB0[T ,akeTJDC锶Of+b~sBzG#CR1)`F"e2_7Ysi.V0P*9eF61j1ewBW ϘY3`>,~氏SHzv?") E#M DM07d AW8WQ5\F#/m;%9=_`1=x{Xym&Dr3Y4R~T\C!(Bw2&o)0tM /&l'e^Q"nA A{vWX N%(;90IJ`,Ou+ Ʌ!|?& O>O*=Id)q|x. A 1؜ QH-NeݥVCI! _v¨?Ҕq|^TLJZӋ޺-bB -%0te 5c?3x85G?{1S GVL힏Xj{gvVW%bWq=a|t%نmn(:mOQ0ћ᝗L6֕E䒹+`yݰ!1< F䣉Ͽ8@Kܽ #B;Po[FnǬuI/t|~dz+uŞ sH[fuZVqƟenljqn08X#4L͓>K[q]T#B>ēO`rCʯi gl\l=ۗ #̻R̅,+ 6Թ[ (@0 !$4j_%! S5Z;kj ,%h5%ҥ;Y嘔~!I1ؚSo*\hG|@fPJqS?|MJ)(԰f%S|Vq{)'H @`ᘬts$`9 &"yNhY=6Ԃo %H4>KQA,}87#%*9?`0-Zi&Oovq+epV sE ?ҔxSwUqh|tf*A#!Bd%Nu_kg;։)0#G֥bJna`k'i179 F6Mc`5>+=*?9m!#)5)l y@AS1%֎k!\KV0'kle9cSRӔjPp Ro2<òA͆/)NKN-[/*=uj?=1A %vtK{Ըvԁ:)lo!g?Ҕ") PgW@ע7cO :+IClwsx>C(>plh|1)c˻JC™€XGIBGaq&ha>4YDfo*J}h.<5}17׀LP ,љ! n1ި?zDQ:}tі|XRa>(dbƤo{2Ѷ;E A +qkuY(O7& ?F?"!)H&۷jaT 5A a#5C’ROQW%+v#c78?xGѐvQ 9uK& 츕5[˂+}`m" IsN҂EO+k2Jƺ;:V WOGnm[K(,X"hաIB<lDA v߱ǰ wLOiR !Ne?C;rI{}P Fc*fYf fwĐ$' Sq~O<‡ 2bL6rр7A膫糴la &cőDZ);'7;B1HBͰ)H`kA`?(^58k6KJ>aJDR ɼ0bU[̱:"()H9JR"Rz3L^Bꉄrsq^3彄 ?D Q(iJx2)z3͌0WOcN8VЄ B |J$1)*'obS1SZY}d t% ӖKQӂOP bPy(p'(aD0)1V>b. :§­gF ROB'"-Cn( C2 cZIC[TAcJR"pB7dZ׾Ct\Pƒ @8l$Ɗ dZ!_+ 6?ۚ jaa fr B:RKE~G+wd)ݽ=D ZPRFK;qiCXyCLjZ$HԶt?H DRx7+(]-ΏwbP ?!,b| _&^Hŧ jIGaiCCJw<+!) ٳ/^ 3EuoH*dJLh Zx%8"!ZI l7^xn`5*s%f|mR ʓ[IA0 cd>?焱)F#D4Jz4 `h% [ߚ7B拹6 fČ1Ng^~1*5@:P'I|,__lL|ġ?|CC:9LlMHh~"f\!)"9W )d?}pb1,1I|,rhҺ43&YC2r0޻c @g!M p?ttҠ$(~v*mt9Q7 Jv$p< 5)q#f\7l0_=Þ_w77#yu͐7vWLJ,b:my1hKx4e̥rP/|1KS.F ݹVCPRJG<@>l`%mKB[g9>NL|wưTEXCm2- ^8 t_/߈|&$3(C 2|JI,W#@: )f: B+ HRFd9PD  7'h;hMERN=! 36*-bFXf(mvYyTb1y)߄f$f@Jt*?""R1nO1!g#)) Gu0x OmzHi} ׋ъoeKh!JDC,EocdGa~PrJR"-M?FXĩ3ͽ8;7 0jh<ٶȸ ʌ /#?㶁Q)G)JDF?Rq\b~WC6 HԛvujUȇ tprp)!~"+h~2HDĖ7./^ %< ȴ1<&gDDWu÷ajL PZMx0|`' YH_a#8>;#g63 -)tlpAsڷsyqBSw*7_ mbpCMkB89>K\G6JUܺ{p`-,#ұ0VOqxܮ@XU= 3y/1渃 0@R=Ozc>c>8hsX:%!dn(AJ3& A7qxBua0F g^L(P@ąa?ʰhB{b(3 =D"P%|0z0(M@jP]жuo#΁N)%I%xPn}kIe87Sʓƶ|q~l>XF~΄J5 COe(@`rIsQ:4|:K2JDƫ+ ch)VJ HFV)IqZs 4_Dv I2=#Rv)$ӕwj9"`" d83,`懅ѿ9>&ض 0%ǁ}hh5Z">?⑿Kg{Y"ؽQp4z (`%%M({Հt$}( xF aNǜ|^oi}% Jr{sƚ{cpVm#ZNW9)+IÜۡ~*╈@͋gY`E\Pj\$5DIpK{j'9iZZ O0rjsxZ)=ؓrs$^Ǩ(:?o(K>^V:{H;9arí:r ,o0y:}pv9c9l )ghv8)v{@c@yl}# ߭FIw>#LBxxt>OouNˠz#:],5 rr0 SSGm  DYܞ3=cAxd|a-/rPxxHԭ}.NCyz~20ѸtQa,#%PXq/o1)o."/A6[_J3q*uf0Z;Ia`5"s’4k8G}9R< /?)}8H݀~.Kfz+wV9'Ze3Ya ׇ!$t0îL-ijLOAX.ϊp:rӁ34 ԗ){ vv<d['$# 5RRr0EDx̥nlkt+<`,8[&=ƇD=Q/'RXy:F9'`,Xzb;c C\^䏎 +$VhA)ul,^RwG.>8Wa03̲ Xg{b=i?53^KZ> ]?)Ay  ܖ[ Jp,{`&c>g6P?aN,(U c-t0 ~[0ZNv$j}Πdsa%fq&q! ̀#)p0Ka=WN~Ogn3PdԥNv1ҐP8{tsL5Z nQAEd6BPfg~Դ?8U?",xm?q+n>`'Ig)smPwK[!qL|@[RoΙw1G3Z:r\C)|sPn䒷4TƝ45e]0<͛huyK=AؔٻZ.rGM@0P< st sQ=l$%"-gf-K-Je#f r"bPJ:PUflKoUi*f7i<&8>#=MP @cr‰MlAPD!*qz7XD5p$0CŇ[X(8@7P88t__@WLܖ ( }p(f9auM! 5; Ӧx;UCnqH"hAxWnOFa;,820S"JZh|/V52!J#'`ٔ7m, K=w5m ;Eі qH Ԭk _8qca)[f$ʻr}2 R"@@T04.Ĵ7S-y5--;<񹭘Pf, umƁ/2LA4YHh\e41)]hYT1o׷^vNr͐"8Tn:{έ?KvqgxaeV?ẻjf;@ԏx{b$P`u ppn5"Yn(ӧʄ)L7hXURQm6ou%#0O"4ĺr~2 GB,SmLPGASƬXuA[.8Nb3hWA",Xч(. D>hcÎԣzO,gi*,3.Fc\3R5Ct7\M(bCU*(x[$?Gex.: sڰLbI Ii g ,( 6҇O;'!&91[1$R4Sqk\Y}|ƒ#V#~pݟfΓ}1+lÃ&݂M.:3'!u"YsG0Ē,MhI &JNK;wvMH \n Q Sfë9s~Ws0ާSz>إ2~Ý=Dh5b[s B SH[CagR#!Jl{Z[K 9ag Foݗ|YSWfYC3KHUV}j"lR7n=l<|Ix2߄+_8wU Jg!#)1agA̴(_FRxyCl !%20{?=y[si j l̜H;% >'VC󃏣JR"m NOou-Kb"UoR1}΃L!j6IYD5G6>m) @.YU mGiH9JR"dhO,gŀ0@~: ~qIiB= [?%#sY FOCd1Vv|+Tde ,5|(\;^6ƇZ-tՆ]XLLžΓih"wҦd;GXinCnWCp[6fK;f洲_Kx ZRdk2}XlU46Zh|x0RG@1L! ^}+x58n !K~^nƳ_lI˭;na ;j|a皳=74s>bq¥Z})_<,aYeq>ayb,k(bMahb( 24Ia)ޖI͋%Vaf@oW|5"ck / $ (90X]Iw@5'!|c( L<ȕ1qhӜSGJ 8)!$p.)L1 0Y4BHb &`ò3(Eč(1r%`tM0Rxb,N}ce3 {[PM d%- 4ll1 P *i^П-gN$Vː 7k ~u8y>x[L0*O\0 ?B\.BPi0( OHja:AWrfFwcy&x25)^x?Ҕ"$L> WDx%=}ohs(]B7e oԵs< ueHc'qs΄mDžDvfb-u J Q AmH%W˷߭Ga'W ~Z DQ -gqwJPn9n0 еm ?"+ю`$ŝ``@S aDX$5C v9 4 (>4S܄fY *lgL]m|ŇC.ّ, DI?l$,hP PVBtqЊl4-k8%HN!g#)-; ]!rR^|~HGKR_o@<=XQä6Vkw:F0R<sRZiQ,&K̝;lddJ4 pD|X @rFr(Pt%91=]&6Tkp +ǬĩPil`k?:$q0u"(bFfus#E%jͺa6I!P̂aAVI.g@E6t#aXEYH=Δ&ɽ uꁝӏT:H0 (_Iecʶ1|W-S%gwǩlh#m줌|p `h )(XAŎ.ZܐRߞ@-.V9l=S0b<?,緃r%3J589 @2R_v;' KHi2]v}847-\j }0jlf[k0cb|<fE2Ta⭄ &4u1;&߀G̢Q>Q>89w W'uIJJDY9,6q\ Gs3N>XCdOlS940%5l'=vNy4Ӝh<=sQXk](Wc#|HuhXd犭Rcvɿa%y±IۏNg|Xu=( [t+ecTǀl0%ur @gFFIU7:#  FJWQ7%'#n SK;v[}ء: l4;ȃ)n<$8Z tHGؐX/-+- .Om`z(@UGcEX-(Ұ$FZD`N3;3vPTh;}7YEyl=5n-J;Zp, f܁"VE *b幮zH@_͔;(YۂK`¦``Qpz (-RYvnӑXjYY[ Xf egd8j@h Rj_mcyú cw Ɲnd~Yn%lIuTF ?Vge$J]vϤNcI=`%wn=ç&bbI4ii,Hh&`‚, cd #j~(IA&:_=j)j9K>e; 6/i.G(iDtolG"LRݕVċOhFI! æ'Hҍ-s+~D޺yp"K -`P~p Qw_g=O)FK9M^5uwേ]b ,lGm̱ý q>cX|a8x$HJDR Hpvɰ ifCL %B~!2zr*DWW@Bw Lj_/'><>F]8zU8tdȂ0[ SdᎣLz=vȃ8tRq\-gdɾ vC8dZ1$i,|vr(s{3 aCBpk/E'+>zDB&I^u]v\ጼD2'N;g4L& \PEs(m=-2೒zy9Kt|v~sdJ5dǚ |B )&I`h!+HOl8aX0 _[̇RX\:d8-aAbSA̒gѱ:ٛ=>ءr;>ڞDsuVe7qηSUQQxi7 %%P,/p2 R(դhn# Qi2޺d4ᥩk#zHv< Cc9G|@,-*x y,_<ɬ%WuEw +u#9o-ƂÃ}u^YN;T[u]h+ M n@į q&t XJK_g5X}܎\~ ;v2 x*2.:Y>cWNص3y9kk/фh~ { Y~Kc+Kg0R&#8)|I~HV ӛv^m`EH\#ڸǝ%Nd3.7iLeݝy", RtʱOnc9f;6_go5$;Rǖa]rC lZÇڠ f|Hsk3ioXnxҊo~4fe~?yPd|1es5ΤJ0Q2) DF?-j7II{.P`R e}m"^.@^X RZ{0 ܌?aDiE ѻl|B+$~pWd 1% vH$l}^|5u)@Ya/ j?[$I1L5Z0 PPܵ{SpAqr*{*@̃]q0jFg= HKLKT3c3 $Z">A%7a;R˘q'#tS:m '. -k+@@M&bs@($x拡Ł@ %lj>{8`s4QahH̦785޲) (iù# ͮ]0Iif sXN4~;-C`g;R5)#̳#@ll`m,-EJuXfQ) $?ܠ4?R"!rAGPi`d`,1nk Hp@8qk[rĊl}9fN FF>1o`<72z>aݖuQ F|=' ᤁ@s-(k}(_pᜋ'HBr3€/$ -x-Fp<"Zp#Pt(TP 7C;a8c01M@.?0 F?ㅳk*MAHZ*X ͯB& t;DQOO?e) a8=hs-5Fڊi05(Cmqn%Z.e=w=@Pu.m/ 0tL/s0f$QY\x?Ń*PtȀ;Ʃ㫑do$̐-,o9jY>{IxO̲vfVNhi>RJBFq1a} ä°&Ƴ< [ugScz8jdAw%\h:G4bE>JԣaH`ٮs}e B@(K1{?xcix+W@_J4JDRP`x=7BF0ŹRe<^7]<~{!#)OǸP;kTE c 1fۉ2&Xp4h"˞ߊZwv4=|72ûf6i-n@3T <`U 5МK4?fI,C%tlJXu3fY>5z6Дտ'e mΦx*$G^0ṅRcJR"8:9h@.犚/? n|> MP )@c%-2x$ fS6յ)Ot.·*ˮ)3W4jV(u\0I5#@ĜB&e0U'#)btF$.x'5.2w>ЏyDsόőPY]? ~8 %vG%rORIh_?4LN؟U(MB>?")38cvf]>`@tL@@h @$$ Q!# ˤ< DR rh݆gi*%#A4gnxia +1_!ǫ' lZOJR iL -)bhj#qj1)HRJ[ubtM #J}Da#s`dK&ėɹ/Fyb&WQ"j f 0M)+?nR8X`aCbOg ,Ϙ8 a;}r` WrHSȃk2LA)HQe{+~c ~f N`Ih}?̎Yuip!AQ /čxc!6@cl#R|fcv8Z$ gpq/gvE=ⓋYl48{:@@#PIUf`I.0 D,5#x "d_RK `!ηh$0*n+%3h`6,a0BV8*{SS%L F%6=.ykR%XߴV5ne8 wLebVOB{YpŁ9<hOc?[*:0Xc%ׅNkZ`a"!Vnl-'8)bk:صc| >ᮀ8qQGKtMLjJwfGdVb QQYpi8x8=ț n]GmF3ssuD4`FYPÉ#I4V/ ii_'#E [η΅pIAX~,"{gz4Ϙ%Gw@Ff}؈9RO<8 fV^ė$jP(HHsL_;Fcs?"&eѐ ?g @2"lK%t%zyt<8ygkE{Jw=qr* IIFX>?"""(! oKa ۹/( ?'TCqmt3-SRSvns))(j\ xJF 8cmPPOGQ86J,~],I{qo!6壘GhCR[!V['^R[T0(ͦ?",tIK 4?$56:C+pv5{tw=KT*][tɫ ㇜$24VslX,.J3GIvI RgB:hStr%p2C]sU}*ݳH > YD7kW'2T^G΢ ;$ib{RIxn8^IۓucVH5T/Z5Clq}4gXA [: ogml=3E'Ə؟ǒZQ% x MNxwv#@]A3`˝Cv xݶ8r–k Ʋ2|1@#G4B."3Zطk(SV 5VS Ŝ ]ev ,t^+f6P^/' iWr./@wBB+p2ƚ`-Yp G-GpӳnӿkВbX5' Z H,2%B`A,~/mƣVAۻcu^>bY,EkM ?X@W #Z*DVEԇ6YِVFCo~/ö9.>]ރ̂]`:-(JDRgMVc{ Py:UPLvV_cRRRz?$qQI_":h^(No40Yh ˟$]& , ܦ?nFkuǣΤAGDF ^͚)3ֱ!7CGeaן)ЏؖÇ[ߊlFPI%B@X^zCs~Xgº5h)H"UM> CqY/:9 jVq PM$'>Sj@pIc.![vJp{z0 (nOC(,M>Kߣ@0 ![rE2iH/!(9mǮ&Kv.@?8gy!3gRIuv  kt^|HQ7eЧP`5P2w  Wf̷p0,۵veD8?hOl>{i;$ f޲br3v @ !d,K9A)/=63Hf ƅaH`Ҳ@Ț$;#~`i)P%f|qpHc3#mc=ԴX(!JDYp23 $v#a9hӖ 4XSfXhR_H!^Jzْl aH`Y?Lz"pl-2Q#2"pr}e;VQzwW akw5J#y6ՄuqHŵ=(߀Ѻ@fÈ$a? !41n<{sB5pXu!g#)'!'7J>^4lia#߻l1D;%պ' ~ ȁV!6b!9ۻ/<0 /NƌGc3Pwrf?$τ @ܲbFngb3hBLNdpi1_:A(0 W!Dk)3HhC:X|5D ̫ -hqӲ즗lK>)狣JPLrr=A@caY`t_)%,/ㅴ>`a,߻3s 1'|Ɗ-8DZBun`Гl{KFieY0T…J^9#InSs'suu6)H`;G]qցC\=F-Oh ;4Pm4IEG:U@b8tR`=?БOЧH 1Ep0~Z3`u㹘!9dcǓ{5|95$i83JR"+wz'f!!>ǙYro.ĚE܋^m i??(q=m;A YrpU~ BgQٍZ ve N}Z0$e*z?.ǵ-,ukjp]'sΝt`V-CX{:ډD7/"N)<y̞3%~g%##'fA63bl.cE AX .V ^-wXq8L4b]x47i٠oYA9'teoÐ9g=odXGXA551ړgnCwu; ="xt"}f<7Bx'r[7Jۿ~cE,Ǐ:/*҂(`@)ɩIay_ǚ GOx%,O@ġO$}Ēp,|#]wXf}z)հ(gu3tu, <@LJR"ef-#uE[%~e#ߘ<}˜5cm\)-aS0E(%$gv/'`rXD3 Yti=mayHNyV̈́zXb2P)d Z}s#;.qĜ<%F?kڜq`-I;v4 #<-$H_NJė`7W ԙ'e%r# n0γVy(d'_v@c{'ҌB-% , fnk,C ##, m\B;]*:@c>e1Ý(GEt3yS6e̥wTs%cs]j&V >dqvd 8Rhq:E 1Z!̀#)jr,Ue|a>, ;:Qsą.nL4,+OFَĊRw԰h}íA}̦JJDQR hH]⺥Q7 ᑙ3#,OXp{Xdl!oaɠ\`Z0 Io=#8X$|ۅOe8PN`8. /ZylJP)TSԌ1/bwfj)Xq4$,>٠tCbC0N`|?'m}ن4ph` $88JԾ h7ֆ^d}l h\&73Ts ?Ҕu%Fel;G:zYS0K.XA~YyϹS:dn !8x)G~aS"PD(ҏWyvd>a EeNϙ(>g aRq>s QOXit\tݯXp3 ӨrFQ}^a0 4 nP҆4,{j8Ə11"DDiά;e+HJDW'˻ЋF0;cwv_@|H"%X!`IU%+|,qX5|Z|ZI]7Hǘzy],`(, 2c>] ؟8n Dn`}!Pg>q^(˭9"~RfE)4p84R[S;|*>&i (ߒFJwS~(1!w^("aӱ)(X2˛h }%AaҮV0t_W)ջ'ɜ3˱g'um|).ƹIQe])ӾPW{Olw3}(a- +l0ؓ)*2 XC}RD)HXw`in |J8R)H.,W@߸Ÿ *:HGvb#xI '8V.1f2Ȕod\ţvZ˞(fA;L.WąIw (NOZYkĶ'̻wU!)9rPWJO52|O7o!|%k|l PX,Sî= G>|`fw"KXnۻ8DV2\{y ޕ\t7oGT*\PzPm >ese 1pQL 'bBPF/rR(dP$$ 0 f=2GBދOVzՃ#лW|^`$ܟ8^FFA/] 8=1~">b ^C}b_^^5[.vYDF :|eyo[}I #y)@[YPChi,(2ծ HTYI3B<[ KBF08߽te,K9m!0 HDĖ g:|xu P??7p= (!3#)9C\Td` %m{~aZq/|sM[$J}I#tY?~29F0HTg.TF5YpI`K/=GՂ%00 (}0Af@M)0oSW'ߗZJ,(YA}DbqM iY|!UJNHݰ光Wq#I"4ߞ0H? (S:[aKSnpFj<7 hԾ 4FT)( % Zz3 ?$~ncaŚԠ(f&YRIJ6׋Y6 -!;|n0vq2ns!9?EELptƩJ0[hcУ\3X_*ZCJ@g$ u􁄧o~vQ+tcu-KDžↆd98<uc(o  c2f<ݝ=Xc3@\,"ۥ'-81$ąةfubC@LuJW*ހ)g0@3I08GhBո 0ÜC/=Do0  kQxy4 | kXrϾ 0N;9.V&L7SW&;IJPį<^ņ:r>dI_c;̈@?@jqF1 x8?Ҕs(M&rh-%2rB c8TGUn*uFmlW ("l33.9&_CY G%PjuZӡ@Z2,#(&sq5˳ѾƟI^>dt֠}/gRl{2iE8 < r$`I+jC (85hR, ZI5d`72+'u9NJJ/.'K8 CB߲-cvQE /@hXhho&)Ą<<d!+‚뒃DOkHi\B( nJsJ>jX?ҔolG!߾%Ydkܤb":[/,C(4gA] 8%$Ũ՜_J>:+f4SH_Q扔Aڶg_„\#&:VF=rN0S)|nFɜ9Ht3՟4ηk g-Huf!ޖ+1HQaO!uU!#)K{EtY0Tx*[  $ns`êB))Aa$ssimֱ0qFIkr{$KIHK ۷|q\z?BGhm!X'ߝNy_{c`U;/;D7^bvu:9>nL `qDM3J/||j![TE#B-'8\P 9"BQ}aJ#2Fg-Ah(xJΖ+$+0Y4rKg洩Hޏ[6Cf#F!@UVƊ|5>~v7ű|bC O!12٫,hHTb"2"M&6hEhj A};s>zI| I$ZO6SZxp!)7gε?",Цj s"ܴא-(:65K& (֧${9";&SPeurp1!R×LFQ0EorۉXd+ʶvrP!*`2ŝsiv\E)6>t&rVD2 I5 @ m5VA] _s %YZI SHK~maֆS_JF15H̤t+1sL 3};o!k?Ҕvlp RH&;m4u&8a+N6kZxt(.Of.6TJ)2R2rm3S7#`U̜5m 㰹(e ]{ZOc8FVY'c?"#RrD&~vM'=<6"F HQEl֙4W PQ~8jw@̱fR?=zdS Nu.d3smE+WsHBFQʥ`Bݰ ˶߱lBs8Ev}Rh!J8> Jr3P4䒿AʎNjLf)^ٝJskl jjiqT01?p0Pko8a)Lb_uԳs <TtE0[%Ͷw?"&0ոpP#x7}TZ 8Mip2<X݀@zRp01b͵ [[ eҩ~yÄEm"K tC K 6(_s*)HsGK2Sqs!RVϭF'%,\QX#gmOZ8yP[rQ}lFk[ VD0 DĔb՗$3$qFNR>qʶUC,iLU>0@7ram 9p\M$!k`JDD`i?ґ}Y͵  w%"u\ik@/wBm|aBay&o۵c:<>Ҽ#4M:!ނ C < S#e&rR0f xqGDwI%v(m8^nwrU=x!V+d#6vcJR"wWnd[Z 01iIۿ|/)ynx՜ %L'sITuD`"s#+ a%z 7ˇEfM`f͙X8nq:ERp*hnN6&X?ҔݨȽ8LvHaTm$Z8D!`σKI-?%!Wn$Q0[CJF"b Ii+JaSQ)ҳ_ݠa2$%n8mďs} Zs9SŖ\cS-7qEc1:A"k'0L ÅBYsQ':sgh}.[g靆c4j >o8֊Ig<1Bҳ :nc\yg'̳j0QtT6ry$ @vM4s%\sH18f]& 4$,Et4N;')'4051^kwGd,qQqvXƠ)d^vg4 XF0P gB:~S:ԓvY5)9u04AV5fC(1疴pϴ tԾI+bc־ʣU%iڊzYwwU]'3k![_aRB`h&P Z $&BFٻ.ӋJՎµi S's3:?Pi>MfCϺ71o07m&#,hXkB/ qa㹻&Ҁl_5FseRp%y{cv7Kg&L"IlOYmW2FT9{j6sq f+& &tX RF(s@T0 0c_%OWM4>AQrט@klEffs߅y\X[Q;S̠̱2YЉ?")P PjxJ${ZI!-Nd888(MsnkeZ2HcRGRv)H9R"sZ]"%7xfOW%ZGIi%?O1ּG=*2e!?-"5'`Z@b8]A11cRnH@X*ar#YpW;moLCjJb@1Gk{'7ҥq[[f4̗ߜ4?cN+E@1!8=(bSi 9y(%QAF,xAqu4`Ꮐs'sv d$w[9!g#)5:zr/hчg`$KcRj(L+VwZ\[d : /ݐsotasbFl yh ,#[v=Wi_J aA?E= La\hX3)c`(hE:@?Ҕa)LFt?")gn4W@&C0Σ?% 8p>9@Wz?"+C0d. ~+Ei)4D0E* *iDij(v:Z>-Ԡj?onX])5'aV!,6hTÍrn$m5 b8rl|QG9k J XM-Р#@ zVYf_*eab`Pn-٦1%a_Ô%$j 9At6aC"PRKG e/zI5kra%m9 sm)ޖ1/T$[(X Ǟ;ӻۃRActD_ ]Hfcu4RRl81uY Q߀>(BBBŒs9-qJf='U %]Ku5SF 9NO[w|,agiI!_{KiP| cͥʀ[O/A,fNm^8Em1lm~b|Qo@ѷw3e&Zp}[Y|@Ռn=qyԿchGe)z9:'ˎ* '*I?bٟ:|s >7¿ (ȞDjj@ѓ>1=fۮ&/߀}>0a4^)<ퟚp0n|PIT\FOUk j6F!J&#GcE΍f Q3?Ҕy:ZC恱@RP0s!G9D.v0Sup|8)aP1&C@:V_ gY-#7 ҚYX_%_drkLFZ79|,7XNԟL@W}` r#{k )H*(w0^!B+4bP7tf9=F 'ڹhA`4ܳCugQ>J5US3IH?"()H鈾:k^8_6> 0_ ,PcxM(g;yLB<1ykJRM3)nP׭a)$. ,#H8Pgvf'!Ć=Ts2턹HU֢23ra7 <Ϭo:,]ԣpAc lҀCyv)HT6L&d[eY屎{8:1vLP3-lx0xQ.Pk@ϐc/oξ"fZ_NcNX0*#X3P|{,r]ŧ`w\x vƋ%pU?\jPs6N3"vЂZ TkL3fk7.c>ƨ|!628a5cAiY(/ף--Ob7[us?J|<`*[?$Y+rqo#f'tPϲ֧|8V"D[ڵ*@0 e\ht C"pgNNrߓ`[wZwng_бTywHZ])=C})8k *)% _Moceo$CEU;-VywteT֣=>U:_f3 sh9gnHu!3#)i*@cGQ/S{:놿0>x@>I?n]&{J%ZVwkqz4eee? Tc% 8c=`!tCq(`ݔ-!O7Oi%)OB?uS ;JPjxwMr2_\nI흺EcE#ƚ{ce4 ]4퐀 1 б:,Y?;܎N\&o@\󲻫i(ߡ*گq>oƳG4j e!}OY:)?ic|>]RmG u5UQ 9f~Q?JDD`E֐YI! n8 ѺP5t2p^o4 9g8#q!YWls`OKa|#18tĢR2 &$axԼ,qnTӷ6 8lVq߶~e%1 [v$0,I~hm'?P_^|7 '0lL Xii B`v9N`GDXb0p]OB?g`>BE &ixr2LVNŲٖe,T,v !1$ 8El=d8nNfN)4'|EVBKؿѓKy`n 4aI%!OÅҍ FsHa iY+C>B06#mٶTI. 9NKF+$Ʋh))F4 JDAVT3 DxQc\ SR0pI3 >a@8?Ҕ@, F>8~`*)Fmߜ7ց7e; (b\F2gry)6P}r,h3Uik%MX-4HK;ͣ^( 3VX@kg@ڃµf 2_Qx4nXH:E=x1ԴFx dņ%|sŖɬ+uS\x(Jc & FFc:s+ڇW۷ūs |իfo#bNMl1K7:,J#Ն yQH!V#>m3~+`x9,dR5y@Sv٧wZۇ|]GDeG*ߪ+|Jł] &HLA=͋J^=ҧIe2.ㆠ+`A=AB'z-e9ۤǴnw5-tKK.ߏPmL'OqP3 53AWwvƐu?EQF`8.9iO-$217σy5a+1"Ln?O:\`EoF PaHFh?Ҕ-~bD\Sȋv6*{~ym)vGqc#"Έi )9 G0T`]k[áXefh4 Qۿ0mˏʴ1ևFW<.1 7pv7 ^m,a׃3xCgQpU{K8aiي4A>vu413!N,$H!DP Ygv Ń'swn̈ b=lPZ?ɂuzRSF޿!Nauˬ{Kp0 i)OcgXo-yr1['1А,Kdv( !ٙ#)ǭ緫'y8q̘inphL>Ґn!.YaqV7-k&I)ܭgZG` Ӌ~^jBPIPQ%}0X םnuDF ·(f2RJ~$ qva] SR6=~x3@<ΒAA+z[OPlrOlFQ(,zdН1(yF`IJW S)nX5- I~ tC%jVRY_7QE|p^]<[C:K7iv},N '&]$glrVaMGQ4\:F bUfV?F4J,@MHB_3g~0[t dKpGc:s!2p1.VCHE% p!K@ĝnsu>M!̽its̵[EIlaéE1K2{ȏE!RaV>ҀPo3p>bQK3Pac!y‰c]#2tp;]7-3VUr{(A0bz9xrNJ]%"`q8P`jQGtuSbut1(xL[pJ7J?"$a/uƩ2u()*aҒZ]A;nhw:6H6>J#t!/?cz*Lpx0W ?K1mWyxbP1yA8nP {8s*YJDACH"n|5vlG7,ʕqymj`QsH\Zr@ LM> ol1*a[l:?Ҕx77sJ:#j]N4?RgK@юbz&`'&MH*,bo `ԆgùTOk C!"s:*c<{;uԍ-_BY|jy|e XUhE?ag ?r[اV0 RQCcmݝ @4`RSnfk>G(LB ݢmB;@~v7 njGΡr(?"&g Sfu:~bo"wPK&E߸*]fnCP,^nNxܳσ)HSI9%ncqgen)^Fߜ4I&bKAXǞyp;KxU6r5<_o"@4V>}Q-tv]#2Ѕ"-z8CV Vd?x $1 $o'-m`a*b#,gaD|(,9tuی.?F59u=Y1 Ǟo;,4g4 t0[o>~zP#]pbY aL*c~{='(Pl߹kcq泛]qJٯP|aWcS-G>C0 'v`k-d[-A)nc[f8.i'֑9{7S~S?yTƏ'?8(MvgbOe(<+t_Hw`/NPi\0Q$%RFQwͻq+x3iJ(uA ه!s 3J6svqq4`b aY)S/0cُa-J7|7kiD5 `TКs51|{XekSQۗ!2cIqcJmAz\Stc'p-nM?n=aA? 1l48ŏ^94RYׅ]}Z'`wαS_]jFG^}hN0VFmm&YS =q+"G݈! g h 9SH `b '<Iw?{9:V1{;` (I(W=:kkrC%ۜPv3v)%#2#Y4jle] ^8 9j 5Sii)5[wf1mb;6Ҧg77:}Qم]0) ]i-@S'8Aa 8. @БH15q{`1SB !j9,TcÔLpɻl95֥cB45n /V)Ls8BN]0: o1yWQNk3N$Ϗc:GYL9 :X4gZƳ.Nn_u`팚kl CBqK$rWzk~xxuxWyfz #"\l 􅂌Ÿ# CA&ں>8>1ppי]wQ}|JDS mv: H @1HG!w)7e8!g#)tR'DF`2QhJH` qiI3rvN %ی99Dy)H9JR"ZQ],4\_竷8;˧̗gre94aPIJ )4U'&ЎMC0bYhO3!AI-$da@F;e:lgcr{g'̵xrS`zX#0#>iϱw"AaZ^HQ&SEc6[c~0z\s$ҒҴB2eOYy(c8g;0$f/Šp>? 8n!i)QZs+(>O<.)HGEqd;,57?ʟ= ϴ͚ºtdPHKQV.C<>y3F?#No(;![GD2'|1 nE:e%뒎/#1ta+60+ԍ 0/‰}P;"Vh v0@<};i?#N" b,X I GQ RFG;b6S(6l/,H!9vƫIsJ;1Wkb+Y‰8• Cskgk!t@;~#L[QhpgT ;Pӕ2c F۵ dĔLFZ!G29af`jQ< 'AUBAL1aBDPxA)&|8LY͌Q̮50a+e`k;OHP#'"*nz C$%44e/XU4B!ddF̂FP:kgs aܒ4LJDV帪X1A|1G Vl+~!K4P`@jKF<3Jldl_wqjU5PFsc ۴W BRPH18!o0o1ֳ}7 w䑜pg¥rCO TJp.etu:u'ڊ~Y/s.#`9uz;X @/LvMȄHF`z;]A2<I!rIO%8Ȱ 8crZ@q f9u0A-d nvZ瑕,?crW!0NؔKr'aX l@ͨa ̌)9JK7  _۱8PA QK0zUpcJR"ZeI =|9XK,C7^s|1 &'Mĩm}~{݇EeŻî4(@0v||L!(3~=~j?b.5  ;FQ&!5lT FU&)'q|=\C ; &Zq^Ԃm{gI⍝͟˾v6X{|XxlLx 3K0~WB_L~V cӐh@\`i(7jn.-L]UvJaM28á>x1!n4ޡ%!̀#)v=B(?Ҕ JR"Ʋs[/hL!/cQ;|ѺayNj<Kd*^; |‡18Dx#61ƚ:wP`IJR" ݺ2s'>u0=d'Vh :e)N~r$Ѝn֥ரN=ED2Y)$KqstIH$a!:0Ey[Σe"ofU@RD) ~3rUF-RQ`M~ ;?"#0=;+Rz?RƝ@ / so6הE$i/#a?aChh:̘`kJ" zJƅj3λ5ThڛtdC7;{ |%uKʅovD4clܮ"dXmkR@)]5޳YX)lo'@#b?*!!rmdB~*9RL$2ƏuOjMNJRWq:^\t᤭I,F09Iƿ״CؗC؊`lí`dcz@Q](g}òn/$V0A X^I{ qXGĎ0P(/?SŜNZO"(ȔꍳZBc nZJ^mr D\|݂/ ԓG X|4> Rz,sdv]jwHP}^z-lr9N{:#: G 4X F%$̌4HwQr =gXw¤He@Ld_s·yJ ނ#HJFgRIh|+- -d~ngjjNT# 7dB Ow#4K|Cqǽ_2,;#>l1G?GUfK#+qWx2@z1 vJȐ F |4*X$s֥ҡ:DX>iDѹ:H(9UZK:Cc ce>Js(y?k5A= b1Xf}|>qjLǃƜFÔt"#3aX0(Y ?$dZ,RR^)԰:CR6tiV^W{.tpcn$W*5]cQ3>#~1Xcѣ/sߡM6cU>^&b霛ACX've:c:#udر__㆒ՋzP~z֯}gH~R7^b#B?M 8q蕿{ٝ ݾBxI\Z1(Oo48bV 䱮`un!yKoG aSf'aF0GEt3Faa av9N;җ2)=#*Xk8O*[R%0輔lpK@_(( ¹0DNw7UNd i9lKsBi.۞rʹe٘ ő ΁j|7nfqgg!)H J:kC_]-w"iDXF :{5])j2żpE0u$*y?҃D](21]ѳ|n~h6* 6tDE@RWe?=/`} C-y}3%703sJ60ɽ{ q sCP n (4fPZZ]h9Q7$Ng`@jGPwi ξvŸ|^GH#:N; X2잎c;~ԭI)bJ{)}Y*?"+s \plO''ZSMo 2V^Oe#OS,M!O=i6nssjS:c9+nY~ݰwl18@|z4f~ VqDf:AGDԆ (C4^S?qL(A)HxDlPrGC;gc;3-B/!<7:xP:H0μn#X\vٞݻ^{cc@{I&P eH. ~3\p$2KK J!4x8ˇl2KKJP܉+~|8[^I= [=Xj 02w=`p;TEk0 <GolaHiH@F]s ?;J`2` P-H-qR}L044jr槝iݛ?Ya2W/ƣnqN'%젱qU?<[2JX~ %a=8JDR ok.>a!#)J;\GǬ0>Yz5M܃B)TR^ZD%l-ah.ƻ-cyPoO_2 U50?")vYۓ=hL, %v_àTYg&=+5`޴R4#[y hg~pP{3#'tS6lk~=xD9d$ 5јaqle*40 XB1ና<h:Id xI$ r!$DV .mvɠ7d uB{Bq±l|rn.Dg{@>A"U93|1,;]?d꤂JR"Rr>DSDگCXj $'RNvt& X-#LX 1%7*adR)#(L|Q ņwv;&Br]ǚ"jW3\. Lq4elVqjPUi͊N+~ۻ+k!ģSƝe֡Pc$r-F_P[x/;?ob!dm6(M{ ##Б |àB +$ !;ќ$225|,x IY)~4 F IJQk+>0D-ǸuRJ+U&eek2B|hG:8~s+; Nԥ'p)_pf3J':{d %vIQ?8Eᄼ;@s%;Ŝc!Аܓܤ%C)\Yؘf,A~[%ZW+`%@#UiB8ݓ')4,?ҔbM &Q:=ڄO:4Xt(p8| <X?R"wQIY+@* H~.qZv9F|Vd?xQaIY+ťۙ4RŇcdh>Ni0ub<טJأ|4!#M`;9407gQweZS=\A-F>۰#VKCuŰNV<-TDHGRQ%_o%ӻ ndRZOl4Kƽ,j+K]eK  IIFn0Br1/X]z4{Z`DBfqGnq7o%ZP‡ G:K)B C}1l㍣mH8}-i3(мۇ|ٵ5GѸR[kB_D3α+0^p#O`b;I$ #G>F" ק (kv5h&B Ki ?}4$ 9`D:( ?3-uJ1)&Bg=i~Z!=صȞwb3HrV>~<!#)4Dj["ҿZ^RrQ͜aim%չXRpW5O 2o~{ 0\kqL"XWg-3}5?wi'q+K)73pGD+CL g041Ǵ<8{|yÞm^ @#GGrvI`E[.Go{,uOPe#18%ߧoJ>[wK,a2]f{S$3@9Lo {)l̶5 pcd7 H?)N s@ ĥ~JCIliT GkW&32|RRӃ0vKp.3,\Q #CQ#1pǪ+@ҎSwNXG?;|X@ho(Qg[sS, Jffa3%.kO,u?-w= s{ی3ΜC &1+Jhα%K&7q`rjocB|sg- 9/.Ufj"mt)chh̑QEu|4@um aG od33E[a}^o ѣSN Ix7U궷r7J!v#w(H!> Q:S]_R_#shiÎ7cVQ)U>qP?[ )w>"Z@rJVΎMAΦ3ۍ# [6_~(_8nAaV1/2Fd9,`]09044Ē%q )%Ƨec5<` \,ݔs0d>T>omMRٳݻ{p요VNx;| ˏP5RJKK0c0I>e,<.N{Rz BLVwQw8c_9cG͍}*d2Q,z`$Ya ?(8-ϋB{Fn~bH;ܝ,>҆=wXC,C}dښW8glu,ȵsW5!'}%# jvnLx;Fa+li̺{g0 # ݖHZى<љdSٰOG:s^5' $ojKV` o)/GmljǞ`9q%ElG<m",Ɉ7Y- c?ggQP ORRr"@Cd-/A0)yBa4bj'E6cJR"R"&GYFOoj?x!)HI "jB6 5aj +J dM cc ;:u*2oG ֿzbe%)Gr[DJDX-|Wۏcm(_RPcGV` \%2QWIerܝ$2L+8<Ri}p͸`Z gcX{^(Q?<_;*)HaF2RG%Hà @_SvU.UZwVFWKŘ?Ҕ5v|XEag``/LXCZs?`*l1Hۤx<̫c|gS)<8ym-\qo5\G>/-C ɶj?"+PͿ?"")<"Ti7"('j_[5;g?݅S)a ֎ݲѹyt+C:SW&P(&lp&7$ ĬxuqivM,Bon?"*xT}fs;uQ['ߊ߈F_>pQx7; zA#gE`*]U?ҔHoxJ7JvZ;(R9RE/~⽽pBWJq垾%#?j5H\K^g[g^}ƏSegh K)),M!Zo&))HBĹ)G)JDWJ,S/˻0 ,4-:n7Umig7%Xp>sç(AÎ<` gc̈h!0b9}}{bؤvBu|0Ap_FxؔgA ϺIzk!4^܌ڞ}Y\M6weD1:ב|z<{Bըz4iOGVs> ?c*`5.7i# >r|B(NH ;aJJDHBQR 8?ғ+;|׽R#7~bbGw-o)m4&jQhWRS0i#…H~ZHoP J0qA4 촍NXay```o oIaVʸGH}$Qx?% 9hɀyt?bH+pylFqR<:J2jSixT Et3|oq~"[$8/0)NLjxp[ !X KHo 'XZJYdcJR"RnBsGΛPٜSFkvsX13PM%FۣψcJC+BҴ HfNz{X9J(fiE  юR1E iɲJcQ(YPxUKMdd<yxsS! ̀#)RRG] `Zƞj HӲ7(5}^$Мl a5#~@g䞎;d X0Y bLJCc (ڲ6:CJR"?0e 䱃;3S=9g">! sL`d靉ǹş&#‘˂X{Aө(m!S#{Āke≠!1QbY{#~o(@KzCtɬQ{IJn[(XTBy4 ͔4NC?NRJ5DpX<c J.绅#@@}:jl6J XAj@ Jb"BPGU6^sl>SoIpk7}vYΤ4w>3 ԩ+~E`X`E%?f;Oeޏ3a.MA~E3T7n!dV cy# ZlPwhslbݘ7=q<>J#4oaVPbD*y?Ҕ?Ҕl^J]h37 ц)M|n?""R!6ha1@ MI]hݛ? JfqnTC(58y/7AP5m, 2n?")7G&:n7]YZ[O{Ed%1)LQW|cJR"a8ƩA lzǬI6!y#)1damaX4 s`uRMrV!nj}? ⛥ۺ$!O@VSQca+= ;7jFZgoXRg`+\NB`hB sYm*{W ހ9!)L;rt&<2ը?Ҕ" ,?5)۷3P`mXu0H2-+h_ؖ(Uxc%ca)D9 elVIl jz6~ߞaE:TTk6]NK6$y걠䤴2@wZ1ɬ>%|vԈ.OCu1Xl(-~0/X`h<Jrv k,jZsXV758\,7q5BL.,4H-дI%p̀bI>Fl4 a }*cL2ѥ5@prhp?>'‘d8ISvւo΋;fݶ8zݵaVPA ƊlڑO|e4 v:B+)d7[\ԡpJDE(?tQ-qYRmli:Y_c18?Ux0 J@j rߣ| -#1&6 : CX h:yYvb pq)H-h nF_H>ŗ4zt_ f8!k eҎL -=!?ғx>뛧Ulg (Yx^@:Pk?*-B']maGʔ/0TsGY- |[Ob=]0oJDY`yj '(GomcFm(` KJ&lZ@D0( eެK՘ aWGRv$$@XĄZrm`*F JDQO-BAd@K-)8{y =#/xn*F =m} ىFf y: 0.Ʃltg 6]@F |+"p,%Z0h1݆ 6b \#dlvv٢@a}Sya>as!E֎?v_4!1Sp[*")UuOp EP"=Em;:F+O04 ݀a&C'6N3w9RQ#~q)H9JR"7,ܖqIkM%,rՐ͏Fd  q),S1u73{\,4I0 C@^G0Vž#D8EfP0n0Ѭ@0Wbi)>t#lTOGv: Rc`(Kusm0&R,8($nך362[wGQݧ"K) H|y}E҂hPF bİC(|` `$+D `=3ōOagGoub T[#0ݎ7u8tĠ bGrv,xtA[HX0*, DanLBƎ$ іaa JzҜxap & O7NR 'E XvDBaA Mi4Z\`),bp6NC(35YpQ8r0fH4=l) d`  npZX%HŨi &7%;f%,j s7vqpn]+JZ O;ҋ(LM)'\npq e7BPٟs\zlM:qe n2 $;m< Ǭ됄b ASP a@"϶!f Rp ѠĀQX?Ҕlcl<8A8bSɸoe1 щ)(?%@vJGǂY00 2y8pOT* %Q#=ïbc%kD]&A Xw:hHiaT>n!)yc|:s.a!r9$,cqR`>q97,}!g#);Rږd`( zt)2S6 a\LG؊]1 a{[?IS˷%D0g\YDbS';|m*Ϛ 2)"5fnf#&S/jDJXlil0 b:\*Cz ԥ_]uhK{<=nښ\i[8: Ǒ\%థ;&CbGmX7ƀt1)2]ǎ#avT0SnNn%ۊb? ʑg_;]#VDD!jC~3e∱An>.~YTƩl*٪15=@{^gbD#=v.S-G*S6\dRn_9aʤ\,4`į~^0Puf- JX#q9NݙM |X" Ͼ/$Xuɟ(j?f#:uayNH#;&K/;؎ƀ}`,_8 .Ǐ F`"~jub^DO%m]0URBxmW-foGD2CSSc2`A{Z@ܕp돿Jf?"#Rv+tZ%-U]Kt9|1; 2Mc b {NJ]S]<iVFк[A"'LJDHDRř܊hO-/P>7Xq7#OAol[*fs=)2#dJdl.եї-LJDAq(r`ND>3[!l<ԇԗƠ4Kb!ܼZǘc^JXQaV0>! %kF[2չ-ve(HrvTv1zqI&kiVXF_lrjV }~7>ޖ[FIԡJMdTLσph䊻qDˤSAg%$31 h}$Ub@uzQ pAHҞI|gJ PbP<5_{4)ΗDa#d7Ĝ-=}%/ 'XZ`WOGʲ)pc<}'?椀b?")<}f7탳q6Ssۉ "[\a4cNFw"υؾ䬅-o^iRVǚ֖fJz贕WZ kn8 /'#WҐN6KhiTN&kk5 _Wq־pU]J+,Cw8 y˶SG5"!): ;Z$ 뢗#X0δ{TX;CK=2y瑠M%հkJAO)xS 2{φlp]ЬG9rجs;B5퍥ڱp{XXr!koI0#j)![%ύ o\?GZ[c6Fx5BvI]!-CL% 09)QhFOh_?nNW8 x54[D A, ;@; !)Ync[73=PF @ d:[Ð|c^56% @' dh~h|JOG7927$uԾ&mF1>4'CIYЊr뾟\튺;~Jo}`NJ-8t00ZCC!̀#)Fg1 RP~M& ŀҘgc@x[Q TL$20SgxKo>C&gO@^/{@t*L lLX~2x@bSuql: 1=4ztGRħc4$R R&B )_H)1)`g IdQPiy|cLJ[ҍ`6pGӥL-B\!XbC o uOVؑ͢W]ա:.$8eI-$gCs M8Ǫ{p&8P 1[ |;td pSN:z .{ B3m8N`W N,b?") -I-1%Ys8Fl}vgمm٬X$@& !Y/s\'<>{}!aY I@)fn 8bi2?֑rI+K(5.W%wGlZ:{!;W m\\c]XiRƍAfJR"3 B2kb-7< SͰyz&-db2pttZ }' 5߿ \hP~?"'쯿eN!Q6/(}W_# n7H7gїsq%ÀMs1fLBwݾP8X% }?1]_9*!t8huQiY;y݂@?3,:tgQakb̓&p`M6w҉4jx>`$3=L qUJ&IűYƔ08$'X ]O<iKW{DLdrI%~h TbP8񆨜I 3 8xDkIo nJļY|58 ܍d^ ciB8 уr+9i V9=;)t)[!@iOݍA5# 14{蔐S.`q0j$7Ud %j0 h0Hژl)JwTyw fB3o{b6f|J{k Wۑ:eCI72RK;ĂVf[:ulsgP`ې]a }1Շ@! N80&$5`9&t_8Ä $3T7l^$qա,SRX) ;82`jw>@I#)S ԩv:G'p4l1dR/!3#)@cnݛY{Ns,жo&hX!400cprԵ\Yj2p {{4?EZDWmn+"RnٝB _Tz뉵JĦf *ωx= X'2\9HaHÀrQ觛4t R[݄9BFlG3 ~s?|c9אgߓ]rn=gGǛ#W=YHdACJR"6ٓ:`w8!]6 U=-'2e#9];Y$c@GuL[|?gnn5,݆9B7Jh@g\YGqv'@P`FY}?~v3]cHpOK;Rs/I2Kl[Ҽ!f7N St2k9](Ae)t#\EE1qBݹL;2J^`ݻ9@8<Ma,cv9\*GP!;џe)ƽjM!/ 45sBB;J,e k.̐XX̞{Nfg%`' ݢPvwr|B~GzH֌ 8C-ǼEsyKM `3JDNWk/g`-@Bg;p[ F#Ҷ38{1ÛʜZH)D.|\ҐPΞSvQa]G!YeFLu0 )q^HwCre9gX0oa:wnp40$竜?*T}%I.FZTǬJhة25/Jff8z\شm<ێ17FU6oHdg|+>HJDA[[I045XjM=9bnv c%n=[-#{%:کI'9 2 , [Af +u>sh.3i}J|{Qe1 g$hCpM,.ݾ /t1>@U!/v#y! y5pXk햼}7ÄIq6f8^(pbq4{|t  2l?CXocZ7c/]]| %i>CIJe[۪_$CR"1%K8SG,UE`:Yv`@?.Ub0-)[ő&RPgbO|vlmS7\*Ԋ#M֜٩zBFuŝ_31XK,^iq "PsD:[%dG:y'- G`y}œ!~LH`юn!m3?fF.5zd'MڸPZë<(?eoek\_kcCa{()e3r@s|q-VRkwY ",E5u*o15q7ѢV9F^,7K C`,=wGDa]zkIh a)܁ʎU`,6 HcR1Lv)0?ҔJ3{jsZ\w 뺚v!"7|HU}&$R7nRPp!#)] u~<5V *R4 s=[8Y7532+ es9+y(0)l[Ha +tT:](`Q4hf9- ?݄+ԻRuY3]Ʋv!J|h"~hxH"Xo! nPChQl^ K(IqHx0mb $uXU,dDA:fݦ`i)O{qk@YN:d;ftgv~r 9$ .J?(aRn%D/9an#]ߕ=;ΝTNZax*-'X&@BmoS@Ρ0rYs9Г =J AY: ۛ!͘ Zv6\quS4 +vS֒$hl{*y-]`CQHg; $iV>IgPq/pD^Z:6<'WcYľVU ,M% ;2|;-i rn $i G@au找:Uͽ٥L:]o6 p8¢YڬߖgQÚieK2t2C>hc8X?Ҕ O\Ca;t $RP1 :Jy}CCJ-ӉN0N4PGf`JKdQ @d~ E ` 8 z{i42C@o,ْaJX_t|"Pm$3N/wq[.~!`h 8@#u?O$(X 9C\e$a=3?L 1Cڐ`lQh۸BM! c-$OD<, ՗uu# JRc%m1$mFYnҠX) V?CWNZj'vyl$Պޏ)HlJDRp߆:D"R@Ѽc1)L=R&8)g?@B&'ljȧUB!$gY夼Ví: 0;<y϶d/+4Q.}bPn&GZB=iiO1CL;e,?ٰVvlc_d8k qYy:Jc !JDR B7IBrSݙ dS*?RyTP?h۟|=vޏ0Ճb,g&&j4bCt3|H^,mo t3< qRCK=ـ_y)H)H3 R"VTz?"+qRR0y0Adn4'P1., bX}2۟J" cJF"SCsl@?Ri gx3:J 3Z?L8XGtmlE\p]VwŰbZ@: Bps{Q0_Rm-7QzNefQ)P8a{p#p?ҋze<٪v(rcX_`=P) +'Spߜ8ӬȰ̀k8q'#wJ i u؄z_.vK CKAa~8=5jіwJ<6tD֒X ; ܖĕ^9;2{u䘵Z\'#(#Δl7%c]h8eG}g4}- Kb-ӳseA$K-[ vIfۯa0pŜfSq?mxsh0s7nōGùm$|5`p{ m,] HJ23!#)/?eu%CE|yP@ajo$.s9hJ|#\+3f>$KYq: @GR!Cᥜos㎦,B\7@H`Q!w|Vp`> -IOV}PL"5{ށ%͟z"P%RtCuFCԇ!vJa8"K&~o R!25D`̵=B>֣^Xfd~pj`.^ GbfHbLQI~Ş)ndͬП@rR1s@K7HT$̅珍-6p~\  9]ja5&$ifo4 X2QG`0IDٜ }2QEdN~?qU;N$By ƍuvkw,ҍ~Xjs<5Ȥf `$>;wrxaa1(?9أIXe8T6h)ٟ.7o4) ㄌAÍ{Cw9'i>t%ጤ~jÏ2>&ZPPB&XƝM ZJhP̭YmٶTC3οdEukt .i e3a*W`Gߐx猵VBGw'x_%EƸ~,!kX?ҔIHDd'e!ƓT x#KpYMη,(v?~V4㹦ߘY}* P)p^ͤuaoEBuL Hş%.xP_NX(zu)3OY pF8`iki[$#h v(8+r=N`@)G0P3 Ld0a kuR@'g֯!!XCC3[9,#6ťCwt9tGD?&!:(oZa{ހ{h`X~aċ~, sqeF}zo}Bx3?f}א A#\ӴAͪgW׌qlxFJsf?k_m({1䏝]c]ks_x/ M5Cb0i`ĘKrXKδz IŖkFD4c᧱2\Éq6ǝ`E/c?Ҕ†-P L68j~vp<; vyvSb5M,0S `A,k k:1ylVv#ݗe"Wn(YkOc -FNatm$c%iE(Q>CXh#R&cސ/nzha:7K e`y@X>Lf ҃nkCnϟk 7)e@P4n^H%ڏQUm^bl$b7j0-Ώ#m)8 Q,.H?gĬ쥜?Z$ d)_ ŏӣ&`aX%wzYZ5/h߾$N/"<7 ?}Zb3j) K$!cBՏnƚ. 'ˬb>"D Fc/7\2ƎoF}ӴGh@*G^S᜕q֑r~w7(N(#ZwHA41A3ט eP^YT(LnhX#m҄Í9g<1_$uX"c +"rE)1H Bڔ K@|4*QhGvqPհ`Խ<} `{C1A6d+~퓝&'ϔy:̖ۚm$EݲbI{>ЦpKȈUPׅAx qǛ4y8i`9T0Ik38WV,Ӱ5,i<#pO<źQ aaekenB,3<⫳lςCٔ#[͘u) r=0UBl?Pц}#8\3bj(0U R% ̏R,4%x/>v?b Y1}FtXhƒ9|*ُs^A!XV(jRβԯΣ;c͕@-7lj0O#+!x*ڜ")Jn0 g0c0D J盻T뫉X׿̍! ~ހed JX +HC'lrЩA ?Z<>HaH#`d^C˷2m[?=EҹDj!̀#)D#זsQ <!3[([HnI >&mƥgab]P:?Ҕ[c(}2?9?Ҕ7:rHG`Q'"B" Ѕ7qu D$QntFwGCTa8C˟Tk^ϓoQ鬵vClwBշs ~<c K#guegZ wǫGDFWIL& :!RC itg7Xb ?90*"usmloݣUu&Y|Z]L.1NTFF?e݀D?$N0w9NjŬ`#ZVM:)] ^f%7p&‰.7'[sLthOnV#DU݉ ق蛘WZ,d;jѬ$p` !LHq̿ ,Cnk8oS:y-2M,%;3`‹: XSwd?"&?z765V7WRu 0|_ OoIϸxu==KSJG Ur$/vvĠ={;F%n@ܶIhbӔݏwu* _%1Mǒpy*̷Øm1Үw,V)l7z`>ٕ#>d~ L=ij`MH&Ђ,〾/;mng$?wAl7amt:>|0 Cߜc>#/G$ 𜱿J95}JpxH7o!ދ/nS #zqw0Wcm@Zó7{U+vdkw'#R[H۲Ɋu5L,W.Ґ@ rwĢRI ú|Uc'bfHHќf~c8݂Cϊ}Prl "ƍ8ƳhV@RfJsǭh"TlČs` : 7Ҍx Lt^#u>jK@HbȪ'K|j*c-]hD00$-'yBF?'-Yk?*XX!ahJrF B6%6G+\!8R%H=f#Qn@ByX%m=F`h!8C^l-7 ~!X 5$9!=Ġ<@L<O<쟕LvۺIJ}f!jv%dTOb PgؕA);! [`>)+m 4À|ѫ)Hԗn0BYŨ.-]ol(>΍AAX,>gŔ19!R)nʒ003IC@SJ'sGVQ;~xSFZ`4@Q/;:  3 ĦCXtB ax{=̶7yD,VA0^%|(AD bp`i2!nŠ#&iaX;ֿsdg{1 =֕Ɛ << E1\ 'YBB= aLjƹH`T-61%'07?| s ssִ-#Sܖӛ) aPc$ַٺ;C`tDvh1Wnz|Ԣ"DB &lZ`?³ ?(uDWSR&%=d$ƠyQG04n=E$$'H[Bʸ?DLBF#!4 ?.Vы@By!~5L0~zJQ-BݼC&A ߿FV@\d5C FBp=Xx|:Ig1Opo2hF!XqQb!3#)(Y8X\>%(#3?H|R\:w -hbJx4q;k /d`nKf40~1.͘:) f1#eh'/Ӓ͐0԰{(!zηv#5h,AG94㕱w{dc8i6Ç!)ddn:i[М+ 0IJДf^847 $ٞ+#Hl46:)z?+ehb# DD4LdM {u|Y,fBp.]O XܬJeF}jiU)>-%[j= ]J9Q!187wg"UORaZFA+ZF ZJR";tzJΪ+hNr-Mcx@.$nteJ,kـk滰Xk; J:R0..!.gh%&g8#9cfНtNN-g$gp=!X NH7e?7PqLl9:["CkdS/'%؟+$rbx6Zȍ%dB{(7nܑd,ElFck҄ v x잔C3E;c~f %N qA!n>ƹeǓV;(Φ<5J\`SnX `х 9:"ϖ\֤5EhϧFlֶf.^ДPf"،9Pۥ'+3rN-nǠr3kIH =0"} W`qԳRc6V?b)Y0 !|J(Q|Xc\ٜ]junU3;)?"!)HdO?'5&oh0>%P1Gvㇸ˴+?03Sjes)&TXa|ə1?ٛmk5Ҋʩ9z?"(#. ꮓ4'--Ghn ΃R^*rrAx?}cߟm JK+r1&;:\K>?"& QPj "$K ؋$KyGmo)GXkC1}pͿۅrpW2Ux"h ne @:ɊF <70уNSK[HJhۦ'0&%F!JDSa5hMvM+8AߛjgK:RB~'R8 9͚)[ZUlR;Gq$NOoH2:kKz: M,@)h5 w"^ RRۆaB8to<0&t3 ;>7(N:bJ'RlYh݆*P 3Vl8e[YJI>=Q`gkd?-8|mNim`B`u_s/h:0dsZ ?Ac0{^ 4h6D?eĩT;B(:KSJtN ;we\Ϧ '_â0p6?"#1h zsrRr0D)Cr٨ V{͑Cԅ!?ҔY%FZ/8Mj+)10Ť0;V#K,L/c8ȇ[-īF1ؤ,mt|@v[6 0(rIXƎ?Ҕ"-D1! @Č * XKZ<=f;QD@ ѫpTbz?҄"&t흶~QdnW |N/3~߱3sh{/lTI$a"Vׁc]z&v7ؤ|jOa{AOd8Eo@PpIc|sglP KtFamIg M 0g0.7Va+15݊OA'8F5ÿ1m$7x."ƌ9N3U1!0Nj1T?y;}UmhR!cEqY9vK_R"=<Տuḋ䙊b0sqI3'>_2|3!#)/a:Q,h,5%#3j|CO:llI 0d3ӏ3]lၡ>,r+<4c b?< )=o߄?;L{%-[uoC)d75)#g )tsiuJn VCkc1[1)G)JDQR(챺h4-z'OacEprJAN'wZ] ҹ@]cW ǚxJH_ ~s,f %Ķ,s  ]=ƤjòJR"P^b K( p|AEnԀP#stC##T,d7d@|X} }d;&Kf*PD [T` 1;4Q-vGsxS b2rF-W= jRJ08s~7 BKJ-:BPaX3daͷ<  ͻq>nTg!JJv|DPXj LL}a{ ޣc`AQ{!rXkHo jk_aoi+GpnL@[#:8#Da+2|BO@13ZF0Y15$ѥ_38&ea&ѴC1tɏ") R)A[;KnӮ ^D\@ Ʉٸ`R 8gR`[80 d܋*KJ@xk^&씼%d=:TRm0Z0YNѐ!w&~ \Ģ[h$ ̀}YwfؒI<D2%I@hQfY>JPPf;Hv uݔ9+q]lzX#SC>3Վl0hv9 =zvn%zZaԌ`t00_ OZ8SIN37(7wTP0mp#dM%(fg;-] of`LKS Ƭqz?]q;J%c?궻!01eYvIK(w-yؑb`% Sqt>RԚ1i/~5*[6Bɩ%?0a i@]J[w8xL~;ַ"BٶVterRxhեHGF R8<蘄bP% it<^vV1[͕P(9{AFV`hn @BI64?+u3 C~n1IBCsK VFf W#rzfn,5ig=GX mݳSrx8 5 J?ҔtX PhѠ{?KGJS>&p̀ I dup##_eAŏ'Ej?"&BcA2et ~`b#c3E 3meAC7~52R(Nkye)2íH30t*PI`H)pK q8&\gﱔ~EQai^xJR"1i˻c~ URn*9A%s|3n 0_ⰋB4a|$lj&u2s530R?Ҕ_MБa3̹!HU LS/A!g#)DqA&Q-$x/-S&L-# ) %bs@!d !9 O[elp%zXJR"jfE;=#IBaO3̫)vFǓ>RۊFBз(K{.NLЌ*&ti b }a@P07QsD t<5X!\P\U!;G-(Gj\f7"p:*p!\:x;wc4-ie#JJY>[5tj"҅LA?"()H `P EE`f FB9+*0Ʌ({I޺b6Y4Zϵly5?7MTXxĆ4  ǰ*(ل0dxj[!Ml-|:tX FiTJDC! v4a ɥ8Sj{cx bi,_@DcezNw Rn:p,g_"v$Q?Ҕ*ɤeP#C &%$by IAi}vڦV{JR" n{tinHTd&?"#x'?A o'4B vY0dK%)Hi064Z]1)BZ ?Y?= bzSaW@$"ҜJ"OG҆GD~H` YQ)i%)HOhfu3;ؙhmIdh]4)1)#  UNcڨ={ PPw˰uF$|DY HU"n8LSSJR"`o n 8Ǐˊ&_BbSַ8U#6cğNE0tmIw $1nk ϒb65AH!bEUM'&m0ĬlFtDR51! RRwJ 9ל36JXoe9 @M/{$+L*{jO$KGE)G# DR<;F?Ҕ6CJR"K G(Q- ؔ&-XPc8,l HeSGE$ mԔ2P< rsR?hPjp|zM[6e) ̱)P'9D‰b6Fbt8Zww:OpnBA.}MjO>GE ĉeNVe$, Wap4LFrV|^ykNω£,4/89L'xS*‰5GMNJ:̱Og 멩f!̀#)'I~Y[JS`hOgf!=tU.,aT^/\轳RCG8B":zƉD]*<#nKA, >%цæ`?_1UGaVɪ&Ol>" lc->tyFp(FeʵxWcd#$ywE1'7ÀPyb/mF:pK[G[. & BOtTٜX6VƊy6ۚyf:F?ґT3y)Z=c|7"W0$XIqpЃMYbIn!݃&(:)!"3mT(vqBl>shJg9.pCy&FlR':cOL@'{&JR"53tm=1mI>&^|P' )ke;f#*w8ЄpB=%E' J22|HLZP_ x4id3ƞݳ./pKnhϼ!!?nah}&CjH Nwgpѧ '^]EUF&(=132RiaȭӐ䓡%ӒYcğ9I`=` 1ܜ+㬘?aJI,'t~[*f0A1)t\9u۠LjbDŒo z(5s>uv3c)cM#1՝t2P쁒D= Wp2c;wO9%,!)C; c@V{bНġg?3Ӡ~ߨg=KP.4-Xg] -= ق@yun?ib'; ߹MZS +Znw?P$j!cvbp͘=I Y/%ݺXNl"x-- 9 uSVIl 8֞uY iM4fX]e{qӳ ?C6LZ:Rf휂hˀtWK=Q)$7#[e!gT]&#CJ9Uj6bBI3n0SSԍp0pl3%f *9=StAg!Hm|.iBj>MIafQqc;9"ǟwzliC@T`bK@ Q5&JNt*؄γ;Tnǜ }5̄$}Y(蠈&Vta!v[&sۼo< x4ycbҗH@-R Ra4mˆyFN׮z2'C-O4態aߺ?)*YAa7<H?I;% _rΔJGoֱzysm>e%\$h,8I D.- hjwahj0w'ae$g7lT sE!Hٟ0ZC0{8RvAU 5 퀞Hq>:ACKFR[5FE [?vtc]G3%߭Jr~ r5I^1Ud ICtť'BRbz I0,3aP,L̋oa`De1lbR/6>0,gmFIe9qjH,;gC'HĮ,"Jf !^M_gqÄJng8)-JPs?PK`v R<6x>U!€zHY@3h6?- %qu { ǚtWP t(>ބbo-̣Ǹ) jJ4^XJ,Q0JI|i|dS1Cl&[H,5糛;|=aoܵ}X̯:&qw]IJ 9+}1bճa`xNHMi[)H;i77ϻn`!g+p1gl>vt~?IYX{0J J0$PR ۠ y+:[|`i!(H $cp @NP 41#s׆$!LdP x dx-i>t >M5#BmxER t?BF?") V;p]Q(Dd 3n5o `'[ rRyMՏI'u((m?iH"f)"Τt^W8uec\YŤN(=?5$Dk %ZLN\{}X`ZHgxC%lZ$ \C)G)JDL̛pE"S #?>WWUL3pB)[),'"gDJVa*MwϮ2-YǑnK#W2P^rOΖdф#i)H9JMI!(CCkKtNierW?_=3o*kV@Uh¬,V4 Mf!hPGo}$W5goQ5wB3 =Y7¨HNJ?j;eeK\a@t-=:3P МFNJDC!@7{Yz7HO>iljASQߊJR"1&RFy=y(KؓaF]rۣ%;wir1qw7}eZxn=p: GGWcqU`4Οe^l=ݸ8:k]Y t=;4 &J|w2 #3٤7íx5_o5,ALIJR"cJR" 2c  Pb FCDL[!K=_Dtg#inlmYdA)ymvᚖ/]^]NMqB@9O#3HkJB]BIryB'i5JDDRݿ;8a((ƃ %t; ʱSX]3R & 5ӛ dl$uU{jdgfV9hwA(,$T} Hfq9%s9į6?Er4DhFcIy㎯I@Q8zIA+IhGr:@dgU ?,5w?~_[~'Oe$g$ofC[g)=0q4la/)QH ƞ@rj% B 7tDCnYȚ ؒuax45Ħ$_~ >oZY;q[' ʻ;!.FMS䒺u䫉cï7?1:"CJR"(XX"ϽY&7  xj=&'1 QRweDPУ  % }3{ UsQ$O8i:qP!C6(RYAN1~}J?:l) `c!Juֶ!#)PS'OY:䯐?v|uaEGaiGKt$ "FZ]!79? yԹ)@4BчL?Vt?Gs鰀"0_$pw}ʹnxI6&rk36by|ea0n)| O8P4(WZ_nyԔGC$ nXps{N|-;JDR6g6u98]lf@ޞDJ qu$  dI`BFx9PDP@E`d` z)Pi+oGbDJp ]>3ETųu4`W]Sц 2&+ުUDXh M3$FQ_wRjdn(~J?nNJX4K1vFAE9 _a0%'qːKN,$1{6>J*8JIL0 4%,ks_:Sq(580%ȗy;ݹyN< X dfsXdсi5;bηS%f+?:hu><:cgN;޴P(P#6Z1?ғDQ#C3u%dmWZF>xz l0Y sD,~'b9KiY?JDGfՋz(b8>?"+~O'Nl8?0M!,*FnI9- kan+ mXSsPu@ ?>#mT~+^|Y00k1!W08:/h03IKA+0y2ltVιh9<-v͎a4̜JHs~Yѷ<#3EvGtޙm^u丐O@N\Z.! 5 CɳWP`(f)Zy8Y&<*  6T{X鬀㪤F?" =vRK 94 &JOMrD$$1N,)U"DwJn8~<)L0no2]I:(Ĵd5 1R2q]) ,l7 &zOvl[kFM?Ҕ6f2*|Sy^=kW!g#);N+cDV(JqY0L3>3 9ͳґjT#%6lH/j3bs0CF&LeFb Kb 1.an램-R<0?Ҕ{:\6Ö FUc9>bNd:4҆jl4T}%{T2,&ep}.a+"ppmF qp|{w]'of#[A vZGڪ/HB9 n}K]wM˴s6Ѐi'Ҥl{XW>^Re4m/n|F[/Vf' :pc!WrrDt?"&ߙtc!tQ0b2gO=<.k/}Z!Ѝ8n–G ݵA*ґRA*lV[|G`„n*L,5bϺ$]Ϫf3,IQ,͹p4uJ4sI%q^&s?ۭ,nu|g* X?ҔXbn[)[+sdk(lT@͡EHq0 JDX_mhK$98wv'8D|,%EbjOH G&PNz=HTEgPn?i#Lp1@,B$9Yx{d|z@aQg5k`L ?"(aH9JR"F d0JR"CJF"ÆPiD9Oo% Pv`Pt0P+oCN$fzB'dSR3uڒPnfYBɥSHdfnOK:)plǓ1es@C7%A)#UX |3%wor[1xGaq.{(@È;<}|PX#y<sm(a%cU4U7 QuGh.{% 6 K$OCI7M f=(E[kp$,l 5rEQN̈́]l#x8}0{c3A#!G\+zϦ `3[3Xv[Ls$'6 e:ζN2Z^3I5X rO`@JۊX"ㅐ&d||m٫73 衜k1L$'b9Z o F3ӌ c܉jη,> mGC7{9N¦N@;yMsT2!$p>4 s_~PJ*G a7-VrXC8ppp ,Į`He:t0k ^oՑ]3 #$~g( Yݹ?\$tV GBNȂ3χ.uԜ{ ItT0J}ţ k=W#f?" ;{)à²Q,{yٜHV<;dv)a$R3]GA V_dɀ6u  5n8,H)-( IktD-IOڰrΡCϊWCm_ woEAÙ{u{\Wulq@塏""Qi ! 4^p10ϢSf̠#WnMHo, ؊$Z7hfT޺6uR{Ra ɜ0R\9âM1)kViӟ@h6S b gF_5 5z28̽XX$â֟JV10Ӎ*a3K)̎C4iіf*- HoΓx9J݄q8=fȴ|.AYk( |VSOy)-YFB ,i>vf^B|wVu,ەH.)H3wMd vH)9$8W26Kt<w-{#<[0zr cĽH?-jQNFje5 &}\l635!Wj 78*AieP̣~ B9]!hCrHϞAm^u:QT SbRD4d )JBB99(}.iEѻ=I!JStcf:DZͦ DJ'k;^^mPtZz!`^5Fς$ R26uu{84ԵGJNÅTZ\C P0=!YNpu I|'^?ZX#ޙYmZ/0)6˧LjB`r i:d-҉H% v|*iFS;:تd2)H/ Hd,M`v+Y zJ)HcJR"}g1[ K.!:ń(b86pIx`]Р?ӏXtRD MP}pJR"R,F'QD&pJ!~P0@;aXŇ{ H<$9ncQI4".3. &0s^b][rO>C ͐jDaitFR,Lb)G<=aaVw+d>f6]v}WHseC,(n~h%?}#X3 {H٧z՗AcJR"cJMHqW`j m apГ\E`d5F RecX$̄X ZsI0]0-5_;Pua%,1p}ㅏ)HaXA /Z|h1v4=X* FNh\}PS;l70,F;>cD :  IHH"~$s0#xS!rھf 0%/D7Jc R!>o^d@N].^=e#-", gufN.]%dgYR|V|9KaQ447̣)(37D0R}Sv`H"WsX B2\5! ?Z! @&CӧD6[1l`(<|u_pG֪E bQ,م4hgG)9[SFg~dB?0JDF`Df6* $i=f):&x DDDB*QE V7śf["U<Hz>!3#)K dJ\֪իw2d4DD)?@ aaJ7sfX  ­R(L3E#H?Ҕ?b'ƏbUJ='kkn[ ~RF0>?X.cbFA2eC{d[vJp*Yweqi#7\Es^ \qº9SU<jFiZ qv>f=<~R4ާ]N@\ u;XP;'CVQ)G)JDCissFCzЗeXP+Q gYZ֫K!jr0yr_R vSͨӃߎΑM  f?"()H9[ѹQ蕐fcu?AGiX,Z)H9JF"+B<ƻkε'7|natu'„h,.)RRlVVd(IE#j`G Z7Ĭ!;;A(7 B, D$ 7n-FrELCJR"wqa=[[_wg[Ee:i:euS|?.tT))Hݍ:0ԩn0x7{{¥=j@\"g,֘h@uv8CJR" XPBE0?ib įbueC[Hdc1 #8!Ĭ(FPΐeDo씀)?Ҕ)Ҧ9o􋁨?}䈜֎R'7K &7q`<eJ.YS!S9~*SNMu<;eu[74n\A"x45o揳(2`2NqqKY%9jBK[6xZG|5X[#h/wk^HGl<<ޓw|c&V}se RF] |b8,Dܵᅣ2~%lԡkjSz{2?+&3 ԒXcPQ]3 ̤1ĀS?w`D7:C]мYIh)Eu^|[R Xb;pL4!Mb7fk5JY;v{a;{'J?"#lƌ䭺Y[c% vUeJcJR"ne4?")ic. ?F%~ν=p@0 ^{@ϴTĈ)ui-x0 1_ &Qd4=,=2էMA3 dV ,gb/Q)'.NOHW.+G-CiāCRԳ$9|a;8ߛ=Ø8g" r3-ba|}s&Z)H)H BB<\ nv/\ rGsMT%ܞ ѺP.1N`jFg4RCAbZ7vÉ[<-0|Cv@Puqԧ>(]q+"᱗IgU$N3IP%rh/ N{c)' oX.ax1;E4P~р'X|ya 4BQO'@9e|sic Ji%԰SSmnBbpm~QpH揃 AH 529o3ыJ ++s? 픡ʇ>1DT{7SQ1qNا 4A37π9](!#)dy'o7 _Mv@:2x5'!i1`C( ) $ycR")W 1X:}PAāpZŶw7f|=:v{pZaYMc8 "IRrE0C c:=&)J|bA{ .XXU l4 &ّXJGaG\~JG+, ?="l2/b߄#wH@} JI HBPo rw4y;l8 ·4`Z᪓p5 K-p`-Ω%)7t, 7$!o֮&T]"ۆ=K8OЌŚXGnt78IH3B 0'E ΐ1%YO8qnl3dalZN- ,KO ،UéI?/3d~u؅L|K1=.?H@9H}$0H;b_XK/ bQ7/rO^oC0݃ۇX2PQ[Q vuGojDJq; utDeMIgDڲ- ,S}r:{>qֈb@$]q]߫vu}m?w?fvmnQTFx2I|IC M@xC֖?  Ͻo M= uOq͒KŒjz :ƹCQ'e52'aWZښiD*/iSq:I+1ZXϔ,\aBSVaԮE)W+`O彧ss{ r޵) DRlop2LF5™).߯fUkSZś!us45 U0rYh6Z7hߥ!hw,3k+E24!1MW9aV0~@@5޷"/tjT6]\*_3< . vpѳ,Gd8a{'7A~"҄ 37C;*?" # ~g4JydE) (D4\kb&]NPZ`iOK@`[³J/7L&-#L;5C#bB~I0 $.0)VSdT?"&aɫpݐ#lP߅h)>fQ*kE;rhT|aړY ጳdm 1@}lkfp!y#)1}azjuxM5jXÇUw({<0Rl=W9CHd;xVON$t.K+\~Y*?"()Hn!*]j?wTbFuGy>mb}9|֚včTmoH{U ,}f2*YaVY̲$mO3:$x "@zڕ*yWO*}k}(Tu7g{VkA!jrc'oqKјnx?Ҕ v7N?809:h{nrV% 0&",Okp ᮗ!!@<9h;}R*تocO } dw8~:J>p?nń،.z RCS&?"$F20̲P#)y ҿ&}t$JDC0nk?7Y)H9F"jaO2qp%x.K#@2!A040н` W@4m'%yt7CPlB3Fb[0 a{ (|OƦd?A@?Ҕ\ O~N?;6=gg J:q\OƷ[uR>LHb?^*&#HvFAʤѱN v؝!;|5g"\]_VO< _URrEߦ2X)H8?Ҕ",1)H6 lI,)j 2;kipΡ* f \ U-]n?56m֙lM:bEy(ebXq$r~χJl\?׎ " XOP \8 ؛99@7dn1ߍ"pvԠvy{_zrRcR5V3`k~k3gF#k:' Njädl<#[$!G43-! @OQM8˘×np&ЍOd SFz窚<%o䪔V%&u , #%>;"{!5(/8Oӟfam1XE)qx.?Ҕ"+L;aC% HNKơ0䔂n~QU#}+Zތ]vYslrZ?z4j-NJkՀ87Ǹ!?"%"(0)JƠ^A+}k)ga?@9tdg9ͤ} L|8t@b^,4hi L&s5b >luԿRvdDd a4[:V>eg֘*(QadwH <1Q7R$w^-Z`)KXXT>'/֌e{,&u t?Լ.nX; XTi#zGcpUQT)LÆJx2٫hXiy :v\as|7.dcld#kslR _scRYZr!8NdT:ڥQl{hKGGofoOJR\@Yg)È!#)s<@Xa@*5MDPy*ހB>2Rfb* ԡ gnwl5]Y+jgc@"=E42)A.dbxтԬj0~:6ډCpa]OI'[ǩgvA3 k+5=;0yBt+hş2e @ϟq`u(40P~[m_;. a-%>NjV7tB,Ĕ$%eh@ ЄNbB'FD$S۞d|84;"'K9Dµ?@AHF0|y/8 ,W-5/#1$~qh0 X1(>6@JIhroJlj6O·m 0u5ʳ D|; @M;Gsnǫsuu(:!Fm0afb1iLId/E@؏# IH%8fJyIY[ #xOC%G*m *{ƥwpO%)\j{f_bjF"1 |i9C1/ӹJ^a*|5҅7P6ŇMFQD#idҰJk4 =!f?FthU;~]\P~a 4~p+s6_!d$cLCTZ( : ?N5$e1{=GSiaP\Z =k2A#Q)G)JDWjC!tJDAcR"F@I+t t| )HPGˍᙽ|Xhcґmą!jkAiQTPw sFhT3xgc\ Rz?$5P`_%¯$QH߿oΒ];`DR@,Ap,>%wÅʓZ@qZn E (-k#*L*$sl?;_ɸ5 M9uН۝. AYUm}P˳ y?< Xq&YRH?Ҕ =b=WFK>vx.t><:ܧR yL񡘭7oGamjbn^uv zo#j߶h3ZSnhaǛIYLI3g_Oۙ1aHRX˳҆'JR"\JDVD"i,bIMf9@)yHݐ[콸`1`>Zi{5Ṭ@S(]!\LRɀa(ے8NH%W12=$ǃKh?,?>"R v@Y0C F@ѥfbx 1-75 :&:I||ɛSJrMUK[qXO<))tdnWa@Ih|{\XB $2㎭V;C89)H'E0|i9e<ɦh4)HK a4꽳1>g)ڬUO8c᣽NTQcSw*z Sb^ʗ)H9JR"&`I&;GXCiQK[Y>Z:}‡@yWj?"()H9JR"?<JDQR Ե*tź5lVnW^U.z_ߥOgZmgC`K}gO;cop4{5Ny@icJJR"T7 @kOGW?GDO7?߬8"txگfR ?Ҕ: C 1m`Tt`M1)fHլyXԾz͙bTrdդ5RA,E;c]C)|?ҔwQ]n93:ޠ 8:f&%JapӠzǑUlI}%6(PfZIXi+>ɡs3猥h(h vcΥ)<9TKt c\sajh`eb{C%/8 g%,75/afniKQ#:eۨ: 5 kj~.h*(LBKI!rbye|J!4*w4{1)a^bRK%n H K?SU6EMyZTA=/*5\Ng"--PT9U4p li=a|lVNMAY'x tM!ri,i,pa5a{$6? #T[h-S㺖8tMP%<4ֶLRjC>3bofNڳ \X3=h:mhb{;`~Y:xQalHFGb{*jaJbrr|c$S=U9Y`\2΃Izh'D6IHB% S+_0`ϱL>@BǛ&%>1QC3ņpѨ=s1S}}mrFMN/>l`X@b2lc*)z|F G,Nhl)ZjHxB1NΠGblvUնnbOsYC%SP@nde+Ww@C%j}pϑ0r}lB1lOuq9W>=#7,qyLpbX?>b:dPCF'Hpikh{7eY-EҜ ks[+X%:[ 0T1=̷zDiD@!c+'(ocѸQ VB~ln %tc1di[k*札-Z&VMV fqKZ ̚&v`\YLB{th;jCR QJPy_R1) 1NXfJC]8&daٮ?i{K,P!̀#)zZ溉-H A}(G~WdoZJ_ %d'uEM- @BIdQi%#V6hp!+mZEa(wGC8알;~*++^)ՂF}@^Pe~zP:sqD)-uBQNfj$!0 1%xzĊG}X4.d Fó\Ԑno("J)vM@!cK]4 XWv WS8Bq<`gv @GۓűY7Jl3qxhA6KC?GcDJF_A5 ge;'}KjI`|KL#u4 >Bhf %Y>/T7Tiokhve ?2iǃ"Hvk2]EzHURyAdJX'V/73R62Mj)9V@QoZF\?ґ҇rDddYڝ2zstP4âaydeڑ _K#a?Ҕ s zj U8X0ػ{PBqRCpU$))HG܋<ߵo@*LI(jP70vNL(!m\?b)PRxb e7s"v\. 9QQrxE[!Wxp0o=i :(v.=>hjߏ+C)HKGgQԞO sva7G艄gN玽jBE4`"_g/7F.jՂCLJDQRrE/+繗Tc +^wC!وG eK bN<{V㛽{IcX>r}Tc;hŲÈ --޳El:HqCNF1.)NʨdPsBl?CrmخN=C)HRϘ';=o lB{N9qetq؁Zm&;e÷4}S#Ui7)abjӨ)ek k[{(N}fFjH^I!JR" u ]%k šFKTT:Z!6>Z"?R:25Rh]la8@CbV)(o#|k緁*ka6=@:&&J3C*JCU/6^/$uO7R?4K)r|Ħ"WbqA)qlۚݟ 䊧cMZ_LZtETb"m'*<5zD3!5=<-?|Qn*#J:\89C\nN"c^APLҒRI G> BrN@PH )H+6?ҔQ.3{Oqt?ҔE _t%JLSw[ˎ_&<ۓt;>{tp`yCCHJ]" )M/](Pq)0߾V͛Z߬!3#)sHJDR hE|:{OHGl6g\Fx-]S>qϡbnwelAE5,N~Cl^GB9V p)O|JDWmF .7X3(`|w00PŭٺA. R"2{j*ʐ?Ҕhl=+\ڠj )ҕ4hCH\`O"1`}""ē[deV cdGnl.FT}l{9a0Zܷ䐞&IPb6)ksyLZ*0R0p|0^ oY:Nhi3+Gp/T!2  |R7_?aC]6(-q A- @}[os6cj졓능w9KgJ[Vjp>8\dxnͮQ+Sss/'b:Fï>|Y)H T57Y9G[[{Pf(@qAXXj 4-O54X CRLBSMjA|cJR"#9F9[uZzuo Rz6< 8p#Uk?' G/.Gjݾ^ eѤg( R ![MgPjv[,1:] [iZBo"؃ 4Jyef?Kd9<@p"h9?z[j䬜?C UY$j|ϻlr|qjC==3FxϒXillӨ44D# K-ӇI1<*GCl4X,#4ȗ!S9# iۋ^s?lw[)H cu,sqϾ0=f[2R`#&1*;Zj8Cz0x%0x iR:L 4 $'7 KS-Ld̢ZvHtޜ*0n|t۲Mo:Va$ }Hq9v[t j(q<| @ܑ47 OŮnqcPTbLrjFoڸB)#vx1vX|Ӻz?;V!#sOp]#AsBKqg)f~d0vd¤tb{ >J.(L͏l}R% mYF6wUL 8#d#8фx5 nrdPJOtGW,ƍX w$+X} 'ncvjOɲ!PͶ;Q#LtCEcxD—K͓19lza[07)hߪOVrXѣ\e$eeFZCL-o˗#Ac ?‡b|(>bR0c}J;r'Tt8c.ڀ*Xc 2CvLt9xŌ1[_XV֢P?Y.*(mgXx`tՌFRw0$e9+c9B8 ?KL`,H+s8>+)xuHB>[ġ rҵX)pEP0ۨ$C gYtk7Pp,:N]eslFF|Pb/#f wMdJ潨QNűPB/ھ4L$!՟rJb57 2‰[aӳY]Ei))hZ0kn@?VVKio2Xab3"B[>{!#)P'X#Tv1fZd_;2F+DYtgp8h?0" HeDb{yI 3G[m//ug6Q)A54!R9aF?E!#s0\M dpzts!2î >b PӨ\88j"UhXFB #m 4ʀfK`PXFZX ,_s3Iƅ( - qD *yHR" O{(8,JXy+93/fKzl}1a"V07bcwmN(,ڐT),tCJzOnփ2Ԝ Z0fO\w>{^!j!ykJN+ 5 &N[IÇ$0K! DX)?b()HXG{j>2sL&Iz,Jz3~,UD{B$n$ g-jckDh$!eȯaCD݅0|u9?=<(1 Z,?rQ9?s)sKo78uĴ3D+{(|Ј6 "nrkmҳV|8;6?Ҕw CQ#c\.rf( mSh}2蝉VuRA :҆9AegQӱ'  ,Y#>D05(;+XK(dLXg8HkXYdJ?Tuؐx4f~ڑncJR"D@zJƶpMҦMm39aUt_g Q0Jr81áe; ={C1u=Q FXH"brfB @g‰e↭._(GYFOJR"nKj(֞+2@;%Qh%$cEPV# 7 yeK#Rh;BH^b7/:d'dTǸ1O GRP;m[oUG%lu!0CA)#Wh]FvOQV!JDC`LIKt3v[nr4M7 [[a};YH)Hyex9TJ 4%I-}0oF%Iwۊ!µBPKGCtvG ҉@_[~1l~;+6ԆJR"R@QCSqq[PsEeD[`BHhSp.>N޸VJDLƮ9u!)3ᚣ'hCcJR" 0[8 δ=+f/BnRbX @ф`^  &$"-P$A݈ `h @j ^Jlcm ̮:؏JX 82h?ґDikdJR"R[k1)|sz?c(fo`aa)wJӸVݸs ԫ1! -YVS}ۙA "ojU[$HXeY9^Pwƌq?Ҕ"#R)YcN!#)UҺYQi(ZNbvHtspQuu?^ChP|룡 2lp]j:a p220󇳈e0_inngHk|g;OݯZFHeG_ep.Edd0J3nl ``Ъ? -:ŭ^, A>&r$Sd`8Ul ,4p&Te(u5XP-nlA}RȢ$ݙODR%|ӻ "r |33zHL\Vep=TÛxf2@4ױV"RG܄d)t&wz")/qaꑹ0v߸kϳ8(!@f,Sl.LNR̜0gO4oS1cs@9۩xAce&*D\px`BKR1Pb@tPi'nj!Y/d])1JF"4Rtb=V@F]f4AlGom(7sĤ8UNJDAP gĢy@h?:f@s"I_axmƅs{gUh.1kVM"Aلeȓ%`DZ2@Σ2I&qWyb= (%@-B+զ'HJ УB<)kh9 uAjKb@ay3<68{ƈŹKK/ao̍H$ Z2dڐ@{ţ-}Ov*G!,#;8r H3NvZX7 h F@þ%iVFX_IJ9c>] >&x}1b'FػmS.9w26DeT:?"&?")Y-SN'H~RFs{>j1Td~iD27 ɀ!bJza)kZ [ڏ;1(EV >Ņ-*"̍ETBҺi 8?Ҕ JIق?Ҕ}Q&թ塏)H+K@@v;*+hCJR" 'fd,$3KtWM guӳ,ݔIf:Zq @Kٌ(I bS%+řG|>]F0]Q+XTj7u0bˌp@P45<҄:(GWI~īG-v߲Dž<a@nDD T m~gWc\)Zo֡،gGE0ORSABOgUї!-gPy )?f7<|U׸JR"頡)G)JDCѼ]B ~eA& ƌtM(`)xBhoMV ^ tnf1Ό>QAF Aۅ\-]O62@Y/շux4jYX@FEVr/`0vI#G7LzVu0CT O?02Qs̅[RACj}=jU4lОT>J^x?Ҕ?!JDA-jhsy7rKYXzδb=%>7Ӈ0^!%r죳鷪 k t!gU!@?"+Qx^@a.cJR"M)H*p@9$ Q瓬 kfB&'!6R0tl'hX:;g29 `0 50Oi3Lu[U4 a D*Pc !}!/?Ҕ@l1#֦1ݗXoGDD!g#)N hXiP\p 'A51#O EL) ]쀫I]R~ dM$&s"Zr Jv5|;»8n@HH neg|cJR"n`@ cuݲ?nuzYkwޮY&kYherVNsGO 1SA2,4%(ǾqÀ8qsa$Y+/.ҐGn5 a;s!Q؃jn?Nם( .Rk"ۼg9NDlg<|JDQ:;``Q`7929(y 2UN|f47 IpU?ͬ0$gC8n0#4Pv8\:PKgR&`4:#g9>]ZVU]e~OmW֬S-<-e'374D[|#XT!q4t<"mb^w;X᳞Cۚӈ*6<+ȇU=]):S-]d@G.p5#|;>f[Av^`"2PB y:=> BVB g:/CF Q |}{Xc7vvN%'|ݓV)n #ݡ Kc̊ vAl}8)RKTe] N$bEaA)8 wBlrV%'4fvwgAh0ƹ4brŨ'g@HZf{69fF0jE>"l7Sj?"'.E QV\k}.^vG?a}'+!)[G9vv ‘`Zp;l`d0oǥA- NY+2N֥$F8ml7(Xތ&cNL&ɩCV{s0 |E LO/$l0 efE쏛MI)HXJC*{/QqzD{2 bQ5B*iYE|47P@E˟\<\ zeME%<}PuTb̶XkIH#U;Xuk(N|tE)|e(L`a9$bXz80fG;oOv(!+w:«F~o`7hP}&@`]Mg d.Ii͎цYt}aElHT>vBY!#0 کԐ`T0%|Z6.ü>'1@!̀#)Vnl44|Q+:pj?"' .'C`ЛiFY0CJ0|RtvI Ѓs_)CXy^a3Ӹ1q $';sv:ed b8@9g)=SfߵR+0J{Hv:sĞ2X;*F4l]pHDR9i3/t ZKB%IOUͳ f ޴CR[6~1;+۫?]WRwBwFfYxn:Xw2-OdSyiH8EU5R9S*eSGt7lj -pwo@ty:Ad17~yQq05R">Y+;6^ .6 8 vњ8P#V?w{&zQ#8?Ҕp®ULYB]R+G@IԽ9uݘ8EKBQL'GK@:!DICFb'hǠz:mG<rb `ZFkԁ@ ɀT4K'-^n  (BҴH0K>rsb@E__?Nң0HFJh?-uK{ !}f<Lj:n% CԂZ~C.FN}9/;JDLh lcz1`2,Ub5lD17ޢfJDQR@?Ҕ: Tph?G&%-NyTI?" Uc:o@QpFc8\{@;aGDm7ѐ>?HUxA is"0'Qa#w@t_6}gX\%ƱV/W#>&"fLPO3z"U֭ a|y-aV#Sczn(K T((k5kP:'қ tVi?IߝDDӦ4#b,*utoEVnb :H a # Ubӵ,^P\`a,f%X0?Ҕ8pKUm'wc ]"HJ3cD$i;UDf]+f=h`[UnBA"P|DA|b?ۥ#3Y)G)JDLP.qp΅YvhP)lBI "r )=:FGD(=md[]W(`*D Z,d [*>aG)JDQR1fYD }ն-t#br 1)8wx0?Ҕ 8K(gA)dC8=_JR")2 y5@JR"!0ɓ)G)JD[]zT73{bمkqh 5nClF 9?Ҕ Cw LݟenFT̺jXL @b9iR1RDD<EO?ҔrD3&M A) ae'(PWXJ԰$-D{U!HB$"hqE+X֮l~]zyylC,$$tƑ=pLJDANXJDLJDS >?۟4 @fGOXO~Nrٳ ~JR"0]_T  `ixu$q?Ҕ?Ҕ"(#9JR"RcLDXttVqҮy2GOsw ytb"aaa'gt!3#)Y- I jx?ҔGDrgvsS^segumW<МnI4ЀOP.FIG޵EOGW]4}1KQ;dGCl36z@š; ގ)oʤO]]l:=;lFY :-n--WZ`;l2 3Sd6?QR9Ib.Aͬ=?5w:{:ͣSiEZDJ ?TjjAe'Ol8 E%-&TYD ܑr1 'ns;+HOR igE~`Ϸ1ʂt=<JDJRV8r0K?"();Rm١)4EC[GQݷ[P^yTgͣ׫ʛjXENA@_J./ht{٢LOLAEw;cc'][%~ 0q82?7 Cr㱟z3c!+ql.ah!܂YW޸ C`†,6V'jt YECڪAhb0%, 9L&FtblFCA6*| ;n:5@B)(tnۆhC;]%]C.PӲGvr|w:uĄQa1)LdR\_ H~Q#a񧦞`d]v0C4]m}It0dd~?B(&h eb\) pLюfZm`;*jgP8Бo^@ZD J'_s1,aEcsNpQ΃(ZWxhPzAHz]4 #[Yi(a̵i߆`&naǎgg? c#NEaHп}j6a2y"&|^ y88G >% Qh%! 9>M{( K^(=c BuSk2! a=;F H` hJa% KJ A=82Uj?BA4VڳQ$t1m~ۚ^fNs;:|W_>ăMql{c?MZ޼0D \2CI i}8hÏöi)H`K:LR@35- @!䑖GF}tXq5h!Ȁsb5-cOk + y/@FaIDHflJDV6I!-næd2IE)G)JDShxD.vT.a1)?Ҕ" PJDLa`66VQGbHO, Amw *%LZG@{n rڏަ- fN}s:?éc)؈Pjs.}Gj>Y36mϐa/]R R)H`p/Jzr*ab2!#)(?Ҕ?ҔeRfNRGV}]RczCNjf ))I[A_?ڬ@ͭwҜJDJ?;`AM _8W GE%%I(۶>/մιh0?Ҕn?",+ngC$I`JDQRJI(ߠCHFh1͝" C6tv_ fps vaهg6r"gY{3(ty)JW*`ݽ?0ǭN{shzwz?̉g]T2} BrPC6->ݨݪhcJR"R4?SmYHY#WZp)&?XM%L-:B Bfo~|! #m_s"%$c5"`ш~f1|8}]h_ p|W 8Pt6]2Gs+T>CJR"14%Fy'uF0F)^ -R"?m0 .Ȭڣ(Fg](l6 M$ĠYIAwU½k)yuVaTB/8هKB0|$   G2"ճAf|G6aы)H)='*V#SvuG r3%ؤӛ@`Qr\Bxt[$Jr ğVؔ(00H`rBpwR>qZՖI5 aA,|ǣd s $,jΟf@v)Hf94A+ O6ihH ] .9SQ#d*x BRMÐ5NtPvε=g_`vfp0,8˱9)N,1R0}OPRz G6LseZ"-*v}]*hh;9pTˡV/ z!#)cI(sC[[`K@8fRY<}Y&.@]R4˴Mg$ D 0ūVTϿeO֩jP4XlyViL|DZ2r?;ômZhYA{r&іReOgbFQ]$~75<{G[]cp/0u(:k0 Z @v9vgSE ?9XyE !ےQu# R)去E lS,k[y^9Y'lo>M-%َfR‘)HECSi4]Z DEa^y'ob~))(EtVCPO'\`|:ΕXR_)2] nԐI adLFej0걚Vf|aPr?j;VaU*h˥L7P7;@8\WM_J8shyTxY‹>Ԗ)B_NG5^GK0GC u6>#0?1ͰV)TBA5 JJnh7k ;Sec>Ui&YK2m摩Gwը?Ҕ>x`NC&  (Hn80 #o`0٠:SH펚<JDQRnh" um`U1*Td9 mY)c샤>GR(lMH ICz:;c-:C:SzyF?b)PLa,M|P8XfJRzQ:j=:,=2bR| 9 #RvAR8j1EJ2F,ErH Qݹ%XMb4 \B`yЙMMo>zW]edc/}w;ID?b&?չ/Wz)<PKGCBsw:!W ߗІr7ށ.lR6Vs:aHUiT"@IAD@JR"aA&#_B3=[lX}tdEf&6OdCzBlpX)txa0?B0|UA [t0eOGߩFq-?w,E09EMXG)kT [i2hY԰g!6OëúK+QUap $o&%a.0=CJR"R~OOF.?"T3 d *)HCQkDV- 'P,ʐԴ2Ɵ u=mauZrFN9+P;:`A)LKf=dΥfJ2K)H=JxjI\4ct'&qNܾ8¿p{'Z(`uT:Qs)BF8@|Fb t,۸E$nݓy6mO<DD`hLh}€JDD;A6m+{:>k֑&[,ܚ#CJ:5.rHIh~׉xY*!#Vq\OWܻ pn=0Ws{ zNR@Cna%ю921a=NT0%xF`pGF1'CI}\a/6 Z_︩ X BS)<'<<A}lvP1\@᭙n ۸ sz ʞkw&|x|".luPx:eH43涀S )F jܒV~GDG@IhOL?"#l :RMn~t +I'[&SxVwKK^Ϊ 7 |$^(fl`@p JK9#"60ԋ0뒌Ih`IwYK$!)YeNpBlx\d>фYg0c*f,u&CP7;C1"jx44%quO{OWN8c>St07'$}qvY,x($iň(,g K`v_ g%8zym*T1 R"f162!"$X9a3u9$|~^kzb`.>O;%YC]f˛I-Fה6u `P9 $.P?$pS2Ft6Af9*2}OCNDLFΛ G2Ύ=^(]@\u*ЈC޵5*%$#Od 탵4f Axdo^>.jCC]Vr`fuE ~Cu 흜Vg' Nygl}H, 2y9T|Vm 1(]eM @I~!99lN#$h_Pl = O[}*N@23̳.mc(DQ‘-8 it !d@t mr!̀#)0lࡂkW43w.qNLigA5NݸVN>kc2ϋe?9K1 u blg;cy 0ZdKFII%!X%1xd-kakR#*Y~2)HF +)+` , \r?8ΰ'>Xn~OGxy>0C2ACmZ{{=KQ[Ty\m߄ o7i 7)kQ> ,a?ψ˷؎ d n=FeƏHwgdq@zm1D{I/?ˡbfx?B.Dя)HPv5@1p˦P`́ H/8[S8~ÄֳHf{ 쐎!#-~khY^ā5sI[e+-G'cĵf#DRDK h03pR;Y5dӔ7`: Ėߌ߶_P>:bLA5;wROWc?hf,(SE+BPs'@R3ldz` h{̜@:O̱[ FYDVjh߀vydXM7F H"_(h&~W-n >~C<(t]؄*iP*u`vnAgIWtDAUͦ]U1 aP >#`XH {hGLXC1pxW|LDxZi&Q3CT,Oc$gN[CJ BP'>.<0=[`:Ng-wGbӃ3bF{xU-̑WkR>aPV砸9  ?Η}i6L+ cý0(I 2Ѩ|v Z"\e(F3o ٭`U@:%'%8\@<5wJR"DDz#ʿ|ڜ@h ;XP3dܝw{=PDD#ܳS@YcD?" Aa4ln !s3#)1!z!^ !:so m}2T:I^k:udi\td`i!P.?'}FE0^1#dff"Rc4V%7u))pRu豗R|LAO>en`%nJDA& JD\e2 `?n/ȿZޏ~"mNA'JDK6%ciPQJDAmR0ORT@J\h4ڑqa'I,gFd񽕝As0S8.`{RShjD؃Ryf[Q ޔ@(?Ҕ"hzB!@~fpJJR"*"flF8>?" q~rZ\<$djRjWswJR" ‘ A}^)H:lp$Jx?Ҕ"#vThwӳ?=ZR"R 7"6X5%==(I+vFzRvZ]{_@Pg (^SM HRr<  @nQe1e}@TW5z`\]x6#)HPDF4[/%gVEoPn'(#se:I._?G>(yͧ?"$H #)H ۠ϻWicJR"nl@!?Ƒm/Q-d?0>fQ0BtM !1dфO>?"&?" 7>1)*GgLJ:SP:te(zi*UVuf.?0?ҔPI;פm: chH0x}NѴ`vMG}oV=2 bPT:!B0+uUg]q0p]Fq)D' -"9dv5CfPi,g%}gn t8^˦¨w|5g3Tսkgh32J;A2|Qў] =A)عyU-gMQ_aB))$orqsJNnRJӜgt 8c?Z ZObbnˡ?jRCh $u%"GB7 噪kurãڋΌ72A| ONt'/7; :wK\p;rs lbS/[kt1*i< '%fk LuD+rYZD$|ɍ LL8V;չ y B@*&%#bf0<$adZ[\7A,")tY3Pt;Rda>,~&[fvZ 8Sďix{k!@QH^ܔZQC0IegfC~9r64(@y4&%'R ~ҏ5Z >SjQ0cF9jhaDʱn=o+ f{dt^/鸂l98Å`H59F3uw:jzyq_!Y #=gw058XOC>9'NPO;幝#0t’xD5(xҞ7%!X`.:ț:..#t5 D uۧXF :kKF l/mڗV냏ȰaE(2mMbP80Ym$fZ .%ϓm a OA0 EtP݂Gc4.a sY~TQ/ 8Ng÷8MPuiLh_pĀ5CҌD :t]k,U|^:j~YR^Laў(8:RP?Ҕ`:dHuCTc$ܟiDlhM (~hW#f ! XT`Kf;{@B_N mk/U*KXGA'D &"?"% J\8cC,R u1),X9*`-EyYL:fH"R`l?" v7I:`mljkD*(/0tl3(|n30(R4 ZHiMυӴaaJR"&@# uaJ_/h ʜ3yDDښ! FU O+ KZΙzQP!(RDcJR"RZ8. IsG "#aqHZ1)L<,$WJq*" s &ґ EVG%4jǠ`H.&Eo`DR! 嗇M@ 0J Yvd#nJDJk&F i.竰E$)I_{\Mƾfc@f 2 a`f?)H JDA$iv٤?""Rw1?" L&J,A>[c鱴)yE0n }Έ@P 0LK -Kg:o,mLb2vz{q^ ltm)i5sE0,-X8jQM!% oz;'um!G&/p$51xMa89`2m`$pDna>Ns䚿WJכˬn 58X/ʜi )Թ0?")k1%1_uj;MX& LE?jM#Q; OP @BMNOFKf@`*L@nv-9ۮǝ6LZ6/G0E-]tαZ2CSK3QN}1@bb*j߻VO~{ @X%8\ZT}>4xB+c-, @HN(pUĢa/9pl8nLNIcRCV@=Lrvˆ!~րi!)QʭMGD)f s0I^s8(8 €fA1 $F :!JĤjOK$fe&NrǺf1>dht⩻5v?"()HcJR"R4iC69ډ im}ej{$  2zzRг$61Rui?kwSM<tm~}}GQOڷPtp8jq !iyC?482{c Ms]8.i($#l!z? Pkjz*zE):ț5_ VpLa@aa| {o9)αl >̤"TRyenrsOgͻd,RV(4bF<~X\* ;71dm  h#I HDY;M׽f)d?noGzU3oX ʮok$ʔ[Q@àG 6Uucؠ^R&H ihXR1E3YGK}iM#vDq̔J94jDV]~\ڠb٦y'CF>cJR" bu侹Va 7MV4CtMBK̂\~#@ܟ2o 2&^fLɤAXP b` JJ+kLdq< l#Hj#R!R [:Ke~9ce;p^nKʝuɀ0 _߾UDP g@g3&TGB@qƠ}- @Hh\[Y.@*TB?R-Mtp>&GK0Fc)kx?xDRlV٦9:igv6.2@Mgp}%?%O2@o'S<)g ?"cJR"CJR"R?""$҆H]Mdj?") Rnp"GG;.զ Lt;RTg5l16$$JrnJӷEh҉_d8}nƷ,nWW#`T?陫+\\8Scȑnv`vˊpR8`,`hNCc;|E¤b\?B6Rn2MTj}?ҔX&?R3NTi LϞ`w)H3q!v2>?^F&A-|p[`&XL(K,4XoZ[3SX@hn[/ N?kjh @@PC,DI+A !)uєa2a3t@@@8w& Ai+8iWj8*a+#7@* @?1O8^aS*E‡GQ=쵩b!JUYRuGDb,z3!g#)e7'YXq/oUb.k=?2 $x7*ytv"I/!eq+ 444 U2` '>r0=,b= g?"`a5%%{dIE't'st@PakoGR;@5 ,40$w\: @:vR7Ý+M1㌹U'j%] B DsoX=vO]}PHKǖhF#$LbM;2m.ߓك a9S[PĤT$ޅ?@n.k#+ HaFnK^KJ+v9;(Q ţzl>ncT5a[܃@+ 7`Ѓ^$DWkَ֔ٷaô 2u 4 @clo J-hH[^&7ta[RVNx0&p[>Iؗ(9hf>y@X0堠,I~gP8->ֳI,4-rd!֧qG6Ć>;hVH$| $ ;쵞[bRId2{$M0l  N$sÌY?jqOPA}A|g/;<"9)HqC{ReN3٬Ϥ5mDL:B ſzrĄs|rpJx2 s:mL폩mSR<`d5{2鱻{PJg"aVdA Y#mٔ%1>}ִ2[8F쏶ZXd jxE4wY4hTBn2 mn2]i8Up덂^.#68s)wGdb[qө"Jה(幯U܁##ڭbIAoΠc`ZfHOCud>0*Q$і -쓱phI4 `NGMUD@ ?o>cNvX=kt*LUB%Xz#w 5iLr>T34 'bKWd,ޏ)H,D@G P ,m5\ XAp@]̦? t{UJFc)!=a}?f.p<Ө]`#  @އ ۻp#H{';uCl٫T 0@v|ΖsH m>LPcȁOF27/]Ϧ>-*iVgVΘ'DB\JDQRi 8$BrRr#wu"&?@n M߿m33u*ґ(ٔ6x-fc}XڜP_M! GM[0r"F?"()3gsNEJIg@c *x&~ L JDWCW0p@Uc61}/׶gRj˄vhJp;W}6ܽCLWSO6R%LN4JDQR!D `U\F?ҳx:JDN5ow8}:?#& 7`"8-@!̀#)zx`1Ԍҷa*"=@88>ZxN J%m] @δao37Wu LJR"ub4[d(sc QE>U'qhDM0&- JDG s60 b5bc]`P \, Ghrd򗻡_v^In 7Gz{Bfϫm?.y`9 [\X+UF|KbtM(0¹HHG2#* CTYXveO~)Sp7K0i{:0NO5,cL{R(\FMYz]&ZڄkR|]ú!mX~0 Bۍjϗ=k‰yژ/AU aҭ(p#r#CԺp(xH nH,5Kcf9!Dwm<$o^$fyqe)3:,1RiNJCIfZL +!LGu04D U]#) <>%޹F=BuF>`Od2nǬr6=Y9?y9lѱ9_,4^wHvs-1ia>jxch HJhXI/ ;8 llu #aǤ_dJʎif̺Զ(_VX?"))ژ%:9Om)X]v;O!)HOQOck+/hP<7-E5}P *qk .`H Rm=kZv)Q۩٧y6 e[ƙ,}^xb%}UB`q 1҅C6Ba+Qcx0=]Ұ)N۽q# *̩{ֺ~Cl\F LLJDRcx)@nE4 jt 6S+g\>R5r|~ aV|斋a_,T7gCf_ _H[R _ŋG0ڐ@A<そbO,xtnBh@щH/DW?~<|0-(0E@1B A # bYC]Ʃn RaHc[?~,40?R"ZR"DJR"PGǭ񂗖,*}AIt@&1@dz:_"4R ѪoA~11 UK^"iJDL|]MmUsDQ NJ{ɣjR+HGX 0GIT# *@xE G4[g킴[2{^z@?Ҕ yU|3Ib[|&?")GD(4H"lC:Z&r`Qcx:JD@! Tt9?E )$%Bq)H!3#))Hc sd3aPynh3#HAA Bgٌ>"hZV6l- $JD@MG z0@?ҔS/Ն26Khl+Ƹ^`P`WDdJJrFթcJR" ݾh<»ei܆ȃ#Rz4X|^ r~VSSDH9 $ ݘLNq),!u)?Ҕ£³TvD܁ lG-$iL.*kR)H+qİuK`6JυJR"m='PaA3_8#WPϽRl(}DFH9ouݽ ˔ sj~eڟ;حAw$ ѳ #yP| @˱p>uk 4iXt*iCGDbhML5wZdPMtD7opec{PdXm,'w0HSBAv4=P7ob1;qF+(~yMs۩Wnqڿht֠xŗzX @\ \z-JDH?""cn< Q𷒏I3&bP̪% IH-3ua2>Ex>gZӲ3'벂4g:ĽN2w&nݬ1Oc#_\=Nٟc?0`0P>uIꚔK c$c6<-s{P@_J JR"39SRP:!`Jl`yew0 vg64%0`K'Qγ320gV$2X[a>efײJdXBF;Xxk&3, 'T<}`R8v3f'WN.{d7n3gH&laƙql<à ۬Ɗ`ܛt*=Q>~}["Ϋ(]rMX]4ˍ"VqAc?8SDKįҤ%J"1{Z?z;0x(*.s^QIp&qa`R)kjf$у9t +^GS Om=0L@vQg28ߟ_3v`>i+'ܐ8@ `ܒgB?|Hx-iObA!nWqnW$GܜNT.& ɉ GbBs %` &N]$<lʛ_bR7ث3cDSU}g. F Z=0%l1%f$2Əwc@m%w9FI;89J :`E}0,hOR@"O=.%χ:̺Q+չ/C'XZR Pp7x0lC ?" )3J0)1W9Sg^YSv̤n⼏lj0,4FT@ylMu2I}<.u!JD@JR"3 bNc#*W.>t3 uukPZJDJ ~N!P%2")H9JR"хBld}5د `{%j8pJ'HzO!)" `pSfmM/lUJD̤vZIYv˶,A;_]ۘ&/!X hu0V?" ?@_ 0e!rh -ց"\#ep@Z)HD91(HcN]sRsSf`ɘR)Hr 4x3z!#)ΫejW l8:GD;-Ž9u(@B?"()H`+Y5*8I?Ҕ?ҔJDAV);`="QRrD\6Z۵a}\0U2"W1)G)JDQRcke[5i)H9JR"V"Rq)M$)H Ck;RQqP*fwJDBu H粩%W:{Oo\xa SYVX\?" JR"R"++牃{6KIl s$Caf,f #+X0PU:ǩs^HImjgei=-x~n2 a]Tupwi(5SHcH8#)H- T @J-(Y!/@f& w' ' @JzRd"Hb.^ P+8Bl)=N9K9 e\p7E@&ӛm>F P)Go1~5/ |~V8;qF $ l6+x^i퓾&- %S1›=#SGEu\8}F1'" Zy>[Q*)Ժgyϥ>`: ABαy*z6m.VT er#] QZJyL 外\'LI&& Ϥ? +s,i4>u|CU+j:ZV4s;) 58t+:BR}c@R ZY{zaǛc07[s؀Bp2zk+75 * +a#I8TKiY^= @暰pqjEu0@MY˦ S/;{aAi6UT"@iw*CN!m#SG[ V9TH:2+ F8> 5&C3?Vv9أwm݊X>^2nHLX!#ۅI_lԕ$ng: YIC:ܞ¬|=|8uĠ>~O{ad6Nf1f\$nI(8nNKnT%0!e<7Ԝ9׉+rQܴh*fҸƘ(y{Ğ 4Z+`d3?3s.nlAēc۽Lhtb޷DEґ֦z(r2^5'uL*T?A:)jKIa7jq xG?w' 8 Ŗ~N9dљ/gb% _-lJlOQ &$fn##N{H: bPo IDbǧ(Y'AVbmvw r}E=,4Ʌ K,xTL8 vc'8']A2 >=( x03dK?$:@̔ E@ 5u?<~4=c=4XT0 ۩~+bR7 G03QA\  KrŌىLfFVl?r:'KiAQUG\(u>}4,9wppDX@w'׈Lj?4ZZD@>R eS_aaz,g8#rx!?zJ߉€$>G 0ћ~ wݸ(u'WC}kOa:]F1̴1/U <KxD2JSSuϫn֪?D uԼ>!#)e9&EWnr}"O͊6fuS@=]XTFA.#+=T.xv@.[ 75jk YclMGE)FEzDRP͈܍bϽh9"x0 bY-YT(X 5 ,BkOݓ=qHݺםjqO 6~ Z@\l̃X+d0s:X,K!)Vv R"cH"J +wGRQQ%|gPtFu5 Zĥ#Ih5RbIDKB0O5G*/ZkI(,|rV`dWAmw0p}<ݽ$LY~31) a44 1%qgOMGMgߍZ۽FqcQiWq*o&`Chk`ooGޱCԼV@˜ ?s,/0Mғ0 Zj&ʤDĘ^xVTJD@!?"&RrD >q:`ߵO1%:}peRn" Ů8 e&(giDW2dm^Ui)HNLߚ,z113[R,L+bd_!)H9JR"dD +|+- d`3!GDDN +, P]ˌ#@ILp@?ҔE0yJR"uhhd?nxݛ‡A1L7,JDQR0Y]8UVqCJR"ZqeRH.9%_r#qWE ~~l?Ҕa?Ҕ4~0YaP;p{Hw `$9"`ĥ@ob-+$:Pe䤤JOݒ3cXuc 1Dg@ceW Ʉ?" c(a0R0̏)H1Wheb0 # `b$BakJDSR# E?Ҕ@cUGD//^KҏVl &)RKD^-Ht;30 Fyݻ+$K(WB +Y9JR"ȘhS$ OBvC~duEnQ9|~@U!`~QxĤ4y๢.}6'=` IJQ%]T>An_tG`:)hz0\I-*[Q1ҐSRW(.B_hV)$?4у{D"ZH"RҊl*꬗( IO2O:P\bW(j?gqɬN ҥGDCJR"aMJNG`RFfK~tMj6*BOV>hU >|dvo# %a8]- YΑ\AÌ|QN"@S$1vd Y2XRrZVP6_}=c$jRdo[ӳ̴x gp.~f:ųXdsc&ЎL%IP*~?1:JDCvٱ/>k?:qE#Qo3QFT;R)V{65<Ir@%-mVm2݀@g,w=Q8xX#';$jS1J [=|@ni5"PM,3B~k@ lOY@ep<JHQ`pcg/'EԐIġIa*Ґ1zxNq> !g#)<}JR"ç6 z?B0_Wxp/iEF%P'e1`"v^ţ'vY s٬:klh@#%#6ElI:HS 0N$%p<uߩHlK.bCcP[b3fsbo!I۷ ՙ RVs' jV8FWGD!)LMGFYEC CC!=''܇E)LJR"JJI,`ĬԧkeD4RFxA|1 %7vQ30 e5:αQi/! wHK!14 ͕q[wٓe0 C VR3OTCIX!bB%xh@`a#6b62g=h>> JR"!)<5=4!p|ؗ͐GxDF?")Ss!DQRrge,DJDBvQQ}Ҝ(kU]MCA4],F\jUƽZq5-0셼P?Ҕ"$?" zÖ.S #\#8?Ҕ7 ?gBI{m@(n+Z36:4jdʶ6d by DR!(MC&v+'`7f'Xô%*d3?a/ُ_i,|y78\hDkvmp'Nnh!?‘hl¶#xW#0hC߆:#9JR"so.._ZGEí¤?"#оD,"[(R1v$"Af?9IfJ\;j[vf|ZZ$30/ n.8`F0i]"0 Ou{*h _vvN8pi쎻BDP͗K(N5avP r|4Lm~'06"+[!.bZOJX-]lX:EC'!̀#) c8]/W;ڸ"RIsTUXznIUGDP% _Z2.Oc#]:zȤ'B ,NΒA_4w;%Q5%*Jz_7Σ씹($t2N4~Q)|sdQX zSRR@8Ð0TrjPLB;g㛺'E䀓 d#,-X!1-nc-kaH;-dG\oM{u۔lPzl1o4UF6sb\2 ZZݏݫ)H9JR"FI AaB?ף$oNE)G)JDAd;$[6jRZG@?ҔC RR1,r.wH4$cs&LIHՉjP*A|$&:y R j7X W@`rAD?" Nbۄzm=,?-"TiХ" 3wɤ*AXY{ &2F/3;Ef  c,ÇdK}I/G-IlwaiN=igeR=n 5oL&?"(aHB7 /m,5HO( (ҕex5ݭlq]ƩV[[e (7*A :e5 EwC KZSؑ@FȁuHѿP9WGb=*Ht@ܯ~%f HY' e{jU)1JR"<8-iJ8Ie p0/GU,P`.䁆 7m!v Ҡ|!s3#)1#w#[#g7jy!-cP ŝl"[8Y gtv% !gCb^I7%8! ۭw3IG"Ձ jeNv*TEiA( #lG$b1:>AD.mG "+MɄ)h.K{nYE$l6Vnrc&  CY#RC7kwtDLPsna+_na6#4Abn|wF@ ?\4pdT~bRCz 7NaK:nw;xeǐXmZRT &t?")I";.*cJC7Fiipǚ01гih҄4Taw 1-aj?GC~>{n—:+ 9r×HpiΎJR" RdW3LJDQRh`\X]Ft= Y%d0#'S2~Dz:Q0jc?9[d> ( MԲmޓa)8xj= 2GK2.u3kŭ)+u[[L&3s7oIķW%-}ُ֑~xT~RjF~I/ Olfbz:R8?Ҕ"R8Yyh936 v)LYHJJ͒`3C3 "HqN<鵌t`WY?"$lՙ8b7ʰy`mJP %Av3W%񣣇Z_K{SFd- #c+$3R0Θev'>^%;3eA,$̺H"MR",*ZRq)LUH Y/Yv2S@ʼn*rycBrQ>!)H9JR"pp``i̚Z1PFN,mզS@B a=3-2 lA >A~?"+${?y>)H$>X2X)0Ud,Q "n;<p#&ՠ)KsOwՄDEjٳC8&2}Rfvώ㥤E)tg]pls?}~-Ԡf8UG xF%hCaJXh3vbEDsc[9Fb\S-x)K6+d:~AVm}])G9F>l/@Ε9WA KqP<8e !#)",JKP$b2vkt04H[d1ەzvbM!ܲ$ 3u GI-Ӆ͎> x\G \5 I:\mqY y?<*XK5qjӤn?Ҕ !ݿ6YnY <L6[c͊Vh̄Ȑ-MFzv 4vI u?9@fC͍Zm:y!.(h%gz͋J4>-r0?Ҕ<mV: |GQ߳%vY߿F?$$;%\9_+Lg,Id RrE)G)JDA.:7War[̙4Bߎ01-4Pyr0D" قLC9\w[fQv 2KV R"w2+PZF#lCnE U]YeJ#QXe}!Ɓl1o" 8?" FL@7HN7(?Ҕ0СD106)H7'-&2y\N[V8?ҔHv@vЦl5w"*1))L)Hl=)cJR"e\D_?Ҕ6R"BRwP,}WZ tlPܔ{/s:RfӮ(˜6@R ¿ܟa:Ir}5 TL])H%v͜}RmTgHdѻ< ?"!-8`76$<ɩ?"()Hl#V4Sp)ԅ" TR# GL)H.:x/H @tB,dҹ]% 1$nUh*(Y<:љq"w" V?eV)zctp l_wώ8udQ]JDS#%, k%$OPAJR qJDWPX?ҔvCvNBw_H&̤瑦zj`m]ȫE)G)JD@- 1)e)H9JR"R"(#HXɇ˂-`5 j;=0[)H`xl"R鯠1=O &#־.CJR" 0m؀_'^\_>K3J{="?HJ{6u:tH<̍ʰ?)=%drJK @Ϟz⬅Ģ[U}TLiu1;ÎcΩ,l-#a[I:FH9S4I4{sBߐq+`́OD! F[ξK?OWg4,Xbx_GBū8Ma -6$' x nvC+!!Аryq9(N,҅:Hٖ4.bƒB̴"۪0&CϤ?6Wavfd" nӡ[xl@Ğ^e)JF);>sa38!a}xM_ tp//5wQO֬(S҇%5<[~h@r0n(2@L?78=$-H#8H2 `AE%p1N@q144Y7] 8HŰ0q{&5d 1E|Prb@OSwyߥ/@B *s$ca OF;M-K2z@!h5ÿ[̶A,B`%+:?N;(VƑe?YСU!g#)j (i 3b߿ZCBNld?&BaI-#a i8#_IἚ;(<T&ca!/aX)Gك%붰`jtJDD`RbUbB-XHCCpZ#Vs({?ҔL#Kp-w8>"s̒#f/~urFmWG)JDQR)H9JR"R" JR"d?)H9JR"vrt VP]Q:[ JDFC?Ҕo)73uh*bc(sawg;@PP1#p}K((b҈bbq7vl oz g!E WE]BN0h0'?jd4LGFw JR"70GsG ~|ФD%@X`UZj ( l:?ҔdaG9|Эh:!?Ҕ@\ .yB\UɫJDLJDLJDE1ZDMN{4H7d?1)RDE)) JDN`YTtZ,BK+~c T?" nHak!R)HcJR"g'2{B-BCCL#/QOD(!:>NWJ\h`iK 4+2RgnjPQe6Y;@%lpMBI;y#uk;wBFCBM` W[^űa(\3:F 2,b8>DD/ƙJml)J_/m *V8G*g$ÜG sH ݢ|Hk=[[wl/nPi9AK=WHFlԶ'EIUd8i\j9k nBg ߩ¾'v2va Mq)H%nEL&?Ҕ#0[R.?j))墌Z"['0"XY $$Ee4BINդlՑ1/ḨÇ@;3ǑK oOb@CJR" s[EzPRyA N H0ބ,aB8fp g)HQjbNrSӿi-6&3<0bC]Y3v5VGO~R(%%G67qOacm,p\K&R+~=Dk% fp,a{I0Xf;KVO/k:&X-Zġ;$Yý0,G'GN:K@12O#Pg*)HcJR"Qr5kΊ$ $`Nۇ0C&aʉeېH 5 }WÍ#Nu݇-8`zTZ`8nfE=wWXu< /H !d( p}fh nMAe$r΢Ճj>RLc!n)H.uAb 4>,4Jg"g ' 3Jwy~]-c TvvNv{q tB[e#XշPtL&CQpNF[_eITk%h!kHIca mL4dSP$$PXZ4jVKdH<yF.\> сB HН003!H gBLDa+%(!+6~-]ƌ@ q<0V*) Y:e*=a 76T|JDR|#.(MO"eetb$*auZ {I)vTfu?a@PmA .u!̀#)V' m(~}8c;B"IHFJR" &gӆeec'_TJr=vp }2C)/sfǡgw+"'nI۷|w?"()H9JR"RL#9E2k+o_̨bMc"?" ]ذϓp?D+6lE@ ZSd$nεtp'do @*p'W2|I݇wÖp' f1mm=P@ 41)jtН'!,hζ4v6|aI(@8T І1HCzf 8f4܈_p6hՌ$bPX)jlS4U3m[`쎞7.XV|N|#'sH;i0Dߚ)p*럘pD{3/73 [<)H=lF?;~;̜  VgGx': SGֳ{]g @ԕ78{۰m~{m˺vqqm6_CSbh{@yĤc2T*()h}8aDD6FtCwZRrE.L&¬ϰ*b\Rr5t_fuSLaf4, cavD 60 &3;~PEqtԠ4Br>vw,}PxX3&ڰA'8`3?",g 6lM rRP_vGL/|- #?p*>B%% hq19=^߯g/ 읋) 83w3s;0%0ӿ2:3 g>(ks77Е^SV WhBNYknIlSx3zB-τ&! *m\MGG[^0 `zJh 俐,oNL2` K (Y>δ:-w8x1aVPA, p6@]cso"Yj>,\}i+cqLw 4 iٍ61[ xoE2F.c5!hHay 8g}Jd>OS6Xn|Jo Շ-;1Hxo?Ȧ~)& `%);%Dv>(0hJd'  Q|_u0@Jdԥ#7 xjن8it4,B;U1)KƚNPZ`3{gnqi+=oJى|5!cC `WLĶ-lNh  f!a77a[~g|0S>qA6Fq#vy}\gX]GN%pv7KHmEzZ(Ҕ)* '98wRq$ZR"x|ohr)pb3AoKAfCRrE3cJR"2!AXJx mQ/bp8Տd a_;0G`8m1?S39±<[p/ l C'1gH!) y&Hj7e֘>a@ "7(+tfHgw!(@_> ( (~P'*{A)G8[ùMׯdN=hުpBhQռ=Kgѱ?p Q9 4g7~P0itY)m#'w> 5 =GA}rUK`],lo:ќGK|5X[*Q_4k## ؒXJ> )Ԥ&wR2ma# =ȗ<?<;Ўucrv8t5J I,[,/yҊIy)bA۲Y(4TfMp1)2BkV~A 5!JDHOm1Iz;4EN;\Y sTB NAa$n˜% J 8iI n06y={)kgluuT>Ռ^2aQ9GqtPt!d$ҊP ҞH5 V@\8j5 fƩ=Ҟr,:R)HC B"Aq+'V.Ik c"V+6X } ސ4f<2 R15dB ~1F'G)R9jt`TJDQRt Ԁ+pPfR/2 cRL=ߒ>% q 5> B5$'V5%@톷rZW8v4.V_njr>w~Pa)G)JDM3ՠRfR`٘CȰ{Y6k4 +!ejK5<;G  ĵ@D>p]  I7Ǒ8ʴ,MK 0:H- ۿB**(Bx,G'*{L /|Nc:_9.VwggF\B\2iޔn|Щ醜] (ߥB?dBxB;d/Gh۟:PZ2zP`օ$#lJ1)% KWEiħuͮp,()X~-zU8Ka燵49m~ Şfhdp>[| wFI1܀ӂ!4f>'!oƟ,{ wCHG >VVxR-$['!#)E$42K-#) JzTy^BFqoֳ; '5lBFa+qI,rZPn`yRzzM6]FPC}s8Kہ ĭ+~ >6A+?KmS~_?Vs&C JF#ȓ#c0iA~ 8E #dPi+2ũte'*th%`C糷- ]#0Dža!f_q4ҀD!Zastha{P{񣡀\©Xr´9w?ҔmZhcJR"1%!JXW(Xk S7EtrPK 7 c0", RJ )$% Jq̨C9&u3dfk q[ $atH#,1 !]1[qcn&~gmZ v͆3yA@7%3 ky،z՜}!.#JR" Z 2z @"}0ߑġ(V;RB?cFv&`BıŧYΒ^I<>JȖA̝0ҀY^l_2x޳ٝ 9Ah%2W( 2ѻ9`cD(ŕ]۬<($!.@yсw# h>mf-4?#~iix`3aK^@bjBlt\PiET^PCgp9䕆ZL-%v uq@'(bG @~bYEa#9g0|01&R,'1dFC$^G+b r otK=n/`DX26l<ˤE0bhXor%+ dn1s1Y:7$ՇS(QT`8?Ҕ" yYq'0Z 't|^ݤɁ.u?ҔZgw[|$sa+3-N8?! ƫǬ?n}! tnu 2cJR"?" >ncGcJR"a#?Y7} nOldPЖn=i ^{' JD@,vquhQhp|(vG]lG?<)Zl 7ogPHONs3 > HqO#h$_:샶:/ӛ$/qZaa )ptMQX36u֞ԵcVm(W*{Kn1qd6|ei nP\ IX$p`n&4q ґigR:W,q}N8ܠW87,Є΁*xF)#'`.Mt[Ya`g W?Y($9rMܪFHO1LZOE83eq9)Vre9|݀x dD)ouU J ð9&{Ft H +-ԧd-<+asڜ4zhv0;zZ7(u0O_*s8Kk>VsR2zpųIC)Q:Q~Nc<~\V+ /ɥZ!!l̀#)F{fõ,qs=qޓdIRR }Oݖ8z~=lQ4;T ~8\w mCF"3qx3'p>"*qYrJR"rB9Fb?\g.ƞ  3$Ç2P m2=hY+oRщf`~k ǴVC2] PB +n$qו`%$qC-%RLO&Y 1 )dq#-39~OXGys 鐌nnvl ٔq8  OAi-+gua" @L23*# B:\PSaL0(9QA#_=9~jǚp]05#nQr.+,%ɿ:&pQ0Y' 1H]:5;󰣞Mlvabz{,u ` :!!ta)sasp@"#f[FjhRdg018WaHƲsZC~ecuPn2{ExXF3SwS+R"qtG"oL?<=#h4>$c0 4vn`b&Ę|qˎH%F)DAqZ)H{! c)H9JR" q -ؗ!d-#"r\'!!s3#)1%u%X(p#M)qhAIŧ2auĮRܥ)rER)JD\)rER)JD\/>d4_7INyY^P0 j]iiJjJR")H".RJR")H".RJR")H".RJR")H".RJR")H"/H`L"Hi6{%;> [cCvf5dOOli# N)H".RJR")H".RJR")H".Vr[we_2")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")Hb,R/arER)JD\)rER)JD\)rER)JD\)rER)JD\)vMAL7:v` a4LC5{n;4ER)JD\)rER)JD\)rth EIyb.RJR")H".RJR")H".R:s"BɡDVM{(F)H".RJR"#")H", o%M ` '!dNe~}W1%[l&o" jOJGBRJR")H".RJR")H".RJR")H".RJR")H"/H#08>оL%Ł&fw4m][`St e\N)H".RJR")H".RJR")H".RJR")H".R32L&VyN^ҋygS\t",')ER)JD\)rER)JD\"/x@=b J@HM $PpIRR)JD\)rER)JD\)rSfJR")3E#u~pĤvpY D33Cq_}$)9]RDRR")H3֔P_W(X@wC4 x4`,032)_ڞs; %g`PX `;, C & rsw^g&hƺ)fg uJ;&ky 5*MZR}\ @UH &Lf Ʉ̀*rV!c2;+͸i~+=]biӷHAbyvOhC-efv;#L+ZBKeJN.RJR")H".RJR")H".RF"6jZ)kLk` I!&' Sɛgd'SzR\)rE)rER)JD\)rER)HXh)XibER+*z;ՖSh:(KTޥ ]T8 ڞެ;0KHͫ 0/Y~_J7oK` ;GJ{)ZfN}׾)(gGsyd.v%3ON>9uy rX^)D\)rER)JD\)rER)JD\X]P_+*XC|М~ XB~ҞǙƩ|R\)rERzR)2]}>&$%`{\`F Rkŀb Y "BAm$]e%#x`P@1Z ^=Rz@,@ (k (l4kJg( &I}+(P qgfraFB QUO-g.n+;APӰ|6%hЬAuw.OB")H".RJR")H!!#)".FH]"JJ֔N)H".RJR"DCIeFA)C3;nmeJ\, HЎUď˳#*Cܥ))ܥ)rER)JD\)rEEz7UQz33ŷͯ^/NMLШ 1!}KBpFQ80 4*v @4^2h4lnz;7m @1o&R.-#5%0d ?{{͕-ڠRqh/V{7(5CrR #;AcE3~NP d2Ph^$"iCLƷ,$4@ ,@Š%10 R I'pMK@ h!`2Ie n) !Ӯ ,?c.q00fjYg. gVA ֪-π& NWn(ʢ]fJR")H".RJR")H".RJR"aH".RJR")H".RJR")H".RJR")H"-2R"񫢥jS>ݟ8nY7x6) |}ݟ#~}b@`;!5m tRKeP Hi&l3:S;lm1)\kЀ;N%tY)Y%8}'G AKs%AЎ[j܀ķ}}} I` ̍rQhu@61aWМ>*i301Ŏ9aw6/ǁ?–]'=^hbB諜SXwkz @QI}wGmjRX)rER)JD\)rER)JD\)rER)JD\)rEz@oPeuwsƈ".RJR")H$ܧkJR")H".RJR")H"ZD[/T2YY)ԵSx}0` 0@bL %!U@`&O(YCr0Ru0iC@~ 4GjxN]`  PS1pw6tZ ;%u#fw@'8!kpZ?1T~6ޒ/#]ɠQ ?WWu`}`MҐ)fF~܂e䀜 \`jPB %JI/[.G@1&81N՟e\A% A|s'-Xפ# -' c@;FdӀgٸX2b`a8{u@*, 6 pg|.0gP+pԍHu3bԡu_RKo{ araJO_W0&trT\)rER)JD\)rER)JD\)rER)JD\)rE‘)JD\)rER)JD\)rER)JD\)rEVxj2z:;s7\zgkgL-o-FyNFhHɅJ&r,jv=DU`.KMmkaD4 IJ^lW.}wD36a֠*v G,P@B_=Zq_U@;)GD`=xF~~{fAr@(&.Y3ߩW,GN;_~} ։Fk 3rXf&#e? ?†#n{_{4&Rn` @|ZIea: ӕu# Vל&<'it)H".R!!g#)JR")H".RJR")H".RJR"^fJR")H".RJR")I)D\)rER)JD[}1ԅQmF4)8 P8;٦"|tVП>?KS(Z7>ZZwaJ\Y1?lDskQZR?+_V~qa㪥ˈ(6wE4^ZMTRJR")H".RJR")H".RJR")H".RJR")H".RJGk!fVJ!䒻Gc{+& s H@ `P* RHDԹ00iiB1JuFyH7>F)H".RJR"eE)rER.thك{k= p b o(t&a͝=[=t5]Z7:+TbN)H".RF"K%qh}z(0 vL(L,BRR:CR~t84'+ c5.ҙ6"̇i]IҋE:(UED]TxVeUW)JD\)rER)JD\)rER)JD\)rEV H".RJR")H".RJR"絖S#/a(yov! WHJ.Rܥ)rE‘ht+ Ϣ-w[h |ɼjxߑC#lD\^ZE9mcLfhQkJRqmiEXuT4ZhM[4\Ќ֑Eie44ER)JD\)rER)JD\)rER# D[4ER)JD\)rER)JD\)rER)JD\)rER)JDY&$t".F"X"ǞX\M,)Iş4J-&qoitaIŘRaHER"ФER)JD\)rER)JD\)gfqp".RJR")H".RJR")H?oxR?ER)JD\)rER)JD\)rER# D\)fo/Y.C %o @2~C&(4b_Nݨ˭%KDR44#mE)IR)JD\)rER)JD\)rER)JD\)rER)JD\)rER)JD\)rLgN^WsDYFm R")H".RJR")H".RJR")H"-sD^*KG^p d ;Xs]W蜕_C'pm>tURܥ)r0E R")H".RJR")H",RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H",ZDY)rER)JD\)rEB)JDY#r4EF+".B0ܥ)rER)JD\)rER)JD\)rER)JD\)rER)JD\)rER)JD\)rER)JD\)rER)JD\)rEB) DY)fER)JD[R\_A},hJBSJR")H".RJR")H".RJR")H".RJR""JR")H".RJ!!3#)R")H".RJR")H".RHQ,HR")H".RJR")H",ҔF")H".BJR")H".RJR")H".RJR"#>")H".RJR", 7w1jeM)rER)JD\)rER)JD\!fE!H0".RJR")H".RJR")H".RR")H4".RJR")H".RJR")H".RJR")H!!#)1%!%u(pƀ#)qh( Hу!ٍ\)rER)JD\)rER)JD\)fo//( j@',C8 1,RB1C5ȫ#oGKrER)JD\)rER)JD\)rER)JD\)rER)JD\)rER)JD^*&mWI)INϵT( %' t|]->kdIJJw)JD\)rERaJD\)rER)JD\)rq%І9R")H".RJR"aH".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")H".RJR")Hb,RjhR FB6f+l;DZҔJR")H".RJR")H 苪n\)rER)JD\)rEF)JD\)f1L &dYZ6-!*RJR")H".R?,RJR"ϴs<@,@hxɤ ƱG%{%J0g)B?GBRJR")H".RJR")H".RJR")H".RJR")HE!oy8@*`2 ZpPh$,󔆫لibER#rB")0".RJR")H".RJR")H^"&P: & $!!BBPW Rc0iaJQߣ)V~VL-uZRW)JD]#n+D_ ) |v>eФER)JD\)rER)JD\)rER)JD\)rER)JD\)rERRY-iJDY&5".B0G[IY$EF"KrER)JD\#kH")Hb-CYSu3BRN((OgᅍHH3!fp HD0YeF'1L2| nYWrER)JD\)rER)JD\)rER)JD\)z EK&gVGvnFyb.RJR")H",R0JR")H".O䏈ޮ"ic,ib-˻X7V<"|&.4ER1)Hr")H",R F$ofBrN)H".RJR")H".RJR")H".RJR")H".RM-Z Hɤ^C!z0,e vsoʖ wL2^9)HR)JD\)nYT֧J.BZN-7熌^quΚsUE_qaIEDZN.MGER)JD\")D\)rER"`<|0aDQ-#J$98} WI)IN)H".RJR")H".RJEcZbER/s #uTZLM_+Nw;_契ܥ)d4)fER24$1 (]@vh y40I5 0 dJjx!IZ0VJ:q:rQ| 9T\; ~g`dnIk"{MJiEЈ6؋X^g>qk?m4GhN.Bib,)H".RJR")H".RJR")H",RJR")H".R-U:(B:3:ғ}' a>`@j`B !!) FF yD=fR;ēS%#d6_VngQH".RZZD\)vZmfD]4$i]D]p*׭"np\Ew Z7OܩE؎?u ڧ sb.Oaixo9ZVJ4hSjN,Rg 䈱JR")H".RJLYXZR)JD\)rER1)b-iX6$JR'rER)JD\)rER)JD\)rER)JD\ibE D][G(wҋ̄n侈БY7-􁁯(bjYu-R,g ohݞU=ԞfAc5!Hll4;כq-%uU0U71ϾVMgiExm`vqbER/b="-cD\arER)JD\)rER1}zSU큽NkLm@ P# bBIxģ RrERYo R")H".RJF"#GH^"֓<",R="!H4".4a:Z,"%/4&k){}tCwSi/}i)#8N!q輅їk-;C@LHįR 0 j,MHV9@J?X1)m:4`1 p|ѩ:Ha4Fzr} 涻4V2',7p q2ZM/_z* !!e9?8AIAxRGC [%IqJkvLK1{΃zĆ5'yRl*('/(ִWQyF'+HU戹[AhDYB0".RJR")H".RJR"eEazt XPht^ }o##&{R".RJR")H9TK>"&xh",ѡHiyf[=Mj6?E6\yd\6pOY>),wq7oݮ`;+rCFsd"7H#Ky0BX9nhɅ.NeO~D&97 % ^BX!!g#)w}wd F-Ҝ0>}3] H>./vu{- 9JXo+ޱi,JOq+X3_a0R󧨟x ~0) !) kHi|҃{oc{{ co\4eM|bcΫ,f]:_A{j^Àb^Tb}X GkH}Q/]P( AXG6Pq %㑤jSB"֑U'"#".RJR")H".RR"-"WcDfE)HR)JD\)rE_(y$,3S̗F'`T04Ltn,eK \))ܥ)rER1-EDIR]ΊEoz-$HCHHJRr3SRר K=@ @05F9J@$ҍ[^ HĘLBKnf]dނ@lQSީ% M&g%`$Fpkm87-&t!nP4@Bߢ$*2Ǽ+)I:tMBarb`Zv#^ 5q00 :$5?z 4&RK G$?x &\W.ٶ;lq3tX-ц>iv3 rHBQ`'n: Cܰhp/ݵ~yؘpB Q˻@vM,8@(ŌČ}%MnHeu A415CG㮀 jW҄xB| B&͹.!Bj4q`Wm7 wK[#AaN+J9Z!!̀#)D&x#ɵKPd]FDZRib-i3-a4".RJR")H".RJR")H".RJR")H".RJR")H".RR"ƔD N.1hrW9:i3Ud*47\ aJI}0/? x L68@$xGBLbv~gIHOoD:PgB.퐐C &`T %p:& Ad8R@ba,3 ru&O{K ( ?ur2!x GĵsZ|0TVx΀0> \(41@)'}w &( Qxƺ02+4OJ!tXv@1\@: 5H8.hĬ4WU] G }:(, -] bMNJ(׼x` 0`fmjxj~ohQ[eR` >žc, ,6E؝{H@fF;NCh`K +=Vӕ@:²?+2WhfWZrHcVCꄆ.r{V}S>-[6+šbER)JD\)rER)JD\)rER)JD\)rER)JDY ȓ+@%q+Eހ%Xġc0 ]KS|3J_^D7;X$a:RJR")H"hyv'MŖ.Q",igD[pݥAo{0 8Ӑ4i-R(`*M AҸaeՍ[P1O|=DWbER)JD\)rER)JD\\Z[D@/ &Ўm߈`!Izo&tK*RJR")H".RJR")H".R?>hR216)rER)JD\)rE!K^bFҐ3UNv2&Jth+ht"# E^zi -;yu+b,؅{)^'dʲbV#-5?K|EχT_<\QU&hʏ}b,ng$<;`C'>v E@ v|Y7x$1+6ԏj:fq Ka0Hk榫&ȏuCʘTx,ՆKjg|)CKu[ID/5(6¹bbR=W"4f-?[_);"lW.%2i&ޡic ".RJR")H".RJR")H",RJR")H".RK:[5$7?egX_@PZW@ LY-8jzP1*DdI4Nxa5%7pĕߌbn5 gS7Ţ-Ќ4E hQ J7rihvDzPX鋭?I-a%11nd 5B9DnNj,ꐀv1$:4o}褚0C _,̔32HzM7bM#vM]i05ij͇D&mW({ (1Zѯ*Y5ѽXa[j.WCAZΓ<;_<q-_}ԅԡA[T꿥di&گ"\{Sib.m,a8HFZ颔`МE)H".RJR")ZҴm q+N)H".RJR")H"-^W(TZwNѣxT"6_Y;1KE֦"o!U5/JU-<8aQ(Ih+Pv^C܋&#: `1k( Nl0-~~dٟ/5bMI %~:00 |0Ҳ `JIe!u4i%: e "m础 PR%3gf@tPgHix,%'db:zTº3B=p䁐  vW{  NlM)瀢&kj@wUb FySYɆCTVL 2o|O!!̀#)y!Jm`0v $mU!ֹu{C#jک\B$lIqT^lP=b)D\!8JR")H".RMgץ5^MI2 { :I\a~L-<0 8▿RR)JDYe”JR"aH1yc,)Xy1icgy"v pE3y7C$hӒd}|yz仨*6MAa/[d2Ht _DRcwU ;Ud&?(̫Ӏ^Iio VHýzxi_ki eBgO^PsB7g,Xo%c1ݍGI˩,1J(M/r-`kt>EQ%Z8376{ +@,4+S^|;S вXh@#n{ :P>Oq֩~e߄3`TCޤy`;C\ It3i=@a& n1 Xtھ*LFYl);fӭjkv iq}3K ֌Q2q`oJVr%qbEGBqqFER1)DX)rEڃsRk @Ie G,@`0 ߿S<2mHҔw)JD\)rEJD\&GgDZ/H1"٩,eOEg:$z:Hy(w&}p\0`F:DkYR0:o=g7؊+jWAxoZ7PlR' mjbҴHB"!H".RR"-".)JR")H".RjHčƍt n5:H@Wz0 2]7>s[; D ŚB2KeJ,^77xIX?+3ҔmsyOh,2O;OvNL{ΖDBޯ~M&)ކ^P&9=h @ECe.NP` aϐ},ZfzNu ;6Px_[J J} ۽m,B[.]_c:T*ow])uz.R\)(BVkJ*OV/P`,!n EY!!3#)$#,` ^)ނPȘpܥ y(LP([n&䐐k47q)03ϼ!9!jBLeB!]YPud\PURAux: U+L[K&*r%ɓ1* 8wͳ2%afN,AМXarER)JD\)rgya)BF ucGkJR'rER)JD\&J?7 Q"֔EHz4i1(Qn 鈸}[vëyh-!` D4@ivUjItm}tڋMHcWg!8 `_ )g=0p Δ/k_0$ :WОOSubVV*եR~wj1Lgd͏^'}t' ߒPO4I٥!2W5AYY=Dx~ia][k"a$/8vG{!4KRK%i؉S6.f54 I43%0@v#!_(&Rr5_猽v#'wAꝐYX &b(5gEꌝt@lZx\O|u 5i=kB Asi=/+Ji^qf)H".RJR")H".RJR")H".RJR")H",Ɛ<\D\fFIbf?(> 폛Wg՝Uu!!ٙ#)U]NSg/ӧ{ppk"U@&H&L7O~N=Nbs.Q+lIeA3ZCFۏ+d]0+|'{! g`[YjfʲlYIYi-}rMB&7mf U#Tk:WβYI` 5SkBB83 A4>@@JH%+ܢi3gBcxP^U\0 ;7TtJC< QxLoگ+aVԏ!LFhJ|Eە#-j]#')JD\)rER)JD\)rER)JD\)rEހ( N̝g'PThJDF> ?'Ět$lrjDMf>(Z;^ XbT< M)GkS^!.Ǒh&fg !uH+풹16(\cPyAaeYи9RM" 2rf^Y 4Q,EBH")H".RJR")Ƴq&IbER)JD\)rER)JD[{xa''' |uɋO[L(Q%iHaEɥ'mi&>Qv4;( %wfXSeE؀ʴSjϞr2ro2Z{h&b$`ƲP?*rFgfӔT^FE @c.V=5Bg(yn":rJM 6ąĴiwIM)^Sl*GWJ<:&fhh5".KZRm$)H".RJR")H".F R")H".RJR")H".RJR"a"-,ťjD[Y[Wҋd6<QqvWCۑ.EVPE![L˜]A68C2tg'w'h/0KA/[KSB7xeNYϩռͦF\A֢Eu[5*l5m%Vj̹z*F&VXlrdI;V9zrillGh*.Rr]4ОYŊF)JD\)rER)JD\)rER)JD\)rER)JD\)rER)JD\)rER)JDY)eJD[KHI?<[vҝH ՟FTEYҋivDY]>tTҋ1iN)4Jғ<",B4إ)rER)JD\)rER)JD\)rER)JD\)rER)JD\)rER)JD\)r0ERf1Ѓ!!g#)G,+FX1B)ը>EMIhؔ_cj)rER)JD\)rER)DY i njD[4csB R"JR"aH:EBiJDY#ric-\)rER)JD\)rER)JD\)rERW:?ґE=1JFq5GzRrE)G)JDQRrE)G)JDQRRmDޫɄ1!(*Rw^ss6 x 4BLE#F)DQM1JR"R"(֔EiF"(i5)G!JDQRrE)G)JDQRrE)a[b )[2"(ͩ8o-NJk$g*3%:9JR"R"(aH6iiH9JR"R"()H9JR"NP)G)JDQRrE)FaJDQRrE&b(B"R05#81JFqFѤtO,R"()H9JR"F"()H9JR"R"()H9JR"R"()H9JR"R"()H9JR"R"()H9JR"R0"()H3HMFrE#(oF"Ő1QJWt,ye~PcfiekF"BwE#8Cc6m퉋=GǍk蝺 PMz?TE#`*ڏ3S;DZiUI(HƑ0 (Ov0ș 08r3 (SH"B"()H9JR"R"()H9JR"R"(!!̀#))H9JR"K_Y؏b(&E)HW§ WЬbh<mI=4ņ`OnHQ]W:vH%Qx=O <6[CmD)jK[]=~z'cp.(H$tRqF=(z,,Hf*aF!DQRrE)G)JDQRrE)G)JDQRrE)G)DQ3JR"K@0;=]{4<1ݞz'GCǮO pΊf[g ĈG|z7s{=[]7*{E gHAE.R4&hj P=yZ gE1GVw8N9=a>QG*DQ) bA҃jr~ΞfUE)G)JDQRrE)G)JDQRrE)G)HQґfVEظ3pQBU֔fޙQ4ذ!N?ujwy JV.*AfILJ<LYyl0WfT|\'4.XD ňQEe%jfsӎoGeU" v䠮έlZK RK讛S=R'GRb4EL:&@7)iCs A 98WT')G)JDQRrE)G)JDQRrE#F)JDQ1 W~ԂNU&ԔQ6DQӝfiEHarZ`lY A %?vbԟX5gN@45!@L)͙kuo;Ռқ Z)(7 L펢0IAAyo[0 B`h -$Ԥ0ga14.!Y])jGAw9 {d܂J>PِWe((0Ћ$*gU3%u~K>! w] b}DeMAQD0ъ? Y7mlѽ>@R224Qv`#bbRG㵕TΏ>T4f?IJ()jDQFrE)G)JDQR1bE)G)JDQRrE#`,01)Nt NndbN5N} Qt@$.M/i4 S` zKEZPӳv1~έ(E)^J#m1G%ZC:>mUJ,D,myQ3} l(+.P۟4EKJKUִl_hBK[l[a0!%(C@Ӡ3@'&B^s9D0qIaO!)[ -d(QGN7wu5L D4g^;/T>U(H`< ta%oOB55<_$$@>bg&ve]4 ֑>Ww=es  f58haCO$"嵖\> Hȵ"ɷXȠeU3mGL<ýg2w{\(ZR3 R"Rb(i3Q+#b()G)JDQRrE#H(vx]#("{[?Y1.qNŒc}[ڭ7t E kkGQ0W߷o0sؽG!-Pi{ָ5˺_wPhhOjNIH`&%(\H|1Fi-br:*Fm*Aha0$ c]g!p{2I/+&a9h$$dƝ_|R58oİ+IIQen脒XRFH43ktc$%9QazCYQhjD,TZS>(^!!3#)S6{Q1ё\v ){V>mGM EƑQaG!JDQ1ѦZڼ$hGzRrE)FaJDQRf4E` G9TΏ ޿aT0(7L3Xb`¹,D_"U0fai[tvfC9H_ɀ`iI|CC7$K2ك@iJ6Ȃ>PF\+)RQ>ez^9H飔*7w'f>h)$1 Ks̫0TQI<y 3.,00|}PR,D!SF]=[8 M \ eɴb v0|i^S'QF%rZ4fZE(BqFk"FjNV:kɑ2&D?Ҕ"()H9JR"R4ۼE)Fe ӵdj?VXW}D)JRw!htx ܝpRyek?H^ QUM]k(܏ӏ)Ē7|.j@bGFfE&UY !i4%Ⲩw`:!'Ju衉]͠M씞`il)y]EF{)q9wz0Tu_5M^W>jb?Wo+I,E4%R"(aH6I;%"(֔E)G)JDQ‘mHR"t+F}uzvtas>zD7.UކʻiC|-l(F['1[*8>H=%oR9a[bArkwyu`'rZY!e I-/% Xf55lUH ϭVl<r)Pn)&fV z\q{Z> s6T|ܛ.k ZQUUmT>߿[S/OޚڮHڙU,J'f"()H9JR""()H9JR"RkaS9MMm2>+mF<&C#}]!늑O 33P|3'.̔t0W@UH! :w[8"yԣU!wtZW HG h?C[ R``&Ry0hJȴ5k E kULl85oG5HʱҚ4NU6^"a!!#)+h7T~'oWJD2h2",$5[R!5"(֓B"R"(a1JR"R"()H9JF"F1ezMF֍T%)sWyɯ Y.>a~dS,+ a:+)N3A ifpo@'8I:EX`Lhfna2`P)#&W.du>\4Ż4x.!|RK@ J +Ĭ`E+Jh`4Sl0uhIzL aPZ,h "&ލ@ *|l&AL:Ox\L[k@ HcI7oWo fLZ ᒚEP2!- ɉVs l5eksExJ,;CO!Y 1fRQRrE)G)JDQRrE)G# DX `E2 8dL&3|ke;>XQFђ aoʏmI'yEK9q2dvqL!dIB6`aĺ*CBnQq˻%#kGko) uyHgM`7 nm:?JyX} :=,0f GJUpJg 1El00P@0&nԛE*!;;f]C-+d@th@g4Q|)YIyvRLn'tLIQ1pk>V02_)" (KƒXcg;8xgojt]43oW ^GV<bE)G)JDQRrE)G)JDQRrE)`T 䱣{3 0H2` ˆ*WGRr1:>$,X3֔5[BY %We1A 3 DŽuf٤i*-t}P03]IiC5^lLmb" j>*zLkbPHgK R,n,T*n]LfؕiZdYU'B^}fte(n4Go?- 7-w**G4iEhh6-1 QRrE)G)HQV:䈣"()H9JR"R"()H9JR"o!tbL-kfF߿h%Fg )ѻJЋXx)ݲ0Nf1 :Q aCI ls b@bި4Slh3eŤQL!DuzpB3nj ʸ4m BLt뫷"x?5v>h::˧LbHLxٞ\փ=/BHas S^j?Bib(%EKJDQFrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G# DQRf"|/iE!{QɷTyQ; 0]ZI'sU:i7B]cD+@.VjgFZdjQCU2>YVh7!Gt 4EpX1,a8"()H9JR"R"()H9JR"R"()H9JR"R"()H9JR"R"()B<2"!H7(ifQgX =Qj6(MCh?(ҴjDQR-p]*RB(KBQGdjQԪ1Rc5%RtectG B",o40"(aH9JR"R"()H9JR"R"()H9JR"J?ґUG)JDQRrE)G)JDQRrE)FaHQBlDpĹ >"dG(FrEZ(XjH:fsK"KXJMH7VKGU&EyQIcK4"(&KY$iN()9H"R"(LmKIʎRͧn<:ʌJJtrE)G)JDQ‘nRrE)G)JDQRrEp|b(#9F"F9RqFc(goGliZ<PaÈRA<7zEa8"()H9JR"R"()H9JR"R"("_=+~Ž6"i5"(qQV(묚!*huySX}%>iJeAVH^BhdB7rG%02hCujU<[Უ洷HW>kr琛~ ꑶѳ=ia lEMOGKN9H[^GG࿵y"Ǧ"UW9ѭ#Iʐ7xeHR"R"()H9JR"R"()H9JF"Feb4E<^3RӦ!?fd%j?]T{fM[zLj6:,X:]!g~RKD:$:!rGTZ {`\ݹFk:A~ٷwO#nOT>ڧhLQ# ʇa4KFH/(w~PH9JR"R"()H9JR"F4b(#F1/f2w]yRbpjR $%dlXnP?zmPL)- ?r FC u/}#.rSvo3]P )0# u3@!)Aw)d,J&9ܙq7b 0Y@:&I'``gI}Zk,jڰ7i@M z <H;nQ |7[\&)>Ӈ>iwVl&j):ZQkqF#DQ)H9JR"R"()H3fByEЈQ#v3$kur8rd2cK8DÑ?_9VUL6|a`k -%6C7$ue̯3A%ΔoG/5鰆V$ @aԵ\-G4fҚ`1MUuߩJDYxoOҦ)H<"sZ#nlL }f]s-NG$.m۰[#L1q{.i1|~¿oumPکkL6z?4'xkt5QɥE cJR"R11f2"%",!̮hR#jӲEMvog"6&on)"MD]N 2$wJ)m6.V}aabΜd;]$1ju5x3ȳpGz`S˃xj6%˶,`onR:Tk˪\|]n̩ DQRr0E)G)JDQRh1I`}*^oFːCIrEC%@Su٨`e^b̒\P[?zLU֠5%k*B_H6,?m)q'FP@ۀ\#G72|SQEC?IEܲ,+ΏqJkȺ;E΃ _^Ȋ:. #-~Ugj\`j\?[$MH5()H94CGE)H9F"DwҋU[TVҤIkvjkmTȓ%ʟ {r/4nE>ZN¬g 6VJkj17{A1v!^ mRa ._ϕ5-Of YKU?{[ )D݆}$LciIEU)BGND2 5/N^nڹpG>N;whmҨlvoT{vyFVd Бd2@˷C$YQI?K-"()H9JR"R"()H9JR"‘b,p}mwGk4/ UmunB{Fz%RbcRx5(hobMGj^Oߟ]X}O^Cݤ%*ԇ"a-鐻XTK)Ŀ͛xPl2TmC(t^-Bǹ^ Jo=o̊%DUv)< "3K1(ґRb()H9JR"Rb(cIE ۔`|i:~V.aթ˪hCdaU[4?y..G4wK/bekGLyVjga& #69tԒK4sFp\ gihV#Iyɟ˵. t0;XLS&IQ7'C CP3S{sg]Zt[R6,lkRPھSH%X SY]R:B3R"Byb(&R"("1 xU!=UȅA Z/(si EH4TV͗*])h4YfLёr#@3B[>z?nF7_EBMN RaNӵ@ bޥNddh2̖HGPS^ ,1)^ 0~jϻtMWEL)(: TstzoNT,;n!!#3#)29v&k8i "(#9JB"4"()H9JR"Rb(aH=C8~rH%eEcg'x21fw"`n)#S.zڵBK4R"_fwΑv?,5d2lRrZyhȼ緣$rbBXW 2 x >rQuUZRUͽv~ȄCd=?_h&:yr~i~FMXKtw4ZGUѢTeN(IrE)8"()H9JR""()H9JR"R"()H3JR"I(Av4WH:ʻvk66՜%f|ݨPuhCOUpֿ'ڇ@^"*& Zw47uPi>C\^bP֏]V&]DXB?]7eϬ'E?3$:6 !ʴdbE{E(섔KGdEigrKDQRrE)G)JDQRrE)G#QƑm!(ia4Euo[e1aRδtu,5pAkkݣw㡒#KeO;[Ehuy]]j<]P7\ nh<޽{,.t0 j?v~nOݴiij~v=UM\6iaH9RQFaHDQR3HR"”"()H9JR"R"()97w~c)3HF" rHJ, v>?)k*iZʹz,4ZĐY2@peSK.~_:hj] ZҋթXQQG[j´&IȦ? '4ʶLj?LВ*wސ1F%*140"()1JR"R"()H9JR"R"()H9JR"Rb(aIE&XVy4h;k=Te!+Mf>S[]I{RH_Uw?Eݜdױ08_WmzsvmO{q7M'iGϞZbl;VIgqFfbR"(aH9JR"R"()H9JR"R"()H9JR"R11rEJȊ7JSp=Me1HW>zb'VZ!o"4twZtv^ݣIPZu=R>O~aU5<%QSVJ,v ՠ|ʪ?KerR"()H9JR"R"()H9JR"R"()H9JR"R0"()H9F"FQ!H7!A?FyE!>i?ڽiKУN~F'jYȃ5[QU[ beE/JDQfEhN(iFQ+YDTU%"()H9JR"Rb()H9H"FhƺE ǧ1z@ JἙc 4f<лgz>Om:=>FiXU,IkFյJƐzߣ&Em]2׳.̣Xnv†?-l(4x>4爹_ɧ,լ~=8e1JBqG)JDQRrE)G# DQBmJM(ZOGI;cSEЧPoeYjOhmNҮ)V7cZl'vFh\O:xVů7wX3U.QT<{,SGUK~SM{IuU)y :_avΉpbZCR[G%5Q)I)G)JDQRrE)G)HQ26DX078P}&~}Z+J(v+j֪mv/OE'[Mv oa4"A^' ^U<$R[%.pt>V- MHۥKuc}r09&H}dCuG d5RR4C+Uc$RhN()H9JR"R"(!H6x<#4(eVyo';&N[o\V2Uχ[_25t6`,13UB}f(۴)vݟ@n ~R{BfT!'dUFnҵle͞K]gM_,9m-gҊBL8y "()H9JR"(&F3(zwWUʚiY 7B8X 0Ƹ Ҩw:kK{ yKɥ瓠=͛UulsrR="eIm'}S4} R!# #)~iF?&v`{xG[dֻ7HʶflʿL*vV™ ! ӜbF^=TXMN(#9JR"RrE(歔R Ee/DXDz[uUE+Jx&@gJF@ń-8ʶEY*VXjy?Riv6>,۴grZ0}QV˷I-]M{9Ѭ␕e%i 8%rY8"(ЌEH(잮x3JO(D?r??-矅W ` & %50P Q&w¤ZzR;oH.=0[} <v$i)HD]ڛRߩJDR~'r&6σ6hܵ)yEh*˾==6^jWGEU|qGE+4qF1i F!=qGU!H6#FJ(잪2Ahzzt[xPn՜mѽR̛`Mt[*Ym ||ZH/y]fwGr[6y[~t~VHg:52N) enЅ"(g*Hο>c_z?R"(zvW<05CEA|mPmwۖq佷GձG54tߩJDR~'̏eˏ[&_j2\,]dGRR ~ m[J|מmT?Fb(EM J(BSi^r5˶olk?ޭH6Myh9q[HzjGBirkm׵&Hqt;kc[|Mg3۾.? LQդQi,EѤF) DF"$eoQ5L Ts\Hꪣ } d(j3J=5OM1a[˥m5 >?VTz댽U)vSH?B4hC)HG~-"UljjZzkT~ZKLQi )8"()4Ec(x5gyER\*Ò*0l2dK[{%I{h]K] r,fazJi [>tyO=禪B-}-Iiﱤ"!Ԅb,8FV*LD{B Q0dvCA$36[~m~ԹSJ'H>KerK8BaQt,vMViEsKUj"GSH3>N to"E8iRFxB_QEMGB7(~)Mb :;[rOTΕVJ LQI,EI N(!3RqFi DQRf2"(wu?k},t6b[_]E=uKh0oh`d%)rP?MW.t󣔥.U6R?R*l*ÛBe-vr %lOh;o{}O/Y*ezEP)5"(ґEcF#Q4e1ry^rꏂՍgk**N\jhn=0$g<Xmįt1𢤣Hچ DxJR" ! ކJ^d.:@Ѩ\M:$JͲ5R|6lutA?-)(KG]#I!FIH6iER"*meW&4Tos&HFcW{9T] 5jsF*25MHI 6kj]R)Hog)H9JR"RsO\Uz2jQv? %]boE=~>C޹v2Hʍ\q&v|-*ַhޮ-u\F"(!IRJDQ!H1JR"QB23HF" =UaM!#&g#){Hy~zצ,#F9k7^馗h_5=r-Mjlvih?R^9}bv?D$IV?VbRI6k`2w=eugeE7>Fx0m4.+=]ftuY ʎV8HM9 "()H3HR"HDQH6'5ڢAB _[u;.ȳUkrtem/[V:\l휛ݶD?\<2up/t_f$?G=VAA#Av_ Ħ:>$fҨY$vkU4YNUɥ;@[c Vztt2N(̱̔DQK RrE)G&b(aIEE"(w WnRm:C[6oꭣ&u[^xuHV 9tG]>{0zdL)SrsT?jv68uᶕe!i=v|G*c gmVI}mIv9v9?,j,nB]ˣF;ThUF34y'*9$QB1JR"R"()H9JR"F5(j)(RU8LXUꥫ}ߢU]-v{nlvMmP:b-Q.%orTdkك%]<hhdVt^maW_ޱcNj5s⽱n,>+UꆝjPU5M,FthQd"!IaG)HN(#H1JR"R"(a3FQG&Ex^ՅКQGeeUo J-ܧ:fgwzl+dz\2 ``hN '^}{D/`j&/EVX_iXF֓~oV|Ue`]!l]05\Цtu,XQg"RQRr0E)G)JDQR1rERZDQFr0EVU($)anK-Mߧ5=j*:kodݳ<lukjt=gP:.+[:<]ABǔx522jY[`Ge'?B0QR7"(#9JR"R"()H9JR"Rb(i9(eEaG!JN()H9JR"”"()H9JR"R"()H9F""(FQHk ʑ.?+?{:B$񋷣ͽVꏦQ27z5IruwW;%jCDRp ĴA!(JR3 R"R"()H9JR"R"()H9JR"Rb(i7ZDQɡ94J) a/<ռٶx-~~T~G'ն5Rc17{J}giFƩdQiFіb0"M5s('bE)G)JDQRrE)G)JD@Z? JF"Rw"(#H1F"R3BiE&QQ嬔R/s蝑9  1ɂ*HdsQ:D`* )bpGWʫJ m][wUXS Tˆ2ZuUtt4nrm^ҳmRD*Ώ+c(HNk**4#9Q!bQUr%:9_ƍgNB"()H9JR"F}JR"R4"(#H9(Y"սLҊ7fR ,y!#,̀#)uV' 5kv%۩zo>M>k`o^ףK[B7z\_YX]̒Z+{ڪF()4c4%iqG)J(# #F)JDQRrE)FiQR26)FiQwQyNp[V7]dwġoGT?=vN(Was(Y,3zɿBvy;nW)1!&ʶ 6i}%1F1,МQc9HR"R"()H9JR"FK-(J6C(%QFcI(h^"h-Zʹ!BzS!*M&`٤Yz{@Iymֱ0d{e_ !)GA"+sxr[['S%Y[D? Lg6AMSK>?-U[-3QFRhN,-Ÿog84#,E)G)JDQFrEЈ"(0QG+%Sy=qҊB6mҋN֞$%PBF^覩Im#Ԅ@_[B.m=smj 9WeO(N٦ zB{b͹滺9_يyz>J5EH*}jG<2:VUFwTTUhDQRrE)G# (+)(E$)W53"|~o)YΏLW멝Hge7f8mQnDgV` h^2o8f$ ;Hi'ڡY[';wiМeU{ѩVc5pbu qsS2أj^C̊>[/WTx崼,:[~Rr_*[U^,aJN(#9JR"F"(i#(5uVc udeUOzJvC Yl}3Jy)Թ^Q%+I>E,N,2LLhrU4j*ͶW۰u0%/E.VZRrE)FcJDQeQF^EzJ)%%m?s<|Qi UQGMVٱytt̞k~&Ohsd\u"?бTegz5#qU)C.٠NlR۷>"{[^p uJ}L> N*2z=[Qurjn﷧g? I刣ZFbE)(K;z +XS{`)j hy#@#SkdDf?E*m۸",07!rڗYja_NmJRQIR' }YT֑]GKYlcb`rRFMU<) E)8"(작(EsJtwFQFg>SgY1aF#$x mZ†Woڨ9.oy/ [ZhڕK&\F~)I}5fհhK5] 6>ȥZ}=<,,B&? J(lm=TvVtvYBW(qL=<< Baa4Zruٚ]kv] 7V/Ucjߞ{:K0JR"R_JoO Is*W1@ثiUiR6j뷨v5˜ ~:1F*%QsDQIgQcK<ִdIbh”j[t,\Ue;]z!#33#)yk ߩHS){gG4_jմaj4.Sʷ)͍ԖV}tSڮwbUQX*G3xyEVzEYtvʚEIY:7E!Ea4]-mE۱E5ޔ-u*ᐯ ڳjUBzlQ2>NUS˴?Uz51^Q"TsJ(z(ztwjbs;|t8CKwi:Dejx6CޔߩJJ()IR1ϓq1GPE)}/I[=B*j[9hn??# h ,Ɣȴ"m=bx"JNY޹wKvzdm9v6֫k1u}.EgߩJDR>UEs[T.vƞ۵Ζh-UѦzz'G\TēB"3(xgQɞS[޾{om{m$,ܡ˗m˴^'[R֫j*:&fd?ͩz?R)#sܠyҚE,>чT0G- *Ќ(]|uSBq*U5rA2@sAXxVet hUm *t?Ry494G߼ե6o]6f6wV* #y^ѤsiiIe'fEFYm5+"ZbŒR.m1WV@r;ԱvHDl JJR"C!1+N_ZiK-UɘK$WBQGE+%QEx_%cYΐ3KK$['Gw֟erXd8ַl\N֏hT&yTzNzN2ﰄEVҮ3^tnhݸAUh׷LmqTt~JI(䭫QdY;Ib`rw!6A !+\7dMBX1OUc5P5.4[Klh"0!(u(~)G)JDQf*`R<-KD3 ~l)y2`y-@Fԋjm]-Qڍ<h4(ݩWH;ZR"0iEYfz,ỲtR dhX\٭꼭6v+mzUZ6'͈o6[(*%2v" 6A6^X+DWayr}nڭ{Ώɼ'GQ H/і26v4"CxB}5XR>Ay,ݷBїVEAn6kI2+33ԥ"()IE$7)HORӚ\W& ?e;Y6!>[ivⷪY5m]*5KJ=v_$5k5ihrd4 ʐWJR1rE u1QԪSE!P8".jeUމS]i%Jk`gr}ޟxurD~%'jF̣)HFd*jjGqMay^mHe;{jmTe 4xZ-QV5R?KT]BT~QYʍagrR4mcFՒLXEi_6s~r%ݹR{@vLlэ5[ѵ*: u*d!%]V+^o[UI(I[%V? 5]=ԏ_Wg::<,-9"uGjQFYiFfQFi"fY&vU!VR%gyXaLQ2IYbB4i櫬ei%(d))\4̪6{?5"źp歮ٳ9F ivykiF4q;4:mTzԼZ-{hژjZ!͹0[v](X˅]UϞܯ[vY*>i4}&WjIi'Ht,ݻQYΎ+*:]digrEeb"ghޚKY%3I#,FkHqH7 #=1HC9 Z<)YKfqh/3/VnbQ\JJ.ҳj5͍20kjgz3Ϸ~]<%󱀱oZ/ۥ߫geꧫKOp<~V41HBC(;^*`*g5N ^5R)ۣ;K'-J_瞤Jf//z른2^?+Uí*UۛYwOH5[*~%1FA^(y*f]崰Ru*\EI]-C[*{wemNԷO-Y;MUS{|Z@!r;^q^U]j?+WHJ(&␌KnvK͵#8$?]"uFǦ.5VKt;]ٴ89?_*{9.ާg dǪ]hKR8UR7~R5tqT, uzz b )f5R-xL ;fս!KDFۦTyѸHYFIfv6XT [ݱUv ].K;dQH0/٥y2u,DTg[$Wt9w!djVg{+J'TIkbIUa%G[64Yر"ۥ&I3蝄X*! ^F$A^Ç_ +^]ۜUv5Mjߋ;r.&JI,?O{uK&48gMhPƵ[ kz>5Dɛ\TB2}sVz ᆱcۡJv{ۦ U8bߡDCRg0*l힕lPK42UK9 'dek@>э='!LjmXwoPhPhqTt O*YIUlџyvɅT{ުT\.P쪰'MG$y[(V yεOHk !yVJGzZ>mL˄I۟Zm \LJ'|~)OL6MC7˦~\Uc"=7 h5fݣ6r=]MDzEER5cX,jr6.]mt5=m lee-SB7<&KfDu|o&IbF'qX;+*%vOW?m5 ][ۧY&v}I5͝V%](Pi`zoΞ|UV4q9]BǕ.ءꏸ&۱"9S] ˾|d~;YΏGvU)FF +ozj2Aum؝˴i詵T>*JlMoOEzhi\UCm[RvGTU ]t)]aOC% .5}{ofMmiOmmCZd$ "v>Vx U[[v.JUg`zꗳUm\s15NuT*7=v`6ۆT>ߵ ! ǛzݫַI-Vɣm5AJ[)ڔ -?αny_^N*L'XJ{yWGd\W2豋Ɋz{ht UѱUYWhz'HCsDQ5M%wB &9szFto]ꫥ7sAm1/mP{yOmmhRRD?z!١"vh61'2^*Oݡ[Tj_ڦIcePOӵ<~)G)JDLz#nXxSv02[* ]-tmU4Bw;ʪ7{N랻 3{BFVjTI lF%A?!4)(iEM 8oڛ1G-PqBX4gMGɤ;#?J^KZk4v)HE{r5XJD=Y }؟U;|6j}Uӊ7[A(쒒Ra?',eQ36IvzfB8EE') 1f&;E]4v#[40T@ȚGޯG_kӳ^EhMbj}x+ʵpF]kF_KBx*ݹOw۞4RB5tҮ36%"(ԌEwT~VY&Q"Pnw>˫BnYvƪ9dR>Oڷ:ΩjHR1%!9Q# )F!N(!H9JR"Z?14DQ(5!Gd~QFFi=)!]ԧx[YEF;ŪO[OhN2;~yjF}-{mqR4#۪נ=VgUgQ|lH/Wflt}s&*@}[+ٓn|։O5ZF$fLN>׽~[uk }vzOnz$&[U.cU7nhkH%GM'[(ф ȝcOGYUGUg"Gb{ۭ5`58!#L̀#)`DjK2 S7##pddhY&=[ %vYj?h\nXt wjYȧ'ӏMVj(izl nr!n tdIEhDR%Ftfygz=lSG~=(=OtP=WUK*]2q3B:Cpk&Oϝ3)HҪL4mzmum}>Rj?h͝aB{ⶰRp` őMT|y'ѤTbHqG](jkI+JNRTx|uUR poRonjv;N^cyK=ZXG RI26)H ğ*ْhTe"0>2kPCT;^ouIgO,UX)}Vo}o%:wwvu9? 'iq-wlV}Wjy"J GO\5OVdz˷V4L-.%$ߞy&5+xC)IE!5].즷 TW[G*細NMGUNY2Ղx-{AڪUv5kq.K<6%tWYiԥ"()HK?RQܻ؎9.]mzajCnRyʪ:* ؕy޴mMQt10uQE*<!#S3#)*LQ3U4ҝI'QMJNn3aXǶYeS[Zr]zU3MuG{B$??_l=SLѲv6ꜸE*!*Ug֚sZR msDQJVUɞIFվX)F}i-,}Y Um~UR2E)G)JDIL{˪m9rtYV۾2'պ\L>쑢XWH&ÿxVID謪Z^S>T 6fن)Mto>R?RPߩJDR5NeML2+̵>GaJmmG1VUX&CI)e;KMGȪ5&jg;ŷ[U'`M^{h뻕^..?5,R\,SS_^xJR"ÚjP [LITLhV<(1Uhk~7]wko+51GdPiNuzkațkhR7ΕlVlYMXOާsEhʱPjoӋ{TwtW1^Y۬mZ7k7rl+Vje:A2亾KJ(ڒ"eQF6ZȊ1[-gR 04>m*jF*[0kGR윷gv"]=okejNuWRΫTf](5[Hט>{>Ohi-z.JwIzjYOquUYkUGʖX/M,E)Fc (޳i6I'8}]){%N޼Rm7d-S.j5T'On4hWY`Ɏ)PTį5NUfکýmͮwV51}?V~.K9ѬqF M,c(GdaJbE&Mo/srnOWƫ|_վ* T8Tk[d'W5Vm5j^]Z.귷R-z_cmfQ*t#\tI6x*o2Ulj꧑St%m-)84" b>Psa'ms۫Oj?@Z*.[JA%ePjYWettB刣Z'*3k")53Tg:=ykiPgڕߦS?vkuv1I}j={io^o-iVHrN?y5=mnշ}*Uͮ՞d]We:A /2Sb1vM%d=_S?f|+cG<ۚҌgv A[nڗߖkz?3\RB<{&^DB<|йw Ҫ|hʦduOJ*k/3=7C]Tf/׫&>oGXDҪrhON4˸쌓` Ia)O_+k JLa#t]<.)HDA<{x^~o<9])- guT͇K%~zĈ@K%N6]18YIYWTQJWmήȝ_88JRQI]{E]/]/U sj=d.zխeکQQ4 %6vì]Y#jm7بQMNNĵSԙzU]oI%)d%ڍk޾~Jx]R%%?}rzWv@[,[KJI%f=*u(^Z-Go[+bEeD;tGFڬR_Ga(u\|5w#&؝TTJB.G]4VDՓڛ3 _gGٞJrR gsvRճ:]?7YڿX쫣Ftwg6P7gGCB8MѬ5Yy֗mQS(144Q">/&rg魸ꯍvmUj{ݵQzºA]WnkJ7zg`/:>f[[9?ק6>߬zլʪ9 k(UEz'GeUk*5Z"ATQʍh{=WhtsX(AQ?@1NT#r!\:bz.f}7魶Ǫ>R`Dt@R (<8TZ_}ՁJcNSSF]Y$iFcHB99nHM{l׫{ҍS4щ+!8'*9H"LR2G)JJ(̱Q& r(g]ϮZ}{C)H9JRQF6՝4GHk2GUi`vG Y]y;ƽ=&!'fJ‘S:1BјR䔫3e{IOT*5ߩJDRDܕ{y[˯9GeeEeV2xg\ dJqNM%ݝ]k:?FI/jRe1rUΙU*=u2S,GOO&}bAD[.bu KMIzm3v:I2k-r"Xzj=,Qdݼ5>aKG!JQ:9Bh>-[y޿ֽtk|^(ݫGR?RE{u"k7oWvBm+-[UtvҵRA-;\)LoL?\j S~yGF4ണؑTykd+_ ]i5iu=]:ޚ%vos`KI,4s kZ箎ǬHEG'\-NяO%ͧGUt=5"ҪMc+MWѱԐSA,F@zR=vq[R 1>יtXGq2B+Ԯ+FsWR]Ƌ'IJR"ƗLUfqVqM=M==>֫k֐U 7=k\ qmNsb;Ns6c!RSԥ" ƨocUSސ_|!pj{\Uk;u%H!`ƪX3 UzkUMrWl%$כtvc)H8]W[+^JR" G!FBCYvؙv~6}*c;whu6URx lRnG5R qe׵$sOo9ok]t)H!#`#)G}zO(dWWEuOi,VUԿ檭tmY bEB|Ve8.v[]=gv{^wN}!r4-;oiˠ"ku7ouMiVkKwƖY,+܂8+l0[z\֖ k_wMnMkΣndԥ"()HXJR"5t糵쮜˷wX~d՗|ʹzh}aU GC>֫F[*묄ӕJgH%BGkAccU-2O^mWUK)—R?Rp)HR$kj?V;],ჺ Ga(ͪ9H7yc%>Hh5}:]]֩Ϋoڹt{y]qw?Z^{=V2iҸ_=JyDĵz<\&6hv-&ٔs+³YjzY{E5RO<|B eyE&uyYϋVۺtB`lήEuHÛ A:n﯑NhሊkU!=J)y#$~5ᶤ.륶en:7 zjLB}WLQBi3)8[ƪgc״ C|eeɗT1:ڻn*OSWs]]}zKYUYUd]új\m>BiِQ;/kkɷVe*$TNK5\H %* ղVJ(xBSߍ53YUGfLcfXڿܖdiⶰc[-37R9]ב%]m5<{~{Msոȓϛo5d׵GⶶZUJde5-]jj_51xФ(1$N)|2Z<٫1G|™ YwGº|^[¨(;{0jVZ?='=trЭ:L>HƃYƗR2:x>ەtfmŞ۝J񪓫<v<^v vQ^Y湭) W:M%Ihpv'.:U$ߗݞ]efŴSy5YwۦCgWM01_U ,GSXF2U*@$z-zOaU gfI aVu<}k¸uod^zj3jԡ-?}=/feݵEvЇRCsZ=oW=V}/=UtwWIg;VޕmWFk{)qU!DM;CaHǑU.tv{_(4P?O.-{N˴GCUak]g*:5wy; }Ԓ|!}y*NN&ٴYt>ƫ`IkU*x'wH|!rN"1OLkx^mQ0MA֑m[r~^[}ng.MYg[>Uv 4ٵSoI:٩k |H,k0j*L#i\5S)MN1$GrREVW]v6+ KIJ=ߩJDR6{.t/b {m.)9\ *4`Dс2rZ?${hvfc!KK)k!\RߩM4d6ܹ>Au֣+?JR"Wz]-귴Tp[+DG>ȓWGۯ֖ BFe>매qbD4SQD*:cIo%wTy}%:=nYI[]_=t))&Ɯe]cTԢﰄnM;KVʑ%z]rJR[_] ]O/! dn_gmUO<aדu1%/TҠwTXzRs[Xz~Iݟ^S^[_y^,Uo yV>FWuR0k0-YWfr-*y8OG–QJFye7= E&Ցy涣j9E!ea{efۑ!](h<5 v=5QETwi(EjoZYJj)zj?RgFi VI h*ܾQh1ʝ6;!w֩HS)|^\5^uD%p/3W`wO{_J3nq 9ki?ιtKS#nj荮箍ʛ!'ɣ5v\ֶrK?G) MKS;WeC)HB~?B0TehYjwZf5UB]9R !y./՚4}vǮ:۝! jXRɧFOa||=\EU gGhVj uUO%7}tԷf9Wj!I5OGRt5& o7=-U#u= ?#SY>ztKGڪ{JA2q/9Oz?Wsv6 ei5ֻ1N]^Rwiлq ]om1KfВ䵣:z9QrԴ~QK[cYҬmۗTJ=#Ò}$ 5̑uT}5]K\= lꏶj5^(ZT*A@{@k;\ϫaMEgcfדIYj]^xJR"RU(M >n[n5]!#g#)1'a'A*GJj ufvu]'qfk*I"(jJ,pK7MT J^y6ӟQf!Dv?RiњR".}5"(|Q)Ypiݸ=[{hfvGj5\»nu=ۇvgkUUg;?65iZ4NЙV 0̧]&j?qW>ᶰ;nuKoɵ2tM=![U%U3J)凵Ⱥo=Sȟ[쑪]#6v_.5Z +\.#*%z'GLurKƫKh UӵYe}u!85].?}-Ȼ.4j֮ +!IUITX-dϿooF\B}{jٷ;5e\s6[k2k%qH(AGiZXE֫|5ك5N6U#5IuYH\k+A: .coUtmP^I#qTo5TjTvBZQQ$zYWNԙfLj6,.١#TsZX=7Y亣5sg:5$$'wBSW[mt{ tu=+2vc?̯< ¾~սgm,T+Vo?y^>oۮOO\UxRnίSWv&J.L%Ujl/anq5QޕDXKML?lF) 3x?Zz\tV3EHB3:j[N?FLy<5Q/jKMTԚZQ/+ Civ4:jF(gxE AWH>]l5K d*vZMcUMg) du]Rk1DR!4.GNz--)s0(Qwlڤ~UKñ0=Wsa|(KPWn[-gJs4=V B[x" KiJh^T=&{dιuUS$mɡ$( # }[竛`nv*zb>GOi{/5m`jjfGRuVcЍu5SRh[g8ήĢ%wt?WT:jޮsG{l}{tykz.ykzoKH=m5-,-nSTOwu` 8[Ɨ#Ω-yTZڵ: ;Xw%V\?2Փfɭl._e޷c,)-:Ôf28CY,LG$%œQWcU"[R~Bj¨O:aVRg<~Y˗ֲkXv 樻~‹NK\tuGzKoҽToOމjfh}ꦏ6+YʴrUGX&ȁxu |mv][2{n/Zc$I[ *+Mm۟.5.)ͮɮDQ/K_Wc]ɢvB?o7\x]?64IZmaNG=c谴ÿ%4Vٲ;;6iJGքΘ鴵p# ykqnyV|[trKQGB}hI.#QTSMR\QVwm]$کe5Q؋}UؚJNjܖ ozm!#̀#)䷻j?>]qTu#YɼGNzm*=^\iOQ-uJլ"Sz?K4/?UH e9G.o0K-Λ>xU6cYEtkeqKKUkU=tQyGhQ#=S]pE2qI{{ gĻ"犷E2*Κ1/ߛMxjߋMUn05N箐-7u/,5-ECzٽKWGLӼɄ&'{!ڞ}/TwTŢ tXkc] w\/[%ёgw4wM\=LӕHˑ&8U=(˺Yd4URn_]1r^EHyU =ߡDH|!sNj˽^}dYnfhga]Un!jjCQJUqӮWl`q?i`Իo/xH\C)Ktf", j46\*0RvSڽUgl-S.YPwVtF}X"JJlݗͶ0WmF[n\h $'ɣDU=v%puD+Q4Ux;~y)t>->dM{Ru&.zASq /凶ޔ K= Q޷H-T$ԽS]WYљODjѵ\+`]YoQ:i-hW,OhVITD^Cm}ӗTJ.[JA㒂[mْ55<]d-Tu]SMMR(ZrխjUޏ !]h-hATX`jz?"tQVkyJH]Ջpl7։MHZɧ4cU۬H@l[ƷyRR_ԢbEċ:*mNъ4֛e6ߨsTe&cv>Md(2CG+?|"?ȕ!۵CX'͐-=Mߩ Y)K,QUUYΌ*,sX_? Ĩ~>‰mꗐW{2ؚ2pz-䍰el|w 1r{E֣2u(ƻ #"JˬfxsRS骚Ɨ<]5EX2"jꛚÑ=3I[V_K G뾨ⶲSR80RzAd>]ֻ:wJhgխS*Ѹ-RU6w&z洣M%)TTҐvN)ٮ{&ɵRhJxHMqJR"RQR:vn:>iU˗eY[|^Ϊy Pd3Չδ?u~V5] a5,S@QHS;\֋^l0R*[1sY8q;4hߣQt%m zj .O-e]ՏlmrXh0rrN)*)ʞ?t%i6GiuwU(jM5-ꚩE.t UI:S۽]euG -q[XpggLBH/nmԄ1XUIg::dqaPiyZ5/zȦUuJ!USL[mԲdڭǶЬ=txWFʪbvsV>Һe::1rPYD~jH[yD֓EeeÏﰚ[(),U{g;/KIaevݏ=AZg)H1 s:3͟vVWGW=t{RɔtMle5kffxRj՛ȳo.a5&Y$wMH(]WYrRYm}Ts,=R۵4=IښoFalK&RGjN-3)WSS;Kkajjiԥ%e;Z86ɉv}[6.vyw+:,fnBii-iViuIm*&L%_K*n Mf*YUK J,UfA! G`uG􉞃kl-mGz?ɹgUGNЦSGL$'Go}vEPDMڈ~^SedԪdqUtO.룮JU*EjSopԘCe&IpFT3~uU.NYdԵ+-gI,%UR?B0~}R}jrQZXgcv꫊!##)Jd{:[FMciGYZ?#1 MI;mղOVW#ce6Ò9iiwa 4wQt}=˝)ATh< ˌu*hUf4MW=Մ l\ԚI".dSVe2KUԷtՄ)S[vIGmtD֜iNm2gWGU[%tX=eUv[+[jl3vAԚ馥!UEXM855Vv$k~BeM '݅qvh UJn[[4! ԒZ7nT}Wh0ҋm5 xoL9`f)),TES[릷Yh~)(}Ր6nxj?='i5tg24Jvh4|h5mWo*NFFT{jκ=gdJuo=1lަf(ַm"Ȃ m%{eUke鳪^C|jX{+˫]%}]Bn(C{سɃttTYUGW=VQ{G$sֆErth-)UvHbn(ͱ}k)OU1Mfz}Uă$Қu{Ui~_ny/cKy6M(Gr%3z'ceXƱY72t厗aH2[iv%ՖJUyIInkJC-gUXjPb?S=m: ?'U, 73l^lN9y]) &Yzj,W~YhX]WZ֢Uﴤ.iP1t:[[i]MGml; X,X~j?M<̑:l)]VU5ߡSR}_+)&N/] =UF5[tԲ7'f횪yE!~R{$c{2D1UWd'B6m8(К-M2} E57m9f8&ݴM3\ّ􊟐O{USZ]-G?R"4zb"eY׿k:=+j4Wm Guf6?S;Y~YWgN<GeeSWzbCA{J;aP TֲW*PjUe)U/ %/(ҵU%ngSQt_5MG۫Ke:4aer=RjU,+=:U4ȣ.e5(%=U_o5kփ,Wֹ씒3NեF6Skf{+e;[Fkfr$=iH}'HDQi ʌRXTm!)R>g14i)$Ut!RF Lj?R4FnDks鮴9VF`{Umjl^kA~Jڻidy()D_HH o] GrVQR=IMTAiE'jjuu/Fկ?^sZQ[UGF`#Ƚ5_O2 C0"G=VdUVsҁ"v@PG4ji6ﱥ, aĵSjQR-C aJwm]ִ~ZׅtuKY$EDR 6hKkO.kK C!55Z^'.j5'i65A*k0 ]Uم]+7i)E:QZG?u%}U]!ip0Zk*aCZZmtY]'U;U#M֒]ML*\zke(kb!##)gt h*!m5 hMcRV,LԐڒ[US\ܶHMmn{ښ]89&uF:jNf3jMNkMaSY6CGK5iaT͠klT[YG1Wuf#]ݵ:Jgus˵)'[S6x?B0T=Rt5].WzjAiXmk'ս$Vj g}&躩h5z?Mmb6nGFyZGf+>k[AdV;ʆU=k[c=3j[K*QIkI53RzЍecV]e'ڹu\C0 /jQE3RuqV;IAcdy*U&n듩i=m~ҝM9J%xWQz䱒ޣHUSU-w5"]]\tS{&`u4[ܻMRmSJKrӚPa5v[c#*Ϟ:2mjReI\]M`srk&z} \vUMM%;y}޿yKtreR2o ~NNjhr[D1_5U嵳W~-<6v򬋆e4ԯU+J^ݫX6ƧoG짒 mvWoUu]IU54< Dj$GM :1HB(iIN.U J6Ӫy?CU"ⵣVU^y\mtcڧE(QTQj+Zƺ9WN1ђR:- E)kM0v{dj?FX?UTRtN o~[q&]wuz@w]4"t}UJUm{<ZxcBӤf퐺Uk55$68aUxUaq$;j͓O>׍Ik ]G}? 5edf?<Sv]}NF1˲^Qmr|d؝;8ﰚ[Ni.bY&?s:紤$vS[M'U؄|5:EY=4R'c)HW&ИMGUX|tOog\v2‚"%]A*]/Y[A5كҔMfMM榣#K=Uhev՛]y5zwk[mvm5&LkS[K=USB3Z|[氼I7!#g#)kI6 k1ԍfuە5@U U)W%3r'%=!d?UicW,.{JAX9j3SS|I\v2ꤠMV]5m#k[ji.% պ^אXPi}~`)5ƦX*)5)/[6)\~)(onůKS&yR{3\j8mo@_Hy¤&Ǎ`5$F󃩞 oV0-Ma tYRyLGGܚZY΍"L/ڏY/R{tY$cU%êMffUgUOzClq5.[ZB1" ͮ<'`tԽq_[U5]NMa9굖G53ԇB7UT~)sm8J'5wXT(BSTV՜qWUVqɬhu5] $Urj>ВYUYGl ] HK ҍjȕ%"ե2t*Z-,U)l2RIpQv&M[/KUƯ\vxwl&!՞yGU_GdKg:5A  eU!vg%U֒W٩_zjޮ3LSVj)uY_weQսC꡽&s)W&7Fђ6qT`pRQtIFkHJMm]ʪA|KJY΍aJN(i,DSwQI5[!U,HF%,Mh(` MY^?ޣJ^}T6ѩPʪV&M7zKJW&:^|UdʪA|7-&jLTHrUJJD4c)HL#ZHHyzzRޮHp1&:Kn>K:e"T$+zMc]eaRd?U}1-%֥-& .JRIuGy+\֔KkR|ky)=}7B{I4^ﰌ.m:_4-W]%iuzuGY-] q Y-TDR幛/>mu3DDNaV<ܫS]rZRx@&cwMIgS)]cJP: 2#m0U/NYT@MK15#;Z)jT4?eaQSU65Qy:C!O鮦j?\w noEGڼi]-f,B"w,DZ鐈lJinO8j}fSlRI䳝SmHSԠ.iM,E1\GCRWWj C*K$9Je4-iGTzYMm^U4'!w:UJKrOR}#H\ӣ0% w_G&XWG]jsĬ4Gi枖C#J4Lu.߃IReΪ媚M檩c]R8MK֌OUC N~)(U2$<֦=r4%Mi%5.eM NxEZ&)K!#̀#)rH܇UTڏﴄlsiY-is޳߻`m}ai{JBd`m&{)ԉ:%YȽKю !õ҅v"sRztr Zł4R}!a:3,Ц.cH->\vQ}-vaϞ]TT;Y#o ۾m}O%oz~LT tsH:]:>EG:䵷>:ޏ1Kc]Z}b(աH(ĵ U/1s6JoWSR bk5vggg 仰|Kcj`u!ܦ©,٩_KΏIYe]VR:'vX{ZվE 5[|pbGIYU(0_ZvDYtf2ϵ.,\zײ#􌊒eH%7"?SSF1jU9QHWR5)Z4%=iHY4 2D-3koUcUR4IUݼ: o%ʳZo"q8= U9sfsДح]cU#H_H,.Gt++=]!U)L :[IU2+yt|3]ީA+UovdcU}'թJ *ʊ=l=lyY ]#az_ݹL2BǾ_hWIMHV? (}2^hjW5=S򑥓Ř2z?|fxNANYʈjϗL _GYegK\ֵm=?{_la\\55.K,TkJ9}(d=o%:CJWTˎ֟55ٶ5$&hg\S"A[ɺU+[G*6m}tqԅ,(!JZuL) \MTۥUwy|*5QzgHBZjު$– 8F1Ⱦ:i*sRzpSYb=5#ϙ \t}Xҋ8u[ƕRRR!Y5Tf%dV MVdVpsk=RxsBl`gUGUa{=yk%*(kB-fNr+Tfk:<7kro pV],Vr;5#WԵvƉ溨Mߩ2ijTNv^U_IfhJ9/-5SD֔%H)#sU+>?o)c]ct /fMgk94jj:MJ]IޚvC9bkJkpԖltkei?<xQ:A`=aԷ6G✺S5UJc)iں.{0;K]7rvl =kahn?S,ڮtoI)FsKG%ӊ9,eWK(#MG'ER1ЏzS7Am5?kkUS6O:iY&fB=v xWL=iGS DXR,v0!UQ56?B4vSY"=5).?IY%kaxe55JW6j.ƴExWg0쵛]*mvh:OF(x/szCKذ+S]!Y u0 !#3#)LMƼv5k5UU5S4S)=Y,%"EU]aOc)Uem,&9}.FpTMe3kĒ)nimn.ﰚ.ӪU Ki)ک>})cOD?1:uKBiɓA!5rrLrEK}e]eia&y.z_ {)I)j 4ʦѩJZ5OGcQz 9/.3HCw${OTSa ]#WpWjj?q uR VXaaGjEtuVa\ԼͪQiѮ[K9,ᩊ RL,,{G jojv.9z25Q7O#Y-5e;jw+&F/B^UzUXayf`ԜhUU!4L*jAgHtXڪ4kyc9EhEEz6tVUD.p5.IڃZKښEzQY=Q`KjKf 5<ߡSsdڒVfG-U6ƺ4!}Ģ*m"K޵ =U"c&{6UњUY,0STjL~zYŽ>.}8#֔zZ"ji52Rڙآr/֞ﱄi1JRNp!6HGM)p!5G{~ԅ,TMu69+93nm}-/ɬԦJiԥ"&?;=]V봝岝Vz; 2*.9ɡJU-C!KtNMo]'޼`{\Oj?4Iqg'U. S͐JѩL({_1C TSA|)rNFxXZj?R[ ܠ]|K%Vj èc# UKgi. H>CCZIuQ^)K1X- $SiJX)L)I)k*X\ ~:\Zoj٫!\s 'սUtxl_fM Ni c%s#NRR)kB?Bi,-,%ª??skK lUKԥ"!NFooޭMG/[S5vI RлR!՘FT),'Q!4dMGR3 R$cMJSw?<=}eMaJzcIN5ߩJR52t9Yc*E{ ZkGYleIX-M%>#K?Sz?BFi$4 R:r%ZVbgG#J.oiG),RM#YWF),gS<"bwR\RSR=9$UgZ紤6$%ARgbu:5#Wfu=ip$ME SRR/[-7 I6[WPGz6]&Ƅ(:*y#h0]Y|fճz?4|!qeMUXʫo~Mw-V5W?5'L~)(~crZȻ-WGYbg:g8QY!DVS[КJojjͮ5)I ]kG9(GҹR a,{]w|hBk0mv4:æɨ%d=y>OR,2?ij粪?<FidvYϯVbKPF!Dz\5K4[Zksucōil0ur.]u'mt~Z(hRΪA$;5XBMgUG;Tv֤mvU;J)dӱkb, 3#J-v/RmtךMryMaԛ]|&H)6YmV6Z_m,=A9rbD1zQuSTG٪s9_O^K[ bQHp|{0$]4~vc2. -2RqFefEibPJDI'FBiEDX2 &zkKfXZMmꩪ14XƗG#(|VԦuLԧ㶩 bRf谚sjGDX: )]dN:Q'"DR_H?15Bj_#U#T!USH~)KćRQRS2ybw)iԧDfԬ&JߚIk!g::嬖q`&]GՖ5ѫQe*{jGiajyMV:ﴌ,t榤a֧i6GI+%5rwƐ#ςbj?q[k9ujv43M7{uvbzejhiXZI>l*UО[4$GM ҮA7 `}#͏XWF՞Y:J"i{JR ;WROJRQ[6:vI^avURrq&5YŦlsX좈JЍ)x RuNm i+,+ѣo'rmt{F}5xYΐb7m}Լ䦆?Ғk ԗt}v'!(z?Ҕ)3y"ѻ."{D"mtuUl,jZgi9R=,kȝ5O-Mn68oshig_"^j׼'WLa3I*Gj5:W[_Cl"$Z=h?9*gsn?Bi`њϪZyNAv$eIcU&#}ܥ䴳Cjf*«!){^;2N5#Y_lB4jjR\&GVXUY#ی]^zY΍Xڱ٪-GBky3)_FG%fzu4Ys#n~*lC"ߡQbg}.5K:FtR56']oMQ2<=Tt]]UQIi$U=X:rQ_DQGINj*V2qFtY k1ȕ&ۯT1/*κ?ѣ-UFY򌛗3sIb2OcUшj{ J:'<vOUY.Mf MhMsS[&o(rjB6YF@*l!7 G ,haא[Ƣ&ue{]}\ODuMtTb*OV/G,8Q+ "I屮$ ^(}5;McVmu6jM>5=S<~N}qY)JQSQw@KʪnK[Pa5Mg)([ E]ҤsܤTXWaUvBWҲU5SH})a:SR]=S}rGH*UVwX~{MT!4TL%ՌvR*N*?5(bY]Rpq}-*G;ꖒQzzWz섭FݡWO2:f?B0M,EБU]92lgFfEz6+cK RS/:ۺɏ:y,+U8IgG\#,`PeU&+L}#f%>aToaiay"`skW$=⏰LEޑk-uG#MGHO-Tu2*4DQgWO}SE MKds{ n\NװNmGMK'!&ͮiYEQGyHhť R6>sߩJDU(!(].V6mwi>Ag]ի<^5E*n9ւv^MGҮʪ;%EN(ϞJ)M1]ZĨ2S'cXWHtl})e9)ERRjX?IMy:sw}S١"U-NM5vr,箍$MTXȮ,D!2I'3 ?RQR)8z]~uwza]ѥ",R b$Ud%v5HU OIYk#URR#K(ԥ%MTEGyvUih#*Cj?U\^QKcU%,SB%mMSQ2Fº3F"<5Q)΍':VQUj}+WGgᩬ&ǵ5cZ !ՇMi${AvJ–sR*Rs!HXFьF.6?B4c.53#8JibjRDtVIc.f SY]TzKR~)LMM!xXvuڐWIæ7 Og/=U-S5T/\Vft0k>ꔅ,iQFi+%:6*G6^&t{& ?>vQQrR#%6cֺ$6w]JG2MpZk:!}S?MH6{(ک"ԎFR5r=1(1VUmGgtos&s&w=}e,G|37M\匚jlZuWZ#\Wl:}% zmJNTW+vCB[i5297kmw]&jy|ZXNsuh9ԉS,C#Rf]]]mG $ő:ٔx묒c8RSi)%Xto4mvm}GW#OWaUL#U5'+ #[On^"X֭\ ʻZꩭKLַeG֟Zk: \"c^ꫮspK4OL5Re]4`uakyϿILEXBս-[,KtiY&Rmb$VPéMv5XV&7mv!r'5a]?_Z=SO%Mr+^jXWG#JDJ6•fS\] 'v"V*ؗ*Rg zYD)fy^yS1}/g6^]vMók2mt*3Ue]Fƻ >Ƌ5Tяﴥ,gG!DLyɌjkb)VjdG9KCC# ҍfe*!##)9HR%H~&Z S[QZJ,HM%RX ۈMw]i$UX,jk%6ﴤl?Ĕ~!gq,*1ꗞA?I5iam6]_|j?[WgU435(#7NTf5Tnz0v&.S;1FB4N1QBm-!2i2XUZJRsG?$涳6b.kܱʺ3Iaj43etW :FUMJtmY%e3ý){SYk4c)K9Jwjzwwzz5SU5n,ҍ4ig*3B" NT4-ѫG嚙ѼM(:$ΪCal_MaiU[M~R2;VCaj?K<eTo& Xbj?FXS:7Q",e:3HF"-"(i+e; 6 Q^McS+Sjo55wuw]Dc-\e5v]k6mv$zjG?UJN\MGFZb N(i,ERQehQ4N@?IYe]ZDRYwxuma/M;MUS.U,ZsBH*JhҴiFcoMdmtb4cW5V>04`+}+끜L#JgF'*3F"WJ?F0(#H34#1er4E)(iI8^Jj?F4xGe%/{nWpE5MGM'F2A4ƙ T)3fB,g:1IYHAd+!eUTI h)M5/LR15SRy^jY`IvΫЭ}GjM 'H'j?OW4 fGtf0'G&ҋU])Y-tbhR")Mj25*UTT(13o ]G)k 5 }5]!g}5)5)0J&'` ͮųFʫ Jk)]F*FszG{9ј1iS3IHavΘS'3Up0mu.R?Y-v4!Mbfcvmt55,R^?I5V,Yc)[.%}95!SmwIԇSS!+ eTHѳҔi|NxRQG)JN'?˳ƭS-t3:LjFƹ0r$&R L߁s]%U]Kf15'pWgUSQ5[u',4b]V2dv?OYg:5yue'M1iƪ1IjBi-SQ{/-5_aSR?ZZf#}ٽ)m<nf{:eM54dRExғ9JR"FR;,[#UYcT٪BjZ&}ڤ5HI!%#)1))a2j45)u"~)LU4c)J"jj?RY0w=c)InI[jnstkWñƪ1%:3Bwk JvWrJl꣮I9R Dn2Ϊ7ZEriz\f29MOL{),\ﰚQ1摥tbNV5kc<ܤ]npΙ?JYWG\Ĩ뒲ZH4 VD3MUƻ6?MU=uʖaaXS?B HѥtbzJ(i~RudQj\thUҠ?UF𖓊3KFEВDQQО",']3}5i)j(JUJjQi^k3a)F]2]u $4˩ca95&RUc ʌR,3MGXJgFr0J2MW~?O,lkMRUWz~f*l84kUvqɬcSK :%p>n T)3 R"XQ%NQeFK@̍!"eZki]QI<,= cD]5,!QXL&EjDR `JS7q4Nh4k=U*ƐMGh|l &%!?tvAIEiZQ4yʵ,z'Iﴌ,媫)='>]5u5&V[:Y9Rq;xfmtBFh#G&%""̛MTJ m[:x!g:M%idLk~xML֓QF5#F)Q'E"bHt|lTکṰJ2M5=S{XQ:3"TmJM*G:F6uRґ]=^$Yʐ#FNB0IjDQc1JB%F!N(0E /iX(0Eш$EiG!5"()3Y䭈vx;)-"T˱1zKDxIcDQRXu)6XU5S]$ӸP'ItFѬ'ExDX*B!%3#)t1F))(#ФSgFfY26QWGق*ZS:Mc! '10HDdt DHX2QiftvF)ԥ,zX)i4,Q5)4lҦGFZ'F%'G")y?R4ΌM)/}|[vԅi^t?X:1 FV0MdDQ3FΫc* Mr)l#%hR94DR uM#JgG&iE#rGI䦣'MZ?RQ:ejܓRihVN]ڡ6UQR9FQ!摍7;QEXZ SXy&0݁0J'FЖrE,/)!1Zj?FQ!IE i#L lX;.|x29HF"B*,̏) gG!Ĩ֓R"R"()I#FcQ2 7)FY)D)9HRqFԅ%fR4QR1:c)IDz?”(#I#F)QMIE)1b&4\]i4ΌB!FԚkIF#JDQ1tԍ4NޡHSbB"BhDQ“6DQF y426?SD#&&Ҋ4i"();#(#IWYvqk1F!N(#5iFe;߽ LcH34QФJcıRjBiEiF)iR"RC)JbciID΍aDU5iS:^uhSk F:BxoR3K!qifuMTM4iRhB?jJ)RX(!?BJRQ!3"'Tצ<UTwtiHqG%")xFnkQ1JRޡ EƔ|(ڠ5SQ3XґbJBr(aFw9QN$e/MGɥ!ʎRF?F(K8b(֓RQG'hjhMGR)I4%)R# 'F!N(#ѴeE!?X8c|i(F"cDS aHS:9HR%Fc$:9JR"FY()NabU1Mg\agFcQh34#(jRLkޕ) })(%rD?B4uJ(JRR1܏P)9HF"cab1I{!DՏ(F2'Fc-") ߏQ4΍h}!LC ]ﴥ)0LR>9ޣ ib() ʍ$b()9"M,SYQGyi gaj?F(!H6#Ff"tmF"Vj?KFc)Jb ?jFZgFiJDߦ# E!FaJDQFb4E#G)JJ('FԖKJ'qԢЄ))'%Ԛш1EtMSL~!LQ‘fjiz?IHQ:3c8j?BrEBQB1o"K5"(hF"MH(&Na4"TbNab()9HR"QRA?tf0E>!'*9JRQFiH4Ny!JgFa DQ3HF"Ɛ{aJJ(iHOj?F&?M J&ZhpBoa4%k Fі26_oj?R4sSU5&5S=H:MҖs?}%%faN(aNRXS BQF&Gd$i-0LΐrJR҉?)ib)?R0Qɡ34>~?RV7 gTy)LQR:7-!L2R"R3QZBQLx,SڨM-3RYʎRhD0%G$y(I?ƑQB1fifQ'bQ03hR3HF",b)DN ] j?H:dֻJFNX™шF#F#HN(# E01rE)84"(!H3JFQG#Q4E!(h1:3 B"n?FX:6#(7J䊬)UMR}TTRhUzj?VjgQ~MXMzjyjSj!JgG!DY4ebo,ZqGmeLJaJD#IEi8%rWJ?RQR3JRQG)HQR9JRQG)HQFr0E!)%_8u5ߡHJ(!1JB"R%bEa8b(iHG?0QFrE)F#JN(#IEi8"()H9JF"RQRrEiG)JDQRrB"C)IEiF!DQRSQQFi DQRrE)I{a(er"RQR1rE)F)DQFbE)8"(!E)FiHQRfEiF)DQRrE)FiDQ1fE)1R"(aHﰥ%bE)Fc,b()H3HR"4")|Wzi(") <y)('>k)1HQF)JN()H3HFQFiQB1f0EiFkIFb0E)FiQBf0D’3"R"))IEiF#QFcHFQG)HLb)H9JR"R"()H9JR"R"()H9JR"R"()H9JR"R"()H9JR" ߩJDQRrE)TMGRk?R"()H9JR"R")E)G)JDQRrE)G)JDQRrD?R"()H9JR"R"()H9JR"RAoJR"K'rߩJDR?RrE)G)JDQRMԥ"()H9JR"R"()H)?RAxJR"K'qԥ"()H9JR"R"* ߩJDL~)G)JDQRrE) ~)a> JR"R~_~)G)JDQRrE)TqE)G)JDQRrE)G)JDQRrD1E)G)JDQRrE r'JR"1E)G)JDQRrD~)G)JDQRrE)G)JDQRrE)G)JDCSQE)G)JDQRrE)G)JDQRrE)G)JDQRrD?R"()H9JR"R"()H9JR"R"()H?R"()H9JR"R"()H9JR"R"&?R" E)1E)G)JDQRrE)G)JDQRrE)T~)G)JDQRrE)G)JDR ~y)H!M!E)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRoԥ"()H9JR"R?~)G)JDL~)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrDRrE)H?JR"R"()HA/RrE)!E)G)JDL~)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)Ho_ߩJDD?R",zkQE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrDRrE)G)JDQRrE)G)JDQRrE)G)JDR'E)JR"R"()H9JR"R"()H9JR"R"()H9JR"R"()H9JR"R"()H9JR"R"()H9JR"R"()H9JR"R"()H9JR"o?R"()HJR"R'E)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrDRrE)G)JDQRrE)G)JDQRxSRrE)1!%#)E)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRߩJDQRߩJDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRRrE%hRߩJDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE) ~!m]hXU2RrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)M@`JR"R"()H9JR"R"()H9JR"R"()H9JR"R"()H9JR"R"()H9JR"R"()H9JR"R"+=l{U5*t匶@CeDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQRrE)G)JDQR '겙5Um*|Wt榴}r:ԥ"()H9JR"R"()H9JR"R"()H9JR"Rp@ @ @ @ ɑgLpwj̛*Tϛ=6hPcRnQy| 2&0 4j=2'yf" t~)mYP YY 6@gV"()+wP3DQsf+DQ@Ɛ kA(eh4E+T"jvVЈmPh;ZTW;iVԈU;cU;"g ]!SJp@ h5454JhM M)&@SU4B h4M%4@̱4HX04JbXfw?4̼S;z;[gyUߩ@ԌɠbXbxVO~t\5<%癲Y2(̼S;P *BT{x2"w5HF߉U "CA GvDQjDQjDQjDQjDQjDQjDQjDQjDQjDQjDQjEQQ=L~c7( 8W:p]L5-Th jjhSD54BIM4 454 SD60[IM6M64@u-gS#"dҦO+Raa>p7(*D//|H~JMݸ̇³~uWP!%g#)>~:J?I>EͬH\+57ȼjyEgy/!3d€R?PqezFDedFDQAah=#(2h=MAfDQ5"KQFk;Q(5h[wwO{]wOKl" ŪjU_wx`a#IYIIY$Y$i%&I)5IIJMfRbc2hAhA2A4 V`d"ǂ畩dλNڀS eiA`Ț뺛~J?RSJd/vH2o݂领]2_핳IqWtҩdo4mU79N=ߩJD@yy;yyif3d\͕QZZhJR"DdFYFL2"HɆYL2"HȌ Ȋ=#"22#"(0Ȍ2,(2"HȌ Ȋ="22#"( 8 2#,"zgAzPh=(2e"T5"T DQjDQjDQjDXnAo!_~*|!.Ã&ghEghEY-G2h;-Ph;-Ph;ڍPh;#,-F -F--MFMFM4E"Gd|QO?{ ڹ|)ɱnhK~*q*p@ 0JR" lSRJR" @ )HRߩJDQRԥ"#ߩJD@ ٗ?!!'ٙ#)1++zE@!3x :i@3ILfi%$tM"amkle<,i. ͛`L |Cf&0 *|]fMda6Lde6Mfd6Mfd6Mfd6Mfdpb @ c$)7I,ȕ!vdev*麞|2ښey'(tSE/"lW=$ ]#)Cjm|ږ2D"K<%CmgR^CH3\6ͳͳJ%fmRJ>86O6۝<< y^Eo^Wr"drB&x04gi" Z"@ȵCE(5zZ-ghEY-GvDQj5CE(j5KE(hKQ(hCQ(j5KE(hKE(hKLvvTh;hF"[iΫjeE#ON  <,X@ %e>KLM;Z-UM34EhEhEhEhE3TZ"֋U4Z"ƋUb(h\b(h[R"֋U"ƌi&iQ,܋ ;btȆXTC ־QD$4m( M]0 KBdB" W*p@ wvPL $ S1(?eAXtQQ(9jD@ c0eEݻܢ4i|Qg~QD7W(XbF{΀@ M z@ M'@ @ u9N#L16u{4ӻqԕ\}}h4]JSJí̢Gj4qO>`dLz" n$ZXY+Hb̀4~1  @ v|]f*Qu>.`T YP*|]fb~7otuY(clwmu4|4j\jTbVCM:YY>wM̡u ïJ@J@jH% h0%@`%!u î DbP:U5<ِ }G2 Vx?k>"!'#)ʈ:v["6h?HVN]f)*n& %(o` ldXGeYGTjYEM6i}fMJ{&CqPZ蒏kݨdEGYlE~^E&pIaDV1/h5%7/8uEX+ *Zbo& q k{. 99W5nkϢ@uv ׉*0qB$hpc ׃!wFъd@BDS1H¯t`"0@C3mzxD4Q--Gp= X0S\2D 3xbyctjQ$ {_l"ekVhwh!4 %O!5fl Oԥ" q^| 1_:y+DQ+X kZ"{9QCH=Ԋz*DQ@d6,uB@Y@KDUʁ[0MBV` >b"`8׀14,]fb;`!8,wNtXY8cfpxEhfy^V cQ‡\7P 97“X2"3ms!$""!$"(EEf"pA{UjmWGӌ5qy7gy<!9_+朒{YZ5cGGzTBnYErj?=@ۧY2fI(1(&YARFPD"ƄDQ"ʄQDX-o>^[Sj(䚍$ER2F"櫌E""3y~m7+"dEW4EI(i#F1ocFh6Y(О"OG(zLjO!52=]H{+{_VLI L 콁e7 sRg|`I30 `)G0StyfAڡYTE*ƂUDQ؂DEt"̄KgȈlNmVڭ(̐M(ΓRH3-%2?+>DR|ERZniBimԀ=&UX1P3 ?6`dITSϽz(oWzxmch6" ؊֟Tm/QZniiM-7M}y W׶ & )-G귶 ɓ `Đ"(h6HV@ 5:5d@Bz6l7K@;'&` / vW=@@a}@+dJ&Qn {PCE{츸?$o/ًE I2 E`x$ސփIȚZ,$߿V@1@ hJBnax>/K@G7oݯ$b@n_â 1_%w@G Jӑш}|D=%( 7π5C|Z 1K Gl>> Qb }$˰&\EH6s<.` J k<}Kؘ>wį\u@D}\&%&,JS 2h < s=]=}eY9q޿c?1zmiԘ=M:"a1` K) 8tlAx<}QfF* LytՈ8BA v@WQ*ƋQV$DQѵF՚D@ #$ҕsJqZ",hւhtQڣh!TNGQJ4l+\ERDh:SZ#Z<GȍZf"u\E\A "hİIj@x!C1P.7Zye|&ܣR(JDA0Kp K;B⑶;I7BwV'I G|UʫΛ:yΗm=[ZkD!#JF d݃t/a6])3O(rC,wm6k6s͜?]M{/-򕼩o(򩦉'ǟϾ+ $ZÀe%.XCg8CMWM>l9USs/<ԥG&jdΐV[ҋ<ۇA -,tq"\ZMyҗ)X\5Qa>j戣5qj) <}>sSj^:C9,f7`0ktX3s!'̀#)L[]@dlwt;C#1 |ZIFefXB"MFcHQh9b(y"M(y"gy(޳b._uk{zzzz{܇{F,o&E{6`?$kTlX%Se{ha010i! 1HA3K&MA>顔9GyK?K b(̰EQB~zGKfGKfGC lE_-伇cb!卒6)Ǵ6,lCm;^/6(m4`C1dix^*dqe6lHcn!#!]ԥ") (_R8U^M(Y} cLPaڏ0h.`PBYX.2ʀȋɤ]زUSc4= *"BQa3-%0" 2?((h9g9wM?X'?˗^\>cIGu7`Z0[__`J_B(~#V#Y(FYE:W<GDx<+G{PFQx=lQy^6QyW lEGeG{XFQy^6QyW lEGCdG{KyWy^";^E<GLGzRO:!B% ȣAYh"ʈi.R]%b( wL)."Km%K卓tr(dɺX\E sdɓoQGddQޯ{fMX؊<#ڲjW&t\E2VGgx1=wO?SOX.&Cږ|6K?پ˾$zMǻ! h ."`ع/ x5众Cx%j5|g8 \Kn ;_%<_%?dUo^x@1A X ` P"`MG@^ "3 Ypx."IቑtW6C~O5Y7SQdot2jrb(W&&"#3x1?sz|E]蝩+T0!tCR8*hRta_.Mg `$v5# Β5#j8 4ޔ/e:)UCd>BaǦM:JYś95g؛& y597Qb(3w cPɓHAӅ6QmmZ*B0,tY2α_`Nv8nl~no5y3:?,x9oo ދSÀ@!'>kEFI~בld a! '#!?Q/ h} !ۣ (Vh`0!rIZov> ,q˴ % %" }7H}:~]@_3̫/@~cU'Z@#D@f;IOy9Y0* YAT0>\OBqq3APU)'B]M,]|2ԒeᖎG@@Qg^nWa7RhR xC(5,YD}|[ E+00ď  'PT`CAi ,N'ֶǶV*=.iO#ʻv*CI ]뻳d0aE݌TZ L $ $l]uEFofj%[U08a=CJ@!Fhv fVO'[9ʻJ tJ$vru@p0 euRY?-s>7su۟Iw&K]軳=n>k@Ɋkꦶhgoک]-Wjk5Sc#268ԑ1=χShԔZr1)ws0+NEDRG'~C'K73k.f}wkuʦ9M!9iWvtTO4g5ȱOkW 黐 <}8xF<;%;<^9%G",I)jG"O̮mny?eUWv4jM͌ʖ.LtXU6tHodXFT14~MJrjuRLKOd\>\7s̩ͬU7>GuhQjZu*7@+Q%XBմiL1/|3U"ɪ戣j(욮h<>|4s]=ѝաCr5dؼ&p٩Pmc)Hk҂Y#b @@ [2>8ܮҢGWwGHj.R媹ﯧxJR"e̴Y!6hXoV@‰TZ!0&IUfE)Fi DQ‘A`F !'#)#z:DQAp1ݪDQ `1!wZ| x"}. RlE<OE)G)JDQRrE zr)s;tL-'#`ɀ bzҀ/QP ,p|z2xPDQ[ra+dA>&DQI`msLQ}$,&\Q"(2̓,82GYeU8M 'U[Zoҭ֣ߵF՚DQתvoaurm7<>]_>(hC{%tuK[#Q-luY,ErIGt+!G]'za7&ױ/%{ccyvQS'+y}?G+"5tö__gvu S),EAlBF@1u-<3 R{_YLO<@! RMn;]S˷3!s\V7/r>UI?9;Ai05#bF70qavO!)#)~4 NY B<-!H@:% Jt@1,: nP#/{w3yWgfOKZ.3liN'T*ae(tMp̝LN:^BnX#\a=i m ֋&KE[ ҕ~&oIJ-!j;x8v3^ vD`ūEJ Ύ&CK[ lguhWWZ ]J&9q ]Ҏ(s]i7ix]sHl irfFxJR"9JI( w{ea.XU1Azs7.%K(ޝ#%R(yyvwɞ/=>tQ >ZJl*^}:&* FQAę43OEyVrz+".3t5w ( z$dtr@`I8? Th^V2,U~DIjtvR~ -PGe`P(K&]n("Bp@L,ؼ|`4ץ y]RsN%}^ϥ@'Gyd$bC"(9d˴ d8Ť2Y2"1YpΡ&vJ>&Y2PM$x` Lxd *B=@v+t> "{y\PJN~7JQa:"+{kkDl*К6yXNQKlOO_hn~ ]41 d<4[y u84F R8K>s#[B(3i:i6U(sCZrZ^cgM)D8Wm-tIwc'EXE4e;@ ,@(_~PT[[Ya11858 `۰ HO&ŵp$ gCosVzZ'5i/-aNJ zåqAeɻڭ1k,9B$&=6 {M5Ҋ(>7]O OZOi7v*)CEɶfg%CIkkmolU5 ݼjkH`Ξy6E$M&qԠH/GZg?hvF&N\<&G)户jly*YZk,mi>k+Mw1ƽ1]CId{k{?IYQPttrg$BkK#= KSZ,nb? H1v9hte4啖_ߗ(]5\vMW4E'UJUii"M]}KIkqgrT [=܇O8[Qg(G}:E13 ֙R`G6mwMRyic呒1?M$b(욮h;&"W:y(R)W(ՠ ܖ㼇 T_K)HSf te4K@[c&P\QY\YԛKc9cG<*<ys{l,HQb6" ؊:u8نX ˺h3<^֘Pݍ֌˿,[ٞ8/HX{Ϫy)H:B &)a4ؤ919 +@@Q31Hk0i$)&@ɴk4YIc9<坎_gsxlLKżax6]ycbޞ<!݇אCCȴ4S%Xi[EAzq`rX^+b-0rԯe_YgvO;~5!24 j?XH@ !?xp(Q:!)g#)6Gt+yR ̄mqB bq[IkkC϶4YLg坮_=WrSĉ2!ɟfӉq4h@i\> `oaܸL{ %|rͦv6'gE`̃e=_Jmv'XG .($pU)$?I/aG ="/M,JR"_ԥ"()H_DfC@e + zR3BTB@\thZEgWd"EȉH!QiW&UɺȻCt49K{,F_iD"hhfP }3@ Rb0/`"(\%$!cKzr b P\O0@³ P1,܀4 o|AU DX_(y:B0~=VZoJ %$4-Ae*MMLϺR4"(eEFXR/?w'ۋb LEHnNb@,(?fX$JFKy` L^,O*q`8 h84}nB(C(  o`E@\|"Hm;|d,H Pt.TDQGb*<W@*Qe U TEx"`y8 DQdHAr 4~ &DQ0\'OH,#|TDQ( ܕdDZ\xP`I E Bfc6 U)p,,? Ebdj,ޓɘX0TcC,X2 5%Q|L˜J`m!ѐGqR%G ;A(#T"֕ GcJ4H7%yQޏm iFi DQBmIcFі1mce7o?MM57d\Eᓁ2a}PNkJ*"imqS(61*"imqQ}Dˊ""(@6 PG,b>㒨J6b$?hJ6d,=y Ab&?%TDX|PDMh IP%Y G ;Q( FMmmmm$1Oz?"DQKH3HR"11f2",b(2FվO^Gj} M@(Kd2dzK$ C&/~0bX# ;P1<n.NiG@ 4(|HU.b oLDE\tkQZGNX4yb(B"a5"(֓R"c4i4DQ<`Mwm|+d˷?Cv>5 mx6@q10#mMlL%.|\r`)}d90 -@q Rk{! @h 0qo~Z bnP(UR`,A d E@- i8A& q"mPA!,A I?[  |(fyo} :/&E; P(P o{,p>fU͈@7:C oh؆6@fFU G!) ̀#)8>cCT6"Ԇz`*e&}D1aZ"qt ;;!RK{ cU8 0L) v^l1LVƍeڦ"M4xDQ&EjDQfE4k33X/7}ɧ66/6@cc&LɃ95?}#` r`p Ix(Sag\'@NMXidQg`?q= vv\@R;L!L̋sT41jM 75'] `ij~PA o<4yu_^Jq!\q 7GH6aBq7X qJM4Q 9+h d> ]ak@j8|{Qc`@.%C `,T^VR\L;@ f`ǿR\\ `nrBCvU'$LXv~Àb!⢈DZc02tI,<d %&inY# IeIO}<[|IMI&?(I' Pˁ¯.l%# h)67Ro$!Fk&DX*^Px@%t`~|ĕb0ǀI@ T J IP%Z[oP"ł/Edc"i* N_t o.H"A _ @ToTP{ NL0- 䨆,.| PRbQ,G@Tc!'` ^@ VCIfr `'-8(#<Z[πVmAx0?|RJ& 8f=bMtbɁJB = 1 ~@,0? Rpp/1Fr`0LNYewBzv@NL87vyEМb.?@'̇`;-#_( .  ;@Gp1E#l׏&k4E(ˢ)F qxkIH[3nڿG /K[jB = iBXL5w(CD442B6FmKͦY5<0"hh0ޜR`/q'@Q m`^*l Ȇ 5&! @-T[AZK_"D\ֻ 2KIdd2@ȸE k`0d[IkBTc ?impIQ%DQVreIS?Iɕy1Y"(a`:(Fww@46Rθeo&DQ)pE1`Sʀ.BH>i ^l2<cթj}|ʇ4|m)fIZɉ6Miz& ?!w?!#>XXC &'v4a: (~)H>Ϳ $5}ZdWt>L( 7I(Iu~lg,g&DQ4%fI,E"2J`j4E0Kpx!J@BW&\,p8թzu͎~]92mIK ~M JR"}{kB:{hlr ](R(͇MC,,lS>l7O;#X:X5ib(E0S aP0 N$LbTL&@1*ƐBթpLe!)3#)MQ{Z~֓wuh6 Ӯ(>BCE09kN@5˽˾Iy/v%ޮ" u?O<6Ykc DQDQKLB5( 4 X\&@TL;@1*0BHl)K>ֈ˞/'b3ZjT` 9 ɜZPr@:+4My=R4&  v!^jJ@Wa{ ']z`Y/i0b Ώv_܇is~T(J"(꒲HamZ(5x!S .&`|܄&dI;a[hh㤹lJPp~Yl0`(M#ޝבXLx%79ìF̻?[Wr e-kz8Ͼ2i/-IA'@UD`ngWl'\=,yC+oB0!x6?R?f8*/]x Pjadk{A1Ɯ ޖ#"5z sNoAh>?B[+_%''oH %$j:DZ>3;Ll OmyRΓ(L #ܔ`| 3N+x ~mf0`ؤ=`aԥ")L1E!}vvlaƃ `+B, pwAr$CA};x7Au\ ޗQ>14=a= QzhdE?@ @hҰ )H4;`vXԑSh(pqqg& Ay'wFLCAԍ'7Dqqnؘ.? u{zFb&551>%abRԸ(C*ac"ԥ") dG ۋA%c*H(t}wnD^з5-d4ͧ]Gd̝h||4ҁP)GGϼEp @4HGRJp&: x]3tɐ7v]գ_zXMgQM$oh Yڻv1%d\@fB2*x>qWaBJR"RP FNo cJ܍2h.1j 0&34+Y=z7Dya:뾈yYQ~`:@j:{`F z '}PuZ:ԥ"()HS k@܄J@p geb%EctTCEj' (a}NX Wg~RC8x4@bD<<B8%C\~IKBWCC_Zрy6ɿsln?GKvDRA ðbIvZY8 DpĒOp IYg,we}fbQ>}ߧuᡨvXh^vOZQf 8+0 rth "NPt4g]kkQPeQs.ӧs: PP!T7uߩJDR\IDՒGJ AZ~bJW Gmg"ACsc3빷Õ{蘔 ~&!OC_vwt)*cח! :EIjHAJ g!(_1gixBnWH|Vm(hrГ]iҊ(yoM,O&{?) l^$!)#)*i #ߩJDRȆ`hJGvB&4tQ dƣsQ=TB *}Ouwv_A]o+6K] 苶O kk7:tqi q6leX|[E M2otϰNIy{M :4"is̥uks#*o&Rfz Iy˾m9(<`S}ۙ<0^NI  !-,0nY(z(힪xG0ʎU>t{]ɢ4]ݥEki7vMolCHkjkXykKG^ǜeߩJDFJ)%bUX 433If"tÑf.-!ȹ6ut&J2$e/9Cqﱽ{q |QiAF#cKj`FϏ~ !_g&#_(;x:;(y(FI4E!gg6YGiڪ"vRk]krlI3ˍ>Ӛ$ci>I"}X 0@bJGذ@ጔ262-ֶkҪ(IXn}(IK Z``لu?*@c U-3 |4 D[|x5=]5 &oGmv>0P@Q :!sɈ i6Vޠ`;bm#;@#Q?y!`r&ַxOZ ks ml@='Jmo߁xa!) #)%<!xa'|'h.#t2rHH mknBJn"h3A<"d"D=yIKSijb,M LP ]JUCY@7< ^+S?虒Z A F$d)dHà Zȓ E"\h?FG(7iw4Q=&fEmJsf1v}7ޙożcQiH/͆l<B"-"(2">>薘=!!0(, 5` <4jCRz}bR4B8~@$܌H LR Fmy« """ǴvrZKGDeEƮ1oQI#F1m#F1o)Ge$EEDQDQJQFhQFEjDQj4E Kiܵ<z?BJDQKH3IiFԖmcFі1mfz%1w],0@D| A^NWn_y Bv ?bHe0>(O$ 4@V$ˊQQjQW9d"˴EڮuRZDQ%(SMGdjGe$EZDQdEZDQ$EJDQI)FEƮvRvRJDQ*Hܰ3S(I6hK6hBmIiFԖmHR",b(2awGZjM-1 ma   ;Ԓ1M,_ /O*^(B!Eg~_?F@8 2zy^02B.AEDQE&?oI"(ꤴ53QꉼEUMGdjF1m)FEJDQ%EJDQjFoI)FoJDQ$EJDQ$ERHDQ%EDQ%EBZDQKH6)Fi DQ6#Fc (oh"閘b @ 4 %<P ͨY}'H7VqfbS00@̄e<tPO=$ ŔTPeAQnQW9cm&l4EZ;-" R?"()H9JR"Rb(c1Fk"c3]?arPPB5.X 0x4XG@` N(5}"(vB8V;3XlJ)!Aϫ5TE0bEiF)5"(&EԈXH5шJOH4ԈZMH5ԈZMH5ZMH5ԈXO5Ј"(֑EaG)JDQRrE)G)JDQRrE#G#I(Ԛ"F11k3)s:d%00ER؟kh<#@7, LӠ0|'! Աx/ `_`[Ӏ 6 s>8ZEh7j?Xj4ЈXM1 F1kIF1iFiG]+)F1uҲuzDQ+)G]'EtuzDQ'ExDQ'ExDQ'EjDQ#H5iF)JDQRrE)Fc (К"MI(њ"M.黊E7S8(gO<|>.̆CA3?F?ŖjFHX!)&g#)1-}Ys{ȒB,VmgYg"a5"(ғR"i="(3MFg53Q׋R{yfœ=6L>"VB"!<"("!<"("a<"(ғB"iDQ#H1JR"FDQɡ4EQYF'bhOZbZ`1D¹e֨YP,5! tK^&/m!dmIud׀WTlE N!X')k:f =Dmј`z?6(du²X4HO4ЈXM:Q4EO,mY-dEdEGab @b`g450P l.?5P 2CXiMb. +DYkR6Л^Py拚h~]=2hlKtESмoIdų؞GۼLBɩH5l]B vFpnU6kI0J^/ [$`2id8*,90kEw#- Œ3@Sh$71x58uX/âj FMF,n@wph֚bHap<^=9( HPZJ ID݋'PxiE)hAp1昛eɀ @tZl^X''q"4lCx؛0mo Y4&&"4+^H4ЈHO,EK4EY(ڲJ؊6"X/:&/iĒA3p*kC1;: 秼C*%13M iDӛ>yG薦鷧 ori|v"Z[v ^l^N79:FFA`Xy`1(2a0R4߷o0! 5,w1g@ [ <DC<-呠; 0ɘ !7>_Oŭ(3$P^x-jf#4pk{#~^@TG(+=_%JVz7Wz ')Ą#CK>#xRûr\`! OrW!&)^0`8 (d0'_Yv 38KÒA>"͏bh ؾb@zH&Gs^FuvVVY }vIĤvrXõ0+ T1}R;>PCx `h !eN؉upB$jlgW]{y6lp@|@ԥ",6t }i!NGP`fFV\DZؔJ92ҩA+4|a͛6lزG)4\%feL"(\4EB%@&Z x*?7)!z*gP`3 @:'B~bY3yRxcè4DQe]dEUaL.!G`h#~zP*Avh7D= eBew鑽Ǖ7<Y䈣If"B"(a6Y(޲"=oT5Ynbbt*4h?Eva?rZq Y It+ yq1% 2)&B&'IjVȒJx(e!h{wL56@>%a& a< Sl'@:;aidw/tM EĎIA mvMMW]UG\F"()H3F",ms JIĎ p 4.gx&!d!@M(dO{E0x JR"Ĺ(H@td(S*!)33#)a1Ǎn>R.mKdڧWꈊ:j(y"(֔EBh9F"FB1mY*2@ w팼ub3m578N۰K<܄,1)B Zsof#a p1 H&8%dT'kcp2cb[aJZɹ.s;y q6646 L.== l7..IP#kA \b'+F{b)%(  @bh}^YARLxI #@PI+9@a)$AV٢D;@!i-Ml4nQC6Ηi MrKK(y؛K~?R NF7!tI a`aRt VF@'wzMth:!H7)F)JDQZDQI*EL$,($$Xa( BfP 0!dԧ+b !O—GBţ%vT{@JZ_/C Ҏa?Z#^BHd؆0%,,|2CW$ T9#Q?whh*%A ,=%>l S<lV h"=d =0'[`;_Ip '@ófɿ$ov#TxuH@PH _dGRdC̚(CI(.<JPA&vsX9X mX3Ik` f-<(\0[F0QDlG ]m[FM ` ` pPǩ| D`hL$䂂x4Pol&̀*1'܀y05 }½1 2;7G:'w߬^)9QHB"bD`C&+"FX!I/H$ɥ l#?Rj(5|8 MH+b g $[a'[_M6,d͛])!56|4 вA4OBM6 )k?Q\Bi5rg@?͐c4@tvY(fLؑ>)6PR0?HaQ0)iI"I5յ:"؈#b+<Cp Jy1$i  叀<G"@Pxu,6N{D/i0@ d( @q `@T`I  `0CNq*)HUb I7c0X&XG ;0 9X> z4Rx-W&KQQ0?eF;P0`>@!ai[ $KIjyɛPÞyhyhfykTd"rQ/~]h 2cPJ@1bD @$Xt+ Ih`;/VkdPRA0C#,ԛPdE CAFI$F3$dY]j-눶##0(Ihb`n@e!@4!W J0\?GDJRj3 ` N"7n?<45  2 sPP(r$g_?Ҕ"(i( bv>@cmDb.F*[HXݨ@LB@ߝXa09}%n?( KnGԥ( opO+R@ 2r@0PN5t)G)JDQRCFJKN_~@VVY0B%높} @*qmd05ҐZ; /`B / tu% x( KvH{--RrE)G)JDQ‘_&K g1;IA?H Bķ&. $Pe&kM& CXLԛ`;&y~ߒJ )9TRRRrQۣ︽[Kvt 2> f^^>Xð2 d?Ҕ"()H9JR"R"()H9JR"R"()H9JR"R"(aHW%#?|o3K,b(ڒ"DQ&V"(𮾰;Ye4)~k)B m&# !ҞE =&&4`b@ )8̀b@0Ƞ(V('?u a(3&jFGYgE+>yA3;n3qkIF)JDQRr$b(BQ#AW?Ҕx?)H1JR" DQR1b1QFj竜QRrE)H+4ɹe PLGJ{m~T4n{!_@ CbX,]@f))8VT 9H@HCAktRNI;|z{. p(@TM8801b0E1 !BQF)HQґr4EcF*k'kJR"R"(aAOK:HT8`$N0^eV0,C+p $ ,?+=-ϚM `b 'T|R AD@5KDi2!5xV%?6K/@WěĔQI>y{ߣP`IwüE`p! M6dC?I4rEIX*& xB JR"=_SicHaG!DQFkR"d?E'rE)G#R U`nORR~ brO{@!n`TC@;I @wjA=ДCa⡻ PbI*b P8p@U ; &!ax5n pnna y*WXFa DR 9?ydFb(#9JR"iHL?•rp(C0D`nb'':>N۳ޏ"twx5)G)HQ1>p(P_^\xb8kYA @1Fri@}(&_3P4^, e!,P0-WɑުZ.\ph6M&RB,jj&bhXRa8I`'HֿʏrO$E)H7/uiWY(4fE!1ґ5US?%$@u08u`ŁzD]`3ib Be% ~'6 IE}7~n0|QhF{ (S-_v#}QBgs)H? (B؉.i ۜ6Gg@Y! qrIDc=M&`ܽKFs@%b=iWq"iJDR 990IQIⰳ7 `&! ݋ K9_,45@ @ !)<;m e@5-=?/_Pvp'I #s[U]~xfY"()H9JR"R*Rk`  d3{ȾG!hd'8r>!)S3#)IG+`tqfRl'tdw@0 AL1l} g.0IĴ `H $P8$ p&=?P @b"PH\ndBJBDXr j 4hBPߕ$cT8wti43 Å%.Rr@Bl3C`R4ɽГ8^T* h=E[k]CrhU?n-i7@Ȗd*A쎮u&\NZX7ni96`0Lbho$g#q4F"#ȸdWZf` R@7LP,B:~F_-@N#T Bd <WrqԀjɠTe߼Qޔ\~HWͰ鐗S&& @ (0`ɄjJ,j(k> hB#x+VH C%K)Rv' YE"986PC`hy\wrrr(# -NC'-Dk1&LӜ#?3ur}h{qdz=R!"\W/Y=G*KRjeYg`lGd3J I}@ XQˁ@ҒM8xQ !: *Y8"MȧWO8^,4Aw`XL܉k(P H YbmA"MWJ@+& A*,^21 C]|LI(4i+ޏ`L-}uw(_k̻,#jF^&Pj-8>&RlB&HRy9P`8 0_ϐEhJb(Xj(h*ؐ6W/ q ,Hh!X|XC0|T (x8G0)<:OI|?J(#3F"R WYeyEK0jPJr/lLᆠ.pĢX% ' H{?!{A!`mQε k%ٌ%:'Jsv 0 H:Jyqp0[@ɬ%O_K,O-<40a ncuPEж'b RmVL/'0+ v^SbaQ(a@d֫: %ƀI?дG# N"fͭYkoor n*,%QRL?  5lbU׷ U1Nz`BJ W Ʉt%RX3#:= GkU$04;{|@ %ar,Nr9@*@ eH 1 p;?!pD(/_YH`b=呢( 5 %@^;@wL A'{Kx? P[BtQl`" .~*L5![Qèx5⭸a7X^n_hF:&OB9@ ƤFX0"$ n nHGtۛ[Df.0;măAs|!)Y#)Oi)i(<'2dM 0@O"ABTJ$t5]̣.0f@&8!%`GIkBqhAx'kf_ͯ5 dX3_C: %##_TG ry#".@yH+CҾ^,jK CR? XC0P/ , $n|4BrC(^`̮z0a%!pG1b2 8~l@C;ddm?p%)0iErСk#H% (7j;poKT"(!E#8K4U,EA&TDҀI h0 "cTEHQ(4$/+  íJERVdlqd2R&X@i( !(A: ` 3(( Nxdw)=; \/̯%!'H `1 ܚ[$`% [1 /:tL7^407w EKj2`:,j_T5{ /W8PD *XHҸg|hhb{ /;seGFsd!)`#)2d9Gmt.a@`6 I-?`3J}Kf`'܀PG&7_9cFDJ& ,Dth2@ yEߓRNP*L@j :MtPԒx #ɀb*{`b|QLyF","(쌓J()H1H"R"())('fU8F08 N&=F(nMnv 5L& !  +? D`K+j<9 "TBlPء @ @-.?d̠# XHqD0 tXM8y'@!@ B@;&M HbP蘄LM#@jπ&B)NlmξQ5? ByEb̊(0h/$]ZRzx/"|@fF1 +TvBqZK @g=/Ȅ?",@ KP0zRXYp - `hE,G` @Icn/7€0p7qj38f,3Bq)~xy\mqA%N} cԬĤF3_H~, Ii푟ߩNĚԚvRe!/f/Ș1Rpzama-a vP|@,|J q%p扰@3Mp&@ :)HU@0<@:/vYX~5 (q}Rl6I[„J/ GHi@eۜNCF2@ ɘ?PA3f@Lt@*9Z`I #9' [`GaBpBY8{ !b*`@! %[gIif_@4l@S ?Ŏ @0  SO'G5%mHR"0"()H9R"Ҕ'fEi(D@L(~L`e {+P>vM|XC/w10R 0 CoPVh0r~H D0@P"`/@"0y;XX~R 7vE"&N @,,q?QAXE@W( @LX >s`iI풻^/=( Hdtb@b5)= YUhP`j ŕp 'x /H<Deb$´A3])8D԰?^ p!I#^Up4ߕPC,^~GڔR;yisͶy珊$~/_JqdK` 0dIB(`JBK-3!)fg#)TR䵅Z/@`Lp< @I> Q3?"-0%"@ 5&{<p zxE:ZELBN5*+`ׄQ).0 ()`{_?}Gե8"VhE ,&@ĎV|L `((% ` 'O1@d0TGcB_ljO\ ^|@@ Hi9 (ZG"+# , „H)3 4E)(4"()H9"QR1rEiG)JDQf!YItEp"Qe 58 ۭv_ '>zt3g03q>bha)x5 0@`G$x&L&CFI]' 苊^!$i)\5(1@@{LΣd2'XP!pGI];2)5 _LLJGR;~yyy@ @pB6Q\$01#_T:b#@MK'ф##6:ط!t$z^7Yha|ݰ)wA3x])@M!0`HRz4kɠe]X$4+1`xI`(!  tD&bbae !% (bͯ``f@t~nC!X}p%d R|F #6I刣iFb()IE)G)JDQR7*RfE#Fi(#IZR9I8zI~ K( /^&EREsQ2PGIAܼ14B, J,;?@@1 7Fp#E0k}נbye?΋,GSSH <:)HGpߞyy|``rBB'xLD0o"/(@B@ K_ Ĵ B0f315Q# __oGxu٥~ +۲044:7/J" 0јM)K+Ou:)HGq~yyypC V!)l̀#)D - ` !HiD NNAGi{(`%,` 6,rY4{0Q% Dɹ4+)ߤ{׺ &f@ݐL@.sGYLż0#jG;I>8 3' "RVH3@ -'!@jT" °4c("() aG)HDQB1rE!G)DQRfE#G#QBfE)Fc DQ)IE)F)N(&EYIEO(40n!P(@:JH@]HLtC1 yICcX`$ % M,';d !M}Ⱥ@'L^⒮{I9+f ½ P^@1!H G;"  JvH^pઉ  P\ %&`% p#Z&ZPQ0vy,9 @`Q\4 âh K@8!51eglL-J)yp Xn姅PYh ̓ - wp$^3߮\t1DJ HOHX`QMautHIAŕQGA''@df'8 H7&bAE)4^&byR|JDQRrE)G)JDDa?)H9JR"<JDYD/Iր;!-վ |,E`#)i /G~g)*$BSF@1!,O'W/ !84 89(~e2@N_lD:&I-1ր疒u,(R Άyb"*C@'&"#J&NnN ֋Ȳ{X `!5=((x Pz~@0 %2@%@Ax?P'ٔpH -(pjCHItRFs?")_Q:"rboh|C 2PI/ (Z,E O  X/; 3ed ;J-#P|p ɤFw p0W9(Q00pqj A`Д 0 d/(h{)-y{O|!)G)JDR O)H9JR"R"()H9JR"cJR"?JR"R") 8 70D4 [:sϾD)v3v;{&sWp|so`^XO[,tJ&C5<tIA$lܾnc*!` v٤ k &fB&fHo `M0a4H}݆)oY@yQ-U r\ERa0ڻ> , b^5$ Z i`P6FF>bPh#]@`~K.)i$\R4]1Ծ|w^-I7#v /XqGT rI !)y#)Dz4 هG-G/~C(133\`\K[;CCM-?D8tao!mPͽt'ZR)-ox?ҔJDQRrE 8Fi)G)JDQRrE)G)JDQRJR"_)G)JDXOf@&$#;w8DH CDM0pQD20>L'1!$NLJe`hәi A[/\LLFC@tM!1-75_XfF) f|Ӊ[ :H[f6Nm0Eǣ91I8>tX 8Ѐ n0V %@f*] *@q, aDW p2i,8K_Y0L!4^yDprؚ4fb8` M1`hF>/4@@;im|ia0`5,߀w?Xu EeRH(F@1j?IkEt"@ Hc cKPq0$ 0f0bq*5#x0#tHFh(MTQ5$ [Sdၤ 8!'|Ox1I :C-pd}X >tM_Pn[huܤ XQ@ ~Y č ?, Ddtaf<R؏LL(9Od}.ݰ ፨?Ҕ y-9)G)JDQRrE ?>?"()H9JR"R"()H9JR"R_)G)JDXOC%܄M (?(Da՞cX4BO@. B  cd!8QH!((&I+ 1@N}W+I :Hj:}G2n!{wFͅv0C/iA-w B0F_sq00D%!YC @iDp J4 J ` sY!cNQC-eE-Ț^ GO2> ԼX PiUtoߘpVB!\q4h(Dc@A"Z3gl@7YCK17 +}\:&Bā`;B 7$0^'Y|IbC&&cr8t`S( jlLo_ `~d0 M% g B/QM@Syqh*a#!턞"Ih%qO<>X/_)G)JDQRrE)G)JDQRrE)G)JDQRxD(@ ?> (&II,XJN3XSCH % ]@&M @&7 ~@(u@F)+#6m)H[??!)3#)1--"()H9JR"R"()H9JR"R"()H9JR"?M_"1@jw``&pHSD 4wN @Mnm\qNRKBRܱPCL#IÀpT E9pmPV` !20 8\d `?DLN8'Bj e Y 4Nt#>Gg~?"()H9JR"RE!)?"))HG¿R9?"()H9JR"o_)H9JR"R"()H9JR"R7JR"RE!SJDR/+)HG~_R_)G)JDQRrE)G)JDR _JDQR@?Ҕ;RrE)HG/_)L/?"()H9JR"JR"R~_)G)JDQRrD)HCnq)G)JDQR|e1&Xy(yb >?M,mY'_x׌ ⭗*Z>0Uʹ*J\UDE* +"**⦣DEI<fh6I+?lNV&*JHF81K$p~"xn7 oUbT?<k,@Y(y'.t׃ QѸN=<:xh 6<_Ex0A%,zR.ݰ"E|'U%9Eǀspcaœޱ}U"ȠKZF{9Z"vx |LvFAC)r;E<6ҙdtzx_@c${55RSTy"(\ +Nr+8{A'TQ'Hx&EnNkv X6tճB\Dhosu*i4(!mTE!+Aq6" 'm#~%a@~"C)a8WdId<@;  O0 uz ~"aR|7w'JC|lfPōo5;ei#WQ\۰oFÖG@5 xF*eŀyZDADRGBVUDRA >4\WȜOc`c *F1yòUa+r}PVR4<]ZF>"+ h,] (V@h2&5yYDȅjo:ȭg51ሉaX30xeL+cD̵\G;?'L8Ȁl* c(1 f>)Qk@5GʨBh "*(&*GsyS 3n1\1]_{ *aI$Y8y&Mf 29tΰ#R9`F̻%4~ R,N2P ]Mpi6t:*Y\P!)#)Ʌ MLZ,O E P64"FZTE'(W5\E!t S}׹J؋EH4YS/A` &Xf[ELBx`H@00Q(C0,p>l-LGH+gÇc{G !>) dGA0Vd#6Gΐ* c=eLARPr**7T™&M"?\S*4 AFh!\L `05Q27}Q5?`Us쾡*iQ൅Hd1 2&HH`C M-wm|EDͫf âakzGUh`sr!"&[HF6l/;0 5W ΥczzDRp=fQš7 [6#{^TN0V0!lHv =!lPfT<{A )9­ȉC:ā:4ޏz)5 HH$CrlَQH$oA  !D2!-$mh3wmiRNb 6 npa:;s@$@DMnANHe׆0 ~ h&)l(!ݶ;E]}0,nA V= cWpsTt d {;~< ` $'fϫDR/h_h1"C@0tS|d`,=fU03W 092 )j8x C~d91[i0br `Sq&۔W4h# qcFrVD)5-&la: 8 > raX 쎤( h@aS}ŀs˃9bYR j@\@rig2Ȣs;n%iGmQDRQ'7(Dh -/p4OσPL sI`;S wX×Ltv!FRNY_ `'hv`<;8@9GT`t;0#E'BjdQc8\#xꘃ܃ `4v,c,>!~>+<} HdYc7Ϻw1 !Q3/\}L@?gB~uar894ødS"87vkgݴxq` kClHň ~/ }G2<〄$!)g#)6(N?"Y!CRA*QEL ̂i4K_Ԃ!&꠩ bQ:#fq1\N ЊZpF> 4Rjbwi .&D=”"1 6C1~&B@qAMDLxu:zfjhjbH(պZP;kPȢUCHkHjy@!0M7g@  W:p)!)G)JD@ ))Ha)B`y 0ỵ'D?" X$`'lAs)/Qtm6Glb. L@B32R! (7wZcdB\PZ3ayC4m],2(g&Dǯ5߽Nq)ž?l&/ fV&OG=VާxC cJR"1|E-5WaUlbZyƊՠ8uL3؅a㨘JR"R!YahOl?%F_HY`G~8EٮSx 'UZ_uVSRwk:<;@ĉG\HJDH!@-^tBNWXf2H?1 rdeYo6{cZN*N'R6 g\y@S%r6DW{  |LgU0 :#H.b l!!!NCĨX[fw@WK#u~5A@jmIg ]R^ EfC$bL6)>jԅl*lMk1pQJbk`8G8@ 8.6[p +],Mx%+evK bQM 3IcI'6C& n:7JbBrI*+'?l>gO$Hʉܺ2_7<9;s^Yw&q:5jqhjd˫DQӪ5n n@lS BüDELːqqNy8e@5~ tr˩8j +lj {*ѽWoHVBpyv [qs`fA5Xu9ULnlx(1Sd} 8\#>92(][DQתz"Dd),QsP ΏnG0TR7AdWC^A._*@=t집?6Ȥt܁98_P4@>$yG0 I1 -L<[#V:")RȦw<^늊}S+T )H)™'Hw ?ȞE,YA!)̀#)ǀkn02F.s=B,<LdǞҹ'Mz/SQxlLb0S2;1:;en``1G}D@:;E BTG o|Q[B遹1) ChWߠ/EgDEL 8fQ 0}LB@w:aLLrT @`B JYUUET&;DQ;Cj)`L.AB9:XUԆ ,Џ`=!"]kuH2B Jv (P0Z  ̟8CQ$r@` 5Ed8TX݉-v7у *~*VdPf`N:X@"Zr_(|f 1PΉmڽŋadF>= )\ZPA}"v@aaQ":+`#+IxW],Q)P ,H,nt]!72(|P;m`ȅ qn:LzhVN :QBD)4yۓS ;  PXnŜ% ` yXI|GDZOGi &Qב_JK"dRK=~Ł(Kp ū'E E= b!1g J5A .wA2RL@i>eU#S1*_p4#x8,I] Loq#_V]ʱƋV>ȈB!M7=:ڝS BycH>)A"ajS(xPq0dcOdKS6f'T†É3|F8F> 2xS*א zp#b P3 ǐ  .&}N:5GKHI1vIX,ਙTiDɔ=%(9$ǖn|/@`2e@XlP[yӜ& ׇv9s;ŋA@?D'EXH[u!O Tf虇p٪`V"(*l2gdt,(%n=v(FS8 .&R9HU |Yu79HJubpxYqL7XAb{8@yʕTmsrAc'n`dSpRNtLQ>JTDX`LWE(>-È&u=|ueR%!?'H9}ӭiDEPJr|GS n+v"kA'xw8,0Gh~Ay|Bٰ2nôRr&/q {>jd)n: ?/Lh 6!<s"ac͎LhMϤr$P24a! Dʘ<!)3#)`sD[S (3+:&dNSnd0 ,k7ah8dayc?9{ jہiT>hs7_8vq8: h|/tۅ2/UA#8?pPh1q1pdFh>jXR'"yikD%%uX+"*`f85( Ka"ߙa@!9BuBS6 # @" jaJ7WN@Q'sxtOydO9GHjb4 Ȼ W2G A>ܪi ,S+T HVasmL0ss@ >p 2p@ jaSssS%O$Rarԅd3Tmf戙J*! %] ܡnq:0jH :E H4 A˶OHì( o% u0 l:UJ%Ϸ2 avEx\U$dY M)S8`bHimn)l lPk$rj YC* R?] 76ڙbz>CV)-Nq1 /cN H=RBB wV BLJQ6Us 0RcLjE;/qq"?Gq@hPqTNltt'HHha{$o0-å{VƞH9Cq9b"\Pw9H U$$ ȧ.VD[()d"k=g2(v"XV,2 Vܿa*"X)[AϾIަ#E2 pa1dLPVhp&Ψ) Q "^L(`6 PCJÂSD!185P7\Lz%L "&3[QEQ ,DH(R@rD2x1ֲ(ړ9ֱa-êb" `E  ^VHX \[lQK P25ppuǑZbuPP[ 3R<ީ `<0t[0yAj >I9 c<(RnjdN}TŎ1fg:u U"s, ddL(|RD#ǀy/˩| +poE>>ԇ^QkF[C:LL ^ToG4V`6:(Q:*  KY;3ΟzA(6[L.h rf@ !)#) 2p@ ܂@iژi<nyDR ’{`S9^L[<"M[*ް t0FR0+R6>ƿqD0o2ޘR}]gbpU%owGD112ᤘ!+%)B6hOksˡ #|Qya)h~@]A571\o%M9L1ADFsE!up"b`24p{ c.D+Hb$NeKa46WV9S'Z_/o`)T7ȥ&ҿ|{<|1}סf%6B} $"  ªEcmI,6$XGQ^oePyh 񊴺CIxw[ ]p :,i/q1뛒3b$?9%R '<1)+,4fb#&( TPeZItWXh%Vb8?bOsʷs>T1G/\/DT!EAx zȵ0>+gp H-1ΰր:G 911 = R>i:p6"p!i' I†g`Kz̨*F=*dn3ưk01Epm} mTu&0DDzaʠ0 jd`!❔b`` "&R Kfjpf(u p'h1 /y;W0{I1\es `h*2E(w^3a)5$ dJh^PTP|L؟Sw~:λ tV>4,g2;)͑̓r!T EVcpsX݈*DP iuA_"} 0@VH|&HqqQ3 j x5Dǻ ƊdL|"?T o!ʋe4. L+ 0:(v%ڦ,TW.CQKaSk5􄂀x8ҬybƀM A"`tTBM^5D(bM>tRdBR&Ae (R?=V'> y 3fr3),SR76@ >p W*p@ 鹾B\w ,RrYيjB`>O>| LYF -+LX#S %E3;RJBmߤAhM ^31mg`JEOfvljlni@cx0 svGn|@bn"=Z5|D*gQ -y>d1FC ä%p#@@ѡ3XvF%,,,Nمqy h+;` ͤfLܺaՃ4Lx05`aI5,$YGcm~/| D@O {܌Fø9 ƹrd Da7s?3 5 ]Wbۛr0"x @Q9Vr\3c;.&XMrL@P~ 5 A-9j #[I2XA)!+#)#)F}x5#aw>0(6}<0bd· CG> ݀fDcs?F2S/pS @{Rsl$Hm@<0!c&B ZtPK/Ƹ0`mϒ7r~] <\L%7wʽbY;Q`t7)ΐzB]h5(Q-#d]OM2^lm}$w*PFutW#`DErM$7$j0 Qa "8qYGyDL)GbBhP6 0xŜ^I@_L_pbFF'8kyds@IƁ [Ϻ 8@?FvN'SUEa뭀썗g>Ak4FS#e*LLh$xQ!dp1 Q?>vXYȧ,Rj 1>9EBDC$ H3 z<oL<1TxS f™VYlP^ pjwP 5AvCş%cָ0p}u 'Ęq!QO8)+5Oa P-sTvul Ls@?G)8YNX?)BC0t[ &A-Hcd Y=TVBZ )cohO01ge@Z.! sY6F8s{n`]8ETNO(:<ݒ*EǁP;+tjSQ7 ##Pt=+ob~D`{D :5CQ !3h)@ZewJS >Iuɤ2WiɃ \[L ,@Gv`(m:ϩ8E 60X<Pc4LlP~mFSQ*#*jRss>yCi3[`u]֜m|H0gU<6c=':锦 ss)@| *p@ $r< )甦椻vy3@uژ[5k n9x}*C"^ C1` H0%v sp\jg&`JDH /׼|uE`AW0͐J:Ue6k< W(D#I pHɇd .P\+A&x@ԁ{ՀS?V͡-+@QG—pU@B/ omLr) 4*t `< VS0 p=n}|m9#*},`ȞEguVU>ɾ{ڞ& u?g09!+3#)1/!/9 l^?܎6~&38Eo6 XemN D/& $@$xXK:<.c5,gFQQB(72nmZ{7㕬/~=]0F918gPL;MP+ɀ*nOAuxK>+L~Is`(oRJP.rWDeoI?&A_NZp" % pJ7.L m1l+ٸ![$]%@۬rn10o ?3(b̳7 V cn۱g"%З0 0*O#amv+a69@Sp!'Wpb5]xx3T(\vh,?j?nY2!e.4E#f9!50(g UH6S lX9D}|`h1<UvЁz!u A`%:4LUEX{ ]`(|E?0($  }ad F`52^xr=p!7#AdjW!l7e+ܢfw$)0TH;PBBa<p0•Bq<>@r6501ǃh c&H*:UUG7@~8U*UԂ%W4p #ȃl _򪂕Hp!7p `bfxfX uL&n 2?vؘ"?>$WIAÃγ=L_ 3`1߀s[FTPcp#WF haȿmH , GxEL1o|+dw!&[_v1j4}f$?S 5;T^]>?ːxp 큳u00a1+tw%؀9v00@B7LKX >&.&R`xXn]ǀ4I+A:+qr< .@:\7h(T€Sx ;\4|`f>g Bf- ^OcnUÝȞ0{O"Ȇ1Xs:t1ΑRls_  Z%a g Z s}RpP @;(z<%8%*L*cH]mHqZҾx uu搔ktTpЎIxu:jR $.UܟztC@IO3YHΘQXfKڳ`!7R26q0 A> q:spBVIdy_$gL ?keyˊJyʯC 1s*[WKh0bOx*A/^[VLɹ̭g֋雴 lE˽0"\%0ʀRnԟ&ؽ +H@6`N<`lf\PҴ1Ĉϔ1sAb&cj+qVCW&vws{ EdÓP`h3 օJLL_ bB%N[tJPQ\#s$xenqW GlI!+ٙ#)?XX/H+;Cd'xR  8,qJz ?w|VG0@k t.K Ral<]/I?xby^-;!GdYF'@0\gB$EΪo%]> qDbQFOrHWOB.IylH,aH0\Ea$ㅅ%djg0=cUG0|oS?P^Q+ `>HᖍDԣ`t |cbmb} Nb2O:YpUө58"bW߬q 2t†u,x1; Cps|8`XmcPa"0!)yOp5dvҀ3g¹#tp5Es9t,RLRW)f>JfUJ:Al}Lx,3eE e+a'PTLA£!S%d 0{Ύd@`ءQ ,u0 !p+8waY>)*1)tb1SǺ#H6Д0\*F€RǩfA?I8`c&pr(v Ig3M4Vb]Iq:["2pHqq s;>1 Ↄg} > GoKg'.=Aӹ؉ @fꂏ&C LX gFGx4<1i,Ez:bgXȺRK= v !4I+AT pba:C? (ިC lB:XuACbg`@:|G:h,)]:R(g"!݉Z.79+)iH#gfs-Rse)(0s@  *p@ )IE:aS!]%7^AkMOb𰨤+ Ddt0k'J#R fgs$E>S#=yXW|LrO(P8 l:tm# JIbu1Mt]aAL|ϢSGgߥߣ5"-Įgv^2J#k] GAa`~ߊ@jRT Ώ[u-I"xi<@lE[b09׆ߖR/s=Sx^Q "R"K# V5{by$wh*O]Pp ca<:G4j8wGtadx0\Q)z$`42A*נn_"* ck2"Ih;Z}P)sB< PhƎ@9rSwT rtNǀq!+#)4}'T(@;9]P3*&eHTEM̰h#(.7{[>3X(67/Rky"ꉁo5:ϔ5A)"sSvtf>Ѻa@ Dqu@`Ͼ:+PH`@N@Q Bx/ J yS:!0FPtǀ$µP ̈x|1&XZD&I@S09DEt*IqژS8 I~* R]XfpdLl꤆ dBӺ!E^cuByöqa* PO>&kNPu"Ra1Bd<* 11pTսP &0G1{Da:-. )"cX*GWak"`x܈MUe>:g*: mP0)nWYjO8 @ W*p@ j3)J\JMHgv dJL8VE˵Rl7sg @H@7(~tP?Q ɀ@Eˉ"r†VWId0&S5EX~X,CEH%-m@ <ݏ%z}xmw (ms,;?HDuoE=\1f yx,|Cqt0jWHߨu)ttHrOkNo݇XK. E\N?,n_ W]^*!Rp00}$QpOX0@ko^н`*\OWz| /B68>ԥ"()H;َM򌐜%gMx~B'Rx`UD&tQ~Ԓ!N{`gzI"*pt574."+e$:FC& D clLFB:6$@ nxK(`Ҽ1f,^6#'*|*\eq3h5yC$}e%uː @jzxx3T e;t9AnG'b; fT0=2$Kȡ1 FAB"&V'̄`6FM@buy$}T.ݽ! r6k LLml+]XP""=wp,ʙ~y :Gg01 L"yU@dLlhR0Jl7Ziϫ l^АyGT3~腖bb8#  :)Daqx\7S At+HAXEcێ@C. xy)S Uf=8x ƗI @g"Pא||$ yD'4ɀkPky /YC\Ep\}A[T |a/Ly/|@? ]P:dӮr]@\+xDT }#h7&E(>l[zj!?Q^1. !o;H%dj]K o«`A oY,<>ז3Jp5rgl0N>րjXlݰ}j*yJ)XwM+aO„O qEl3cq+d|}h oNtg:O Cp '^כ$j S큈:τ@  vB5Ҹ`2- T!! jY4*z0-E >jJY-#JDGQa*ӃHGr'a͡P [{⣌HQwS7 |T8^'IsMgXR۝#5㇚t @hd:L XY>CaFؘR=D"CTͅN/pt(~ FJ8/ET/Kn~|j92^&!&n:eAo_R`jai_v|52l W ?XpZajX3sdhF 9|ts S vh <t|"}cpaZD`gpgCBN͝F#nI5#D|CsaDY*bA"g?"9Paǁ8r ^Wawb$>,lN Qp0>JSFz HtT, j%p#'ּ;?L(|NQ(ߤ'4_We (!3Nj` 'Q?fv~epI?s,/$q.:!;Wۛ1FZ:˃rcZ)21h͈50x?gH!bSsz<Ge"kLku{<̓){q*"IJ<!@4W8?ۙ/Lfnj.VA1G@QN/x{b׃8Gُ=qNca,8Q:KQ”H;XܓUX8$9=2==RyG-R:`,At-Txlj pXEd|`fC1aJ7N@bx P9AF<?QVnA0@v8`};¾01)B BJ,g4(x_ 9p5\V X`=L y–lWCtL#W(ՐE[_tWdkߺ9!Tz0Ne,<ji;nǀ(D#s"Oqb(–ahjf-, : n aDB,B5N XAR#dax!@tim"!+̀#)[ݔQ7`5❀dE?G4 (G|2eA"B)lY);7$rveDۻаArq>;M 4,GsO`ÇpduK ҖyyN1?yS p[` )4R 9N1f?a Y# kZ6Wv<Ϯ0EGX! @ [< Ӭ& %A1nBtdC .gcLw*aXEn㈢ā@:8G`d$PPY < "(< gn`@&g1='] 2?$:m&cA5*[gݗ]if X,a#iI-yԛ2pkwe&4Uج)SFl@ "p@ ʀSwʞJ}%}ul# RGDuߜ&ۦ ;htl`Pc\#&Xoh}^7[AKb- 㽗o%q: ٹGV[H07O}R :L-[(Dagv΀uVe_2 \^$LL)[DFFqҀYVf ʞt:zurDziCI]όKϗ#zѕ?inNuauQ pp #@X @dlt=pK>G?| !!s B؄+c^aJJuWOxQ8& 2F8 52@bľPT#65`(ÿT,8( M)spu3Tbt[ת8rhĎx](м'A8S =A'FK9a dDGWp8Ҡ;lT^YȃuNJWWNPR ~"j`aN 2 ?xx |)i1zI ~P5D4R$srr8B1$↎X`l L)d?RFՃj<[h8@WMLx**DS  [P1>*-@ @3lcpNY% kZê.?j"֨(HR8:") PxR4oh?:-ԊM@huPHNkn j%89p8,Q$w@n><umm"n[  I @ *p>?" A)HR*?" DJD@?ҔJnK&@|JDA% RDGD ?"$?" PX̖X?i`%)%9,I !*Ћ`x+6ʦj՚pvMrӔlBfq$`G}l1T{A`JyJ(d$ah0 Y%YD,rz I=f)h `O3D҉.އk:vX lR@`)!!>nPjcD Z1EQtyy NI1bR. &lH-e.F;c 44أrSNӂt<&=,gw"*~''CHA ?u%Z>ܞSERCA0ED i-G$ ssnE1:zŠ$mP0)#!HCvW>z?7=up  Hm׫Ṽ0=7h3q€oH>M̦`׫;?Y Ξ.onPMIҋ(Q{% "Ymm`6AjC0$ @1:'&'lo5p 7C_C&rb[M5"h֊ya)[ qv XqIGG#BBرth *4"Qc/hIETU# 8x#_\}bWi8  0@r(ߋGha5!!nQ| P:B DJ PӹΑb1@;;Y.La+RT])!+#)#P_Pѣ0|(FRZԿȷeY%VoUTAR ѕw~]̘BzޭcdVH1· c0 aO `y%;WOPD' >KhT.yN:0cfԥz)zhjkBe jJku@mvo/_W':^POޠߛC]vT v̨PQT|}Xoh@  "p@ |]':h :x 0 %yt6S 02t*2%äi6V\Ul4ֳ+0aD/ևP6?ա~h2oX1Ҥ! ^Pa@jaNr>^o(/tC -zEPΙC!L)iIH7*H\C,>G&l?YCc> ޮ,5yډeq_Ai,(+-ɤ0~o"@taH! 0| YE0JxI|0b3 ,pƒ@v GL Iqy cOBppc[;Y>%̒; Hw]\__מEh;U6Qst𚲸00`%p #1P:‚i)Hv@n<, lhcuc힆BW&qQ݀]|e8]P?/(@1À|$Vیq5 a Q AK P s;ìpD.&@щ L*i\* {^L `(  #!@4hi'L,a&lXp .!زN0Һ@tbIA~D^ϘTmz ?a8X`2L~: 1bOS7}/yyW:>~t^,@*KS8:WP %gt` %+5((@ R!-Ѣ`ܳ{HAAr> 3% " ޔ-}6?@hb}ؤ,_ZC\Yu!؏^J& zI ; 8pc$f:JOk6O|?_cbV`ULѻ8(.0"PQ/|>X QRM<x@PW=䠐x ̡FMLI$=+KjfETؖH0F)py<#}; &܌#]Y @occ S?߁ kϗ$o(ð8󣞘`uoEP !3 r-Q9bo65E@H'0I)X?#I8t*^'1fNu;SpLJQ@. GTZhH+O:T)#mHP:s#:H2G koX"eQ4؏cܺd%"0 T 8@_{ue:+#EKD dsƀiTexN9ڿ>f} Q88%`-]LW> 勥NJ<g)O@U @ e@@ D "p@ :Yt-jЙUMY*U*UZW'ˋ)R-\4¦6L$dh*+n.[d#%!(`؃կl/!-̀#)11A1!hLH C@rr#Wdz*:&O q`4(j5-N%⾛ u3@yui4 {Eba$pfYf+xLJL^$A?ZjG m?'3 VԞO 2ᅠ(P Aڏ)H1 ID|*|%@!03Y0h`ta c)#;iYNWvpP"CF$/2%}{EB`{Qz#L$(.e$@ ԝx-U>HSc},NŒJh\ 54`3lnxn HE/}4ݲ^[t8G ! (v_ 1(AۤODλ# - P 0vp$؁1c և>jqT} ?|@{x.FSr=@䷎PT^VǓ=?bxr 3Iw5$, 8i4IM Hŝxt0h!TIb":jH cd% 7JGoţ1k7" 3i-Y|$D<PD9]^eO$re缅Pá+6ZhyjnuQ?<)t3 QIcB'ŧcE  ,סRBy- 0ByM{)arPY @2SQ A[D _LP{ cR$::8PuP{Z8l?Im(*<AzqFHBUΟՉҸ.dS]AcoPB(uGaj ā*PbgYQfcL&dFS#Q%4-)aٮf"<۱, gَIJYiJha}Qۓ-rh`* tM ,39.^PlK}.oח'U4ӝC8_6Rc<'z 8 )BV,yD`lHPa03>ВЂP2Q T$$ u*cc[>_/$*:WQ@P('=!QƀD [+[Š'ZL?^x?P3uon8&W1`ĩ(k X @Hh]Aၣe @2OTB @#!1lPbsP6gFTl>''WRf 42Eaq<!-3#)Vަx|ZSq!O X .43<L^η \')ʌ&X'@1PGX_j86x @vA4GRGdk!8cM?)EgI%0p I<ĈqFl̹8 zN 2q}/"ls4R8pZ0/ `2I^/E>@wqDIK)Tq03 XԀ4U@2 ;Dԝ@z,p1;^4@2s 4x'w~pH^OBz=Z2NONj'{c|p[u8ŸU0DR&Tk!$g7?84ߑ(%PM-JЬ 8D RSLJLJo$[q=x a1#VD0|MB3?F(>@*M .IJ]RYjac 13~bzAe. $|ǀ*h5"崖PB*.&-ӏ> m!*a5*F4_3|_,PXLŌKcxXmuJu3X UAjBߓPJ@IN \ YXJ 7JpbFc?A20}~8$[6o HPxE.LXW:B \I\g` 4!@`@RL#ضnHD&$Ŏttq0%>B>Pn4wƇ{[¥q~ K J'Xu2 zK;!cgkkF'vR-9/1A p`*L(-+:S?\ a,u9TĊ4ġRiT&S.v5 PJFp'ɸfUPcTĠk: hC ^@tP|X ۲J. W %ZFh D!rVf$@iAD*C@"|R ePC@G)Th ,IR3ď+!V9B7W0!ݏh ' GS5¤Mp1]^]&\_HG;`!)3h4 1, 5I,K +3Œ7;k9g 7& `&^=I:!2y% |NGLpdD h (;@aᯅ7<F;#> G<Za0b ~P}~SvL J:`aWh7pXh@؋$7%QA3P(JJAvNyEpR 5% !-ٙ#)Rl:/XKJHA!BFä'3)J(X4O+I>gqva 0b AdN_gT`D`*_Gd IBY VK*aRZQ"RIlb/?p7Jҡ0$4|CI0ˤ ? 'nrE!|S/@)ax`%g 1`a7cĜ9swbN\ [~( 44W5 _^̄@*?dZMi0g`MHJ[F`:&`*G XbG6a(|̠! P0aEZ7la'p bhOί,*-3qR0`"p 6 @bĠ0ѝsq $asπ2,?$S %8+;@+ @ )&)4( ^D0`?:lW&0Β0~"nXU0df &@ȉUlum83An`d"`g8Ab;n ?ljuܽbA:I1)8(He@d`KhXMɡ4n0P#sFMg3rL (8@0'2"^[ }tLe=nnhhrတϘc4HG#@QW0J h䐎;m6X4(n|PjRlPGBJ; {|vPrwcn!N@? P7!B f=1e}CF9q*R1y:0iDo; 5윆P40HiHZP?ǂ8"9t?f< N438| Nx+o,@0I(L++8lf0`bVKOܑ "R6@ 2p"p@ uv]h$UVGdZVWTaSa1 ۳X\4T՗Z M~͖Fp0?a،|ߝsg׮,? s|" ݷ^4M\s=ҕ_۱/ObpOkh̦$٫ d3`dߍ?9$PtlR`_ !}CTA> ƀy_p|u]T:Ԣ=3I=Zn$@׉K@pNJJ m0KVew'o<J?!~|3~hc 3ڀG.agQɉQh3iKAbvi[.7xAFF TĄq Ԕ '29:~S$Dvƥ\#36eXH ]1Lcg'@;U%fs#2,1#:TRdH0 Ģ^#pN 3``ehk!-#)3Fū*$\_Zh4$PX8>Ii;H@vľ)N .۵,5SWR$ALo&5Yx|B壜8:Ж`pCq!#ʀP*I`&&ie<[Ua& k_<` #_`'CTV<`gI? D&J` ƬX60WCOW#Tk9ȀC&<51: ?9f G=G+TL2t`/>K+KP4S##f;?Nc ֨#8*@S3@ `0ұy.ԘMI"!% VZJ< *bBq`@WNJm?zR0  cC`TIOf[B)Bp &-,Z@:IlŇ@: / bxz@f` :t<Д;r~S?+RÂ`@`PE:( ,=Բ/ /tL#)ݙ~0n!` RL!cx1-#o㒖& )l@Ke!tmLbl^$+aڙSbX(&Ҧär8207!t5R8\$O@v:O FF#c}dG@ j@ @#"p@ ٬4Bv.8Օ(V[V,.&pah k6 ,Ui. l.7= _„ 'VGHU,¬(.a9:aOO1eH;unguȂo9%X6&rG "7a|?{NG?`V|"HI:Zw2a>`H o}-I$oόM/ݘ*LT$RR8]J jœ GFE 4`%!I:i ‚,qÄS ZZx xv'Ƒ@0P0PwP;̳^K,鍒uP}@uSe㕀jB[<0>0U O,8}&=7h{Vbyl˾Au`x@d\*S`}6AA@ ;xpŪY`c6]8Hod`"SͲ,dx@ K!-g#)q2p9!_l='"xX Tk{?@@P'BN}HĞq '쬻 %dj'xtC o+Rf)#ǚGx)( T(oA@ r Z2$[qr=ק/av:؎ST6tT_7'%+o8' &|?wA+h)s8KsXW PYcQCIC/+^'?$7܂AKc"3p ]&a<߈kBW 3w (G,T͌Sd?iYƊ( {oJSAnn?4G)?t 'Argghi`d4%g2pkH_3`7^yJN TZ4GPh?guaXH. €)a~/,yǑݖ! 8iS<Ø*bSۨKU HaせBD?}G \pX0ե,$6`#'G-#3GXF;OµN{cI# IORzE;ogYeenq!<ye1zsE>'#Bg Q/i?bKIq@?|w;C+ 1eu`#=CTOacfYr23;^$~#i8O, FŞy`ڙCIAI8輠ySGS zHJxR P~#E!$pP[wEB\<j"U O?-E<6+g'xn`akh|I Z-k݄Xp!u0HC h;NRi@3"J7:^:aՃ?h6^; XAO_||X846Pﹶ-3Ocu 0k@7+*N$v7p:x yT< @2NO8 THqB˗郣c l)B=֦/$t/ { { Dzfj4@ue32ԓ @ 1W"p@ 3l7L2@3+V>ż]M3a7W-Cfy]RcqC6K Q0v,ӱ,Xbv1]//4$P^_ϼN"7X#iei88MbE$a8<>1G@͂0ƍ-wwƇ!-̀#)[*bp6dU:^׆!<:-Q(Al*?Y8'b@qC 9RxTD9̗7~4znJ7+ y*9k@89!~Yg 6)F>l J~4=ֱaUuIvߜ ߞtsA'Eu=)yEUĄa狾c$ A?x(4phVH13[ۧ@;\[ [%MhRlI8\1v#SAH;nV=|*& )*YjHf`W?n/Hta5͎ @# @0أJ qcoǀnH=|1)W'nN#_Gpi[s5+('d< 5g0uq{*L[bXC~H_Vϗ~#pzB  - e$ 9,r<f}CC63s0k,lF|jwN9cRhS5}44{0'S<8cqq507qsF!+y2m7#Dr d>OR [IK)0K Y?ǀC:D53w>Ȭ86 ēoq(ATM"@P: mQ4xK:t RFpaR -ybl,)r@T l)U$p}IY|Ig \!h$U6qUcL'849<֓$gyib|0|8U砡lEx w qknԒ& gOG0zWOu5t$vexkɥ?Ô%ǧR8Y$ 4"bSNkU0#:I 02Eν j.ixy5zRIqIb1r"tq1,0Sk%#/ٺLj <, d)]{!-3#)uepq>OkBH~V 7K$&0YԔ|= 5T1$s0 n>3%ڦlx\C+l bͱj>'! pv<(άRXw4 wN<@KN#g/V vv ?פqD^@Cc5 sIN+E@1 H!r8'һ8gh`4 >L_4(mJXtj;(0nsx'4XiD|ZYk$ >~hW;x[8CuǘF.{@'8`e;%Jv(A'A8Ω1bc"2yP~V'f;:VHvJqhH@9@ ;@'O Ű sl^$Hc^+#Ap,oJ8O ?0GRPo)7eƘeL 3.@7H51! n/~//Tʋ@ <4{=DIm N̓r(%DHꠠ#+ꨞ [˔7"9"0Q'b*9@P cXc05(: O3|!,Ɛb=)\gX?PP j/AX *}P\[:X݀hjl$nY9P @ "p@ ;R!Zۥ&Y*" -yҐX*iRpI&"H_<@b-@px $a|;؝X|p;Ώe3 Ea8>`$ _2qutyʯxVH_<{ưץ|؉/p _ :8 RjHIS3^e9V✎gd ֞{/}k3#{S0W`41/s|o"K3u v~G0LhpLmfv3^<a'eD  u*[q 7W`!W|~g\9M-/V8O#9_ek qEHLJ4PO:$lpy _x3Ų7ަ dI6qđpdA  ?T=W?4cEփ[7~|?L +|47mLy9 @;Ɵ@J#X= 53bxEZ4oS0~tMaŰE|\ 83X\m$oS ɃZPqun0[3` C54x(tI& pđă _KEQdcǁ-LI.HPTcR>lp j4EyRԀ&B^Jp*&\X38:؅  D{ >S o? tM%(UQcMePKxPTBRM@I/cY-"$(w-w@ @8p@ W]\ky@i|u. V&@q=k[NU5+p9Vv6sz=K߬\%sS:7DXvQ깂( auʸ yssaj(æ}ZPUOi ]q̀}7Y@[qЩ785V-VC ,8fjÄvFi(:;ԉuua@}yD},p>,JƁq0(0 `86<Q Yǀn${WhEא*>DŦ՗9r,i8 5]O#I`2 @ur+`e55yqLXrZW@"xehA[FY'I-պ`2f@ly<f`"x1PZ!Mh] @UoêC9"Wr4zCV GՀyVP^Q> @0 q"5]S6ye D>$`hX%Ǒm e4`@竊]Z.x}L Pp8"pw ?=DOS7S8{x" k|Y՘Say.wYtF&`8H-PG_7GXU{dH{KÏ'+1a'( :"r1;-|<X}`ƀ 89X8 BFYZ‚Yn@kNap|tF=#0Ω"s%#]L|v"A L0 l@`=`57|O# 8h 53 |`jBIIǏBQq`D<v0: `0 0U0ye:08hx? nœ̬m ?+ub׫)~h-j=U1xX= ,P=X[9=uA,|Rr?ajE~l?Ҝ)px(c80 #P@;~p҇Gdg'H|xt&w)c!/̀#)13a3AEu9#JjZZ]m$R=LFY|+ Gc0H=#24/x3O-p5ǏB#Ǝv`4$x04  |CDh0@/*?a`?jiB0sj0< 8,Y',1H#Z>"5Ӊ-0Z< <28Q_YuEZSR]PRmw}rPmU6T@#Wp@ |`-Aۭ-6Gjp1@a@6dEh@j` |@wT.7NtMP `00L,@`|`'Amh :˦Ts}" ]? fj9,nP]Pq Jq YaˀiB?}K.]՝N&π8|jwU v&;fi `0\`tg]o]A##Qs:?48i:*ڠ@ p@ @ AN ؑ  ?nh?dYk/u`X~ k>s/ӠX @_Rˀ<&F8qAւm @ p@ @xJD@  F@npI:T4  lZ| cmP @p@ @ @ 3/@ @ pWp@ ^fҴYrz˃㦼( z_*,\Sy,ʽ~_׬\ G2xx`΂:VAR뇎{*^|W|jX'z}/CQl+ ő](y>4ڽ < >}X=f:wzuV/i{U]d&U|fYP ê< >Q  D XTI)Q ,WVS1^\4~|>~jT(Yvi"A@v"ڭ09-\Qw+'3}W 30{Xw5 .N"ôqIw1O-GY'ݡIJ~"E \\q$?> \%6<qPט@Ö;0{[ǫph jx|Fv"Wp|,P_==04G y iucH+.$U*BDmz,M^<:sgzn'K8/G|wcuqSqDL=BM,1P`mcl̀iŪ31471^ee(]|; E@Dx2aMx N{ptycrut/z `1Nh^x ۏ=Jx~:@^T0*?5{t>@soX@v7|<~M!/3#)[pǓc X Y&|,>+0EkiAl7=_- 8UpmXUcfV>לE;]L9㗔,E8Rp3,s;y`pk9C#ڦ`#`>øB")-()9\۟Ũ=#>z?`D5LiT݀jau螬1h^(`<qtsZ $.ߞ$;JQ,ט{xS9D㦯Q=s,S7K@X( ڦx|okpaȇi<܎טՀc ?',na~Vh\VVbcy?c a'F9J_aڽڼuYLGP3??<\hYyF|xZ9D(Rǭcو x@Hc+?4q,'J (qjnaaٲd0,=Ɗ"k 9;{?ykx˜2iT0pcdʌLDӰpp-v[`8(P]{#\iQ>c ya£k>6s؜NSZvQb>&ͧ_a\IiǝUp`scA~-D-`4~# >gy! zaqNc݄,QGS;=L0-L`z }~O * [Sq`|znNEeqcۺSۭ͇lzcr"W/@a+Sĉpxyc|8[y(sNULp8`SgR2 i K:`y9<Ʊ@C Cx\ N Y8lMzOyaPYkKe0>r}}xz;f-G` [8 x&2v0hFC<يГ<<`kw:AdvEx>l9k5PaÀ}'ƁsL~nòǨǫ+bq\qACāv8cs%K>`L`v?8tpgnynxy?>vg'Ƕ8TLH#AØ݇D pFS@~~=8pysp>sgF0~cp+ `":'`"8xhc@i㑛%cp!/ٙ#))pCin8'ƈZzջLOxz(qгa=D >aXStWOڏ"v~i>uT t˺G6 *J>Tt!:MTя*akRl\Q7T[{8ZW@pp@ \ @ @ @ Np@ @ @ @ @ 8p@ @ @ @ @ 8Wp@ O0: NM4h 9֏ `wFm _evehj`Q؍7g|8*p, u8.> 09P9:Q @0x @ha kD ** eD4B3*q:dڠ>X1OsGlHӃx <u A{Q*/"@ <tD6[yQ}743Ph:oU'Rcb5[qQ &>D@j*8 ,H{Z}iRb.86G2oArvd1и6 T<5@ȟ@pp@ 0 F@ lPe 0ju076?6 X3:8ց'H3VjcpjV6G@5 Mh lD@m b &JW@e]#@i*`0:6 ]`9;E\OTnj;at@ p@ @q@Kt@Ck7@qDM8EFw,MHnk;@a|@ p@ @  )s@̀ j;at@ Wp@ @  h;l@ 8p@ @!3S3#)X  .j;at@ p@ @  .k;@a|@ p@ ?Ҕ@)H@!)[|@ RPgx 6N@ AWp@ @  .k;@a|@ p@ @  .j;at@ p@ @  .k;@a|@ p@ @  .j;at@ Wp@ @  .k;@a|@ tpclient-pywx-0.3.1.1/graphics/planet-icon.png0000644000175000017500000000177610773624641017411 0ustar timtimPNG  IHDR(-SsRGBPLTE@ @ @@@@@``@``@@@@ @ @ @ @@ @ @ ` `@ ` ` @ @ @ @ @@@@@@ @ @@ @ @@@@@@@@@@`@`@@`@`@@@@@@@@@@@@@@@@@@@@``@``` ` @` ` `@`@@`@`@````@``````@````@````@````@``@ @ @@@@@``@``@@@@@ @ @@@@@``@``@@@@@ @ @@@@@``@``@@@@@ @ @@@@@``@``@@@@5htRNS@fbKGDH pHYsodtIME #32jIDATU0t,tE("~8/EfB0byjaWPKs4b+l@D93?hcyٻjuUc?/!D)IENDB`tpclient-pywx-0.3.1.1/graphics/link-icon.png0000644000175000017500000000036110773624641017050 0ustar timtimPNG  IHDRbsRGB PLTE@O7:tRNS@fbKGDH pHYs+tIME $ QIDATı @Os;4ذ "q[i,W<\@^av ^Wm|stQe$U$BXIENDB`tpclient-pywx-0.3.1.1/graphics/finished.gif0000644000175000017500000000332310773624641016740 0ustar timtimGIF89a +a-j3n 8l 4o7q8r:z<|=}<@ =AD ABDEJLJ MNIPQKM U RSWTUXRVYUZ XY_Zaa[^X_\c`^ a_ cdefm/icgl*o2ic lek%k hmr5not6os&q0qv8nru)r ss!x:npw+ty;wCuu$x}5v zx |}2{+~3~"+~=5L#~/?%?9@N':23CJ;4D=KR5E>LF?M@NHUAOVI\PWJ]QXJ^RYKSZT[[aUh\bi]dj^jk_kfgno! NETSCAPE2.0! ,  H &xa #|B"G@ D >c&ieǂ TId9uI")pĈb8A&JS^@ /YP=>6@Ŏ&w2i>x4R^ נj2b۪3I'VdQ$w:bU)V@VX-JN\ٲ*k$ լZZ7ˤQb"Uc$H}B/pHUPŽA 5LbIF/6*2Eʇ #ЁDƁ[!El\("(_$Q8qFUl!G(Ȣ >gh2%2)D8lQUr$d҉&ZT6 [4!(2!d6@.$G @Caб v@1@tqĚ {Ig5t! ,  H &xa #|B"G@ D >c&ieǂ TId9uI")pĈb8A&JS^@ /YP=>6@Ŏ&w2i>x4R^ נj2b۪3I'VdQ$w:bU)V@VX-JN\ٲ*k$ լZZ7ˤQb"Uc$H}B/pHUPŽA 5LbIF/6*2Eʇ #ЁDƁ[!El\("(_$Q8qFUl!G(Ȣ >gh2%2)D8lQUr$d҉&ZT6 [4!(2!d6@.$G @Caб v@1@tqĚ {Ig5t;tpclient-pywx-0.3.1.1/graphics/loading.png0000644000175000017500000010635610773624641016615 0ustar timtimPNG  IHDR9Q]tIME& pHYsaa?igAMA a}IDATxܽ eWU.::WRU*> #"<"(pQ˃FAQsDD BHBڪJ5N}>UA gZs99XD?!x9܆m_ZBQf(gJGʲ.4X;]Os4E 0+Qe}B i~'͵=d#P<49=#q_q4eJe13:綕1q>;QFf]_adY䗿EL4ݢuԬΑq_wɥQ*TpڝndBfHIy bDX /IE"ӳs^kǏ3ןto3ceGbUcYSM3hW"fniQLDH&lo Rq|hoWZQ0K.?1! mLqXSu8R` xOAHmUp)O ?0'0̜K?fV}y^!kBgkTLm;NLvc@׌wc[H@, iubw4ChVغn03CM*]\]U 0O%8 ` x>yj p`0AC3ιkiSzbDf}G.^N _ʯ7~t>Fgu[|2U߽Lho~I׏58W 6;7}|-AFBHPc*&Ur&* ^zP(r[֯Sҧވy֚d-;K;_+{$*k1>TPž~[W-Ү-ҵk>~鍟tm1_?>q^QM=ꑺ:`gog'J>sӧ?ξر:կ-_U *pZTk-=+THG?q2BXC,[qlͱ"@Ol kҖZ#?_>L+ͅ8(bY<5߽ͮe*DG1i}kHevge@Bù>-b`G$=3aošw N.efXHVyfX"8ZRO.5Yg>w_aVJUuW5}egGDq=4G 9ՆXk{KuGrpa@0| ` WHyԴG;~w᩶UPXRܟߘGMԉh5ya[Uty(u;\^c*x*̉ T%FWar4ș+\y5cϼa>/ ŞOO鷿}֛tqzEhDҗ}+/}]$p|g=.}`TO Uєbv[v}S4\3kQؕzZhJ~kٵ\= e bD!\|Ԩԩ7h ( P8e\,,/ìm\nB kG%׼&F/]>ryTHieIhz6AKN>ta[%ρM02ϻ%VGUWbv]u[,5O_{1ZЯ`M{h8ouWIw~ԇF8V#)܋iz~ wTv3X)Lc@ Ã&F[wNo뺳FkΠٿ]HpdB^ؑ0|ͯ! 5` Xj@eP |>,)`^j7႕hZAj}<1Lr~w_GDb~K|bP]6XP8PHw|}N>"$#Jm!~pqǦ6o :ض"߂kA+fWq)7[^DL2&LW7Z-A%e(( ۯ*&c>T1 fv/{9W|*rm  *?vv ӌ( 1gXl׌2{~'kjS O7S /S p`dfU:G}؟phI_ G`#ųLC S  228cw s,X7N9vmQo/CtƫGkIl#[Cʸ$L…u xP41X;0t(D$(؆#I_ y6fԆ&Ȉc lr`2 ̰?1~C "q2wWྦjv?r8 /bu(&x@E㲸d܀Jհ>@u=躮26՞;yCkE8"cEy…":-G4 |s.[xcMp; (tF5I54u0H-ah4)<8P3΀v;EͨqH_(dGr$܆ ʐS R7"lN.›n0($cMϵG>P\ t {0zӰ6챂Y^I& FXE"*_##?q$ k0DOZvf :v{b&|K u!w`ٮϴR"F`2G ͺreJĒ#y4*=e?H {wq%Ŷ-s͊j\My{Y,4}iO0}&}Kt3Лh߻fҡwAN{/ ]zEԺ-ƯGni#KaZE.ZV~9︡_l҇po)K~ZULz'{ i#u::_MPZ j!Go*lO$(d~OAgĖ3/c:!1pjV C>pfZndTвTkn|#߇%`oѳ`2-˩49RpMB_VY(JV nY_X70ϱ4yyd;~=_: %>SpcPF\zζ]o2 a]R ZgуG~@*0Kw_e@vX?sM5a6J1&Q2h2 p@ߴiY< $ܤ*\Iz}Τ^q yյtEӟJ`8< DbV1C>= K %]r۫ʨW&]n(4=;M73Nw Чb]mm9zr*u#Eh ھ]knza%~]f-o"c`e{sJapoPQ^ᅨ݀K"i& kIlU+p*hiq[+zXaŦjG0Q `KDOV}mrJ#4u~j{EwT81ޣ%'s6WZr= ӓA5a] 4 Yp"өC}ys9Ӛ(^:4J/zl"KuT7K&mhڑg?<9\XLgKPFyIxsd9霣񖼝+YZFJ0.p?~z&ƪV/xR2x`N̪꿾ZލyH,g]fF9~eM k#f&vGiviPYc./N@VrvvÐؼg)!:#c["1(+"iU6-:>h贇<=/:]6,ôX"Lnx[k ,M;ݣac}kwK_kwڟ_hwXvUUZ>H%Pq4KrNZwGxw֎M9 ^1nLf1uH+Te0yL Ա2QQo\a0o~Q+C{8x%7^.ph1*:Ãݙi!4_$Y"guNJ2XH crF!<+vP05M}D36t ɣ$8. c{<q|fo{rMH}M/p·tZi[y?͏v-_@X4P“c6NJ)58fJVnXe%~f̊wJJ$nx~/z!!) EEBOz]偣I'OI$trB{rYxUX-⒜ .{/Lk|Я W[3e;4)3\JlFESˠidedENـ.X :㮃򇢠PL N@3Dj$&0 "8DT)L>g"x8|t(L#+x*6s1IURGIO%kHVWH< &XcZ4/Z*M :GC p صua`cn5ۮ[9{Y\Mհτƈ:?,"ڳM1&l(t9.)˟QR R*4&x5To2`#BU %u@]i$"ڶl_{qe ,jvY@4/^(bKOB{X v'=,ΫcNS-UysXy0, #Hͦ\u?_bs%&4 %A@J pj4N%߇Q=kvAO *FG+s ݮIhoҥf6퀗' ¹W`UEl[Ys_(cL#'bv0 <78%C)jrY#݄˭NŲrWzil@@ $*xܴsV#ŷVb j5/Vum PKyͼ*$K8vL>/&1"Lȓ;-lzd `? rss #*_v¤Hr,auprE-2h U{K_Ci $^:Q=z]O=uL4)38Y8B]l]w6+FlO;GBy?-8z%Y3!BBt00]94F2G$J&$]u:67+,Lp!dhM4W^k1DJCewhUg,Χc Ƒ}U֘` >gÁlh搮Ș0@0 2F!ZtMK5 !,WJqtݭ8aPJ&㳲b~/K'gg`'~OWNbGĵw.y,W~_Lw|Kj0eiKUM=JY|@ 7CEVpᑠӊ;degZ,zYtH}]^Ϥ3dztpR MlNhƠ[}+gz9wHϡ*Eo=/m]t [w%{7'>`0u '} 邻+t }Ghh jDyo[zQ7'[6ﭞ$s0t櫪ȝn)Q qPU3eq&6hعWyqJGod@_EWS?FCBnyIWS7h>Pv{yz&:Gw?@/}tr~𽧨PA}('j48MݠU:H5_REeO P]D1 '\3x;pb9F6TL醾sd[mLGgdJgCq.}鷇wo.o΢rytAڒ*-Mk:kJTa*s"rϓiqvEMRl%|yЧ"# P_.)並Bxv0v,;_JCmp`,\Jo[rTk4^rѪ#jt@vnL_:g=$:N>q˗9K6pAOY9۽l>#=їQ=T*Gj1֒aSn2 pfuzJK`օ1Mi4vh4nEۮݸ'4(u,9oz5 dBdY~^oUiz )#a5 pY@t2/qj4R "ul37m -JJz?~󉏑!0h-L Ap2'u)qL(L9[ufb.UTgM ]{K~K/<~CR}hHOutxL(MCsd>;K#s !mM;QJȱ&srr- @-ICGܯpVg!`Gi|}L$ޯ@ N_dȫ^1 *h/^Si(&HM#k(o^pA4N613$S؜ %؋j hh:a)8*%$+tӦ }dr@ۭ.}3ߤ}P^\]gmUn3BmZO+r S̄FaKCwp&u\fN׭MO3G1oly!Mq6I8SKGL6_#0+Iw֑#V8 HIҙ:ckPH'hV#rk%hג(3H>#P51dG.,/H#}$ۖ=|sdۓNF,< &]S\?xL_-MIތ`.oFW;>oWBxH괊+\FQ7/ZQJ-́ ֨.3VppJ+Uz>O;8}πy7BaInS bk2W9f[h1Y6uC_-L1L}Wѥ 'Ys-fJ*dVf30-4jMw#δ e`Z, BNkK"Z(@[ncB+}b`D오+`}WDl 'c1A Xoz[/~گ%Z ]>sO|P ~7i\24߁b UGⳇe0o _b[% dY|_2P6 nۨl޶mySYݦkjmZ-ft"#> ݙY,(#mD]Ӵ<]mB v$Lh1PD]Tn*rJn4ـm:N{"7lo2 rT7D\7y;V>iƒz9]7XjlTejd2es[ XNLt0)C lMdl'o*;dUS53HØ@i:SzϺ]ƀ&n2JI׮jJ*]L!r0:CPy]aúG]i.=Np._1\׏N.j4kaXv@YdtƩS!'>Q)HD,(z!I{F`c6{i#@X!q( 8%9;q+?͏="I}~Ht/Ngv/H N2uEoJ C $:?vidYy IHɦ1$嚊$"M0^m,= FEӄyxH;y_"\ht~lEF& Zi>셒R"%e7$CH$fE2t~Db&@.2V O163sq]ĩ$'!NE@A5|V{#Pc|\nlJIZ+Y0RWncωdq0~ @= _J= &pŭ=Id5daj2];A19ZOql+0!9Uk` Y' N35Yt~BH PlgD 03{9I:L`S1` (5[U#2MVUE9`azr `KHb'&69Bv$eeYJs1mc2#Y@}.58y8lMU7\qF|/JpjM`kZJIL;ĀYf\/9!fq r4!83 Ns_^%jpXg$1K./ygǜ+Nɶ b{~ty')8334EJ$K̨* (΅wO qs|c={Ǝs?:n`sQ<}.Y` !"Xxp*091o{ˡa8sYI #R5SFsO3=J_?ܦ~B4; tdduE#/;\_@|8bغ\8̱G4M"s\8k͖!bl J˹?Y94Y?qU8z\6SX f&I㼡g˭*o:Tx ڞJ!"]a ԡhEα3?}i}F) wjƒJp. "E\ϗqEY*b"XDg,"mp808M׼pJgvFb4N GNTђ~=u!qM>_ON ,|r]j8C2IDxeܥ+Lx}40U$A,2% 9Jgv5K8Rvi_s|609F`aj9aYDoNbNNx3>St{ 4-.MKb+vVqKLzHŚ dA1K np} asQ q@_Q@%6qnCYwzq+['^̻ɸ)syT8Y$pn*dh~eZf;TyQ/&@DVaH"OTd +aM- kF^K}o#dr;╇}VvmP:+2D1q=f.T/G6DUgg &mXN$W:IpȼٮQosPr7(QkQ]JskԖD4%Nb/N2ŒJx !dpQL[oƲǼD\alt jiXi\;2ts3&}s R|y% Nxoe"tܸy/8BC׀m|wTr KF,ULLe)Bqy>؆t-J~hi"39d+Zd_"NH gqO%Wj$D<&Cp۴3B3-gQ8DzB c8e8#F0}?'\|ʘzN1T2Z.%`ɅyT-QH VѾ1vr-螤".bNK Ay2V^/<$%fd.+U#q:,ENkCã;v*: 0t0t1(CS%U ku-BO~t:{ W|R?Ы[KO*Ez Dڻ(w"YH $OThlX+\(g"pޠoFtP*/ᗫۡ9}5}w+ӥ:M*uݺLYnl@XZ)9dm^eY$>qX FNeӽ:O7E+8!4eb7q CK qp;gVrM_G=B4=]O<\^U?4E߲z;ttrtі>%s527JQn8$ou=9<2CStgu7si`YY]/nuiw<: t|NUzGm\@Xp9|YJD s%M5bA\S*Ig?q%tpŅ~'YG}^*^~ULl.t-R1g6P>nk?FCc]AehhMĈM^xxTdDGTں.z2['Hu7TxPu %A\~"|UZk4nr+_l >vӴ2)47]6A4UZ- -Y[6ԣOw YeE>iiuс ir7HlfDP'`&yceE nɶ06.{mx0WR:0&ƨ LHA՛[39Um9LwyN2ʍ d66[P V)$>×ɔ#6+尿/'ډ2Lb 0xP+x]R "ݾ|I麮prp*s' ɐNmIʡՕ&kQNR=lK/4ـǜ<-恨'iI|P|$yGO鉵{O|*qmbt"!U[(}$z|3<7Sqh@;&q t}&̰Au} Uѫ=vG:.+TBjBvd㟐>ysLF KlzE:i^{ LN;%4 I7)(Orrd>uz,Ӿ4 P8NQ28Jck$7Ldؖ~(@_ J&`+iP߹.x >e ͦb c!q@u>M ZsiW+:bl Y $)SK?#H v"Ȗ[ܴɭ{ADs+ U;;#9S ac6BBp<.ݺ*uG(޶ij8A:\v4ؗ%swlkF#Ez5y%Bs>MA&,ۮ}!dv۴s}p؋q$7:I?ׇ g4!q#e~K6Xu^G]L ͮ8+Crv_:@JdtV53wS#PiScrK:l+K=)p(AJ tŵ5^#N48=\ u Q h&29 ߔH},,GRso,;y K.{ ZڶuMN-R_!n(ٰel+I ^ZB+3vjB8ḁHeۛ;vey RqoMdLhp"7OJ1;3Cp^۱XzUʰ䤫PvQ6 fDv5896$Ld[L>jZ)lIS$4 L+!&KW]x:zHcki*W:b*+FH5btgh5 1ANT#a:d'O6P1]U &ܥ,R<\(-TuڏQђY7 y*պ$iԀh:*wJqVW5ft.Q`G񜢤 år5M+|S½TM©5ZyG3e~?[hҖjKTB1I?w0] Pwl ѹ` G7?/WåCIŒeh=>%K/;a<酘[F1zy WÓn\ud7og=UO[ps`NVKlf+Q}Ru}| ϊiaf*Ԩy/A; Z>Uއ ۮq X/'WYI#̴3[jb ")mP$l]lZܗzz͂YAd=ߝu( s[W-|"vWg Ԅ"k%|}klucA,K_3I('uQ,{$MYdVGVІX5&'OW tI|jڿ ʐXH$."U}_m khC*q+k.׸fPPUk\;{Na\1n $M6.EcTդːw1;hB3*q-*lK'ɹ8}%s(A {|{NO\#*|LPF +pDUӻ\շ`!-rܔ]FxS}@O>&ղm9ߥEl̹;ox?!d]cCܖy@sgF @ [= k#YbE<xQH U,aCZ,W7IGD6? ej=qKRq%vq, Y7 } .Mf苇z:$F2@6|Y| qD$>AZ4 dWAf*h8¥2 -^Exd]/N[Tx\1xAC}%w)e TOv$lnՍ8nETN|_'޳s} JAp<k/@S*= R|˘g-w [i %]݄p>p'ǃSu v}/q;Qֺh0҄wP /(JtrI0mѩnmKmE}*rla];veXe(g;7 ]K2OnJt;YĤl AC]BNnucUS jX:ܻС4rR  gnݬ3]3m!|XANmh(ɲ F êaO}tWVEUa= 53|xOv |P&z;(0à+mZ;u"M[v10CAĜ/lA(&<ϭVY zt00W-\kAĬa0Ͱv57m.T+м2|J38Yk;Mm+@K];q1r iI?%:%'ңS*+VGw0L0hcdrXfrYgh]6l5Zi!n3d`N }{* ,`kVDu16ᘢY,Yn8uL,Nvr,hCA.7Wh05Lb탺.~c 08=;X\\hbԛ:3[k,Vi?k#[fgJZkPrՠg{h{A+2-5κ?=fgumXjou>;3m+y^Sou]O]W uͦ[[hNէ@4aM_Ln© D>L߭rkM6vscb]x(I!{EkiUFN0b<iGih~趕w"%-2jv*Oo[&CC52N~u`srzGtӪ8Sm+@.F&I7f?+5nǃ)*<0(r|֍M?L#6Om4yzk>i֞0a1shZ.+<+D^=2>NX9n_㻆kcPmǩ{牠QiqTL \}vK5~b~,#Qހ}=?~҃.2[KUbiۡ:F_l3AD1Q!)0ԈIL ڵ-| `&Y56S)Wkx|p4[^%s ӒqB՟IoqU5h*6en7hVyԒC\>ϩ2+܂p]1[ϕ㏼^H3y9ǡFsZ EyaZkCViAǽܩz*z2[wFL [VZ!U4ti~1BRũnw?5I*3답,E?`\oox< ֶײ)guk{I٩7rAq*0:>? 'Ufb,I ״I:/xh e:> nB"{?rVQ4UI C386)a29\KvZO ^8Vz,4>qŒWvetRO:.mJ6bӆd.vl&uAdb J׃%d wfA<<qDUr,z=nh-}W2B:)6=XRbs!;92@(obUP8#JhIVrH>y+jZƕQnk!ߢ KCuy"n#lw0;h O8r;^mŸ}jn&,07噖$$bˆ *^0.!qFgh'P_K MnN0 3ǽ6Lx?%9MH3񭤮\NVL3|OYV%c>|M{XMs(0'H Dk˄#[Ȁl&RLڌuIeLyr&[99[픒"% hFϷ+ۿp uM['\, gue m(7.q$q ryiߓEPb'7#K rPZ8!̅arK\uY4ȝ_☛tO㳚 ǸAOE.BLyk;9mQ0 43djʝǀq1P}L!ظ\z*Y9]=:yo Vتr2=o݇2kB;r/)f[f+IݑPFMu8'ĉZsUOl/&hۇmvӈ 1F2}+i* M pIbSV6=#y֯n] UMt Q8Ws1:蛀ME}V*h94G.kZg:{8)4bڗjUBs"'²I8xn՞QV47F e =dj6pw^Q$aԫ4k(SC!kV(uD0Xjm@JCi3+R_[W\)␢Z  QP|8'qBr5,`r[#:k(m!jl }upxhZ$|6rp5 ƜM5f* 4h6OyJ췷If؞3Zťty|50b]QPq0*R }Ϋ/>]\8ewAplCii,2o'/lU"r  $'ݘ{٘\BmמBwg*\%hIe^1.FiHسL+EI{mtV=nPEe'ﺼ(Uj ׯ 9%Z:N['{;/~7~XС3cݷ|`5+`naLW]^9@d@J$~HQ*%j$rj*7Ug)N oh*uMQ֤mQ/|_8s$UvTyj5P4IrDKD*Bs;^,13I3tMС *ö~Y r$/Y:e, D6'U؂Si阦"dFӑqEttAQSqZk*q%E=ngBZ6(@q)dϾhzM2ݶ A'x) m=֐dO||"rd`"IdKh RU)Z;)t )|ZSA<,%VjJ~uE &Z2d&"=w/6)dP0zP\Msg(6KM(L-DcUϋ̩-HD(q E#]nﵶQl&{ jF,\i1 J FC?(P# h Cf]⹮l AZ҂DTfj]^Psjm'J0 QSRtoBaeNI,KRU94%-~\LpAdnų',@Dem`dKdg/[XA͊xB+]%TU"OA;tq(=99k =sX[>biϴO16vlMk-қgQQW90ӿQs}[3{JoOә ttvV6?*|hzr-мeVeR"Ŕ+Wemk@r(:C?tI܅3s$sqͤf&krbɨ7uc_$V9x4e~ڶcmw%N ), c_C_O̴ 3:[O Oو9HFEd\wQ\7 @jM銯L'0ΥoR-ռ[ *,,Y)f珜K[-7u.n\S^ _{/tΛ,F7&;^/8*buy8Shҫ!Ԯ60xAYNܺc{0F4v&.3˰@5gd&|Pk"z,ZBgb,֧'W&]f:k7QͲs)ć B94Ҡs=zmZ [Pˊ牟iPbT bq@+e.mTxoѳd!y*X]jԢzݷ}/=hs{zJq4?N̨֊sWC§ᬚdhc|8fcuh /8}~[BBZ߹Bݽ1sPX\zawBaYT% 3?X:y=qH1$K[Jk>2S6*m| wv\ (::Pt)s*XCy?n"s @ۜOl*$6bB{|%&cx 9=*QFtSk9,57M)mHcb>"VA nͨ!1}ߧ(u“ŬA)UOVm5'#JnIl1R@xLW&/ýckFm5$Ow&1Pd_-E`?Lh$r]> 0ֈJd8Nʞ9^|k̿Gwؙ+ fӭqy/av]=LC?YwM_vG砫:)( N8\(xM-6 @vYT32SEߩ+|qxUQriڒji B.?2C RF#zl a+wÄQ$.=# \7GZuW(A`d^pW|;ra8 @jqcӖ7jHҺ,/m3l|G/eӦVw]`icwH}x`eIBGݶ8\l!lE1*NdoVc+_Hr quưXeE\d$TBMG3[xFy:cPQ12mX~o:P9R\ "c" p!@v/ F`bX;'^e6 73jAFnlTM%yYė8_MhBG쒵FNh`”αqMEL@{aƚ:Ϭitݿs8O\G.P۟3z-7}s#t:FU,5L?{.rQ/M١K+=lLPu֖Jۏ=WOK*wLtգ]ڧBt3%FVT#*6'~$z0jLa kG FHD Syn9wkFۉETSˡ}2je \/ݣ9>NuEz;ЋOU?}"*=ڦ|w,yC=N;+?~JLե]wmߣ_Wr(6Zw7;mz>@-/3ߢcTi~U7Ⓩ_caK Q;>z~+[W٥= 6sr~j~@o`7+￁أ=N}brK׽YM/:o{Gb-wۥ&,?Kٓ mO/7O?I Z5%ZC(ٺ -j7|ܤR n`Nƒ`5W 8%>l6u6! M0,oO1g\US||EI'Ny ,PR*OW2k$9(]_AK܏O#@xx ~te^FcM4PO=*WI*=0UMe ^)UHMmPݛšTwjTv-Z;J 3*dx~fy}M(p\ U7MDXdmlslVT={m.n:9`vvmHA_NY6mñ~}\FN-ś\ "mƂϥNܥ>HAW"),7č&"vBy$ʋuI:v5M[~ﲀvTk:hZr5fk|vqOK3'Kpd$)2%j"a)\WK_ #a$T2 51ΎE^sG0|6I%6e%@l6GJjƹpPcgt@͠Ej[pJoTO ɢO7Bnunl&4 lipCeQ g:-Cz%W@p.D\CĊ ~#J: &KUYd!Pʓ4H +OP'T;eY$&HE7 ͫPP0c?djE ԜәI|sSlim7.ʒO?&,$Q)vvW@ /*0ۖ l" sѭ#tGثG;WhnٲI/7)K)q&ÝQ kct߽㓋3RsijDUo~f{͇zVD ^=ܢr zMBO_;o^n_ z5yجw"8_oNQ}>&zc&lR z׃=ojnmYXzheOA%6')]IJ JTmQmyC^kc??M҅/!~6 -_0I.(2p$vslqjp<_w՚r=Do|Ad890ۡ(O$u~Mtéz){zUoLP,*jݷ.Їxہvn&͋4m9˒.NTei:=Q0|<,ӽGߏJ*;W6i?S{OM Y Yeލ|KBUwI1CO;A몞9e I H>1YALTݙr3t r6sg n4.,e{&9χ76jrb)B4~o@W'8ƍS\'ۤ.vYw9r (u%bZ(VY_k4[ƲN8٩[-zC!]>MkO^ZXsgo?E?ۥ{գا.хֶDU;Te@h+:Z{f*}L>UENKڻA>kr0Lʸ|i[цJ/^:'EXGz2th'/ i)l|iE P@H̄QK#* 9`eRr\ ['[rʼnӓAziO1=D8+8*NXd3r:2`Uݤu>y1.kmv́)fzA}y@[ߦ7vPXLE/ā#!296= ?v*UWj9 ԽBksq5Q 33&21(HJ.զP* -7X<^Mć?N0e{a診,qv 6kkT=`d8F=:s/WdWIldHNUߤՋzh4i ru_g[q%d~(ԡ14t7%@rEbs|AC?oh[| T$BpenSAH\ iq%/ɡ`eb2Yh6\ǝ ޘMfi>55vFJI| sKvEF(tc-,辿w;Zuij胿:wexLiGbt߳=bl'z*m찝viK^Rn@)cec9`´q{lGqʾJdvy#qpC\E=1^40(;5@mbؐO H(!Y~`-W'QP *[6W]a4`$5 .YfNzl8,kK,Yw̋w3Lf aSY\f$HbJMEܢgZ_١K;9euh;D 1N'oMXg罺f@'vKUf"$팿6LNyYc3ӕt}PE&:YZٔnD+Ő!C/BHRJHbV3MOptOf&Vg` &hz"=- ?1/@;ϩA< :%>V,$9X 򼒥 Ӝ{5״ZRdgԴ9R :9 IYA0mE>z| C>K338Ļ iTtۭM4a_|zKn0a3p #*j37t0߿=s[T.{47;ͯSEQϡ'Ztq4z {.DHQ5VcR|> &QHB,TXmzg+ _[jhKm&yn<. =7K7 *~SdAQef>I@3\L:͒8Ŧ}قmSa\, %vI@@Ql yenV&Tip_NP MH@ܔ?VT/8Muf直|| [KǼ^eeD.FpAI]~YUqQO舣~jES5PmbySr{"4̜O;=hMN~W~%?|$£1&b%V8,|ByP`;O4;yai A|u쯲Qi_S'8{r{:7K$K[e7J)+9|'XնXe ѬdV.2z#eU ")g&PIliIۖR,Jc {ϻ6zi.]Xm=Qv:~ڬ 'p<aq|tD bT V*B{ xBz}LW}R0 #v{'4{S ~|+jP!(F%a^<2:~] ]7\ͩVJ`/9 ^oY2mwhQapSe+lx|$6J| g +B/}eϖKT=yZzUB…Ϣio.ypvw٩Z!CŒc[b Zvu~|#xez>,fǖD /P\Бn>|&;*8AvӜM0Tɛ/^= ̭tz4<0b_>0%R#:lRIA|7冂)KYee[ WضN52l\`ł3J#SKe:}V`HpD1h wU@0TL(^Oه`'MGXJ!ᡧķ&Q {S^81e5Lńz.@BC/NA>l'7wOʿ7T8{Ʀ!Ht{bZWq SzCY?"H`/E 425yO!Kͧt#Sq48fOd';;t5:66Bn>ɛa笧sd 7֌ojS4a݀#?*tdq_ȡXmn)ۮr!.qۼQ0AD~#S0scBf}O{_d9KIh0^v '60#ٜULTȦ8:L &V(sA/}c Q@@єV9r=D=(K8r"ŧƑ̞>nPdS7'muu@ҳt'I˗R]?^ư(/gϪo 9!{C4IH:Rϊ=Rr 4-ĺ XEzS SCO" j^(`F2b7 A<iIaa OلճKe0מlZ kiLpL{+;_'4(bqD6|f^6 9=* ᨓ%i XI&kZ?sY/AA Gq?T6uUFu6q\l06GTasEyJJ`dJ.$bTGlkf8` IS},b3!l⑦nhl8Hc'}cN"+Dvwt#Rw,&8A]/P:ء#;})DR*: R䓿DP1&"kq|I2>Yv,8Au_bƤ8E`8nb.X$a'vk@RE=fMU=iiʵIثⶢLz|{rR'%.W}{otO A!9؃92O6"% #xd7 >4)ҒFY^u^9yNtn)(:ΪZr 4eG-xccUk3 ,+@hǂXKģ\4:0J bd(D'Y4_DvP^zܵfɺʁ:sHǷNXyYl>r;PDIa0i.KD&<WE`.Wnqi'dqIb<HV\!Y~FX8tU ozCJJRE, #Ougq 0c+=wq,oɫ]kks6mXR_W,=HU|i΋[۵Ճ~+U< {;rU 5PwihYh|0mEu?]4^@,p 7L2OjYUH:9`87Yf)L0?Y4ȱskw5q-l+cJշ֮VyܠrN4#_g|`I{a` LZY옘.no>uO)-\;mq,͚R1PaRf%o--gZaJ ^22l>\8n0/n r9F/@f1(sƦxQH`})dT;WBLaLt+QfHhɅou2UA:ٞUp +~_jWk >%o3)W383k?v|6fm_AB`2A8e[Ԏʋ;fiil6&3 l"ww-۬>J FhAY[ԾL^Q~0:3uq>v{ϵ_e~oHMc (LP[SV 8@NU=E!kW(tnoz˨a1LUj I) a?'u0ny~K|e4 RߋѮld ~6t~aaкryh IC2O2H&b5hBkodײrV*[s+lg .]̀j;d P. K`CY,͵$`$#CuR Fkw kjꀓ= Ma@9iUF@ś14QI227M$W_V%%arPɱK%XLViP\"} .I9I.9_9P7@H`Ư[jfa{Z5C? b`}bp+;|fU9f~l/*B~V~:1LjpxIMaQ*10 Kg!"PDfjcpw&gKrDAΚS@nLm&4uAF>ܗ$EBŭ920iX輗*?,4>#X c I79p `)|-ƅ jxf*.g)$s a7~.N>j]8lGfƥdnm'Ԧ@^)\3z\;0%k'J5~eAw%A / V6`SM1 )J Ĕ1oZ|P[6hZ!\EX*l3!$ȋ'C5XOXN PP8a;n%s+L3k2T\>A B{-a@dp}D-Ѐ|oV"~iR[M::c(b\wIeZ>cHdY*_;rɯ_Pњ&o\Ȇjvv c6Ph84YA\#vJH*Ip;Gi?)+ZrP-,e|XQ^vRzzQW1!5sЛe< ռS/=t`D<o WU ](>d*siASs^f CG^o(nXHqhhhF$)hQj !vJ!PpOohB\pݎ7%D)ŝ9\p8|):q;;- jtl&s,ғ !{w~ B!G1 Cb=Le|z7*!˲==mn!v۷/E"{#.'696RaWecNCcC77N==zb.88`q(c`)p<~ϙܪZ47?IVV{Y YQUY ΗI18(͓u^}.;#Dbdt*>X \.8rR 4qҥg&/32|0ҋsW$X\65::$>, 0GgA<>r760=;;^3˲auSZO߮u~gFuJz2!_/R!iZJS84aOeH%HvHBPn1il8.V ̂`OkIENDB`tpclient-pywx-0.3.1.1/graphics/mousemode-icon16.png0000644000175000017500000000074110773624641020261 0ustar timtimPNG  IHDRa pHYsaa?itIME IDAT8˕=@] zM,lEkIF_]6b+V֗F2F9Asx <̀pnVEgwbA)`u\DMӐ`.sH)Q(d0%@854M$ CB0~0Ma<S r" h`\b2RD"4MLSK8PJ|>C۶@DR>kZBX,BJx|>G,8xf88N(޿|ABIENDB`tpclient-pywx-0.3.1.1/graphics/mousewaypoint-icon24.png0000644000175000017500000000174010773624641021206 0ustar timtimPNG  IHDRw=gAMA abKGD pHYs  tIME4K@]IDATHu͎D۩? @,Db4BlX0,x^^}6<5&Pˢj3X\u眲^UpE=(ź7z& MWO7ZU*w|DR#e#JT/*+p)[?%UPږsCn{](b, pq0%Yá 81^)iD*>@ro)P!_/OK&Hyq2VC`sM7؏ԛU0qōk8/MH;ml6XA$γ3jl0݄l#m+u-~^JYƑciYfn&ʪ@0o"LrRNqSC3#rDOh6#v"(;4Ub%s'] +{TE?'ͷޛH$ɻw-Y%?Q$eO2R1Zì]򌵿e]B"f۞TsS<EDzH/ȍĂ{V 0(G"wsEfwoDC\F"M&>Jz2&>fye 6Uɮ br)Yx3UK~|"ųn'Q 4m [yeû?Κ;kQe@7R cERi=vc 3=Uu\,[mه&noyRbpzDu= +;'rw9#P jx|_ONw^\o.mS){tIENDB`tpclient-pywx-0.3.1.1/graphics/ship-icon.png0000644000175000017500000000055010773624641017056 0ustar timtimPNG  IHDRasRGBbKGD pHYs+tIME % ;'IDAT8˕S x݀9 0P7o+9Hk}ɲ43qqC'oVHZyI#e "9k{HD7s{U{H)av74bVRPJA!ZS}gֺbpY03/ؐj>IX`{l'k[l̦u_;/'|J.IENDB`tpclient-pywx-0.3.1.1/graphics/mousemode-icon24.png0000644000175000017500000000113310773624641020254 0ustar timtimPNG  IHDRw=bKGD pHYs  tIME2ǵHIDATHǭ͋NQϹI Fo%,EV6backB׬h"kMHHx>w繏:{7yRJ Z[*ՂyO؄xȢP2WͰfװsH270a}m/،}%uA:-npbquMC0(lUg&@A$X|Ѱ @c6PnoC!˘ + D0Үc 4u qS8_xG1?|..l8 +ܬ}+\3 WCezSgb0Nycd[Crda0G"I7#7 f;Y;8^ ,/'HZ.RJqt{ MRsȘn5H3]#u5h3BgoD p/\51!Jտ7KubIENDB`tpclient-pywx-0.3.1.1/graphics/system-icon.png0000644000175000017500000000037710773624641017446 0ustar timtimPNG  IHDRRsRGBPLTE [^tRNS@fbKGDH pHYsodtIME "݌YIDATm @Cw @ .ucU, )m^4N2\ J9ye.AyVys尣(PTTָHIIENDB`tpclient-pywx-0.3.1.1/graphics/waiting.png0000644000175000017500000000317510773624641016635 0ustar timtimPNG  IHDR szzbKGD pHYsHHFk>IDATXý[lW9gfv.7vbR"riBTTTnB }DH}CU5!!xA@y⡁\\W<IѴ&\pԷ^ݙsx_Dl'fwG.%&:s7hM75iwK-QMO~m֧٘e OLۓI<hϵ_3;^͔)' .}R $*%قEy[0j9+]KK|&ҥ[Jo>[:rX3H澁{;ݧ-Jc1:@k@T eq4]Zy)_YWߥ_tw0 _F9XF%HAglbG;dnwR`x|!\@q"Ʒm=\J}Qb#-5P={DB$of@MԋzJWz5L^|HpcPWz:DRqO(  PjHC\,G&?rkݘL}||rެ[>z q Kw{,iIq |X}˧܋8햘 `:4i g'd͛Č|(^ǯr)q='-t tea"V溨eʿʙ! U"hDݒ#Z+b߸! ( &@$1ϹUPl A` [-A($L<,qPYO#b #ݡ ([qxmeoQF`11$xj:ֿ5ZTdnBNC a )9f%1K>c*2U@pmQT3x6D=nbÆ \ 7;jdpqGw'D5B)$( D؀2t 0 H͏.Sw{.UU(DvG;@)\<7UH~óӽ\ur*:Zme8ضV D<Z Cq?w܅<$d0qkP-yN$6ef,^B2 }x/g/?١\N(?|΂dՐIh+'' {A>u'*:')vxJZ8~8|c'r͐cl+<SA KAút*`x7/60|jaP5tMAەb=V:m+To\}< @P9s'lZx03wmb`qŁ9}`Y{B+T^%e36n_e!IENDB`tpclient-pywx-0.3.1.1/graphics/sidebar.bmp0000644000175000017500000045760610773624641016612 0ustar timtimBM_6(<P_uujrQnBrBm_MkJsPyL_WHka`\b]NBF{|3^s2yn!ccccccccccccccccccc`[=W/W?g[d`][|SBEMK[gq`TKXSib]rVUsUzvZy[vf~lnut^pJpBiGbLsMvOpPJcUgbw@Epb_qqq kw^tJqAiBe>lApTzULfTxRp,kcccccccccccccccccccccccccccccf n+sFmXrRyJ@gVvg^UWQ"|b`qC]wUzp|6z*ecun[}xo~m|frOpEoBd@i@kJ{f:>WE@eddmmm555   f~gZKrKrFoIy6*tFccc;#j@A'e<G*\7cccS2S2Y5/+VP]T!l}y^z5k{=u,s'o|byn^qlfwe|gbNwHmn0FQ2PF2:?<KL+?0..-A@@TTSggg||{SPM-)&'#!!!""##!!!! !#$"$$""#!%%#&'%((&**)&'%(('!!()'"# "#$#$ %'")+&02-;=7;=799388277144/22.00,33/++'&%" ~y]dccc݅דӪ֯ԱӰߜȲ ߧ cd}w@9FHA@B;>@9CC;HH@HHAEE>>>9>>9==833/0/+#" dccccᤤ䊊۞&&&ժ֠mmmXXXͰ槧춶󛛛,,,驩¾---󾾾 ccc[U48dF$*%242CCBTTSccbqqp3/+)$ 4.*;4/3,(0)$70,92-1*%/)$0*%1*%2+'5.*3-(.'#2,(+% (")#&!&!(#& '"2-)*&".*%-)$3/*840JFA73.2.)20*21*44,991;;3<<4??6<<38:037+,0%+/%,/'+.'+-',.)13.+-'02,02,.0+.0**,&02,340HHF//.yzy231:;7=>;885552896AB?674452;<9DEB5628:2;=5BE=LOGLNFKNEEH?HKBLLCQQHYYPUUMJJCHHADD>994//+$#  =cccccCCC~~~ZZZИɣxxxccc\\\eeeccc___达 yJ]>($0/+==;MMLZZYhhgtts`]Y50*;7194/5.);3-81+=5/A947.)5-'91+7/)81+80*91,=50?725-(4-(1)$/'"3,'4,(1*%0)%3-(@943-)72-83.:60;60MIC;7162,75-::0>>4BB8CC:FF3:=523-4614615808;4MPH=@979336/8:3<>8OPNUUU333..-896BC?>?;<=:?@=AB><=9>>;AA?DDABD?BE883-94.94-72,:3->5/JA;G>8G>8NE?C;4?71?70<4.A82A93PGAYPJ=4/=5/ME?3,&6/)91+E>9;4.:3.C;6HAV]HW^KIN>AF8MQG=@8794793;=6;=6LOGFHA>@9=?8FHADE@UVTZZZ+++01/DEBHIE?@7UMFrjd|tmZRKC;5D<5@:3?82>71E>8HA;>92>81>8294-A;5B<683-;5/@93C=7E?9GA;C>7LG@MHAJD=KF?IC=FA9C@6EB8IF%c# ~~~  ט 221 %%#10/>>7JE>@:3@;4>9283,82,?92SMGPJD=70A;5C>7E?8GB;HB;LF@LG@LF?JD=KE>GC:FB8GC8JF;NJ?QMBSOD^ZOTTGTXIRWI[_TOSIJMF;<7<=9EFCDEABC?DEAGHDEFBFGCAB>JKFY[V[\[+++664BD81:4-;4-<6.<6/?81SMG~wd^WD=6<6/@:3<6/A;4C=6>81A;4?92<6/;5.JD=LF?@:4B<5D>7HCLH>NJ?PLAQMBTPEa]RYXLPUFQUGFJ>SVLLNGQRNRSPOPMHIECD@IJFGHDGHDHIEFGCLNH`b\\\[+++231AD960(#! sJcccccccݘ#""ա ˟ŭ Ÿȭ TTS+,*##!*+)453@@>JJIXXV^^\eedmmluut}}|ϐ20),*".,$64,30(.*"41)30(:7/3/'85-C?8JG?3/'96.@=5MIBTPI@<4:7/A<5C=6@:3>81A;4VPIE>7@:3OIB<6/@:3@:3A;4B<5C=6ICMI>NJ?RNCSODZVK[[NVZKOSEZ_SIMBQSL[\XZ[WBCACD@FGCWXTJKGIJFFGCHIEMOJ^_Z[[Z===-.+CE>JMDQTJPTHNRFSWK`dX]aU[_S]aUcgZejZfl[jp_gm\ntcpve|qw|lvxissevtggcW]XNSMDE?993/+%$ mOu7cccccc~~~ ᅅ ˟󸸸iig"" ,-*231;<:EFDNNMWXV``_ihgonmvut~}}nj<:3,*"?=5;91,*"/-%42*/-%0.&,+$87/42)86.A?7=;3?=5GF>FD<65-87/87/:80:6.A;4MG@:4-?92F@9D>7>81F@9?92?92=70<6/?92C=6GA:ICHL@?C8JLEXYUPQNFGDCD@EFBHIEJKGMNJIJFIJFXYTikfXXWցMPHVXPTWMTYLbgYgk]cgY_dVbgYfk]nsdntdhn]puepveqvfx~m}|todrkakbYcZRZPJMD?81.+## hK҂WAkccccڗVVVxxx˟@?>*)'%$#--+775@A?JJHRRPZZYbbaijhppovwu~~}ѵ\[U,*",*",*"1/'?=5.,$97/./&-/&*,#/2)02*/1(56-58/24+57/:<3/1(13*13*24+35,980A;4F@971*<6/?92E?8=70B<5A;4B<5@:3?92A;4E?8HB;KE>JD=NHAJD=PJCe_XMG@KE>LG>RMCVRGPLAUQEUQFYUJYVKVUIKP@EJ;KOCAD:DF?QRN]^[GHFDEAFGCKLHLMILMIIJFJKFMNI\^YWXWݾPPN^_[]_ZY[U]_Whkaad[`cZbe\dg^cf]eh_gkagkailcilcilcmpfuyotumyuoxslaZob[j\VZMHJ>;:/-,"" bTuUZ}Tj cccݟ---ۦڗљ"""Ψggf$$"++)553>>81?92E?8GA:ICHB;LF?LF?HB;LF?LF?QKCQMBQMBRNCXTIXTI\XMZVKRRFLPBDI;CH<=@6>A9CD@YZWYZWIJFGHDJKGHIEKLHKLHOPLVXRac^WXWʅvvuuvuvvuvwvuvuvvuvvuvvuvvuvvuwwvwwvvvuvwvvwvwwvwwvyyxUKHl\Wsa]bQNQB@@32-!#   ]JePlRtTyZ{Pq!c___ՓΨtut+,*&'& ('%11/998DDCOOMRRPYYW__^efdkljqrqxxwϐA@80.&<;2.,$+*"+*"**!+*"ONE?>6_^Vbe\8=4',#@E<04+,1(26-6;28=44906;2.2)+0'-2)/3*04+22*4/(50)94-84,:5.:6.<80D?8?:3C=6C>7B=6@;4A<5C>7ID=OJCHD;JE=ID4<@7>@9@B=GHEbc`YZVGGCRSOWXTNOKQQMVVRY[Uce`ZZYР{{{**)D?>n[Zwa`lWW^LLF673$&"  YS\SaSpTyQ~T|wLzze }}}LLL wwwIII sssRRRkkk??>))(%%$--,665==6?=5hf]MLADC8GE:ED9IH=JH>KI?TNDYPF\SHYPFXRHYUJXVKUSHMMC@A:;=7<>8BD>AC>@A=CD@STPigcXVRTRNXVRWUQ^\X`_Zhhclni^^]... =67oVX|\asTZcGMN6<;(+' IUFTKO_MeIdL}kL{zxGUS+/*0.(.*.3,?&=%A)?&V\8 ##"++*221::9AAAMMMOPOWWV]]]ddciiinnmssszzyִ^`Z14+14+),#+.%,/&-0'.1(+.%,/&(+"),#690DG>wzq{~uJMD*-$14+36-*-$'*!&) %($'$''*!*-$-0'.1(-0',/&-0'*-$25,14+25,03*25,34+75-75-=;3DB:<:2:80@>6?=4@?4EE9@@4EE9GG;JJ>NMBWRGZOE\RH\SHb[Q^ZOVTITSHDD<:;6>?;<=9>?;@A=GHDGHDHHDgd`vtp`]Yda]b_[`]Yb`[gfalnh]^]111DDD5657766656656656756757865645544544534645646646657767768769661..8--x[_emzU^lISV9@D-20!$  4^:j>nIcXZUZZSqtagx^tyqZp]mdjtnrttQ mC) !"!))(./.676>>=EEDLLKRRR[[Z___eeellkqqqtttzzyՓ-0'%(&) ),"(+"+.%,/&-0',/&+.%-0',/&>3JJ>BB6BB6GG;JJ>ONBSODXNDg^Sb[Pb^R]\PPPDLNB=?6?AFK287%)# 2J:P8h;vJiLb}J_uU]vc\vc^vWdlV}UXxFUc!"$%$--,554>>=AAAHHGRRRVVU\\[`a`ggfkkkppouuu{{{ӞILD),#&) $'&) %((+"*-$,/&,/&,/&.1(36-47.@C:),#03).1(&) &) ),#,/&+.%),#(+"%( #"!!$%(),#),#),#25,+.%+.%'*!),#&) 03*),#/0(;9186.@>697/64,@>6EC;CB888-AA5CC7GG;GG;II=JJ>OLAQI?WPEUPEQPENOCJL@CG;;=4:;6=>:@A=IJFBC?HIEKLHVVR]ZUjgcspl_\Xifbifbspk{zv``_+++>>;fe^qphssjsvkw{ox|py}qfj^gk_fj^bfZdg[hi^gg[ig\qla}vlypf}ogplonmoswdl]g{R]hDNU9@=(-* 'P5I?M4qAuHe|@t~=~}AzDP6\ ##")*)110887>>=DDDLLKRRQXXW]]]ccbkkkllkqrqvvv{|{޽`b[47.14+(+"),#$'.1(-0''*!%(.1(-0'),#36-@C:>A8/2)03*/2)690&) (+"-0',/&47.36-MPG:=4 !""%$'$'$'&) (+"AD;25,03*),#+.%'*!44,;9120(20(64,53+31)53+54*;;0DD8HHLL@KK?LJ>NI>XTITRGPPDY\PKPD?F9GD,31$!   =A~(P;K8c?vBs6`$oDJ$!!!''&,,+554:;:AA@HHGMMLSSSYYX^^]dddhhhmmlrrrvvu~~}ںdf_,/''*!),#*-$-0'.1(03*14+),#),#=@7,/&+.%(+",/&,/&69047.*-$'*!&) &) ),#+.%*-$"%),#7:1!$"! #!$"%"%"%"%58/'*!(+"),$.1(,/&(+"&) ,,$0.&1/'/-%0.&0.&.,$10'75,@@4GG;GG;KK?GG;GG;II=ML@NLARQEPPDHJ>NSGHPCAJ=>D;=?;=>:CD@FGCHIEIJFNOK\[Wb_[\YU^[Wbaa,,,@>>=DDCJJIPPOVVUZZY__^dedhihmmmrrrvvv{{{Տ/2)),##&;>57:17:1(+"+.%+.%9<3BE<+.%03*,/&),#14+'*!'*!,/&.1(14+7:1!$!"$'),#$' #%(#&!$!$"%#&&) (+"(+"(+"47-25,&) %((+"47..1(%(-.&/-%0.&31)0.&31)75-:80?>4DD8HHDD8VVJUUIONBQQENPDCG;JQDDNA8C68@6;=9?@<>?;?@?>MMMRRQXXW\\\aaaefekkjqqprrrwww}}}噚<=9#% # #%(%('*!*-$,/&03*03*.1(14++.%.1(),#47.),#),#+.%(+"(*"#&%($' "&) %'%(')!%'"%$'&)&)'*!),#*-#),#*.$14+*-$'*!+/%.1'(+",/&12*31)43+98043+>=5LKCKIAII?JJ?MNBMNB\]PKL@IJ=]^RTTIRRFIJ>ILABG;;C7:C6:E8g&I:%  FFF^^^bbafffjkjrrqttsxxw||{Z[X$%" !"#&%('*!&) ,/&/2).1(14+14+03*-0',/&-0'690/1*')$')$$&!&'""$ !!"!$& (*%(*%#$&) +.#37,)-"),!(,!.2&+/#/3(6:.26+*."04).2'04)8<137-57.57.:<39;2:<3TVMKLDEHAC=BC==@99=6AE?BG@FGBVUQNLHED@FD@GEAQOKca]_[W]XUga^vpm~Ž"""OMJwz~xmqodrqexujxshrkawoewmcvkaxjc~nh|jdngnhnhpkpmlny}nshqbo[jP_|JYf;HP-815),0$15)48,59-<@47:08;29<3LOF@C:=@7LOFQSJFI>gl]EJ;@E6[`Q=B3CH9=B3?B8>?:9:69:69:6;<8EFBUVR__[]ZVSPLIFBKHDROKWTP^[WUQM]WTohe|yĽƳ,,,HEBx{znvrgwrgzshvmcsh^rhri{kc|id~kf~jernnjlhmiljlpquhoku`mYiM^yEUc8FJ(37'& =W     VVVtttyyyӒOPL<=9*+'+,)341()$ %'%(&) '*!),#+.%),#-0',/&.1(03*),#'*!'*!#&$& #$ *+'#$ %&"()%"# 784+,)+,(58/CG;04((,!+/#.2&/3'26*7;/<@448,EI=<@4BF:;?3>B6=A6?B9BE1;@382CG;;?3AE99=1=A5>A68;2@C:7:1=@78;225,25,26+26*;?47;/7;/59-:>359.580451784;<8673>?;HIEQRNUTPQNIJGCHEANKGZWS^[W^[WXTP_XUngd~wt»ɻ~~ws}v{ymvsgxti|vkzrhzpf~rhtkvn}je|idlglglhoktptsimiolsiu`nUf}FVj;HQ2;:%+) B-2  9:6*+'$';>525,14+'*!%(690*-$(+"(+"(+"+.%*-$$'#&!#"##$ $%! !-/',0$?C7=A5AE915)15)15)8<048,9=18<08<07;/48,=A5;?4AD;8;225,-0'14+03*9<3+.%.1(25,/2)/3*<@6:=535-25-34/562895784=>:TUQEFBHHDZWSIFBEB>FC?KHDZWS]ZVWSO\URngd~wt}|txtlrpitqjwsmztnxqkyqkwnhyoj{olxmiznkzli}mknlqosrtvsv^ebm\jRbxDSd9EI.57%+$  -'*  ֕-.+*+' $%!/0,"47.-0'&) '*!*-$(+"(+"(+"&) $'$'!$#&#&!%&"*+'!"  #$ '($03*/3'8<08<0<@437+04(6:.;?348,7;/6:.7;/15)26*RVJ=@6@C:?B97:1.1(,/&+.%58/)+$)+%*+&./)02,<=8;=8450BC?9:6784562673784:;7BC?@?;IFBEB>OLHYVRQNJURNb_[b^Z[TQkdayvZXX~~~ppoeedggfponzyx~dNR_hYf~O^rBQa9DH.42"&   ꓔ896!!"%%(*-$+.%(+"+.%(+"'*!$'"%"% #"%!$ !!"&'#%&"'($!"$%! ! #$ &(#,/&15),0$6:.6:.7;.48,9=1:>237+48,26*/3'.2&26*15(.2'25,36-*-$/2)$'$''*!%'!$%!'($,-)/0,?@<:;7451MNJAB>7847848957849:6;<8>>:C@pU]{Wb{R`qGT_;FF+1-   +,)潾\]Z !./+  ! 03*,/&+.%+.%7:1690%($'$'#&!$!"!#"#!#!"%&! ! "#$% $% )*&  !()%(*%()%-0'/3',0$.2&/3'37+8<0;?348,15)48,04(+/#*."-1%7;/37-*-$&) "%7:1'*!$'#&#%#$!%&#)*'/0,@A>?@=12/674451673562JKGCD@;<8>?;==9A?;?<8GD@OLHGD@MJFWTPokgfa\yu{/..%$$OOOKKK3./ePVy[d}XdnHTX6@B&-.       kmiZ]X$' "$& # *,%,.'&)"!$"$"%!!$ #$''*!'*!+.%(+",/&/2)+.%#&'*!%(+.%'*!!(+".0&)) /0&**!$%""!#!681*,%)+$58./3'/3',0$-1%26*9=148,.2&15)GK?59--1%-1%.2&6:.8<1?B9&) "%;>5+.%7:28<>8;=7>@:;=7=?:;<7??:IJDKLFBB=EF@DD>[[U~}vx{xultriusj}tx|tkf`JFCC@=IGCNLHDB>1/+.,)MMKxxw--,+++332421842;53?86A:8E=<@96A97A97D<;D;:B98<31@44rZ]`hxS_hBNT2A8&--    "$(+#JLE$'790"%$'"%$(36-),##&"%*-$(+"+.%'*!'*!%('*!),#&) (+"'*!&) ),#58/14+'*!'*!,/&'*!),#*-$+.%#& #&) 55+LL@AA4??3II=88,66*00$(* '*!'*!%($'&) /2)/2).2'48,7;/48,37+7;/6:.15)15)7;/,0$,0$+/#9=1/3'-1%04)58/+.%),#36-*-$&) ),#35//0,/0,*+'23/340562895:<5:>48<19=2;?4<@5<@5GK@W[PHLA>B7?C8@C9EH>SWLei^eh]lmarrfhh\aaUaaUffZii]ji^wshlh]hcXc_TeaV{pvuqXWW*)'<63bWRn`Zqa[sb]xe_ub]s`[vb]zgb{hcwd_}ichamgge{abwV^qJVg?LU3>;%,+!    %%%%))"WVPdc]44,//&32*NME.-%+-$$'.1(),#%(#&#&,/&'*!+.%'*!(+"'*!&) 14+25,),"(+"&) *-$03*.1(%(%(#&-0'),#*-$),#'*!#&%(23(;;/<<0??3RRGAA5BB699-/0',/&,/&),#),#,/&03*25,6:/7;/8<0;?37;/9=18<037+BF:7;/(, *.#*.#04'?C7/3'+/$14*03*-0'@C:58/%($')+$562/0,()%./+/0,451672>@88<06;/;?3?C7<@4<@5HL@Y]QKOC<@4>B6KOCW[Ojnb\`TWYMccWhh\ii]eeY__S]]Q\\P^^Rmk`caUa_SebWgdYqodttrzyy;:92.+_VOl`Zn`Zo_Yp_Yra\q`[sb\tc^nhud^o^Xtc\jc~icva^t[\tSZoGSf<4./&+.%25,=@7$'#&&) '*!),#*-$),#%('*!'*!-0'.1((+"(+"'*!*-$/2)-0'%((+"),#-0'(+"03*47.(+"'*!(+"23)88,??3CC7@@4;;/CC7<<046,47.25,/2)14+;>536-7:159.8<08<09=17;/48,15)?C715),0$).!&**."37*/3'*.".1'*-$*-$+.%/2)7:103*-0&46/'($+,('($*+',-)12.340:<4;@2>B4@E7BG8AF8=B4EJJJ>;;/55)AA522&68.69014+.1(14+:=4GM=KQAFL;JP?PVE`fUY_NRXGV\KZ`OW[L^_RYYLVVJUUIZZNaaUeeYcdX\^Reh\dg[[^RXZN]`UJKF[[[:86NGBdZSma[fXRl\Vm^Xh[Ug[Ul`Zoc]k^Xsga|pik^Wqd[n`Yo]YrXZpMUmBNd6DS+7?)-   !0+&2,&4-'92+=6/@81?70<5.81*B<5?@703*.1(*-$,/&+.%/2)25,,/&690,/&+.%,/&+.%-0'03*.1(%('* "%(+"14+03*&) *-%.1(),#-0'(+"(+"25,>A8@A6==2HH4.2'37+>B6/3'04(59-;?37;/-1%-1%*.",0$.2&(, 59-04(.2'14+58/690;>514+03*,/&*,%')$+,(01-+,()*&01-./+37,8>,@F4FL:IO=JP>OUC\bPRXEX^L\bOY_MU[ISYGQWESYFTXHUUITTHQQEPPD\\PeeYaaUWYMMREOUIOUHLREOUHTZOJLGFDBQJDbXQdXRl^XhXRl]WbWQbWPcYRi^Xi_XeZTf\U`VNcYPcXPk[Wx`bpLUk?Lb4BR)6<((    &")#;50:4.92,<5.A93E=6JA;OF?@81;4-==5<>524+13*23+24,-.&46-25,3:>269/25,*-$/2)=@7+.%*.$*-$:<5-.),-(-.)01,+,(@B=<>925*9=,@E2BG5DI7HM;KP>V[IY^L\aOW\JSXFRWERWEPUCPUCSWGVWJOPDVWKYZN[\PopdtvjZ]QLREHOBHOBIPCHOBPVJ^a[XVUSMGcZSaVPgZTgXRh[Uf]VaXQbZSd\U^UN\SL`VOaXP_VMnc[dTPjQSmIQl@Lc5BO(46&#   %"*&"72-=8271+;5.D=6C:3J?9G<5C60?3-=6/A<4=80<6/<6/GB:=7/B<565-.0'12)12)35,-/&./&34+20(86.1/'0.%.,$?<4:80/,$0/'//&22*00'--%11(CC;\\TFG>>@646,13)@C9BD:+-#%' "   "'(#,/)582),$@D:36,15*/3)48.*.$&*7:0;?4#'!%$'&*%) 48.-0''*!(+"47.-0'),#+.%25,8;1ORI36-.1'14*14*-0'58/8:.BB5VWIGH:FG9MN@VWI\]O^_QYYKWWISTFQRDSTFRSETUFX[MNSFSXKKQDV\OV[OgnamsgQWJINBGL@HL@JOC]bVQUJgib배mkh{wqa[Tc[T_TM]TN^XP_XQaYR]SL\QK\PJ^QJdVPgWRplhTSfJNkGNk@Kd7CP+54#!   %!-)#4/)63+F@:D=5@6/F:4PB?603*-0',/&03*-0'"%!$ ! &'#%'!+.%47.),#-0'47.*-$#&&) #&#&"%!%&) &) &) +.%*-$25,8;2-0'>A814+47.36,04(*."*.".2&/3'=A5DHHF;KI>QODTRGVTIVTIVTI[YMRPESQFSQFSRFQODKMAIQDV_RCL?DM@DM@PYLPYLHPCGK?FJ>FJ>HL@UYMSVKLOE赵~|qokqnijd`jealidnjee_[g`\jb^lb^k`\oc`oa_rcaeQPrWZhELh>Ia7AP+45#!   %!+&!1,&52*ID=D<5D:3I<6M?9I93G82A5/A70@6/C92ZPIA70A71@70=9153+86.63+75-97/=:220(72+4.'<6/=70B<571*:4-94-52*;9197/42*64,64,=;3;:201(*-$*-$(+"%(!%(" ! !!" $&!')#),$DG>14+),#%($'"%""$'!$"%&) &) &) &) '*"@C:+.%03*-0(*-%),#-1&-1%.2&,0$37+15)=A5FJ>KMADD8BA5GF:NMAMMAII=KJ>OOCLK?MMAMMA[ZOQPDPPDRRFGJ>ENANWJAJ=?H;>G:CL??H;CK>FJ>DHFJ>IMA?C8UWP›srrponnnmqppnmlmllnmlnmlnmlqonQDDfNQcBIdN*27%#   $ +&!2-'73,:4-LD=MD=E93H:4YJD]NHF;4B81@6/?5.?5.;1+>4.G>7B=5<70B>7A=5=91GB;EA9:5-82+:4-71*60)3-&3-&71*3.'41)53+20(<:2DB:<:2><486.-/&),#*-$'*!$'!!$(+" &'##$ ()%)+$(+"47.*-$$'&) $' #!*-$+.%-0'&) &) &) (+"),#&) 691,/&/2)58036--1&15)04(15)26*7;/GK>?D77;/9HJ>IK?DHENA@IG:AJ=?H;AICG;AE9AE9DG=IKGJJIAAALLL___pppyyy|||||||||||||||||||||||||||eee,,,:45P<>`AGb:D]2=M)29&%    !"$ *& 3.'51*83,C;4H>7G;5H:4L<6L=7SHBJ@9?5.?5.?5.=3,?5.<3,=4-=6/C<5D=6B:3D=6JB;B;4=6/>81>81:4-82+<6/;5.3.'97/31)31)42*EC;97/64,0.&68/25,8;2),##&/2)),#&) %&!!"$%!#$ &'"(*$$'(+"*-$%(&) '*!" !!&) &) !$"%.1(14+*-$&) !$),#9<3FI@37-+/$26*6:.37+7;/?C77;/59-27+28+27+7C7JOCBH;JOCLQDCIMQEGK?GK?CG;>B6@D8DH68;6;;9::9'&&,((M:7A;4?92;5.:4-:4-=70@:372+;81;91/-%1/'20(53+:800/'@A8DG>@C:03*%(%(8;2'*!!" %'"+-'"%%(-0'!$%(!$"% #!$$' #!$"03*,/&*-$'*!#&*-$:=4204(59-6:.KOC<@438+>D719,6>1@H;.7*49B5:C6:A4RVJLPDHL@@D8>B6?C7AE9=A6=B9;?7=>765043/742>;98640/-20.85341/2/-51/50.3.-2.-,('*##J9;\?E`;Db8CT-7D%..   #-)$,'!/,%4.(81*<3,B60I;5H82O@:J>7=3,C92I?8E;4A70C92C92@5.C71MA;MA;E:3PE?>2,C81E=6GA:E?8<6/71*71*;5.72+1/'20(-+#1/'53+31)42*21)56-69047.14+&) %(%("#&("'*!'*!+.%!$+.& #!!*-$690/2)),#&) ,/&9<3+.%*-$),#-0'8;125,26,37,48-48,37+59-?C79=17;/?F9*3&'1$1;.+5(2;./8+7@3QZMhqdIRE@J==F9;E83=01;.4=01:-5>1;D7?H;;D75>1@D8HL@EI=>B7?D:AF=OQHHF>C@9JE?NHAKE?@<6=71D<7C:5RHBYMGQC>F94D:7@85C87SACW;A^9Cf=H]6@E$.1!!    &"+'!-)#0,%5.(90)?3-F93F71F71J>8@6/=3,@6/A70@70@6/@6/B60>3,A60E93B60J>8H<6E:4@81D>7D=693,93,82+=70>921.&-+#)'75-42*-+#,*"75-890,.%/2)-0'.0'&) !$ #$ "#"#&'"%&!!"/1+35--0':<3') ')!;>5!$"!%(25,69025,/2)25,-0'*-#+/%-0'-1'-0'03*@C9;?47;/37+26*7;/6:.?C78<0,4'&0#$-!.7+.7*6@30:-1;.@J=KUH9B59B6:D77A45?25?22;.1:-4=0@I16?3>G:?F:GK?FI=CF:DGFG?MKCNJCJD=H@9NGANIBD>7LD=KA:K?9RD>SD>OA;RFEO>@T:@^;Dc:E\5?E$-5#$    " '$*(!/,%3.'5.'<3-@5.D82E82<4-;4-91*C<5?70C<5A92D<5?6/B:3A92@81@81IA:G?8?70<6/=70=70=70<6/71*82+94-1.&/-%0.&97/:80-+#/-%0/&.-$./&//'00(..%++"**!%%!!""**#))"++$/.(+*#((!23+<=411(--$,,#))!"" !#%"% #%((+"+.%47.*-$-2%6;,28)05&06&.3$38(2?C748,,1%(.#,3(+1&8?49?517,39.6<18>4AGGE;CA9CA;B?:EB=KFAPJFE?:IB>D>:IF@IE?F@:H@:F;6G;6J=8H;7E:7H=4-D82A6/80):4-93,:4-;5.;5.92+IC<>81B<5?92=70>81E?8G@9?92NHA<6/F@9OIB?9260);5.=70.+#/-%,*"53+53+0.&42*:801/'42*:8075-20(,*"*)!)''%$"/-%0.&,*"/-%,*"-+$42*97/64,.,$-+#+)!)')''(.0'*.$%(*-$CF=7:1.1(.3%6<*17$6<)6<)4:'28%39'9>.15(<@49=1EI=6:.04(+/#+.$)-#47..1(9<304*/2(03*+/%36-@C:15+69047.@C:8;216--6,09/3<2IRHCLB7@6;D:<@7GC;FA9HB;LF?LF?OIBMH@F@9F?;F?8193,<6/@:3A;4LF?@:3D=6@:3<6/;5.93,:4-60)F@9B<5=705/(<6/GB;30(.,$+)!.,$-+#/-%/-%42*=;331)20(/-%-+#+)!)'(&'%-+#.,$'%'%*( ,*"-+#/-%:8086.1/'42*42*-+#+)!,-$,/&14+.1(14+,/&58/,/&). ;A06<+39'@F3@F47=+06$27'+/">B6;?337+/3',0$*."%)),#36-.1(-0',/&47..1(-0'25,/2)8;2;>536-690;>527..5+/7-.6,6>4;D:19/2:0>A8GB;GA:TNGSMFLF?PJCNHAF@:C<9KDAYSPVQO@=<=;:BAAFEDKJJQPOWVUYVU[VUdZXTECM99N79S991*60):4-GA:GA::4-71*<6/?91A;4=70B<5?92:4-93,82+71*93,LF?LF?D>7;5.60)2-&/,$31)0.&/-%/-%64,/-%1/'1/'/-%1/'0.&0.&-+#,*"*( +)!1/',*"$"'%(&.,$0.&,*"86.75-64,86.><4=;31/'-.%.1(9<336-&) 14+.1((+"*."6;+39)38)BH75:*/4%-3#.3%/3'04(15).2&(, *."/3'),"-0'.1(*-$,/&&) BE<:=4/2)/2)47.8;2=@747.7:158/6:16;2-3*8=47=3=B95;217.=>6PKD]WPsmfOIBKE>SMF[UNQKEPJGZVT865EDDzzzĬunoiYZU8;];?e@GmFPd:F`6D[4BK*5="*/!!   #! #!&$)#/(!2(!;/);0)5.'71*60)71*<6/=70=70>81>80=70JD=93,93,93,93,71*:4->81;5.D>7<6/93,82+1,$0-%20(-+#,*"-+#1/'0.&0.&75-:80/-%64,86-,*"/-%*( .,$,*"*( %#-+#+)!/-%0.&.,$0.&53+;9164,75-64,1/'01(690-0'/2(-0'14+/2)$'*.#(, ).!/3&6:-/3&*.!+0"+/"26*HL@9=1+/#%)'+7;/7;0+.%(+"'*!),#14++.%25,36-37-/2)36-.1(03*-0'/2)47.25,6907:1ILCFI@ICKE>HB;XRMVRP<;:nnn@@@---(((---;;;XXXϠZGIX49^6=c:Ec:F]5AS.;D$/8')      '%-' 3+$4*#7+%:/(2+$0*#3-&2,%71*<6/<6/@:3@:3<6/93,93,82+:4-60)60):4-93,5/(82+71*4.'1+$1,%.+#-+#.,$/-%0.&1/'-+#0.&31)42*-+#42*31)/-%*( 1/'1/'.,$-+#0.&-+#0.&<:297/-+#.,$31)B@875-20(42*20(+,#'*!(+"'*!*-$03*%(#&!%"&#!%(,!(,!*.#+/$,0%,0$@D7/3''+(, #''++.$(+"&) '*!*-$/2)58/47.CF=<4C=6E?8F@9E?8B<5F@9LF?_[WEDCddd$##.../../..322433212MMMN8;]7>b:Da:FU1>N.9@%/3#%   )( +)!3-'7/(6,&7+%6+$5-&2,%2,%60);5.@:3;5.82+A;4C=693,60)60)71*?92?92;5.71*5/(71*<6/5/(+%-(!/-%/-%/-%.,$.,$75-64,86.1/'1/'/-%1/'53+20(0.&0.&0.&-+#20(EC;42*=;3DB;:8153+><4,*"+)!53+64,53+20(,-$#&%('*!14+'*!!   $',/%+.$03(:>28<0-1%04(*."*."&*,/$&* &) ),#+.%03*8;203*;>58;29<37:158/58/.1(25,?@7GE=A>6@>6<91>;3>;3<:2A>6C=6A;4C=6B<5>81@:3PKFCA?WWW...0//#"!# *$$2$(3"(4$*:+0H=A\WYd^_K05\9Ca@JM/;E+68!*/!#   ! ,+#64,83,6.'7-&8-'6+%81*4.'3-&93,82+;5.@:3=70=70PJCKE>A;492+71*C=6@9271*71*82+2,%5/(0*#,&0+$41)42*31)20(1/'GE=64,31)20(20(30(0.&;9142*42*97/@>6<:20.&53+42*42*/-%+)!/-%0.&.,$-+#31)75-53+10(*+"03**-$""!$ #$&')!"$!!#%( $&%))-!'+7;0:>259-/3'.2&9=2&) &))-#+.%03*58/790]_VCE7=7060):4-93,82+C=6@:3@81@81B:3I@9@81;3,?6/=4-93,:5.:6.62*73+51)50)1-%0-%1-&=8162+62*51)1.&40(,( 1,%2.'1-%1-&52*<80@<552*64,2/'75-:7/42*1/'/,$*( 66-//&//&44,<<377.32*23*,-$%&() %%''%&11(,,$00(==6,+$%%''**",,$#%#'',!-1(&+ "'!&%*&,!%+%++0$/2&EG;BB7BB7QPGBA;;94<:454.971:8275096082,5/*81,5/*81,6/*>72>8251+84.73-3/*72->:4NKIxwwSSS333#3'(I9:C01F.1T08Y3<[6>Y5>Z8@Z9AO4;{sulllA;B<54.'3-&=7093,60)<6/E?8:4,D>7A;4;2+A70H>7E;4E;4E;4H>7D;4;5-<7/72*HC91@;493,60)93,@:382+D>771*60)3-&2-%4.'E?893,50);6.60)71*61)D@8=8171*0,$50)72*2/'10(21(-,#21(76.=<432)/.&1/'/-%/.%1/'10',+#20(.,$B@8-+#20(/-%'%(&0/&$%!%!&!&"'',#"'$)!(#,,4$37(79*88*DB4>:-@;2?95>85;51;5282/82.930:2/A63:0-8-+:/-8-+;0-8-+C;7<831-(51,2.)62-C@;CA?CCC0//2&(B.1O59L-2T17Z18]5<\681>8182,;5.82+5/(71*82+5/(<6/82+>815/(71*92+<3,?5.H>7A70UKDC91H>7MC<@81QJCIB;>6/<4-:3,80)91*@:3?92A;4;5.60)4.'1+$=704.'3-&60(@:2?9260)?9293,IB;92+@92:2+81*81*70)7/(40(:80GE=.,$52*-+#/-%64,75-31)97/<:242*31)20(/-%31)-+#1/'0.&=;3*( $"(& !"""!"%#&*-$+0%,3%59,:6380-=30D75E86F97:>;:MMM-**,!;&)H,1U5:V39V06Y39X39V39T49Q38T9=K26hW[ifg|||,++.$D+3C*1A*13%*   $")$60*>8160)5/(71*82+5/(2,%<6/;5.60)71*5/(4.'60)8/(<2+>4-B80A70?5.QF?SJBC:3H?8I?8E<5>4-<3,:0)<4-IC;?92=7071*3-&;5.3-&1+$1+$0*#0*#:4-B<582+4.';5.:2+A81D;4=4-=4-@70:1*6-&60)30(52*2.'62+3/(62*72+41);91B@8;9142*20(75-/-%?=50.&.,$/-%-+#1/'0.&1/'('"#"#"#"#(( &',,#/0&79.RTHttiOMBXSIA:0@8.@6/<2/@52K@>G<:A64D97;0.;/->0.C53L><>0.<-+@1/=.,L>=I<<=705/(60)5/(.(!3-&0*#2,%1+$/)"2,%93,93,@92<3,C81MB;D93L@:B71;0*>3,;2+70)<5.KD=4-&5-&:2+81*0+$86.;9131)75-42*97/.,$75-.,$75-.,$20(?=5RPH@>6-+#*',*"$!'$41).,$-+#+)!21([ZQSNFF>7=3,?3,?2-:-+=0.20=0.@20<,*B10B1/@/.C21M<:@/.K99H58\ILB/2=+.A/2C25WNPOIJK26Q/4d?EZ39_7=X39K/4K15P6:Q6;H.2S8@6/A70OD>F;5E82E82F93QD>I<6E71?2,?6/=7082+71*:4-2,%4.'/)"3-&/)";5.60)82+3-&HB;:3,<2+=/)@2,H;5F93B5.B4.F:4J?9>5.=4-?6/;1*7.'@6/A812-%20(,*"31)31)<:2<:1/-%+)!1/'HF>20(86.CA9ec[QNF30(*%-( /*"3/'.)"40()%1-&1-'=94KE@C:6C84?1.@0-=-+<-+;-+;-+>0.I;9E758*(E64E21>*)<)(H54G43K76I54B-/D,2M54-8.':0)D:3QG@E;4E:4E71F82G82G82O?9TE?M>8L>8D;4;4-JD=93,>81GA:71*60):4-4.'60)93,LF?>8171*81*>2,H92@0*G71F71I:4F60D5/J=7F;4E93A6/J?9:/)<1+<1+92+/-%75--+#/-%/-%/-%/-%(&'%,*"'%;91<:2=;3<:262*81*5.'4-&2+$4-&7/(3,%1+%930IB?;2/>20<.,=,*=*)?-,@/-:)'>.,>-,<,*=,+<+*A.-F10C/.?*)B-,A,+A-,B-,G02I,5]?IM/9L/9H*4I,6T7081*<6/;5.>5.=3,>4-MBMB8171*;5.C=682+F@9A;41+$?92B;5<5/GA:D>792+B5/F4.H71J83M<6Q@:R@;J83K<6F:4A5/=1+I=7?3-9-'?3-81*)'31)20(.,$1/'A>6.,$-+#*( &$*( (&)'*( .,$/+$C<5@817/(E<5B:391*?70G?;4,*:0/;//H::F66?,-=)*>++;)(A/.<)(A.->+*=*)?,+@+*R<;ZCBF//D--C--M66U>>E,/K+5I(2P/:O.9L*5N-8K,6n^b✚phieXZk[^eVXcXZbY[]STYOQHABEBBsss312*Q*4]2=W-7R+5I&/<'1!!   '$51*4.(1+%60*60):4-71*/)"2,%6/(:2+;2+=5.;3,>6/B92?6/?3-B5/;O?;UF@E82C71I>8C92F>77/(91+:1-I?;C:6:0,C95RHDG=8R?;P94M72P;6S@;TA6<8030(3/'84,,( 74,+)!,*")')'(&&$31)2-&B92@70;2+@70QHAF=6E;5A848/-6,*9.-=0/9-,:,+;,,G77E45F56B/0E13?*,@*,=&(?()I23J34A*+B+,A*,W?AR;=F-0I*1I)0J*1L,3K,2J+2K,3E+0sjk͙pmnURSIGGHFFROPlkkLLL100$G".h5Eg5Dd4CV*7N'4B)1   !)$=824/(71*=705/(3-&1+$2,%60);2+;1*@6/>5.@6/;1*I?8B70B4.C3-D4.N>8M=7G71G71G72F53K98J87H65J87L:9H65H65L84O;6K83Q?:H93@3-;1*5-&7,(:.,B64<0.F:8<0.A42NA?T?=dIF\B>S<8R=8L94M<6I:4A4.;1*=3,E;4@6/6,%2(!;1*3+$60)50).(!71*>81.(!2-&30(-+#<:2)'+)!)')'86.A<4;2+;1*A70A70@6/H>7H>7;1,F;97,*5+(9/,8-+I><4)'?22G9;I:20?31?31B64;/-?31G:8M97^D@V=9O94R>9N=7PA;I<6>4-<2+;1*:0)5+$8.'6,%90(1)":4-0*#4.'0*#-' <6/2,%96./-%,*"*( *( (&+)!(&93,>4-=3,9/(9/(9/(9/(B81:/*I<:7+)8,*F:8;.,6)'>1/A43?02=,/>+.A+/C*.G-1H+0H-1C),F,/F,0F,/O48Q7:P69G+/O15V7;G(,E&+L-2Q26M.2I,0F+/?+.F<=>;<%%%&&&))))))&&&  ,,,401(K$1r4Ix6Lw6Lp2Gn4Gg4FR&4E*2   ")%*%/)"83,60).(!/)"82+1+$4.'=4-@6/=3,E;4PF?@6/E;4C81@2,H82G71D4.I93G71G71H82O>;M;:E32H65G54L:9M;:K98J52H3/F3.C2,@1+C60<1*8/(:/,?31E97A53?31@42>20B53J74S<7N83H4/I72D5/C60@5.=2,;1*8.'6,%6,%>4-7-&7.'4,%5/(.(!2,%0*#/)"2,%0+#2/'52*53+.,$75-1/'/-%0.&/*";1*A70>4-:0)5+$=3,I?87,'D64:+)<-+UFDK=:@1/>0.>//A/1?,/@+/A)-I.3M/4K,1P16O06K*2L+3M,4N.5N.6W7?Q08T3:Q/7N,3Q/6O-4R08K)1G'.G,2D+1<%*6$):03=782/0+)*)((,*+3019463+-*;&[,:z8M=T~6My2It1Fs5Ij3ES%4C*0   72-72,3-'5/(5/(0*#60);5.2,%3,%:1*F<5;1*LB;D:3>4-;1*B81A3-D4.I93E5/F60F60H82O?9R@>VCBM:9I65B0/G54K98R@>J52L83I50H72D60I=7?5.?6/:/+@42@42?31?31>20@42C75A1-J61K72E4.@1+E93<3,>5.<2+:0);1*8.'7-&6,%5+$;1*2*#2,%3-&0*#2,%60)HB;3-&:8075-><464,EC;:80,*"/-$2-&7-&;1*9/(5+$=3,C925*#Q+6Q,7R,7T.9T/:R-8R,7O*4N(3]8CY3>M)4L-7H*4F'1D&0>#,H087#*1#5$4#8&?*Q)6_0?k4Gv6K7N=V6N|3Jx2Ho.Cs:LX)8>'-   "$ 50*1,%2-&60)>8182+2,%1+$4.'0*#5,%A70=3,SIAG=6B81B81MB;G93E5/K;5G71H82G71K;5G61O>;Q?>F43E32G54J87L:9UCAO:7O;6Q=8O>8?0*G:4K@9=4-<1-=1/<0.=1/=1/D86J><=1.A1-H50H71A3-?3-LB;80)5.';2+?5.:0)4*#4*#7-&8.'D:380)71*60)0*#2,%60)5/(2-&30(/-%42*=;320(31)1/'1/'61)8.'@6/<2+=3,6,%9.'4*#?2-A/.A.-J76L98L87S@?R?>E11C,0H/3U:>J,1L,1N,2R/5Z3<^2@`4CZ.=Z.<]0?^2@g;I\1?Z1>W.;Y/=V-:U+9T+8Q'5R*8O(6S-:N(5K%2L&3T.;T.;S)8]':f.Bc,?l3Fl1Fo2Gu8M}3,B4.C4.H82G71K;5K;5D4.I93G53TBASA@H65XFEK98VDCM;9L74\GBM:5F5/H:4A5/E:4C:4:0,:.,9-+;/-<0.<0.@42K?2,A81G@94.'/+#70)6,%7-&H>78.'3)"4*#6,%5-&82+3-&3-&71*60)71*61*41);9131)1/'31)20(20(0.&2,%6-&=3,7-&8.'7-&:0)<2+E62C0.I54UA@S?>C/.A-,L87H23B)-F,0U8=S38Q/5Y5;Y39X.8Y)9_.?`0A_.@]->d4Ed3Ed5F]0@Y,=[.?]0A]1AX,Z*:Z*:b1B\+Vx9Pu5Mu5Mv7N=TG]y8Ow8Nt8Le/A_/?K%23"#    %!)$.)#94-;5.0*#93,HB;@:3:4-5.'4+$A60D:3:0)C92@5/>4-B70D50A1,F60G71I93D4.G71M=7N<9H65K98O=;L83H50A0*?1+F;4>4-<3,7,(8,)7+(8,*:.+;/->20F:8@2.A3->2,<1+7.'4-&2-&85-:4,3)":0)<2+:0)A70E;48.';3,=7060):4-<6/;5.A;4>81:7/0-%.,$97/0.&1/'/-%/-%4.':1*A709/(8.'7,&7-&B81M=:C.-E/.I21F0/H21E//E//E-/O59\@EN05I)-Q/4[63,9.(=2,8.'7.'1*#6/(4+$?5.A70@6/B819/(A70@6/D:3>5.7.'7/(70)>6/KC1-=/+;.*A30SEBE53D0/E10C/.G21L76>)(K76I22K24I/1H-0G+.K.1N/2P04U19[1?^3Ba5D`2Ba2Bf6Fb1Ae2Ch5Fe1Dd/Cf2Fg1Ge/EkBT1!'A7;H>BG=BG=AH=AH>BI?CJ?CJ?CI>BJ>CQCH\KQkQZ~Xf}GZq3Ft3Go3F}EXc1BR(6G$05$%    '".("8/(>4-=3,H>7>5.;2+;2+<1+?1+K;5F60E5/F60G71G71G71E31F43O=92+60)5/(4.'.(!0*#2)":0)8.'8.'I?8KA:B81ND=;1*9/(:/(9/(;1*:0)7-&<2+:0);1*=3,E;4?5.:0)8.'<2+<2+:1)C92<2+6,%B92[QJpf_QJCB=650)/+$3/'95-:5.72+:0+?-,G54J87>,+C20@.-E32;)(>,+A.-@.-=+*?-,=+*H65D0/C-,D--D.-D.-E..G00J33N37\;EeBN`;GU.:]3@a5B_2?i8Ft>Oo8Jk2Gs7Oq2Lp0LtEZv{qITn3Dm2Cg1BZ,;L'3= *-      )$.("B93LB;=3,<2+<2+=3,=3,>2,H:4QB4-9/(6,%MC4-9/(:0)9/(@6/ND=?5.=3,H>7QG@UKDKB;ZSL6/(4,%6/(70)6/(5-&8-(<+*@.-B0/?-,E32C10F43H659'&A/.?-,?-,?-,@.-<*)@.-@,+D/.J54G32E0/F10G22J25T5>P.9V2=T.:W0;Z0<[0<[.;_.=h4Di1Dr4Jx4Nz2OzAX'%% AAAἶbENa0?[,;R*7E$/6&)   "# )% ,'!8/(;1+<2+<2+=3,>4->4-?4.C5/?/)?/)E5/F60G71G71G71G64I76J87C10A/.F43F43F53SD@RE?K>8?3-D82?2,=0*=1+91*3-&1+$.(!.(!-' *$0*#;2+2(!4*#<2+;1*=3,?5.ND=9/(:0);1*I?8J@9?5.;1*7-&7-&<2+B81<2+=3,F<5@6/<2+<2+>4-B81?5.I?8YOHXNGKA::0)E<5?6/90):1*;2+8.'8/(=0,@/.@.-@.-G54E32@.-A/.=+*H65UCBC10=+*B0/M;:I76@.-?,+J76ZGFS@?E21D21D10F/2Y=DU7>S2;U3;Z6>^7@a9B\216>26=26:04:04<26;15;14>48D;?E=@NJKqlmB&/V.4-?5.@6/A6/B3-A1+B2,C3-O?9TD>G71C3.E32F43E32N<;N<;A/.C10C21G;6A6/B70;0)>3-8-'8.'?4-6.')#;5.?92.(!-' )#4.';2+7-&5+$=3,5+$:0)B81?5.F<5<2+9/(;0)?5.8.'=3,5+$7-&=3,KA::0)<2+?5.>4-H>6B81>4-C92ND=j`YkaZWMFE;4<2+;0)@5/;0)=2,A5/@6/;0)=/+;)(B0/<*)B0/A/.B0/>,+>,+@.-?-,SA@B0/B0/K98O==SA@M;:UCBK98J87E43E94;2+6-&91*I@9=5.8/(\SL1*#71+B<52,%5/(("-' E?87.'7-&8.'H>7B81G=6PF?9/(>4-9/(:0);1*8.&6,%>4-:0)I?8F<5<2+>4-;1*<2+VLEG=6A70@6/E;4^TM[QJcYRI?8@6/E:3=0*A4.H;5D71C60?2,>0*?/,A/.>,+>,+B0/=+*<*)?-,C10@.-<*)?-,>,+>,+B0/B0/F54A20B42;-+@20=/-?1/=/->.-C//I34Q89S8:X:Ot2Fz0H9Q|3Jy3Ip.Ci,Aa+>_-@W);X*<`)>h/Dk2Gl3Hi0De.B],>zfmnnn824>",M)6D$/7&*!   "3.)*%2*#7-':0)<2+@6/@6/=3,<1*=/)?/)>.(L<6H82C3-B2,D4.I75Q?>R@?E32E32F43F43K:8A7281*<5.4-&91*0)$2*#6/(-'!71+/)"%+%@:35/(71*6-&<1*>4,B81D:3?5.D:3=3,:0)8.';1*<2+8.'D:3ND=;1*<2+<2+;1*;1*@6/D:3VLEKA:@6/<2+4*#F<5A70B81<2+?4-K?8M>8G71L=7G82G82H:4F71@/,K98K98B0/M;:I76A/.?-,>,+Q?>C10C10B0/<*)C10J87J;9:-+7*(?31>20;/-;.,E86H97@.,C0.G20L43P55V89U56T67R68Q37W5<]5?_1>g4Cj2Ej2Ej4Fn9Kg3Eb1B_1B\0@]2BZ-?b-Ac,@e/Cd.Bf0Df0Eg2F^jono.+,; )T*7J%1='/#   )$2-'5,&>4.C92@6/<2+<2+=3,>3,B3-C3-C3-E5/L;5A1+B2,B2,SA?]KJF43TCAE42F53B10E53PFB;6/40)/+#-)"+' +'73+*%'!%4.'0*#D>7F@993,:2+E;4LB;=3,C92?5.@6/J@9=3+9/(:0);1*6,%7-&=3,:0)<2+9/(:0)B81LB;E;4E;4C92=4-5+$A70<2+7-&6,%7-&9/(A4-M<6E4/G60F50N=7SA,+O=,+8)'5+)7-*A747,*3(&6+);0.9+)A1.C1.E0.H1/Q75W;:M0/Q54X=>P57V9>W7>Q/9X3?X2@W0?Y3A\6CY2@X1?W/=Y1>U,:]2Ap>Pc0Cd/Cd/Cf2Fe1Ed0DzUbsmoaaa.,,8%Z+9R&3D*3#  !.(#-& /(!70):3,:1*91*E>7@92;2+WHCO>8B0+E3.@/)G60I82F60@1->0,?1-F84C62?1-?2.;/+=710-&0-%)'*'&$CA9;80'"%("0*#0*#+%2,%93,:2+I?8LB;@6/C92J@9?5.C92<2+:0)9/(:0)9/(9/(A70;1*:.(@3-=0*E82C60J=7ZMGG;4I>8;3,1)"@70ME>91*A912*#@5/D609*$L<7P?:L:5N:5I50H51N<9I85O>:A0-E41?.+=,)C40WIEB40;-)=/+9,(9+'7)%3'#:0,6-(9/+5,'4+&7.);1-9.+<.,>/,A0.P=_:E^8Cc=Hh>Kj;La0Bh6Go;Nq9G50B0+@.)B2,?2,=3,=3,8.':0)>4-G=6<3,0+$,*".,$.,$(&$"$"&$"'!+%=70:4-2,%<6/OIB:1*H>7@6/<2+>4-E;4<2+:0):0)=3,?5.9/(6,%:0)>4-7-&A4.>.(C4.G71L<6F60J:4I93H=7;4-5/(6/(>8193,B;4;5.<4-;1*?3-@3-M>8F4/E2-J50J72C2,RA7]SL>4-<2+7-&8.'=3,OE>ND?9/,<0.A21I97E32I54E/.F./B)-I04U<@V<@K26S:>N59O38T1:Y5?U0:R-7U0:Q,6_:Dc/)A2,A2,B3-B3-A2,>/)>3,<2+J@9=3,9/(<2+=3,4*#.*".,$'%&$+)!(&  '"("'!2,%=701+$60)5/(4,%@6/A70;1*9/(I?8>4-=3,:0)8.';1*=3,;1*>4-B81;0)<.(H93N>8eUOH82F60P@:UE??4-5/(F@94.'2,%2,%:4-4.'A:3B81G<6B4.QB.(E5/SF@B818.'7-&1' 8.'2(!E;4>4-=3,5*#5+$E;5;1*1' F<5E;57-*:-+;-+>.,?-,?+*?)(F-.L26M37I.2O59L26K15I.2Q38U1:R-7U0:R-7W292:4-71*5/(<6/?81K?9=0*?2,=/)OB74.'71*7.'5+$=3,:0);1*>4->4-8.';1*;1*I?8E;49/(<2+@6/9/(PB7/)"71*4.'SMF>81>70?6/D92?2,H93@.(L94J50F3.G71<,&J:4G71C3-@0*@0*B4.:0):0)3)"5*#C92<2+?5.=3+2(!>4-9.'5*#8.(5+$8.'<2-D:7=0.:-+:*(?,+A-,C-,E,-H,1J.3H,0R5:Z=AN16N26X9?T09S.8d?I`;E`;ET/9V1;W0;d7Ge6Fh7Gj7Gr?O[hoZ`tpq-'(<'d0@g2Bi9GP(48#&   "4-(5.(5/)E?9=70<6/94-?9260)1*#8.'<1+8-';0*D93<1+D93C81F<5=3,;1*9/(:0)8.'3)"0' *%$"'%#!" $"#!%#($5/(5/(4.'3-&/)"0*#5.'80)9/(:0):0)E;4G=68.':0)=3,:0)=3,?5.<2+;1*=3,8.'H;5K;5F5/E5/F60H82N>8D4.6+$1+$.(!1+$B<55/(93+5/(=6/A819.'A4.C5/E3.YE@O:5E1,@0*B2,@0*C3-N>8F60B2,=0*:/)D:3@6/6,%5+$G=6A70;1*;1*2(!8.':0)9/(2(!9/(8.)J@=;.,9,*8(&B0/J65G10L13N/4U6;O/5Q17O/4O/4S5:kOTsU]mNWuV_{\epRZkLUoPYvU_wR^|UcYf[glPZ:,1JFGtnp5"(\/=i4Ec1@V)7J%08%%   %5-(+#.'!2-&2-&5/(=7071*;5.1+$6.'G>77.'6,%6-&8.':1*:1*>4-J@9J@9:0)6,%9/(3)",$%!/-%,*"#!53*'%$";81@<42,%93,?92:4-C=6=702,%4,%6,%:0);1*>4-;1*=3,<2+D:3>4-<2+>4-8.'=3,6,%;1*A3-E5/C3-@0*B2,K;5hXRM=7=2+3-&.(!0*#71*82+82+5/(71*>4-;0)A4.B3-E4/H50I4/G4.C2,E5/E5/P@:\LFI93A1+B4.;1*E:3=3,J@99/(<2+8.&<2+8.'8.'9/(I?8J@9?5.3)"8/)?528,*=0.;,*>,+K76O:9S79O-2V38T17S17S17T17[AF.#%>68A:C;=G?BD;>E;?E7?5.7-&4*#=3,9/(-$'# #!'%$"#!86.>910*#1+$3-&.(!60)71*D=6:1*8.';1*@6/=3,<2+E;4I?8>4-:0)=3,>4-;1*=3,?5.?5.@3-C3-A1+>.(C3-?/)YIC>.(:/(/)"3-&1+$5/(82+82+5/(5.'5,%9.(E82D5/B0+F2-J50H4/B2,C3-F60O?9D4.TD>G71=0):0)>4-<2+A70A70;1*9/(:0)<2+8.'=2+KA:=3,KA:8.'8.(8.+>20F86G75C0/G21D..I-/T06V17V17U17W28W39`FJDABB/5_3Aa4CR,9D$/7&(   -'#*$/)#0*$3-'0*$2-&3-&1+$2,%5/(4/'<70/*"84,83,94,73+71*@81LB;A708.'6,%8.'2(!,#)%$" !$"" '%$"*%1+$3-&0*#:4-C=6<6/93,<3,>4-B81I?8A70?5.=3,=3,;1*>4->4->4->4-<2+KA:B81B5/E60C4.A1+I93K;5RB<=.'3)"5/(@:32,%60)5/(82+71*>6/:1*9.(:-'<.(?/)D1,H4/F3->.(@0*A1+F71;+%B2,A2,9,&7-&6,%?5.<2+<2+:0)>4-:0)=3,>4-=3,8.'9/(<2+;1*8.)9/,:-+<.,?/-B/.E10F0/R68Y4:U/5Y39Z4:\5Q,8C$/8 ()#    $ +'!-("1,%>821+$C=6;6/2,%93,72+;6/40(1-%;7/;7/B=5=80:3,70)7/(6.'>5.E=680)-$4/'$ *'($'#$!&#$ 3-&<6/4.'3-&:3,2,%0*#/)"H?8C92B81;1*A70B81@6/<2+<2+>4-A70E;4A70B81B81D:3=0*A3-=/)D71E93D93<2+5,%,&-)!-)"*&:6.A=6?<484,93,4,%=4-5+%>2,B70?1+?1+;.(8-'<1+9.(6*$9-'4)"4)"7-'3+$7.'6.'91*5-&91*7.'90)>3,:/):/(<1+7-&<1+;0)7-'90+9/*:,)>,+F00J13F*-Z8=fb7@[19\1:[1:U.6J06:136026015/16026/1501712:356/2702702802813813812701.'(*Q,5X274-&60(70)-' *$%,&*$'!?:3.(!("3-&C=63-&-' /)"1+$1+$:4-;5.<3,F<5C92>4-I?8A70?5.A70A70@6/<1*LB;G=6J@9?5.@6/B70G;5?3-<3,;4-62+20(('.-%*'+)!,*";91:80:811/'62+5/(=6/KE>>81=704-&81*71*2+$4.'2,%3-&/(!/)"3,%=70>812+$4.':4-4.'5/(2,%4,%H=7J>89-'OC=F:48,&<0*8/'4-%6-&>1,C0.T<e6A`0m=IrBNf7C_04-<2+<2+9/(E;4B81>4-9/(D:3E;46,%<2+I?8LA:?4-C71@5.7.'5.'1-%42*,+#>>5)'*( +)!75-20(GE=/-&0,$2,%3-&LF?XRK;5.4.'<6/5/(4.'5/(,&.(!,&*$+$<5.93,)#/)".(!82+;5.2,%6.'B81;0*7,%:/)8.'7,&:/(8/'71(6.%E83K85K23R38X5<]4>`2>`1=d4@j:Fl=Ic3?_0<_2=\1JkV38O/5J-1@'+>*-.%   ,'!/*#50)71*3-&93,@:3JD==7093,<6/<6/5/(3-&82+60)4.'<6/2,%/)"-' )#/)"*$("5/('!("*$1+$3-&+%+%,&.(!;5.:4-60)A;4B<5=5.=3,>4-@6/>4-=3,@6/=3,ND=?5.<2+<2+9/(8.'@6/F<59.'G:4;0)?6/1+$-*",*"--$:90'%(&)'.,$0.&CA90.&-)!5/(2,%60)OIB:4-60)1+$1+$/)"/)"*$/)"0*#*$%(",&,&)#+%/)"/)"("+$4+$5,%2)"2(!3*#6-&6,%<4-5/&80(<.)C0.I01Y:?qOVnFO`4?`3>f9Di=Hc6Bb5A_2>^3>Z0;[1<[1<[1<\2=^4?_5@]2=b6Ak>Ii81;5.93,E?882+;2+;1*8.'=3,A70C92B81?5.B81;1*:0)9/(8.'<2+:0)<2+A6/NBa6A`6A^4?_5@d;Ff@JrMW]gYcqHRc9Dd:Ee;Fg4-8.'D:3<2+H>7QG@=3,<2+;1*LA:?3-8-'90)71))&.,$66-,+#,*"&$)''%/-%+)!/-%+'+%.(!0*#/)"4.'71*1+$.(!+%-' 1+$:4-("'!("("'!'!& +%'!.(!*$0*#'#)%&")%)%*'+' )$1,#D;3B50G41L34O05W5]5@]5@rNWjQWM=AA58I=AfVZsY``;Eg?JjBMb:Ea9Ca:Db>GU@FA69wkmR9>^>C`BGN48H36=*-4$')     !$ +& -'!82+82,4.(93,:4-D>7F@9@:393,82+93,;5.<6/93,;5.D>7:4-/)".(!/)"?925/(4.'-' +%+%+%-' .(!/)".(!.(!5/(82+;5.?923-&;2+8.'>4-=3,>4-;1*A70=3,=3,:0)B81I?8A70>4-@6/;1*I>8<0*8,&:0)1*#*'+)!)) &&(&*( '%+)!/-%-+#/-%,( +%0*#4.'3-&0*#-' 1+$-' /)"*$5/(0*#'!'!/)"/)"("*$,&%0*#0*#%)%0.&&$$"20(0.&" #!/,#60'?6.A4/J74H/0O05U3:U1:U1;[6@W3=V2<\7AW2813.&71*2,%1+$:4-2,%*$+%,&.(!/)"/)"0*#60)3-&71*82+5/(70)E<5H>7F<5<2+?5.@6/MC<@6/B81<2+9/(@6/;1*;1*;1*8.'D92;/)1' 4+$-' *&%#$$&%*( )'+)!(&-+#)'-+#0,$-' -' 3-&<6/4.',&;5.60)0*#.(!-'!93,("%%& .(!82+>81& 5/(.(!$!&% (()( "!"!)'1,#?6.@2-G41I01M/4V4:Y4=P-7T0:W3=X5?U2`FM}~YWX9+-I15R<@@.15&(/"$)     #"31+/+%1.'C>7;70@<552*63+73,40)62+0,$62*62*85-62+50)84,30(2.&/+#4/'40(-(!/*"-' ,&+%,&0*#60)5/(71*4.'3-&4.'C=582+5/(60)81*?70C:380)=4-=4->5.A92F>7>5.80):1*80);3,90)4+$2*#0)"/( 0*#+'/-%*( ('&&=;3/-%+)!,*")'&$)'-)!0*#:4-60)3-&+%,&-' 0*#KE>60)-'!-' *$)#)#)#-("1,'1-'$&"'#(#&#  " !)%.)"5,$J?7I;6F31K34T7;V5[6@Y4>X3=S.8X3=lOWSJL,++544=::WSTfbcB,1V4Y6>X6=[8160)<6/;5.4.'71*93,81*:4-60);5.:4-:4-;5.:4-:4-6/(3-&82+2+$2,%<700,%-*".+#1.&.+#0.&'%,*"20(86.<:2*( +)!+)!$")')%0*#71*,&1+$-' ,&+%0*#@:33-'=700*#)"-' *$*& )%!/,()&"&#%" $ !  # $$ "&!("3*'8.);/'D6/I94G41N88K15N17T2:\5@_7BY16><3:8042*A?7=;342*42*75-31)63+2,%2,%4.'71*0*#3-&.(!4.'60)=7071*1+$60)2,%60):4-;5.82+A;460);5.;5.82+60)5/(4.'2,%1+$2,%+%/)"4/(.+#%#42*A?7.,$-+#+)!/-$DB931),*"+)!20(-+#&$)'*'2-&@:3.(!.(!/)"-' *$@:45/(+%-' ,&.(!'!*$*& &#*'#)&"%"$! % ' 1(%4)$F92D6.A0+D1.F00G-2I-3N,4Q+5U/9\5@X1;V/:eAKZGLJJJ5231 #V6;_;@eHMwyԉ@:;D+/U5:W7<472*2,%3-&>81:4-71*2,%60)71*4.'4.'5/(5/(60)82+71*5/(;5.>8193,93,:4-71*4.'4.'1+$3-&3-&/)"1+$/)".)"-*".,$/-%20(+)!.,$,*"+)!64,-+#*()'-+#,*"'%-+#.*"B<5+%:4,+%0*#-' )#/)"5/(/)"=70D>7.(!,&/)"40**'#+($/,($! !$+$!;2/B72C6/H:3?.)@,)A++C*.G*1N-5S.8U0:X3=U1;T/:]+.Z/(?.)A.+@*+D+/I,2L,4O.7Q/9O.8P/9R0:bCLJ=A<<<5-.K15Y8=[;@Z:@q]aZXY:-/P6:[@DV;@S9=q^a_\\yxx.,-* E04M:=7&):*-*   &%1/(.,%31)1/(64,64,20(IG?;911/'0.&97/:80/-%75-53+86.75-<:2;91;9142)><4><450)71*82+4.':4-93,2,%0*#.(!,&5/(GA:D>7<6/2,%4.'93,60)5/(60)60)4.'71*5/(3-&82+3-&4.'.(!3-&5/(1,$1.&1.&,*"+)!.,$=;30.&.,$*( *( '%(&)''%)',*",(!.(!.(!-' ,&("5/(.' *$("("/)"+%5/(60)*$($'# #   !!/,(-'$4,)90,>3.A4-C6.A1+E2/J45Q8bLPojkzyzC;7?923-&60)1+$60)71*60)60)3-&4.'5/(5/(5/(2,%2,%2,%3-&1+$2-%41)75-,*"53+64,20(-+#-+#)'.,$,*"+)!+)!(&*( -+#/+#3-&0*#.(!,&)#.(!+%3-&& ("4.'+%4.'5/(("#(%!&#)&"%%!!!.*&1+(81.90-=2-B5.L>7B0+B.,C--O5:L/5G(0I,5M09H,5K/8O378G15U;?S9=W=AgQTnghOKK;*,F/3T>AU@C`UW===433*A,0;(+7&)/ #&    &$.-&.,%86.20(*( 20(0.&.-$-+#,*"86.64,1/'-+#A?7:801/'1/'86.64,64,?=5<:264,:5.71*>81C=671*1+$/)"4.'4.'5/(82+:4-?9282+:4-;5.3-&82+:4-71*3-&;5.C=693,3-&60)71*3,%3-&1+$71*94-41):80.,$31)1/'/-%-+#-+#+)!0.&42*,*"*( +)!.,$0.&/+$0*#/)"-' *$*$0*#& 0*")#)$2,%.(!,&*$+&&"&",)%!,+'"%($5510-)72/?74<30:/+0):*$=)'E//F,1Z=DR4;J/7R7@K09I.7K/8P7?bUYA;<@,/Q9814.'82+71*A:3=5.>70@8191*6.';4-<5-72*GD<;8063+30(0-&96.3/(2/',)!.*"*')%+' ,)!0-%+( +'-)!0,$,( '#%!$ ,' *%$ (#)$)$*%&!## %"-*&! !&# '%!:5282/92/?539/-6)'<-*9)&:)'<))O:W=@Q79\KMᖓndeh]^YST[[[/..8&)A,0=*-8'*.!(    $"%&'*!.0'58/+.%*,#),#*-$+.%),#69025,,/&+-$*-$-0'-0'.1(13*:=402)25,03*02)52*HB;82+60)HB;:4-60)71*;1*C82F<5@7081*74,*( .-%-*"0*#4.'>81KE>;5.:4-82+E=6H>7B81ND=A70>4-QG@G>7E>7?92>81<6/50)3-&;6/2,%0+#2,%.)!,&+&/)"*$.)")&+( '%-*"+)!'% !63-+'$$!$ '#&#"!%!1.* (%!"(%!0-)"+%"<202(%9/,>30<1/;/-7+)5&&=+-6#&:');(*?,.?,/@,/C,0I-2H+0I,1J-2S6;T8=U@CXXX200>11Q78V;;W<,/F15A-06$'/!(  &$23,$'24,?B9/2)),#),#),#'*!&) ),#.1(/2)-0'*-$,/&8;2/2)14+7:114+9<369002)@=5HB;2,%2,%93,>814.'6/(;1+F;5G<65,%1+$-)"86-87/,)!3-&82+E?882+=7/82+=70D;4VLEG=6F<5KA:@6/D:3@6/LD=>70F@9D>75/(5/(1+$4.'0*#<6./)"/)")#+%*$82+0-%20(42*(&'%&$" " !'$ *'#(%!%"&#" '$ !,%"?31C75UIGB64E97A53:.,4&%;(+6#&8%(:'*>+.@-0E25I36F-1E+/F,0F,0K15M37D,0[PQ1//4++F11S::U<A70F<5LB;A70E:3?5.@8182+A;4B<571*5/(5/(4.'82+1+$,&,&,&-' +%5/(41)1/'1/'&$'%$"#!#!" *'#EB>1.*0-)41-,)%%"$!)&"+($,%"@53B64D86MA?D86A53;/-7)(8&(;(+A-0A.1<),=*-D03H37B*.A)-B*.C+/C+/A)-H04@,.4((+""6+*H55Q::S<21E??-,, .--)''."$C14K7:@,/<),5#%. $    #$$'&)!'*!13+,.&),#(+"),#),#&) '*!&) %(&) $'&) '*!),#.1(-0'+.%.1(/2)13*>;393,4.'2,%:4-@:371*;5.>4->2,8.'80)4.'30(86.21(2/'2,%3-&60);5.=70;5.71*:2+B81D:3A70B81B81PF?A70E=6>81;5.=7082+5/(71*71*C=6-' /(!1+#60).(!+%-' )%%#-+#)'&$#!&$(&" )&"<95*'#*'#'$ )&""*'#>;7# ,)%74093/D97;/-@42E97D86H<:D86B439&)<),@-0G47@-0C03F36I58A+.A+.C-0F/3B,/D-1D-1A+->+*;('E21J54N98P;:M88I54E32C10:+*3)(1))*##%)7)+@03D14E25E15E155#&.!#    #%( +-%%((+"%( (+"(+"47.,/&&) *-$(+"$''*!/2)(+"%(),#47.03*),#*-$,/&13*?=571*1+$82+71*:4-:4-93,?5/A5/B81H@982+63+42*10(52*83,71*82+B<5D>7=7071*91*=3,?5.A70I?8D:3A70KA:G>7<5.82+60)93,5/(82+HB;?912,%-' .(!/)"/)"/)".)"+'&$(&)'$"" $"&$$"+($:73*'#1.**'#2/,!0-):73$!"&#)&"-*&3-*=30C75E97C75C75D86<0.;,,>+.:'*9&)C03@-0H58C03F36>),<'*M8;F14F25E03?*-<'*@,,C/.A.-D10H54K87L98K87G54F43R@?F43A0/?/.@/.C21H79B25C03E25A-1F368&).!#    !*-%&)!47.&) (+"'*!7:1/2)#&&) #&%((+"/2)%($'$'*-$,/&),#*-$,/&/2)42*:4-60):4-?92<6/=70D=6H>8D82?5.?7/;5.;8031)32*<91B=5@:382+93,:4-;5.;5.>6/@6/@6/A70I?8D:3E;4TKDB:3;4-<6/93,71*82+82+82+5/(B<582+,&,&.(!.(!-(!+'&$,*"(&#!" !" '$,)%*'#52.*'#$!&#/,(&# $!'$ *'#.+'3-*<1.B64C75A53?31B64E97G99B02>+.?,/G47?,/?,/;(+<),?,/C14H58=+.B/2@-0;(+8&(;*)>-,@/.F53F53I87K:9J87I76M;:`ONXHGXHGSCBK:9F54F58D36E14F25F15=),;(+/ "#     $&%('*!$''*!03*),#),#(+".1(%($'!$$'+.%'*!%(&) (+"(+"*-$,/&02)A?7B=693,E?8GA:82+:4-HA:TJCOC=7-&91*93,41)42*44+52*=70HB;B<5=70?92=70;5.?70B81A81A70C92E;4B81D;4<5.B<5;5.:4-93,;5.<6/60)1+$93,93,71*,&*$*$*$)&'$75-*( %#!!'%*'!+($$!.+'(%!(%!$!!%"'$ +($.+'2/+71-<1/>20B64B64G;9K?=E97M?>C03>+.?,/H58>+.:'*>+.H69K:=A03VDGJ9..;,*<-+D43C42G86K<:P@>aQQ`SSYPPC=5/@70F>6D<493*>9062)20'98/:90:5.C<5?70?81A:3@81<5.=6/?70C:3F>7F=6C:3B:3C:3I@9<5.C=6<6/;5.82+<6/<6/71*/)"3-&1+$-' *$*$+%+%,''$/,$'$+'(%(%.+#)' )&"%""!!!'$$!-*%.+&52-63.40+70+@30F95I<9H;7TGCZMJL>;G86D02B/0@,.;')=)*9%'B.0F14C.1A,/H36E03A,/F04O;>XIJaUVWKK?00A00D33H77O>>fVVTKLWSSdZ[?.1J47H25P9=C,0@+.1"$   $&%( @C:.1(%(-0'.1'%('*!$'"%"%$'04*04((, '+#'&*+/#/3'<@48<29;255,84,81*C82A4.E71B<298,76*?>3::.32'21&54);5-LC7C;4<6/?81F@9<5.;5.A;4HA:C=6<5.<6/:4-<6/60)2,%71*.(!0*#.(!.(!.(!,&+%-' 4.'61*,' )#'"'"+&-(!+( +)!#!(%%#")'(%%#/+$+& 51*0,%4/(73+3/(>4.N?:P@;TD>K;5QA)(;&%=((@++E0/C,-F+0J.2O37J.3I-2O37kTXQHJ@45B.1U?CR4-B60J=6A;144(22&==1;;/33'55)77+:4+B81@6/B81E;4F<5C92A70>70;5.>81>81F@9<6/;5.<6/E?8C<5=7082+>8182+4.'?9282+>811+$82+3-&0*#*$-' .(!-' ,&0*#.(!*$-' .(!)%'%$"$"/-%,*"%#$",( -' 0)"82+<5.60)=7093,?5.J;5L<6K;5K;5QA;M=7J:4J84H32B-,?*)=('A,+K65T?>F/0H.1J/3L26L15O48]CGfSV`[\>==)!"B,/V<@U<@gUXTOP*)*)))433866KIIlij@02M15N16J.3C)-5!%(   580&( $'$'&) #&(+"!$"%"%(+"&) "%),"'+ %)'+'+)-!*.",0$.2&23)64,63+=80?81=4-=3,>4,40&00$00$11%99-99-77+66*?91F<5LB;I?8J@9F<5D:3?5.@81B<5IC<:4-E?8C=6>81;5.D>7KE><6/=7093,60)60)C=660)71*0*#82+2,%,&)#+%+%-' -' .(!-' -' /)".(!+( # &$(&(&" $"53+.)"2)"7.'>6/D<5E=6JB;?6/@5/K;5I93J:4VF@]MGXHBG71J94F20B-,?*)C.-J54F10K65F01I14G/3L37T;?N59S;?_QSqoo```4220#%L05U7<]AFVHJSRR111)%&) 6%(7&)I>@jiiG>@G,1P16N05D)-7!%(     ""$%( &) -0'%($'$'"%%((+"$' #!$ $!%$(#'*."+/#.2&04(53+:5.>70<6/:4->70=6/;4,/-#..".."22&DD8CC788,?>2D>5ND=MC81?92;5.:4-93,=70>81@:3;5.=70:4-60)93,3-&5/(4.'0*#-' +%82++%)#-' 0*#/)"/)"/)"/)".(!(%#!64,0.&!$"(&LJB@;47-&3(!A70@60;0*?5.=3,A5.H82F60L<6[KETD>SC=L<6J94F10F10C.-E0/K65E0/G21H33I26H26H15M7:K48U?CYNOIII4019%(R48T5:dIMOEF...301.!N27S5:S5:cHLxlmnnn623@(,S27Q27I,19"&)   !$+.&*-$,/&47.&) 7:147.&)!$'25-),#"""*."15)%)&*26*37+26*73+A81A81=6/>81;6.?;3;90/.$--!11%44(44(55)66*ED8=7.@6/E;4E;4E;4F<5>4-D;3>70=705/(=70F@8B<582+@:3=70;5.D>7HB;E?8<6/71*71*4.'82+A;42,%/)"+%82+'!+%-' /)"0*#-' :4--' -' +' )'64,53+&$(&)'.,$1+$:.(:.(:.(B6/=1*>2,A4.D60J:4VF@[KEO>8P?9QA;N>8SA=N98]HGQ<;G21J54I43I43K66H47H47I47J69R=@^KNRIK???4/0A-0R7;R8C`>C_=C_=Cwaeqqq/,,:%(V49W5;T6;A(-+     %'25,7:2?B947.36,'*"58014+ #""%!"%+/%(, &*%)15)26*)-!*-!7/'H<6G<5G?8>8163+/-%-,$22(.."44(33'//#11%33'66*;5-@6/A70D:3H>7C92>4-C:3>70@92:4-71*A;4B<5=70A;4<6/C=6E?893,<6/>81<6/93,71*71*=700*#1+$<6//)"1+$,&0*#60)F@9/)"<6/1+$.(!74,)'0.&75-,*".,$0.&1/'7/(>0*<-'B4.F71F71E60G82N?9WGAN>8RB.1H58I69aSVVRS6451$&Y8>gCIgCIe@FeAG}bfplmggg/--6"%Y5;W4:J+0A(,-    "%14+RUM`cZFI@9<3"%!$   #&#&15*#.2&,0$37**.!)-!,/#<2+C5/K@9IA::5.;90**"%'*+ ,, //#00$22&;;/66*87,NG?B81F<5ND=C92>4-F<5>4-7/(<6/;5.82+HB;=70:4-71*?92E@94.'93,71*?92<6/93,;5.=703-&3-&2,%93,0*#71*:4-1+$5/(?92-' -' 1*#*%73,1/'-+#42*20(20(31)42*:1+C3.D3.L;6O>9`OIXGBP@:H71N>8M=7SC=I93P@:H82K;5O>9S>=YDCP;:L76L76L76F10H44F47C25A03@/1>-0J;=E>@TTT8558-/@46F9;ZQSZYY6556$&b>CtNTpJPhCHiCIhlKJJ423;$(\7>W29L+1?%).    !#"$&( 03*HKBRULCF=&)!!$!! $'$'(+"&) "%!%$($((+ %)(+ -/%:3,>3-G=771)0-%65,)) #%((**-,!/.$00%<<121':8.=8/B:2C;3PH?KC:>5.E<4<4,4,%7/(:2+:2+F>7@81;3,=6/;6/73+3/'72+50(;6/40(51)0,$@<5B>6/*#1,%1,$A=52-&93,/*#2,%1+$3+$3+$2)"F<60)"0+%1-'2-'3/)50*51+72,F<6J:5C4.B2-VF@UE?WHBQB<<4,,F<Y4:N-3A'+-    "$'*"#%(*"*-$36-8;2;>5*-$! #"!"%#&!!$"%!$-0&+.%'*!*-$/2)54,74,96.20(-+#*( &%%$*) 31(0.&+*!*( /-%,*"20';8.94*=8.C>3D?5@:0;6,83(:1)@5.<0*A60D82F;5>3-I>8OJB20(63+41)30(63+1.&/-%.,$=;31/'31)1/'31):801/'-*"-(!5.':2+9.'=1+9+%>.(7*%<1.;0.6+(;0->30G<:?42E:6H=7?4-@5.J?9H>7E;4C81?4->4->3,@5/@6/C81?4.B71L?9N=8K84I72K94K94O=9H61?/*;0*<1,C82@60?5/A72^YUJHG5-)I?9H>8[TP]\\0..9))]@AiIJkJLmKLjl422*!"O05_:@X6;T5:P7;0!"     &(!57/+.%*-$(+"-0'*-$(+".1(!$" #$'$'$''*! '*!),#!$14+-0'*-$*-$8;299097/<:1/-$-+#(&0.&,*"%#(&,*"31),*"-+#/-%-+"1.$2.#>:/JF;JF;>:/<8-95*>5-F;4K@9D92B70G<5C81NC=JD=97/97/CA9B@853+53+0.&-+#/-%0.%42*><420(75-1/'.,$3.'<5.?6/;0*:-'9*$D4.=/+C75B64<0.?31>20L@>A53A62?5/8.'=3,MC4->4-<2+A70>4-A70D82H93I93O@:SC=O?9F61B2,?1+9/(>4->4-C92MC;jaZ[UPᔓ:41J@9D:3[TOXWV5335&&X==dFGlNO}dexjknll4110!Y6<_:@_5C:3OE>@70A81?6/@70QHAXSK><497/1/'<:2/-%IG?31)97/+)!CA997/20(-+#0.&75-42*-)!3,%8/(;0*E82F71J:4A3/=1/A53C75?31@42A53E97>3/>4.9/(>4-I?8OE>A70B81H>7H>7?5.<2+>4-G=6A70F<5C82B5/B4.L?9PBCM05=%)1"" #%(+$*-%03+03+36-14++.%,/&),#(+"-0'&) '*!!!!!$'"%(8;2,/&+.%*-$+.%-0'21)DB:31)20(-+#)'%#%#&$,*")'/-%31)/-%*( )',(84)84)GC8B>3A=2LH=D@5F?7RJCG@9=6/:2+G?8;3,NG@HC<;8053+,*",*"0.&0.&*( 64,.,$31)53+-+#<:2><4.,$20(/*"1*#;3+A60J>8PA;M=7D62E97B64A53A53A53J>4-I?8=3,B81B81E93B60I=7H=6L@:MA;B70B60H>7D:3MC3FB7GC8FA8<70?:383+72*72*3/'62*52*31)20(/-%.,$.,$42*42*.,$;9020(75-31)1/'-+#1/'85-50)6/(?6/A6/A5/H:4F60H:6NB@A53F:8A53VJHB649-+8-*;1*;1*KA:=3,<2+5+$4*#C92:0)<2+<2+9/(<2+:0)=3,@6/I@9MC7H>7I?8J@9A93RMJcbannnb^_?13K/4T759<3-0(-0'+.%+.%(+"'*!%($'#&.1)'*"&) (+"&) ),#&) %)'*!%(*-$-/&10(<:242*1/'/-%31)+)!,*")'%#$"%#0.&1/'&$'%85*62':6+=9.A=2HD9=9.=9.74+:7/=:241)53+/,$+)!.,$/-%0.&0.&0.&.,$/-%42*31).,$1/'20(;91,*"31).,$1/':7/4/';4-G>7B71I<6O@:G71D73E97=1/?31=1/B64>20=1/9.*;1+C928.'9/(5+$6,%7-&8.':0);1*7-&?5.9/(>4-C92=4-E=6?70F>7D<5>6/B:3=5.=4-B81E;4>4-B81F<5G=6H>7H>7@71E@=?=<++*)))(((%%%!!!!!!$$$&&&$$$###!!!!!!!!!3,-F.2L26G.2E/25#&(   &(" #(*#,/'25,.1(.0(),#-0'),#14+*-$%($'#&58//2)%( $'%(-1'$'*-$&) -0'.1(,/&65-64,42*53+20(.,$.,$.,$+)!'%(&)'&$+)!&%%$85,73(62'@<1=9.=9.=9.95*42(32*32)+*"-,$1/'20(*( +*!.,$/-%0.&/-%31)20(,*"-+#-+#1/'31)+)!-+#)'-+#A?72.&4-&@70J?9M@:[MGSC=D62D75B64@42@42;/-?20L@>=2.D:3MC<9/(8.'9/(5+$7-&F<5>4-9/(9/(A709/(;1*=3,:2+KD=B<5=81:5-82+93,:4-@:2E<5>4-?5.>4-C92B92A70A70B81A82:3.>:77530/.,+*+**+**+**,++,++-,,.,,-++,*+,**$"#$D,0P6:F.2<'*4#&)    !$!#%(),#*-$(*"),#$'@C:/2)#& #!$!!$;>5  #%,.%23*$&57.24++,$/.%=92>;373,3/'2/'.*#/+#/+#,)!0,%,*"+)!0.&11)99142(>:0:5+HC:?:0;6-EA795+;9022*11(--$22)A@8CD;--%+*"+)!20(42*,*".,$/-%*( ,)!,(!2/(.+#.+#;80,)!0.&97.,*"3.&92*A60F82N=8L94I84D73F96B52B52D74@30>1.;0+90)90)6-&7.'8/(7.'90)=3,I@9=3,:1*6-&7.'8/(?6/;5-:6/;8063+>;396.:7/A>6B=6:2+;2+:1*:1*;2+;2+<3,=3,?5.B81C92@60>60;4/.'#.'#*"!+! .$$4))2'&7++6)(5''5%'4#%7$&G/3N58H24F145$&, !     ! #.1(%("%#&$'(+"/2)#&%(!$"!$ "!#"#"+*!+*"0.&=70G>7E<5:1*:2*90(6-&7.'5-&C<5C=640)54,./&/3*9=464,72*>81>91B=5>80@;3=80;8087/65-42*,*"0.&54,/-%,*"31)A?7=;353++)!0.&@>6?<44/(3.'71*0+#.(!/*".)!22*&+!--%72+A60G72K61Q84O94L:5J95F5/F50N=8A0+A0+=1+5/(82+70)2,%2+$60):3,IC7B<5<5.81*5/(92+40(41*53+31)75-86.75-53+73,82+93,82+71*71*71*71*80)B81G=6A70G=6D;4J@9F<5H=7G75C21G54G65F54E32K98\HHS==N67J34H22P:;F23>,,9))1!"&    !(*"(+""%"%""%(+"+.%9<3&) "%+.%!! " .,$-+#-+#><4D<5>5.J@8B81B81<2+:0)A70F=6@81A:3<81=;3+-$(,#)-$86.KF?D>7?92E?8NHAE?8@:3;80EC::8053+97/=;353+1/'/-%-+#.,$0.&/-%)',*"*( 0,$-' -' 2,%3-&0*#0*#1+$10(47.88/61)=2,F5/O:5Q95M83G61E5/I93F60A2,=-'A1+B7171*:4-NHA;5.4.'93,:4-?9271*C=671*@:382+60):5-51)2/'31)97/><464,64,0.&2/'82+@:3>8171*:4->81=7092+D:3G=6B81QG@G<5^TMH>7YMGSBAJ87H65J87O=81F@9GA:=70=70<91HF>=;375-75-53+<:242*20(20(86..,$(&/-%1/')&-(!2,%/)"93,60)60)1+$3.'42*@A8?<471*A6/E5/P=8T?:G50A3->0*C5/E71A4.6(":-'7-&1*#3-&<6/;5.3-&=70=7093,=70GA:93,B<5D>7>815/(62+31)0.&/-%42*1/'/-%/-%/-%1,%71*71*5/(60):4-93,70);1*B81J@9G=6D:3E;4F;5G;6O>7E;4E;4I?8C92>4-?5.=4-7/(70)1-%:80BD;37.(-$75-<704.';5.F@9;5.93,4/(52*;8064,53+53+42*;9175-CA9;91@>6=;364,42*GE=75-0+$93,2,%1+$0*#B<560)/)".*"63+<6/?70@5.G93J94J83B4-=1+;0*<1+>2,F;58-':.(6,%71*93,3-&0*#82+A;493,=70?92>8193,82+@:3;5.4.'2.'31)20(-+#20(0.&0.&:8074-82+71*82+>7082+71*;5.IBULF^SNSDBQ@?TDCTCCRA@Q@?YIHdSRN>=I87L;:E43F54H989+)3&%0###  !!$"!$'36.&) #&"%),"*-$'*!8;2%(%(!$$'"%&%(&'%(&1/'0.&.,$;8092*@6/=3,?5.B81A70?5.@70>6/;3,>8151*10'-/&(-$+/&,*"0*#3-&5/(60)93,71*3.'0-%1/',*"20(1/';91FD<:80:80<:286.EC;:80:80IG?=;32-&2,%2,%1+$1+$4.'82+>813,%@92>6/JA:C92F93N@:F82F:4A70>4-<2+8.'8.':/)?5.7/(6/(2,%2,%1+$D>7LF?:4-@:3@:371*82+D>7D>7;5.2,%3/'2/'.,$-+#/-%0.&75-97//,$>81LF?93,5/(60)60)GB=:74C?4-?5.@6/>4->5.;3,=5.@9284,0/'.0')-$.2)-,$0*#2,%4.'60)=7071*2-%1.&.,$*( -+#.,$/-%><4:8020(?=564,53+86.42*<:275-61*B<5=7060)60)4.':4-=704,%?5.H>8B81E;4F;4H<6@4.D:3<4-;3,7/(4-&3+$G?8:2+3-&?92<6/4.'71*:4-93,=70D>793,93,@:3<6/4.'A;4;5..+#0-%+)!64,42*20(<:275-2/';5.@:35/(4.'82+71*KGBa`_onn60/7,+=0/8-+1'%*"!# !$+.%,/&),#/2)03*/2)25,14+.1(+.%,/&),#<>5;:2FD<31)1/'1/'31)*( 74-@816,%90)C92C91@6/;1*=3,;2+92+93,;6/43*13**.%-1)0/'5/(5/(5/(4.'4.'60)50(1.&,*"-+#*( ,*"/-%0.&42*31)97/64,31)86.31)20(0.&40)D>7;5.;5.60)<6/C=6:4->5.>2,K?8F:4G;5B81ND=G?8@92;5.>9172*2-&72*61*=7061)?92;5.60):4-;5.IC81:4-93,A;4?9282+3-&/)"+',*"-+#.,$31)<:231)B@841)5/(1+$4.'5/(72+5/(EA<ڨjjjEEE222,,,,,,,,,,,,,,,,,,,,,,,,,,,+++"""5214*)6,*2('-$#%   "$,/'7:103+36-24+/2).0'.0'68/-/&,.%56.02)/0'54,86.20(31)CA942*,*"0-%B<54,%70(IA:H@9=5.80):2+92*92+<6/?<4:8033+/2)36-64,:4-:4-:3,81*;5.81*82+40)1/'-+#97/A?6/-%20(86.?;373+51);7/;7/40(51)51)50)>81:4-<6/93,<6/=7071*D:31+D82A5/@6/>4-VMFB;451*1.&1-%3/(3/(40)96.83,71*3-&71*82+5/(IC653+0.&20(/,$1,%3/'<7061*84,50);70WUQUTT{{z---,,,.--****))*)))))*))*)))))+***)))(("!!-�)&>74,&#%'"!   !%' '(!)*#-.&45,23*56-23*22)32*21)/-%31)DB:?>675-><442*-+#,*"0.&-+#0.&.+#.+#.+$31)?<452*1.&;8030(63+74,53+=;3A?743*65-43*83,;4-C;4@81;3,<4-80)F>7;7075-20(86-DB:?=5/-%2/';4-;1*I>8E:3OE>E:3>3->4-92+>81QKD<6/60)GA:?9160)LB;=1+;.'@3,?2,@4.M@:MA;90)2,%2,%4.'5/(61*93,60)2,%4.'60)82+71*>81GA:C=6?92=70;5.:4-4.'1+$5/(60)1-&2/'75-/-%97/42*97/1/'64,.,$,)!0.&<:2><474,:80IGAonl::9666))( %#($ #!"#",($-)&%!""0*%0+%,'"$     %%)'!-)#3/(40)=81<7095-95-53+64,42*97/<:2VTLFD<31)31)-+#+)!-+#+)!-+#.,$,*")',*"53+86.20(31)CA942*:8086-20(1/'31)86.97/53+61*91*D=6IA:@92:2+?70E>7=91?=597/86.?=4MKC42*64,92*<1*C71@4-G;5A5/D92C7190)60):4-93,5/(60)>8171*5-&5-&6-'>5.?6/>5.NE>PGA91*/)"1+$93,;5.82+71*5/(71*71*60);5.@:3C=6@:3F?8IC>=*("0/'30)4.'71+71*5/(71*1,%71*71+60)3-'3-&4.(4.(,'"$!   $!+&!/(#80*<3-SICD:4H>7G=6B93<80B@897/?=5<:2;9164,31).,$+)!/-%:80.,$/-%.,$-+#,*"+)!1/',*"+)!.,$20(MKC86-31(0.&=;331)31)20(86.:6.=802,%5/(:4-5/(>91@;4<80A?775-97/75-64,;91:8071*<3,A70>4-A71?5.>4-G>7=5.71*JD<<6/2,%5/(82+<6/40(30(62+B?70-%30(74,74,50(2-&=7093,>8182+60)5/(93,5/(;5.:4-<6/A;4F@971*A;4;5.=70:4-SMF93,1+$0*#.*#1.&-+#,*"+)!,*";911/'0.&31)53+=;30.&53+97/TSMaa_FFF('!.,$0.&1/'63,A<5=7060)5/(4.'3-&71*<6/OIB82+5/(1,%0+%)%)%!"  !*$2+&9/*?4.@3.H;5D81PC=OA;B6/94-75-:8097/31)1/'0.&1/'.,$,*"*( 0.&*(!/-%-+#,*"+)!%#.,$*( ,*"42*42*@>6<:286.53+75-1/'?=50.&/-%,*"/,$0-%74,41)/,$41)63+52*0.&53+:8086.:80:80@>6<7/:2+B;4B;4=6/E=6:2+>6/:2+>81`ZS:4-71*60)1+$82+:80+,$*,#13*:<3+-$02).0'/.&:4-F@9>81F@993,5/(5/(82+82+;5.:4-JD=E?8;5.82+KE>@:3B<5>81GA:C=6<6/2,%/+#-*".,$/-%+)!+)!*( +)!.,$86.=;3A?731)86.=;3PNJnnmiii22142*20(31)1/'2/'5/(93,5/(4.'93,71*:4-71*@:3=705/)82,94.&")%!'$    ")#2+%=2-C71E82D71H;5F93F82=2,73+31)53+B@820(0.&.,$-+#,*"20(,*"+)!'%.,%75-/-&&$+)!?=5*( ,*"@>60.&><4><4,*"0.&+)!+)!,*"+)!*( 42*;:2*) 65-::1,+#<;3TSKEC;75-:8042*42*31)31)41)52*72*50)@;3@;4KF?>9193,:4->81]WP@:3:4-71*2,%3-&.,$12)12)890+,#*+#*+"-.%53+93,93,93,<6/3-&82+82+:4-60)4.'82+:4-82+82+60)>8182+;5.<6/D>7GA:93,50(40(2/'/-%-+#+)!*( (&)',*"/-%75-31)42*42*?=6@@:3:4-?92;5.5/(<6/82+82+4.'FB:40(50)-(!/*#2-&=81@;4;5.A;4>8171*93,B<560)5/(:4-71*71*82+:4,60)5/(5/(5/(5/(71*:4->81IC<72+2/'53+20(/-%0.&-+#/-%86-/-%20(HF>75-64,64,<:3985fff/.,"!.,$+)!20(JH@0-%3.'.(!,&/)">81NHA93,71*:4-72*82,5/)2-'0+&($    $$)' -)"EA952*74-,)!2/'.,#)'1/'(&&$&$&$'%(&'%(&,*",*"HF?31)+)!/-%&$&$%#" " $"'%%#$":80)' *( ,*"+)!,*")( ,/&&*!/4+16-$) $) .2)16-CD;0.&42+&$&$0.%,*"/-%(&DC:-,%<:321(+*",+#:902/';5.C=6GA:@:3JD=D>7>81>5.;2+@6/8.'90)>4-?5.=3-=5.82+;5.<6/C=6:4-60)@:3<6/5/(60)D>7F@94.'0*#93,93,2,%1+$3-&60):4->81GA:73+53+31)-+#97/;91.,$86.42*0.&42*86.:8086.:81BA>;:9#!-+#,*"*( 86.63+/*#93,;5./)"60)3,%93,@:30*#4.'71*/*#2-'0+&)%   "%&$$&'+,$%&00(++#'%/-&" &$" #!$"&$(%,*#63,-*$/,&/-&IG@?<5)& $"(&%#'%#!*' :8175.+)".,%/,&&#'$*(!(*!%(14+37.&) &) *-$+.%-.%-,$1/'(&&%('-,#(&&&23*67...&33*() //'99063+.)";6/=80>92GB;HC;E@9E<5I<6H:4K>8L@9N@:E82?2,<2+61*C>7OJCJE>94,3.'61*83,83-4.(5/)2-&4/(2-&94.KE?40)61*72*73+4/(:5-94-52*85-63,.,$30(/,$31):7/30(20(=;342*64,20(21)WURbba0/):8053+/-%53+31)-(!4/(40(,( -(!.)!>911,%51*4/(93-0)"1,%.(#'"   "! " '%!10+#!%## %"%")&")&!%"(% )&!'$'$ /,'-+&)&!/,'.+'-*&,)%<95.,'%"(%!)&"-*&0-)&#'$'$ B?;+(#)&"*'#(% &#*'"52.,*$''**!CB:87/,+#//&00'-,$-.%11)./&$$++#--$"",+#:80'%$"0.&+)!(&)'%#.,$30(:80<:2?=5A?7FC;PHASGAK>8J>8G;5L?9QE??3-A8174-=;3NKC97/1/'-+#1.&0-&>;6.+&-*&,($,)%,)%.*&30*0.&53+<:220(30(?<4:7030(51)50(0+$3.'@:3@:372*96.52*64,31)53+64,75-IHBttrXWRdb\EC<980LJB=;386.:8096/86.75-:8097/GG>42*/,$0*#-& .&!*"& "   "!" +)%B?<-*&%" $!&#.+'+($)&"'$ )&"85141-41-/,(1.*1.*41-52.52.1.*,)%+($(%!<9563/,)%,)%/,(*'#<95,)%,)%+($)&"*'#+($-*&0-);82,*"-+#20(/-%-+#31)32)75-0.&KIA54,0/'@>6FD<)' /-%75,(&'%CA9/-%'%'%&$*( -+#53+1/'53+;91<:2A:3LA:G;5F:4L@:PE>H<6>3-;5-75-53+@>653+-+#.,$64,42+41-0-)*'#52.41-/,(.+'2/*0.&.,$/-%,*".,$.,$B@8>:3A;4D>760)60):4-;5.93+;7/75-42*31)1/'97/HF>20)}̓``^ONKFEBFEAEE@BA=CB>CA>BA>CB>DC?DC?QQM`_Z0.'0+$0("1(#'(!   %#%",)%&#'$ # &#-*&>;7-*&2/+30,2/+41-962EB>?<830,740;84@=963/.+'2/+.+')&"(%!-*&-*&/,(1.*+($41-+($)&"/,(*'#+($.+'1.*2/+/,&)')'+)!75-20(-+#1/'53+52*<9141):7/FD<52*53+/-%1/'0.&+)!(&&$/-%!$"64,0.&0.&1/'31)20(86.<7/?6/=4-E;4SIBYPIB8190)=7/IG?20(,*"/-%/-%0.&+)!)' .+'+($0-)0-)?<8/,(?<8B?:1/''%.,$20(*( 1/'CA995.72+60)<6/93,71*A;4JD=LH@KIADB:GE=86.?=51/'31*861mmlqqqxxw+)%*%.'!7/*(    $!/-)*'#&# +(%)&",)%&#8510-)740962851;84:7363/GD@DA=;8430,0-)0-)1.*.+'/,(1.*/,(0-)962;84.+'1.*2/+2/+.+'-*&851>;7-*&-*&41,/-'+)!)'0.&20(20(31)64,85-82+<7/:4-;6/82+61):5-84,0.&,*"-+#)'&$!'%&$20(,*"+)!0.&0.&;91HF>1-%5-&92+6/(D<5KC<=5.H@92-%75-.,$42*0.&+)!-+#20(63-.+&,)%-*&>;71.*63//,(/,'(%+)!.,$<:2.,$CA9><4?<41+$0*#82+<6/:4-=70LF?B>6><475-53+42*53+0.&64,20)54.DCA110$$$***000222333333333333333333333333333(((,+)2.(/("-% %   " '$!852:73.+'>;730,.+'@=9=:6:73:73851:73851962>;7<95B?;52.=:69622/+/,(1.*1.*2/+41-0-)1.*1.*30,@=9:7330,2/+30,41-1.*/,(MJFGE?1/'31)1/'75-64,<:2?=5FA:=5.D<5F>7=5.;3,E=6B:3C?7;91.,$*( *( %#*( 20(+)!31)0.&)''%)'/-%><4.+#.)"2-%4/(61*72+3.':4-62+42**( ,*",*"1/'?=5CA92/),)%,)%.+'0-)/,(>;7)&"*'")' (&(&-+#2/'53+53+40(0*#0*#1+$2,%60):4-<6/=9197/75-64,42*20(42*53+31)0.&,*$10,>><110,++''&''&''''''''''''''''''''''''&&&(#-'!*#&#  !'$!)5/96274041-1.*1.*740:73:73=:6=:685163/52.63/85130,KHDHEA63/1.*0-)2/+1.*0-)1.*0-)30,30,30,52.63/85196285130,1.*1.*0-(31);9097/53+86.B@8HE=;5-B92C92C92MC7J?8E<5@:330(0.&0.&(&)'-+#,*",*"/-%.,$(&*( $"-+#)'-+#,*".,$0.&85.75-31);910.&0.&/-%.,$.,$31)0.&0.&/,&-*&-*&0-)63/,)%*'#(%!1.)1/(*( 64,31):80/-%<:241)0*#.(!/)"2,%3-&93,=70C@8C@853+20(0.&20(42*53+97/@>61/'/-&-+$%#!  -(",% *$#  !$")&#-*&0-)<95+($/,(52.740851NKGFC?851:7396262.41-63/740<95:73/,(/+(;8474074096241-2/+C@;7:739628510-)63.75-53+86.64,53+=;3=:2C;4I>8G<5QE?aVPSGAJ?8H<6>8164,31)31)20(42*CA90.&,*"*( +)!'%:80,*"/-%,*",+",+",+"-+#.-%1/'/-%86.0.&/-%0.&0.&.,$0.&42*.,$20)/,'+($)&",)%,)%(%!%"(% ,*#-+#/-%/-%FD<20(-+#0-%61*?925/(2,%82+>81B<5@<553+/-%86.JH@42*42*53+53+53+31)=;3><420(1/'1/'1/'1/(.,$31*31*)',*"42*/-%..&)( ,)"+& ("*#&   "(&")&#-*&0-)/-)8511/+1.*52.962:6251-3/+63/85162.84051-73/841?:79512.*62.62.61.61.50-3/+:62:622.+3.+61-;73@<8<74@<9951>:6GD>>;4=:3=:3<82>:3>;4C?9JB;`UNRHAcXQMC<464,0.&+)!+(!.,%+)"-*#$!(&*' '&)*"))"()!+,$()!34,DE=66.1/'.-%-,$0.&-+#97/><4=;4/,'-*%-)%-)%+'#(%!)&"(%*(!,+#,*"+)!52*63++( .*"-&81*3,%3-&4.'82+95-74,20(1.&1/'63+2/'52*86.52*41)/,$64,DA952*31)31)20(1/'/-%/.%,+#.,$)'-+#20(;:1*(!,(!,'!+%)#    '#!*(%,+'-,(/-)10,1/+,+'0.*3.+5.+5.+70->8581.:3081.G>;>42=30<20A75I?;198.54*;7/2,%4.'0+$60)50)B=661*3.'3/'50)62*:5-71*=7074,43+:;2AA9890**!++#00'/.&84,/*#-(!*$'"%!   !,'%,)%/,(1.*1/+1/+31-63/41-71.81.81.92/E>;HA>LEB=52D97A53B64L?=A53G;9>20B64J>20?31@42NB@I=;L@>OB@M@>J=;NA?K>MA>[QMD>7@:3\VORLEB<593,71*=91kia_]U53+/-%0.&/-%0-'1.**'#$!'$ %"'$ +($**&&)%)-($'"#'" $$(#CFA./*/-%31)65,86.1/'64,97/1-&83,A;393,0*#0*#0*#0*#1.&;:265-<:2FB:@:3=4->3-B5/C5.C7/A6.?6-?90C?674+30'?92:4-B<5:4-60)82+82+;5.=705/(93,KE?c^XZVQOLHFD@CB>FFBSQMZYSKJC65-21)/-%2-&0*$-(!.)#($#   *%#9420,)0-*2/,41-51-4/,<85:6292/92/:30:30<52@96?85D=:SHFRFDMA?_SQQECOCAG;9C75F:8NB@H<:K?=K?=F:8E97G;9F:8?31A53=1/A53G;9I=;OCA[OML@>OCAQECYNLB64G;9SHEIA<>81JD=[TMB<571*5/(5/(/,$EC;`^V><453+20(85-/-%31+2/++($%")&"'$ %"&#,+''($!!))%%%! !&'#''#**$-+#/,$1/'/,$1.&:8096/.*#4.'0*#1+$3-&2,%4.'71*41)20(75-95-;5.I@9I>7D71O@:RA;G>;E<9MDAD;8>52C:7@94=70>81IC<93,:4-<6/93,=:264,@>631)53+:80OME0.&+("+($*'#)&"(%!&#$!%"+($+($(%!31-(&"$")&"+)$/,'3.'3-&50)61)50)2-&1+$0*#=7093,5/(3-&3-&71*<6/KF?@=5=8193,>6/F:4H:4I:4UB>U>;/.-zzy۶lif?:44.'82+2,&,'!*&!  1-+.)'/)'4,*=53>52SJG?63I@=D<9?63A:7A:7A:7C<9C<9G@=KDAF>;I>MA?MA?K?=SGEK?=G;9F:8A53D86E97B74E<:@96?85=74<635/,70-:30E?:<6/<6/?92:4-<6/;5.83,74,42*42*42*31)64,86./-%0.'+($+($+($*'#*'#(%!%"'#*%")$!(# )$!)$!*%"D>;;405-'<4-KC<7/(80)7/(6.'4-&3-&;5.A;493,60)81*82+B<5D?7=6/=4-E:4L=7L;5N;6T=;\?@[=@W<>X@AR<>K78F34D64?81SMFC=65/(60)93,;5.OJD;97[[Zlll--- (((QQQkig3.)=710*$*% %   "+&%50.4+)@54?42F;9E96XLJMB@E:8D<9C<9C<9B;8B;8IB?SLIF>;H=;J>:=:60-)51-73/4.)=70IC;;5.71*:4-<6/>81:7/86.86.86.53+97/<:2DB:1/(-*&-*&-*&+($*'#)&"*&#,'#.'$-&#+$!+%"/(%0)&?85=517-'SIBE;4:0)<2+@70?5.=5.93,93,=7093,60)3-&E?8<5.A92F=6I=7I;5N=8VC>ZEA_EDb@Eb?DbAF^?DX714.'82+4.'E?8>81XRLFD@``_,,,'''554:98987:87<:9=<;987DDCwvvHFD/*$1,%+& '#   # +'%2,*:0.C86F:8C75F:7L?=F97J=;@75F?;MB@MA?J>K?=`TRRFDH<:J>^RPOCAI=;J>PDBSGEB64=74;847401.*,)%1.*20,DA=;71;5.82+93,<6/=70=70=81;80:80:80:8097/75-LJB=;3/,&.+'.+'.+'-*&*'#+($0,(3-*2*'1)&0'$/-*5,):1.=2.?3.G;5L@9C71@5/E93D82@70=6/:4-82+71*:4-?92OIB>6/C92H=6OB8S@;WC>YB>eHHuNUhAHe?Ga>EZ:@T6=Q4:L89JB=93,LF>5/(:4-/)"QLG@?=)))###544#/)%;3.2($2*%1(%82/NKIlkk30,1+&,'!)$"  ",'%1*(:0.B53H;9L?=PCAYLJNA?PB@H>NCANB@K?=K?=K?=OCAL@>I=;G;9H<:YLJH<:VJHYMKJ=;K?=OCATHFYMKH<:THF_SQdXV^SPGA=CA=64031-0.*/-)42.97384.:4-E>8VOI<5/;4.?82B;4=9296/95/:7085.85.=:3;911.)0,(0+(0,(.*&+'$-(%50-61-5,(4+(4+'2)%:1-8.+=2/D:5C71A5/F:4G;5I=7B60A5/?5.>70>70:3,70)5.';4-@81C:3QE?QD>WGARAS>?D94<3-@82:3-92,>82MJFoonjjj%%%**)-(#82+;4.A93G<6@3.B61B61B728.*931kkk?=;/)$0)$)#"  %1)';1/>20I98J:9_PNdSRVEDO>O@>O?>N?=O@>QA?O@>NB@J>;>96;524/,82/?96PJG@:7H?<@52A63A63:0-9.+:/,<1.=2/B84;1/F<9RIEJ@=WMJXNK;2/80-1)&5-+2+(2*'0(%80-81,:5-;4-KC;>4,C70C5.C3-L=9PB>C62B41J<9j\YE84I<8NA=G:6@30B51?3.>1-XKG[OJL=9P>;P=;Q=;S?YEBWB@aGFjHJeCF`?BX;=S8:T:O=TBAUCBRA?SA@SA@Q@?M?=MA?K?=J>J>B96<52JC@JC@=63E>;?85;41A75A53B64=1/9-+@42:.,?31?31A53@42>20H<:C75H<:C75<1/C85=1/9-+;/-8,*<0.=2/:1,;4,:1)E:2=1)D5.F5.G5.^KF_LIQ>;H52L96K86Q>=]A@cDE_@AY;>S>=K66P99M76E10M<;>1/G=;DA@???/.-' >2/F74G63N;8S>=L68O8AO8oabggg+**%5(&7,+*!   ( 3((?11D54H87M<;aONQ@?TBA_MLWEDQ?>R@?UCBVDCTBAUCBUCBRBAL?=I=;I=;J>I=;I=;I=;J>G;9UIGL@>H=;C:7?85@96E>;;41<52;41@96=30C75B64@42SGEA53>20:.,B64>20E97C75=1/A53H<:>20D75B53A42>X:;Z<=Z==W99V9:^AA]??dFG\=>jHIsQScAB`>?`>?eCEdBCgFG_?@]??dIIT;;R;:S>=L87L87P:9N98K76D21B31G;9MHGUUU0-,D76N<:Q=;V@?R99_CE^@D_@EW8=]>DW7=Y9?bCHyehywwVVV.--%5'&0#"+!!  * 7**D54M>=J:9VED]KJUCBQ?>WEDSA@TBAUCBUCBUCBTBAVDCVDCTCANA?J>A53C86D;8A:7B;8@96<52:30=63F>;RGEB64@42H<:MA?;/-<0.7+)<0.OCAD86B64@42C75OCAC75@31J;:QB@>.-?0.=.,QB@B31@0.B1/E31F30L65M53S97Z==^;=dCd;@eDuLQrINf=Bf=Cg>CjAFf=BfBE]@AX==Z@@P98YEDYGFVEDM;:R==N:9N=@W:>^?BY8CZ6VDCP>=R@?YGFgUT]KJZHGUBAYGF\JI]KJWEDSCAOA?K?=RFDPDBJ>K?=L@>RFDPDBH<:K?=J>H<:H<:F:8I=;J>D=:RKHA:7A:7?85A96C97^RPB64<0.@42<0.>20:.,@42D86G;9A53K?=?31D86E97@1/I87I76I76E21G54F43B10J65G12I24P68S79V79[;=a?Bf>Dh:Bi;CxJSf8Ag9Ah:Cg9BiFn@HzMUl>Fm?Gh;Cl?Gm@Hl>Gj=Ek>Gj=Ek>Gh;Dd=C`DEY??R::M98XGEYJHJ=;]MLO<;S?>XCBS>=S==V@@^MMTOPA*/Y7=_:Ad=Db:Ad;Cc:Aa8?`8?_7>a9?nFMip0//+((- :*)0"")   %1$$=,,H66_ONTCBVEDR@@UCBYGFTBAWED]KJYGFWEDVDCXFEWEDTBARA@QDBMA?RFDPDBJ>J>;UKHE97?31?31H<:B64@42>20B64<0.E97E97A53B64OCAA53J;9J76H43UA@P<;J65L87H54Q:R59W8^9?a:@c;Ae:Bo@KsDPf7Cg7Bd4@k;GvFRl=Hg7Cf6Bi9DlDY?@Q;:M87G54I:8fYWM@>O@?L98VBAR<;V>>]CCaEEU;;uvն[KOc>Hj>IrDOo>JkJ>J>F:8H<:NB@OCAI=;J>74I?=E97A53C75B64B64J>_8@d;Ce;Ce9Bg:Dg9Fg9Fe7Dl=Jc5Bd6Cf9Fh:GsERg9Fh:Gd6Cd6Bg:Gl>Kg;GeJc;Ga8E_6B`7Ca8D];CR;./J78O:;UCCWEE^LK]JI]JJYEEUBBYFFZGF]JJ]JJZGGYFFWEEXGFUDDQCBOB@K?=J>J>[OMH=:LB?LDAF>;B:7B96E<9C;8H@=B75D86E97F:8F:8B74H<:D86B64I=;E87G:9H;:PCAB64B43I76O99I22N78iRRXAAM66cLMX=@W7=^Ea:Bd;Cf;DgKb7Dc8Ea7C]1>k?Lb7DrFSj?LwLYc8EuIVa8E]9D[7BZ6B[7B[7B[7B^:E`AHK56E11H56A00B33E77G<:THGQFEYMMaUUeVVcRSbOPq\^gRUgW\Կ{~raeqX_lRYbOS_ORYKMC9;4/0MKKTRRSJJB--H11C--7%%/ %  ,#$:./:+-E47N;>WCFVAD\FIYCFZCF[DG]FI^GI_FIbJMZDG_JL[HJZIK[KMWHJQBBUGESECM?=N@>OA?N@>M?=M>N=L@>K?=J>QBAH98J:9RCBbTRC75E;8D:7B85D:8A74=31B85G98J89J79K9;M:;L9;K8:O<>O;=P;=G14O:WW:?\=C^X6?Z9AX6?X:AK6:I48I47H15O7Q?>P?>O=OB@PDBOCAMA?J>=E75G;9F:8I>S>AO:=T>A[FIYDGP;>O:=P;>J58L7:J58M8;QQ8^;EZ6@eMSeeeNNNNNNNNNNNNNNNNNNNNNLLLDDD???>>>@@@EEEJJJLLLMMMLLLIIIDDD@@@>>>???777822@0/?/.6)(,"!#  #1#%=-/H69PB\DG^EHdIMbHLdIMfKOiNS}_dhKPsX\kRVaKOZGJZHKWGIhWWcQOZHGRA?WEDTCBSBARA?SA@SA@R@?P>=N<;O=NA?NB@L@>K?=H<:E97H<:SGEN?=F43H65G54G54I76K98aONM>?V@DYBFV?CT>BZCGZCFQ:>P9=RI26O7;Q6:Q6:O48U:>Q6:R7;V;?[;BW2<[6@fAKtOY\7AY4>X2=RA@N@>M@>K?=J>=P<=V>BV=AV=AW>BT<@U<@U<@U<@]EIaHLO6:R9=T;?iQUV=AO37S5:[=BhJOZ<@U8=V9=ZV1;\5?c8C`6Aa7B^4?b8CwMXwѦzM\l?NoBQpCRf9Hf9Hb9G]8F]7E]5C_5Ck>Mk'/A)1?%.B(1B(1C'0F&0F'1G(3F(2C'0D(2B'1A(1:'.7$,6%+5%*3%(3%(0#$4()0$$-"",G54@/.5''3)()   ';+-C/2Q9=Y?CdHLiKOkKPmMRxV\pNTnMSsQWhnsRXnNSjLQhMQdKOeNR_IL_JK^II]HG]HGYDC[FEXCBnYXYFEUCBYGFVDCR@?UCBVDCVECPCAMA?L@>K?=J>P>=M;:J87I76J87Q?>RA@G65K98UCBR@?^LK_NMQ?>T=>hMQaEIY>B[@DW<@Z?CZ?CX=AS7]Pm9Km8Jq9Kt;Nw;Py;St7Ow9Qy8Qz6O9S8R6O9R:S:S9Q}9Py8Ow7Ns9Ng9Ja7G^5CZ5@X6=U6;R58R79M33K33I33H54@/.7)(4*)5,+   )D25B,/Q8<]AFhHMlKQoLRqNTwTZvRXsOUtPV`fciqOUoOTmPTfKOlSWhQUaJKu^^w```IHoXX\DD`II]FE[HGTBAcQPaONQ?>TBAq_^\KIVHFL@>K?=J>W=?hINcDI\>B\=B\>B]>CX9>_@DX:>U5:[<@O05Q37U6;cDI\:@Y5;X4:X4:Z6<[7=a=Cd@FZ6>fAKmGQ]8B`;E\7A_:D^9C_8C`6A`6A`6Ab8Ca7Bd:EmCNtESzBVo7L}EZx?TzBVv=Rq8Mr;Oq_>a<_=`?`?]@]A^C_EaA]C_G`s?Rl=Nh;Jd:Ga;D^;A\;?Y:=U9:R99O88I65B0/7)(/%#(    '6$&D.1Q6;^AFgEKnJPqMStOUtNTtNTuOUySYyRXxRXqNTpNTmNSmPU~cggORfLNmTTpVVhNNlRRfLLpVV_FFZFEVDCWED`NMUCBVDCXFEWFEN@>K?=J>=ZEDgRQZED^BEaAFaAF^?D_?D\CoOTW7<\H^9C^9C[6@fAKmFP`6A`6A`6Aa7Ba7Ba7Bd:EyHWD[x;Sv8Pw:R{>UD\}?Wz>Uv:Ry=T{c>e?g?g@hClBk?eAcAaCdEe@_EdFeD_v?Sp>Pk=Lh;HeX:;S;;P::K77D32=.-2(&6,+"   '7$(C,1Q7<[>DdCHlINwRXyTYbhzTZySYxRXW^dkvPVrNTlLQnPUtY]iNQsXZcHHeJJgLLdIImRRlQQcIIlWW\IITBA]KJUBBSA@cQPdRRL?=J>K98K76L98^KJP=DY7=]9?`9@b;AkDKcF_9Cd=HcW>WC[AZ=VY?ZA]AbAjAmAmAm@mAn@n@kCgBdFhJlDeEeCc@]x@Ts?Qn=NiE`=B\<@X;=T;=I>=O<;N;:\HGaMLR=_JJmRTy[_iMQV=@\EHs_awymquU[dDI_?D]JpBNqAPmMSeAWD[I^F[z=T@XAXJbJc;U=ZB`Bc;]>a?gEtJz>mBq?n=l@n@kDhCeCeCcCcDcCbA]z@Ww@Uq>Qj&.O3=bCM_@EdCGnKOwSWsNSuPTwQVwQUzQXzQXuNTqLRnLQpPVnPUkOSrVXpUV^EE[EDZFE^LK]NLWHFVDFS@CVCFUBEUBEZGJXEHR@BK?>H=;I<:J;9K:9O<;M98`JIiRRYDCM87M87M87O:9R==\ADZaKOyfh᫔zZ__?D^>C[;@X8=Y9>]=B_H`;Eb7Be5Ai9EwGSrANn>JxHTm=IUatFRk=Ii;Gh:Fh:Fg9EyKWwFUs@Po:KpOw>Q|=S|AWv?TyCW|BW=SAXAY@X>X>Z?_@ckAoAn=i;h;g>j_<]AaCbB`?[z>Vv>Up>G<:I=;K=;I97P=<]HH\EE[EEP;:O:9O:9N98P;:R=Ji;GkOr>Ot^@_>]B^IMH58<*-5&(&   (7!'A%-O-7]6AbAS@CTAD[IKRFEF;9I=;L>U?>Q<;P;:P;:P;:Q<;Q<;P;:O8:[CFN7;T=AL7:ePSs^ar^ax\ahHM\CiIN`@EoNVd?IlGQgBL`;EqLVjEOjEOg>Ie:Ei=H`4?hIi=Hi=IoBNyKWi;Gi;Gi:Fi;GwIUjSI]xBVw=R=S9Q?VAYAZFbBa<];^=cc=`DeHh>^:Z<[=\;Z9Vu9Rq9Pk7Kf9J`7EY6AX8AQ6_ONbSQQ?AR?BUBEXEHTADZGJZGJJ8:H<;G<:J>H25K69L6:N8\Lo;Lt@QpOuSq:Oq;Oz?T=S=U>UAXAZ@\_=^;\A`Ii>^;[8X8X8X6Sv9Qv>UvBV{M^jBPT0;R3;N39R:>Q:>F/3C-1A,0Q>A9(+*!   $1"?$,O,6^5Ag;HuDR{FVXhQbPaQbQaV`U]~MUX`}RYvMTtMStOTnOQfLL`HHZEDU@?UCBN>AM:=F46H;;H=;L?=M>=R?>S?>T>>U?>VA@S>=Q<;S=dDIiIN^>C_U>V?VAZFbA^Bc@c9^7\:\;\@a;\<\>_@_?^>]CcJiHh9Y8Y8Y6Ts6Nq:Pp=Qa4E`8EW4>V6?M28H04I37O8$+N,6_6BuETxCTGZJ]NaPdQeRe]hS[S[QY}PWzOVuLSrKPkLOfLL`HHZED[FEkYXO@>N>

@R?BTADUBEQ>AM:=K8;H68H;;J>N@>Q?>S@?T@?V??VA@WBAXCBS>=T?>R=C[:@bBG]=B^>C^>CbBGgGLpPU]:A_:D_:D_:D_:D`;E`;E^9CZ6@W4>X4>^;E[7A^:DX4>Y5?c;FiJk=IuGStCQVgvBSs?Pq=NuARpV?U:S;W9WBb@b7\8]>_AaFf=\9WH-3@(,B,0A*.>(,;&):'*. %    .!=$,M-6`8DO]|EVM_J]NaQeRfQd[fXaXaZcOWxLT~T[xPWkKNeJK_GHYEDTA@SBAP?>P??O>?Q?BP?AP?AN>fRRP<C^>C[:@`?E`@E`@FiIN\;C\9C]9C]9C]9C^9C^9C[7AY5?W3=Z7A\8BV2<_;E_;E^:De=Hj=If8Di;Hm>Kl=Ij;Hm>Jq@NyEVq=Nq=NpOr:Lq5Jn4In8Lp9Mv:O]6U5T3S4U4U4Rr3Lm4Kb-Ab3D^5CS0;U6?I.4B*.A*.>'+;&)5!%6$',#    , ;%,K/7Z8Aj?KxHUN\M[N]P_Q`TbXfUc`m`mO[|LVvMWpMUpNTeFJ\DGVCEQACN>?S@BQ=?N>?M??K>=L>>VHGE77D66E77I<;K>UA@XBA`GGdJJ[?AY=@dKNs\^Q<>J8:K<=I;Eb:Ca9Ce?Hc?H\;C]=DaBJX7@X7@^Y1<]5@_7A^6Aa9Da9D_7Ad9Eh:If7Eh8Fn;Jo;Jp:JsOt@Qt@Qm;Kh7Hj7Im9Jr9Ly;N=Rc9^8]5Y7Z=_:Z9X6U0P1Q2S5V9Wy4Nv7Oj0Fl;M\3@R.9T6?J/5G.2B+/=(+6#&1!#+ $   !/#>(.M29Z:BlCMvGS}KWN[P]O\SaUbTaQ`\kixXfMZsITlIR{W^gFL[BFQ@CK>@N?A`MP\FIN>?K?=I=;H<:H<:F98H<:I=;H:8M>=S?>VAA[DD[BB[??_AD]@D]AF[CGL8;M;=D57K=?M:W8AZ5?^5@_5@`6Aa7B_5@e;Fe;Fe:Ge7Gn>No=Mj5Fn8It;MK]p9Jo:Kl8In:Kt@Qs?PpV|=U>W|9R;T=WANACM?AP=@XCFQABJ><[OMN?=M>=R?>U@?eNN^DD_CD[>AY=AX=AV=AT>BVBEK9Q;>U<@W<@Z];E\V5>Z8B`?HY7A_=G_9Da7B`6A^4?\2=Z0;c9Dd:EhPo8Ii4Eo;LvBSp(+9%(3!$, %  )8$*H/5T5>b?HXbwJVyJV~O[Zf{JVamYeQ^S`R`UdSaMZwIUpIRnHOhGM[BFQ@BM@BPBDR?BT?BO@@J>=R?>U@?gPO\CC\@A]ACZ>BW<@T:>_GKjRVW@D[EIVGfCKhBKf>Gg>GoDOd9D`6A`8B]8B^Pt:Ls?Qk7Ji3Fn6Io5Iy\RoQmMjPlTpOlLhNhRmXsIdHdKhJfIcMdMcyDWpBRhCPaBL^DLZCHM7;9%(6"%2!$, $   *>)/X=DY9Ae@JwNYS^UazLX|NZ{MY~Q\Q]P\Q^Q_RaQ_O]NZvLVpJRfEJ\CGQ@CL?A[LO^KNR>I=;G;9C75B64B64H<:NB@J<:I:8K:9S@?S?>V??Y??[@@Z?BT9=gLPX>BT9=X;@X<@Z>C\=E\;E]:FiDPc=Ie;Gf;Hl@MlALd9Da7B`7Be@J\9CZ9BV7@W4>]7A[4>`9D_9Dd>H^8C_8C_7Bd;F`6A_5@b8C]3>vLWj@Kd8Fh:Jp?O}K[l7Ho9Jt).O4<[;DhCLlEOqGRVa{P[yMYzNZyNYyMY~MZO\Q^R`Q_Q^O[zLVzRZhGL]DHRADJ<>L=?R?BRX8=[:?^;B_HeEOX7A\7Aa8C`7Be;Ff=Hd;Fc:Eb9Db9Dc9DfOs9Kk4Eh4Ej6Gi4Fj6Gi5Fn:KuBRxGWh8Hf7GqAQvEUo>Nj7Hm9Jn?N\4@\4?\3?`4A`1>p>Lm:HGY{M^E).O3:^K?=H<:F:8A53A53C75G;9H:8UFDP>=R>=S>=S;;X>>fJJjQS]EI[@D\?C\;@_Od8Ii;Kf5Gh6Gg8Fb7Bc8Cc:EoJT^;EV6?X8AY3>a6Af;FgNh8Hk8Ik6Gm6Gp7Is9Ko8Jh4Eg3De1Bd0Ad/@e0Aq=NxEVrBRj:Ji:Jm>Nn?Oh:Ja2B^4AU1;[8A_:Ea:D`5@{NYh9Ep(.O3:_>FgBKjDNnFQwNYxOZtKVtKVuLWuLWvJUNZQ^N\O]Q_Q_P[W_zX^`FJVCFO@BbRUdQTU@CRBCL?>H;:H;:K>=I<;G:9B64F86I:8I87P=?Z@CS:>_CHtV[bAFc=DdIi>Ie;Fd9Db8Ca7B^3>b8Ca6A_4?a6A`6A^4?nBOqBRf6Fk8Ij5Fo9Jm4Fl3Dj4Ef2Ca->i6Ge2Ba.?e3Ch5Fj8HmM^4CU/;W6?X8@Y6>W2:[3K:N8:R:=X=@gKNZ;@\>CbBGcBH^c:Db7Dd9Fj>Kb5Cd7Dc4Bc6C^5Ac?IY7AV3=X6@U5?X8AW8A^:D`8C`7Bc:Ed:Ec9D_6A^5@nCNa5@b6Af:F_2>b6B_2>a5@k[0@X.=d8Gb3@_2>`4@]2>\5@e?KY5@Q/8T4:O.4R/6W29Y18_5=c8?i;FqNY_Y[///=8:6',9(.9'-9'-9&-9&-2%=.4...A;=5")8#*6#)3#(1#'0#&0%'1(*%('"   ,=(+O48jIOnIPoGQsJUtJUsHSuKVsITuKVvLWtJU}S^VbQ]~MYN[O\MZ|LZwKXrJUlIPcFJU??_MJ[JHT?AS<@Q:>O8YGJn[^O:=N7;Q9=\BFtW[]>C\\^3>b7Bj?Jc8Ce:Ee:Ea6BY4>^>GS4=dEN[k=Ie6Bf8Dl:HwBSl6Gp:Kk5Fl5Fm7Hk5Ff2C^-=g7G]/?Z.=Z1@R,:V1?Z1?]1=[0;[1DiELnFPsITzP[tITtJUtJUsITtJUsJUsJUuKVxLW{LWNZO\O\N\{N[uKVjFNfHL^FF`MJ`NLWBDT=@S<@R;?O8K69O9=O6:S9=eHMbCHhINX8=_@E\Y9>\`6A^4?b8C^4?b8Cd9D^4?U0:Y8AW6@Z9CgFPX7A[:C\;EiDNd:Ed:Ed:Ed:Ea7B`5@e;Ff:Eg9Eg9E`2>_1=yKWjY1DiAH^4;c8AlMW^Y[,,,7(-U+:c3Co>Ne4Bc0Ab,?i0F~SdTMP***9(/U3f*@c,?X(6P%1X0:N+2>$(7!$4 #;),*    2!$@*.Q5:^=BhCJmEOqHS~T_tJUuJU}S^{Q\uKVtMWqJUqITuKVwKV}MYP\P\~LZ}M[vKVkDLeEJ_DEWA?_KIYCDT=AT=AT=AQ:>O8CW:?W:?Q48Z=BZ=BeHMW;?T7;Y5=a9D\3>\4?Z2=\4?Z2=X0;X3=oLVa>H_H^:DvR\tLVg;Fg;Fg;Fg:Fe8ChW+;X.=S-;Z6D^7D^5@V/9S.9Q-7N,6T4>R4=K/6I.3J.2O05S27X4:\7=[4:a8AiLU]YZ2229,0W0<_2@a4Bb3Ae4Df2Eh2GsIZVNQ)()9(/W"6c)>W#5Q#1K".K&/I'.D*.6 $8$'2 #+!!   !/!@*-N27`>DgBIlDNqHSyOZtJUsITvKVuKVrIToKUnJTqLWqITuKVxLW{MX}LXLYR`yKWqHPgDIdHI\DC[FDWACW@DT=AW@DT=AP9=P9=L59I69J9M59N37Yi;Kc1Dc/DwQaWQT&%&:*0X%9_(M7:I69L;>Q?BT@CQ;>M48N37V:>bHLU=BN6:S;?gOSS<@R:>L48Q3;U3=W5?V4>X6@U3=Y7AT1;Z4?_6Ad:Eb9Dd:Ee;FfM_3B^2A]0@W*:Z,<_/?`/?Y+;V)9X.=P)8R.DtNViAK]3@X,BS=AI47M8;XBET>BM8;M7;T8?U5>aAJgGPT4=U5>P0:T4=[5@b7BlBMgJj5Bo;Gl8Eo;Hg6Be6Bc5Ab4@d6BvHTd6BpBNg;H_4Ce:Ia6E^4CZ/>X-CW7<_>DiOSe_`ӴMFGeJNlqvRY`8DV,;V);wL^\EOrpq|||(''1 'R"5Z':T'8M&4O-7J,5A&,C*.;$(>*-H68- "   $3"$B*/U8=vUZjFLjCLqHSrIS}T^xNXvKVuKUsKUlJSuW`rR[hEOpKUsLVuLVwKV}IWIXLYvHQoGMiFHeFEcGG_FHgPTdLPYAEX@DT<@V>BT<@O;>J7:L8;M7:T=@U<@V:>O27N69K59L69M7;Q;?S=AI37K48T8@Q1:S2<]=FT4>R3bBKe>I_4?j?KgIc8Dj?Je:Ej;G}IVt>Ls>Km7Dr=JqR6;V8>X9>^>CiNQi`a~~P=?{[_oLR[4@X.>[2BnM[;15BBB.,-."R"6U%8P%6K&3K*4B%-=")=$)<&*<'+J8;- !   "1"#A-/Q9:]ACdDHiGMlFMoGO\dzOWxKTvHQwKSqLSlKQlJQmJQnJQoJQpJQrJRxKU|MWyKUvKRrHOmEKgAEoKNeIKdIMgLOcGJ_ADfFJ`?CeDHeGKW;>W;>S7:W:=[=A_@DW8\8BX4>X4>Z6A^:Ef?K^5B`6Db9FeNo:Jr=Mk7F}HWpa6Ab;G^8D^8C\5AX1=W0=cV.:X2=Q+7U0;P,7K(2H'0G(1C'0A(0C+3=&.J3;ZAHI07K18I.5M18P3:S6=\16hfg1./.V+9P&3I#0H$0H(1F)2R7?G/66 &3%,(!    , ;**J56Y@AdIJhHMnKQpKQvMTxMTvIPOWSZtMSmIOrNT~Z`qMSmIOoKQqLRvMT~SZxNUuJQsHOrHOnDKkCIbBFcGJfGJlLPgEIhDHhAFmEJqNQcBF[:>Z9=dCGcBFW6:Z8=`?FP09K,5R3Ml;Lv@QyCTr=Ns=Nt>Oo9Jn9Ih5Dm=Id4@g7Cc3?d4@a1=c4@c7Cb@wvw...+#%8"Q)4J$.F#-E#-@!*@#,N45 (-!/"-!)    )5&'D11T=>dJKgIMjIOqMSsMSuLSxMTRZV]rKRnJPrNTyU[qMSoKQpLRrMSsKQuLSsIP}SZyPWoELrIPjBIeDIgHMfEJgDInINnFMmEKsIPlFLdAGa>D]:?eAGhDJY5;[8>Q/7U4=Q0:R1:^=FX7A_>HbAJa7Bf7Ci9EwGSk;Hd3@c3?f6Bf6Df4Ei7Hm^9Cb=G]7AaD,4;$,A(0C'0E(1A$-F)2I,5O2;N1:O09S/9S1:m\aë|||(((0-.&B(N(2A(B *?(@#,8&3#2$5 (/#- -!#   $3''@00M99]FFeHLqRXmKQpKQtLRwMT}RYwLSoHOpLRpLRmIOrNTrNTqMSoKQqKQsLRrKQ[a}V]tMTY_iCIhELcAIhDMkENsKTyOXpDNnAKj@IiAKg?Hc;Dc;DdQx;Mw9Ku8Jr5Gq4Fq3EvAOj=Id8Cb6Aa5@c7ChV1;V1;S.8Q,6O*4N)3R-7X3=S.8L'1M)3K)3H&0N.8N2;G-5A*2>'/@(0?#,>!*?"+C&/D'0F)2G)2O/8T0:W2>`FJmPTlMRnKQoJPrKRyQWwNUqKRqMSpLRnJPqMSoJPpLRnIOlIOoKQnKQtPVuQWkGMtPVkGNjFOe@KqKVtKWj?KpBOn>Lo=Kk>JmANj>KnBOmBNhI^8Bd>Hh@Kb3>l6Cp:Gl6Cp:Gs=Jn8Eu?Lv?Ov?Pt=Nt=Nw@Q~FW~GXzCTFWx;M{?Rv:Ls7It8In2DEWr?Mc9D_5@a7B^4?oEPi?Jd:Ed;Fe?IhCMZ5?Y4>]8B_:DrMWW2U0:S.8O*4P+5P+5M)3I'1H&0F&/@$-B(1F.6C,4>%-@$-C&/B%.A$-A$-?"+B$-G'1I%/J%/K'1C$,C27?9:,**(&'/--+%'!6#G!-C +B *>(9$6$3#1#3&0#- , +;(0/$    +!!8,,F66O=Mo=Mp=Mp=Ml;Jm?Ni;Jl>Mk=Lg9He7Fd7Ek@Li@K]4?`7B_6Ae;Fg>ImCNg8Dn;GxEQm:Fg3?k8Di5Bn:Gq=Ks?Os?Or>O{GW_prPat>Oq:Km6Gr#*6#(3$)3&+1$(,"(/ :'B,D".A!+>(E)2R9AC-5:'/3 (/$1$0#- )*"   *!!6*)A32J::U@ChPSsY]lNSkJP{Y^xTZtOUmHNmIOqMSpLRqMSnJPlHNnKQnMSmNSmOTnOTkLQkMRbCHaAGf?LgaZ5?X2=[6@Y3=P+5P+5[6@M(2U0:Q.8E#-L,6H+4?$->&.<%-D,4H,5B%.A$-D'0G*3G*3L/8I*3R.8R-7K&0I$.Q,6L'1E",F"-I"0H!/F .E .G#1F$2B"0?!,N3<[FLYJOH>A@7:H?BSIMA392&/#,)'   ) 9--=0/G87R?BeOS`HLfKOlNS}]bwTZvRXnKPnJPnJPlHNlHNrOUoLQlIOkKPjLQkMRkMRgINdFK^@E\=CcNl?Po?Pm;Lq_7A_8Bd=I_7E`7Ea9GkCQ}Ub_lsKYb:I[3B_7F`9G^6EZ2AX0?Y1?]7Cb?IX5?V3=T1;S1;T2U1;V2;Y5>W2&.?(0=$-?"+?!+> *>!*B%.D'0@"+D%.H#.K%0L&1K&0U0:S.8R-8^>GdCNV4@I#0J$2L)6A"/=!.Q9BRBHHCEomntprOCH(*($      #1)(;10OA@M==Q>?ZEFbKMfLNoQSmMPnNQoORnMPmLPkKNpOSzY\rQUjIMkKOiJOjJOhINsTYjKPgGLcBHf@JmDQlAOmAOnAOpCQi:IrDRsEQm@Lg;FhE_;C]:AZ7>]:A]:AW7T6FX5@Z6B\8C[5Ac;G[1>W-:]5@T.9Y4?P-7V4>N.8R3H.6H&1P.9B#.K1:SEJdabggg???OOOݭ5).%(!   -&%=43NAAI;9N=_:@\;AU8=S7;V9>W:?XBY>AP8:S=P99O98P99P99P99S=b7B^1=W,7`8C[5?S/9Q0:O1:R6?P5>L17X=AT9=\AEQ6:H-1N27G,0I-1G+/D(,M15I-1E(-F*/D(-F*0C&/>!*B%.>!*@#,@#,A$-B%.>!*C&/H+4D'0@#,B%.C&/K)5W.>O%6M#3N$5N$5O&6`BN[TWB?@, $>"*A *F(1WCILGH///###0//434KJJhef0"'/!:-.     *#"3)(B54G87O==cPOhQQgMMjLMoPQnOPlMNlMNhIJiJKmNOkLMlMNpQRnOStTYjJOfFK`@EjJOfEKbAFgCLhBLgAKf@Jd>Hd>Hd>I`:D^9Aa>D\9>^:@]9?[7=_;A[8>Q38Q6;R8Z3>Q.8Q0:L.7M1:V:CI.4M26N37U:>P59I.2[@DJ/3D)-B(,B)-I/3N48K15I/3L26C(.?"+?"+?"+<(@#,C&/@#,@",A$-?"+B%.A$-D'0@#,?"+C"-N'5K#3N&5J"1J"1P)8`HQokldcd312#H*2H)2J/7PAF~}}ZZZ...*()* "'C=>hhhC=?). !!   !)!!4((?10O>=VCC\GFcJJy]]sSTmLMnMNkLMkLMgHIhIJjKLfFGiIJjKLiINkJOnNSdDIaAFmMRlLQbBGa?G`H]9C`M59J26M59O8=G43J87SA@L88R:>I,5L-6K*4Q.8R-8S+6S*5W.9Z2=_9CU2R7?L27K/4K04N37L15K04L05B'+=#'?'+C+/?'+E-1?'+@(,H04?%+A%-?"+<(;'<(P2!*D'0I,5C&/A$-E&0H$1I$1M(5Q,9J%2N+7WDK}~KJJ3/0*E'/P3C`@EbBG^>ClLQgFN\!*?"+M/8?"+= )H+4H+4B%.C&/B%.@#,B%.D&/B!+D#-D#-G&0M,6Q2>dKKiMMjKLnMNzVX}XZtNPmLMjKLgGHjKLhIJeFGdEFcDEcCGcCHbBG^>Ca@E_?DiINbBH\=E[>GX;DY;DY;DZK8;iUXWCF@,/B.1C02D44B42K=;;-+>1/B42?1/<.,B42<.,;-+<.,9,*B42>1/?1/A.2C+3E,5G,5P2;L+4L)3P+5O)4S+6`9CR/:K+4E'0J.7J/8F+1H-2K04G,0J/3H-1G,0@%);#'7"%=),6"%7#&9&)=*-;'*F/4C&/?"+;'B%.@#,= )>!*A$-@#,A$-B%.E(1H+4E(1E(1@#,A$*D'-I-3L/5F)0O5;F<>@@@0)+;$+L1:B*2N>DPMN444)"#A03@-0E25:'*1!UFIlhiihh+**- ($  !/##<,,I55U>>aGGlMNoOPrOPzTV}UWwOQoNOpQRlMNjKLjKLlMNfGHhIJgGKeEJbBGaAFcCHaAFpPUaAGY;DW;DY=F[?HW;DS7@W;DW=DL7,/=+.A/2<-.NA@J=;<0.8,*;.,9,*;/-6*(D86=0.5(&>1/C64C75=1/=,/B,3B+3G-6M1:P1:M,5P-7T/9a9DT.8K(2O.8I*3E)2G,5G,3B'+H-1E*.F+/F+/K04L15G039'*7%(5"%6$'8'*<*-6$'B,1A$-:&>!*Q3== )O1:?"+A$-E(1E(1E(1K.7J-6E(1T7@A&,?&)>%(?%(>%(>%(J36C9:PPP3+-:#+TC[;@\H9;F79E68G8:@14G9;G8:A13<,/I9;WGJ@03:*->-0B358++9.,9/,=309/,@648.+:0-2(%:0->429.+3(&4*':0-7-*@13A,3F/7@(0V"+>#):"%:"$;$&9!$>&(Q;=PGH}||<583%B+3<'/M?DYWX0/0 9&)N;>bOR@-0>,/`UW111201/ !*$  + :)*O9:V<=fKMiKNgHLkKNqNRwSX]b{W[sOQvRTpNOlLMlMNlNObFFbFFdIJ]BD]AD\AC[?BX=?W<>Y=@Y>CVAM:=J8;J8;E36I79D14?-0=/0;0/>32I>=7,,8-,5**8-,0'%3+(1*'6.+5-*3+(0(%.'$7.+91.5-*0)&4,)0(%4-*0(%B45M9>O:@K4:H/5I.4J-4Q18^;DQ-7W3=L)3M)3Q+6S-8O*4O-5F*/C(,>%)<$(=&*<&*<'*@,/9'*>,/H694"%4!$3!$1"4$8 (8':(?#,C%/N/8[:DB",F(1G*3@$-<"+9 );#,8!)5 %4"7!$8"%:%(:$'>*,\QSGBC-8 &;%*QAE[YY.-- 1!5%>'.4%TAG~111!#-! -" $    *9'(R9:[?@aAFjHNjHMoLQoKQvRXyU[vRWwQTvQSxTVnNOhJJeHH`FF\CCZCCaKJV??^HGYBBR<;S<=V??V?A\DHX@DS;?ZBFW?CL48M6:L8;I69L8;S>AO;>N:=M9L16V:>P27M-4O.8N,6O+5X2&*:$';'*7%(:),H696#&2"2"3 #3 #6#&6#&7"':"*5%@'/I.7C$.I'1I'1I'1B#-D(1M3;B*2M6>5 (3!(7%)3 #1!2"6"%9&):(+XLN߇* 9"&=&*SBEXUU100!3$4$9 *R>Ek`dkkk433(+ * &   ):()M56Z>Q;=[EHT>BP:>L7:P:>P9=J48I69N@hAGuIPvIP{MT{KS}MU{MUyLSoJMlKLgGHfIIdII`GG[EDWCBP=74C<9.'$0)&+$!-*'+$!.'$://9+-:+->+.A-0G14I04D+/H-4K.7H*3U4>\9CP+5M&1N&0L(/E(,E+/C+/;%(>),3!$9(+=*-9&)8%(6#&?,/D14=*-=*-B-26'6'9 )?#,H*3F$.G$.B *B",>"+@%.F.6B,47#+7$+2 %7$(>+.A.1C039&)8%(4"%VLMҒe__RLMVUUԘ[VXG@B:57644`_`rqqea`4*(2&%4)'?53+"!!   (9((H02X;aPSO>AJ8;G58L:=F47F57J;=@35E79H:\GKK48J26F-4K09K/8R4>X7AI&0M(3L&1I&.A$)E+/G/3?)-XDG:(+9(+7%(4!$2"7$'3 #5"%8%(1!6!&7 (8!)9 (< )A",K)3D",@(B#,?"+: (4$8"*2&2 '1$D14WDG?,/<),8%(7$'7$'/!OHIgff~~~øƼkjj.('0&$2'%+" 4+*   *9((I12X:I;:E67QBERCED46E68E68C36D57>02=13?35>24THJQEG>24<024++2*(1*'.'$/(%4-*.'$.'$+$!1*'0)&81.1*'4-*3,)6/,1*'0)&/(%0)&/(%-&#-&#+$!.&&9/16,.OBDdUXsvaMP`JN>'-C+3G.6I-6H)3K*3Q.8G#-F$,E(-D*.C+/C-1?+.7%(6%(2!$4!$3 #0 0 3 #6"%3 #>*/7 (5&:!*=!*B#,T3=G%/B *E&/B&/H.6;#+3%3&4!(:(,>+.>+.>+.<),:'*:'*2"0!)>89:99'&&)))...---***)))---///...+++***))))))""",*)-#"0%$* ')#"   !. <)*K23Y:D68C68;02@68=45:123*+8/04*+7./0((0)&0)&.'$/(%?85.'$*# 2+(:302+(3,)/(%0)':30>74/(%1*'2+(1*'2+(-�)&+$!-&%1*+0()PFH|oqorK8;=(-=&.A)1C)2P4=L-6M,5M+5B")C&+>$(;#'='*5 #2 #/!/!6#&2"B/2;(+5"%4!$:'*F26>'/;#+?&.>"+? )D#-A)B!+='C'0E*3?'/E/7?+3@-4D27:&*A.16#&7$'5"%4!$3 #2!$,!.!#*"#>::755.--)((''''''(''(('(('(((((((((((((''! * 0&$0'%.%$2,*  %1""@+,N45Y<>bBGlKPpNTmKPnJPlIOkHNhGL_BD`GGYBBQ<41;1.;1.:0.D99E:;F;<<13A57A68=13=236-.@9:C;767234-.MCDXLNykm]LOL;>9%*<'.?)1@)0F+4E(1I*3E%.C#+B%*?%)<$(9#':%)2"5#'.1!3 #D14B.1:&)4 $7#&8#(E.6:"*N4=F*3?!*?'B)B *H)2I,5O4=T[>@bDFjMNhIKiIKiJKhIJgGIfGIdFI\AC\CEXACP;<\IJM<=J9:D75@42F:8C86E<9<30;3071.>76;43<43?77:22>76G?>>656.,90/7..=437--:11@76?65.%#0'$/&$/&#,# 3)&/%"8.+4+):004**1((.%$5,+6--4++0'&2*'6-*1)&3+(2*'4+(7/,<63931=44C88I;*-=+0<(-?).YAGN3:D(.G)0G+0A(-B)/L5;9"(9#):%*3$8#(4#7 &8!&;$*7!&@).?(.;!(;(?*?*F%0I&2D,E ,B)P/9U6?jMVlRZH09>'/:%-7")8"(6 %4$3"4$4#1!3#4$'3$&5%(2#%1"%-!,() ' -% .'"1)$2+%70+>50RCCF66C33F75WIG:-+3)''    (8&(F02T:=Z=?aCCfHGdEDiJIiIIhIHfGFeFFfFJ_@EbDI[AET<@Q@H77H97RDBJ>;82/<63>85<63C<9<52:414.+=41?31=1/<0.=1/:.-;/-;/-;/-5)'0$"1%#1+)A53H=;?333')5(*9,.F:<9./5)+?349..9/,8.+5+(8-*=20=207,*6.+:20F<9.,I54G00M34D/0I7:>,/>*-D.2@(,@&*A%)K17B*2>'/C,3F/7?(08!)8")7'GE+3=%.?(0B*2:"*8 (E-5?'/6&6&6&4$5!%6#&4!$3 #0 //-.&!.(!1+$71*82+60)82+?61F55F35C01B0/E546(&1%"$   *:&*I15V:>kMQiIJiIImLLjIJmLMnMMlKLkJKhGKcBG`@EY=A^EI]FIN8P<=I86L=;J=;E97A85A:7ZSP?85@85=52<41@85@85?74=41K@>G;9@42?31?31>20J><<0.J>13>136(*<.0@24:..?319,*;/-=1/K?=I=;=1/<1/9.,<1.D53K:9F32C--G00>*+F58>+.@-0H25Q8$-C'0=!*?#,C'0< ):'9&?*B+H!0L%4E-C+B*C+D+E"-I'1G'1F)2H-6@(03$8 (;#+7'8 (I196&4$4$2"1!-4!$,,.1!1""6.)0*#1+$3-&5/(71*:4->51B32@0/B21@0/A214'%+    +;%*K06W8>eCIgDHlGJnHLsNRrMQpKNoJMnIMoLQkIOcBH\=B[?CR9=R;>P:=P;42>41A64@63C96]RPsgeaUSMA?D86E97?31B64:.,<0.6*(2&$4(&7+);/-4(&9-+=/09*,;+.?/2>.1>.1:+-:+-;,->0/5'%?1/?1/D64D64?1/D75A42@20?0.H86L:9D10C/.;()>-0<+.B.1='*?&*;!%G*/M18P6?E,4=#,>$-C*2A'/>$-=!*@"+A#,D%.M.8> );&>(='D-D,D,J"1E-G /C+C*B*D",C#,?"+;!*8 (1!?(0L5=6&5%1!3#3#5%;&+E25;(+N1.?20A548,,"   *:#*K/7[9Bf@JiAInFLqGNzPXsIPnELnELxOVqIPpKQb?E]>ZEDcQPWGEI<:H=:D97G;9G;9E86TFDM@>D75NA?thfnb`A53<0.<0.<0.=1/;/-<0.C75<0.4(&>207+)C64I:;>,/<*-<*-@-0D25C03=*-C23K:8A0/E43A0.F43B10F64VFDM=;E43O?=F64F64?.-<+*@/0;*-A/2I58C-0I15?%)C&*C&,B%.B&/N1:L09D(1@$-B&/B$-C",F$-A *N,6K)3<%C",A)F.H!0G /L%4D,G /C+E,H%/L*4G'1B%.9'3#1"1!7'6&7'5%5%3#D07=04C:;B9:E<=B9;H?@B9:C:B?'.M09Y6Ae=Ii?JpENrFPqEOrFPuHSnAKpDNpFMh@F_9?b>D\;@X:?V9>X=@`FH]DD`IIZEDR>=N>=QCAL?=K=;UGETECJ;9G97I;9PB@pb`|zfZXG;9B64:.,8,*:.,>20>20?31:.,4(&8,*7+)5('8'(@,/?+.@,/@,/B/2E14C/1C/1@-,K76VCBL98L98O<;L98K76F32G43P=M-6H)2I*3I)3F'0G%/F",N*4I$.G#-H$.F#,B'E ,E-J#2D,G /U.=C+I"1K%2G$.U3=aAJeHRC)18!(.4$7'6&5%2"=%-=%-J9?OKL~|51-+#!$(#  '8 (G(3V2>e;ImANrDPsDQtDQrCPtERp@Mn?Ki>Fh>EkCIgBH\9?X7=W7_CEW<<^EEbKK[GFWEDUDC\MKRBAJ97J98J98RB@XHFRBAZJH\OM\PNPDB9-+7+)>20F:88,*<0.=1/9-+7+)8,*6*(:.,F97P?@>(,J48C-1G15C-1G15J48M89H32E0/P;:\GFWBA_JIN98L66P:9R=1/=1.<2/9-,;*-D25;'*:%(=%)B(,M05B#*O-7T2HcCMeHQM2;;#+6'2"7'5%2"0 D,48!)C28\\\EEE999666666666666666666666666555***,+(&"    #3$E'1W3@i@NqDRsERsCPuDRxFTtCQrAOsBOj=Fh=Dc9@c;A^:@[9?Y9>Z;@Z<>eIIgMM[CCV@@YEDO=M:9L98N;:Q>=I65H54H65F86UIGTGE=0/F:8=1/?317+)9-+C64E97=1/4(&5)'9-+J<;C12B*.H04L48F.2O7;@),A)-C-.F//N87K54N87L65R<;M76P88L23Q::H32A1/?31<2/A96I>=A14E36:%(5#:"&>$(?#'@ (G$.H%/G%/G%/J'1K(2H%/L(2M&1M%1a9DO'2S+6H +G*F+B*C+@(A)J#2C+P)8Q,9V3=K(3S3=Q4=VDX9>ZN:9Q=K65J54E10H66B12A00@/0C23<++C23?./=--F86C53C42A31?1/>0.;,*C0/A*+@)+A*,K46R:"(F$.G$.O-7J'1F#-G%/F#-P+6Z3?Q*7K#0M%3R+8N&3I".Q*8F.B*D,M&5J#2N(6I"1F-G!.^9FJ'3O.:B%07'6&3#/<$,=&.3#:#+0!3$@/4icdzyy211655211! "$ ###$ !        #0 F&0T,8h:Gm:Ft>J|ERIVxDPtBNp@Lj=Gb9A_9?^:@X6<`BGU9>ZAE\CF]BD[AAX??U?>VBAO<;L=;K;9K76S>=L76M87Q<;M87G21G21H13D.1B,0D-1C,0D.1E.2@*-=)*C10D32XFEL;9?-,C10B0/>)(I43I43A,+A,+B,,D/.D/.D0/M98XDCUA@Q=-06%(5$';#(G%/G%/B *K)3J(2I'1H&0M)4L%3L%4K$3`9HK$3C+E-P)8L%4K$3K$3C+A)?'A)C*D*J"1A*C!/@ .8(3$4%6'3$9"*5&J3;3$?+2_RWustECC(/'!:1)<4+>5-=5-;2*=4,;2)5-&'     !/ B%-S.:_3@nQ;:Q==H86O;:WBAO:9M87dONaLKJ54F10C,/C,0E.2F/3E.2J37M6:E.2>)+C10D21D21?-,A/.@.-F43G32M87L76C.-C.-I43N98K65O;:T@?O;:N:9R>=N:9P<;Q=N'6F-M&5L%4D,H!0H!0O(7S,;H 0F.H!0B*G.J!0B);%;&>+:)6'="-3$:#*R:B8!)1!2#M;A`Z\GEF(*.$ 7.)>5-?6.A8/@7/=4+@7/9/'0'!( -%&+$$   $/!A$-N+6Z0Kq?KsCOtGSgP27S8BU3.>4/=2-<1,:/*&       !0!B&/J(3Z3>d6An=Io=Ji:FoBMlAL_5@d;Ee>E]7=X4:b@F\=BT8=L37Q8?W==P87R<O:9Q<;WBAYDBR=Z:?\V6;X8=aAGX=AF04G14A+/@*-?),8"%;$(="(<$S0:K)3@(?'@(D",G#/K$3C+C+B*G /G /D,E-D,J#2I"1F.A)K$3I"1M&5I /C*>'=(9'<,:*2"8&9%8$4 6#S8AJ=AMLM-(*#,/ 6*'5*'3)&6*(:.,:/-<0.<0.5)'1%#      #.;!)I'2S-8`4@l?Je8Cd7Cf:Fb9D[3>^8A\6=c=C^;AU4:]?DR6:S:>S:>W;=W<=fQPT?>A,+E0/F10D/.D-0A*.@)-I26C,0A*.A*.B,/E02B//N<;E21F43SA@E32B/.I54K65M87H32U@?O:9O:9O98S:9U9:U9:X<<\@@bEEY==[>>[;?eBHtPVdAG\9?Z8>]:@]:@YO(7F-E+B)@*F#1D#1G*7A%2:)F(1>(E&/>(F'0P4_3>d9E_5@_6A^8B[7AY7?Z4;]8>Z7=P/4\=B^CGQ7;ZAE\@BW<'+<&)=(*?,+Q?>N<;B0/F43D21E32H43O:9S>=M87N98M87H32Q;:bHH[=>Y:;Y:;\=>bCDY:;Z;<^;?]8>a`;A]8>`;A_:@Z:?O49X?C^DHQ7;N48F,0@&*= 'A *C!+=%G%/G%/F$.K)3^:FU.=B*H!0D,L%4K$3G /F.I!0O(7G /E-G /J#2E-G.I /E,B,@,=*5%>".B$0F$/;#B *;#=%<&{###2,., 9%)=./@31MB?7-+0#%=03I;?1#&.!$("   $,7'D&/M+5V/:\3=Z1;d;Fc;FW2=V4>X6?`;BZ4;W4:S27U6;T8=T:>S:=W<>W<=L:9G75H75O;:I43C.-@+*D/.K65H32M88G03G04H15A*.>'+@)-@)->'+>)+>,+>,+E32H55D21H65P>=L87I44G21L76K65U@?aKJT>=^BC]>?[<=[<=\<=`@AW78X9:Z8V4:Q49V:?bEJO27N26K/4C&+D%,C!+A)G%/Q/9P/8O-7B!+J&2F.D,A)A)Y2AP)8?'?'A)J#2E-B*J#2P)8I"0F.I /E,@*>);)<,Y=I<);#:":!;">&8 U?FE>@! !, >*.>-.:-+9.+8.,1#&-#1#'* %"!'1(*"    -".!9#+E+4_?HS/8V1;[6@Z6@W5?W5?W5>Z8?W4:W4:S28Y:?Z'+A*.B+/='*:&'>*+C.0G24D/1F13Q<>R:>J15Q9=cKNTA]?CW6:[:>]<@^>A_>B[:>X6:Z7=Z5;Y5;Y5;Z6T8(A!+='>(R2'='=)=*8&Q2<:#:"9!8 =%=%E&0<',7$(E13@.-<+)6&$7('8+,0$%+*4()"&(%!#    !(0 %>+2F,4K-6P09U4>T2[;@[X9>X8=V6;W7S27O/4H*/E(-@'+>'*='*=(+E.2;$(>'+<%)?(,=&*<%)>'+A*.B*.F/3U>B^GKJ37E.2H15H-4D(0K.7U8@G*3S6?T7@X;CT5;U4:Y8=Y8=Y8>\;AcCHY8>V5:b@FZ8>W5;[9?S27U4:X7O48O48M26D)-K04D(/<'<(;'8$>!*A$-> *=(E!0E 0?*@,?*?+A-?+;"'A)-A)-K26F-2N59?&+%-G*3M.7T3=V4>Y7AT2CR27R27W7Z:?\BP59K04E*.B'+?#)B%.;';':&?"+D'0= )=)=)?+?+>*<'C.A-A",@).?)-;%)>(+='+F03P:=?&,?#,9&C'0G+4:&9%4 4!< )5"7#4!< ):&2:#(RDE<65VTTrqqsqqmjjnhh=11%$&(&2'%HCBXWWDAA& $!     )-#4"'A)0F+3P2;aAKZ9C[9CU3=R19R17R17R27R27R27S38V6;Z9>dDIY9>\'+=&*G04G04@(,@)-E.2C,0@&-@#,>!*A$-C&/F)2P3T7;T6;R49T7;T6:T6;Z#'E)0F)2B%.8$= )>!*B%.>!*:&C#/=)>*>*>)K*7G&3F*3F14J58J69@+.9$'6"%C/29$(9 (=#,6$7&8'5#6%4"06%-0//6&O@CMHIwwwٖ.'%,!9-+." (*QIHXWW    $(1#:")C(0H*3R2;L+5P/9P.8Q/8Q07Q16Q16O/4P05R27T49X8=_?DhHM\),B-0A+.<%)D-1B+/E.2@)->'+9"&=&*A*.C,0C,0B+/A*.B+/D,1J/6O2;?"+A#-= )J-6]?IN1:L16O59L15N37R8!*@",B$.M0:E(2= *;):(C&0A%.E,3=*.;),@/2:(+<*-9'*:(+9%*<%-6&4$0 7 (7'SKKK! 000gffTRQ$3'%-!-!1%#?53nkkVVV'$%,%&HAB     "(3%9!(>#+B%-K+4L+5K*4M+5Q08O/5R27U5:P05S38O/4U5:U5:X8=dDI]=BT49P05P05M-2O/4S17M-2K+0G*/D+/A*.B-0A,/;%)9"&>'+:#'8!%9"&?(,;$(A*.C,0?(,<%)=&*C,0G04I26A'.E(1>!*A$->!*B%.V9BJ.6@&+E-1N6:V>B\DHQ9=N6:J15M6:J37I15K37^EIS;?O7;P8R7;Q6:M26O48R7;G,0N37C'-?"+A$-;'O2;@#,A$-?"+A&.B)/=$*8%D+1?%,@'.B(/R=B=-09)+7'*4$';,/=-0F68A/35'1"3%/!0"0"D.6B+3. 3%F08. ;%->(0KY9>Y9>Q16V6;U5:S38cAGV6;L-2H,0D+/B+/<&*>),@)-7 $J37E.2;$(8!%6#;$(@)-B+/>'+:#'J37J37<%)B+/C(/> *?!+A$-A$->!*A$-?"+D+0G04C,0N7;H15H25G15I37K59J37I26J47L6:F04L6:WAES:>O59R7;N37R7;_DHM26F+/E)/R5>W9B<(J-6I,5D'0:&<"(K58@*-@+-A+.C-0?),<&)<*,B469+-7)+=02:,.2$'1#%0 $/#1%3', +- /", )'0$&/#;(/G=AutuVVV444+!9.,>65{{{966"2&$G;9(2&$aZY}||yyy322     &*0"8!(=$+G+3M/8P09M,6P.8O-7M+4N-3O/4N.3P05P05Y9>U5:\'+;$(=%)>'+<%)?(,?(-?(,>'+=&*;$(>'+=&*=%*;#(P6=D'0@#,E(1E(1?"+@#,@#,J27C.1@+.H36D/2I47G25K69G25G25E03G25G25J47H36N9340$&+!-!#:,/:)0)+ + ),!()D29-"%,!%3#)B:=AAA.--#1&$6-+YVU=<<%* $UMMcbb.--    '+2#D)2J+4T2[9AW8>P06Q27P26S79K/1M12T6:^>CW7'+<%*8!&B+1A)/M6#+G/4?)-E/2D-1D/2F14C-0E/2D/2L69G14C-0I36H25E/3L6:H14P89J14I03L46J13I12D+-P4:E'1A#,=)F'1K-6B#-?!*B(.=()=()7#$:&'<**7&&9))2%$4*)1''-##.$$*!!(+!!0%&-#&&%-"@05+%3$(0!%&"#6(,>8:;;;+((&1&%5*)SNNRQQ%  #E=>WVV*))      %0";+E%2O)6X-;W*7[,;]-;e5DY(7`1?gBNQ09\C]=BU5:U5:N.3M.3I+0M26H-1G,0I.2C(,C)-C)-A)/;%,7 (8!)?(/J2:?(0=%-@&.B%.C&/H+4C'/E(1@#,?#+="+H08D+47'7';"+<#,?'/E.3A*.J37C,0D-1C,0H15H15C,0M6:H15A*.G04E/3J37O8U0;W3Q16X8=S38H*/D)-J/3F+/C(,F+/G,0Q6:H07:"*5&8!):#+<%-<%-9"*B'0G*3B%.A$-Q4=E(1D'0B%.A'0B*2<$,5%8 (9!)8 (6%;$)E.2N7;A*.C,0D-1H15M6:H15C,0E.2E.2E.2F/3J37P9=M79L76C.-H32E0/Q<;F10J43I04B&/>!+<)?",E(2B%/C'1C)/>''<('?+*9('5'%3'%2'%0(%/(%*# ,%"&#"# !!!)&! $"#'+ *7+-?:;WVV0--"'$+ =35ebcԠ?;=*"3%+(!JBE{z{KKJ0//         $0=(I!/R#4]'9g,?g)>n-Cz:Or2Gp/Dn0Dl:Jf:Gb7CW1:]:AO04T9;N44L/2U5:U5:W7K04F+/E*.B'+E*.C(,J/3G-4<"*;!)D*3J19H.78'C*2@$-A$-?"+;'D'0A$-H+4:&?$-;#+7'6&6&A(0G.69!)<%+@)-F/3A*.A*.D-1A*.J37N7;E.2G04G04F/3F/3F/3F/3K57S>=H21S>=K54[FE^IHJ54H15@'.G.5G.5D+2Q7?G.5C)1A)-@));'&<)(;*)4&$2&$0&$-%",%"%' &! !"$$&$#!#(/"$+ D89LFGzzz523!$(/#%XST]\\'?48IDE+++/..     )5 @'O"1['9e(=l*@p+Br,Dz3Ks,Dv/Gt0Gi-Bi3Eb0@^1=^6@O.4N15L03P15[;@X8=Z:?Z:?\U5:W:>Y>BK04D)-C(,@%)C(,A&*A%,@%.C(1G+4B&/A%.>#,@%.@#,= )?"+= )<(>!*N1:B&/;!)8 (7'9!)7'7';#+:"*@).<%)?(,H15H15C,0E.2C,0F/3F/3E.2C,0F/3D-1D-1F/2F02M88G21M87E0/N98]HGG21B,-?(,G04G04B,0F03A+/B,/L57Q::B-,>+*8'%3%#0$".#!+"(!&(!$ ""$%&($")*- "%4(*UNO?==!!$)'VOP[WXD;Y,9Q,5O/5T6CY9>S49P38N37K04H-1D)-G,0I.2A&+E(/M-7T5>J+4B#,Q2;E&/E&/?"+@#,@#,@#,<(;'C&/G*3: (8 (8 (8 (6&G/7=%-8 (@).8!%E.2Q:>I15M6:H15E.2B+/E.2E.2E.2G04G04E.2E.2F02K65E0/I43F10L76P;:J54B--A-.?+,>*+F33<()<))C/0I44L65@+*>*)9('4&$0#!,!'$"%%-$#,!#"#&#)(+ 0#%*&%)JACDCC&)- ",!9/1vtt\YY,,,221   $.:#E+Q#3])V:>M26K04G,0F*.@%)E&.G%/K)3H'1G&0K)3G%/J(2C%.B%.B%.B%.?"+= )<(=!*7%7'7'7'?'/Q9A;#+<$+:#(=&*A*.D-1B+/G04D-1G04P9=G04F/3E.2I26K48G04E.2G13J54I43G21I43O:9S>=P;:G42A0.A1/>-,=,*?.,;+(;*(?+*B,+A,+>+*7&%5'%1$"-" ( %##(!)""*!%$(%$#+ /"$/"$,!- ")%*1'(pmm0//834 + /"$2%'3((D=<~~~XXX""!---#"!"%"    #.?+I#0P$4Z(;o5Nl.In-Ix6Sx6Sq.Ln,I}8U3O|/Kr+Dh*@^);]2?R/9Q2:M-3M-2S38V6;V6;V6;W7',B+/C,0E.2H15C,0J37L59]FJJ47G04E.2G04H15E.2E.2M79N99N98L76R=<`KJfQPVA@I65E63?0-@1.;,)8)&:+(<-*J85I32@+*@-,<+*6)'2&$.$",$!'.&$+$!%## +" 8+,'+ 9-.3&(.!#.!#0#%2%'.!#5(*.!#&'&(!.*+*()  *- "2&'3&'/$"?98?==$$$---""#     +:'F#/O(5Z.>d0Fd+Ce*Dm0Jr4Nj*Ep/J{8Sy-Gx,Es,Co.Cl3E_-X6<[9?V4:Z9?X:?O48M25M15O47S8;cHKR7;R4;N.8M,6K*4M,6D!+D!+I&0H'0I*1D$+C#+F&.J*2D$,A"*:&7'5$6&:!)<#+;"*A(0O7;D-/L57YBCK45D-/F/0G01J35I34H35I57K79C01A/0@/0H66F21G43F10P<;o[Z|hg[GFN=;TFDJ=:B42B528*'9,);.+B20A.->-,;+*9+)6)'1%#/$!-#"1''TJJ?662()/%&#$%2&&*- !3&'3''/##0$$7++H;<4'(3''*+('%'(#%+-!"2&'4('<0.4)&3,*.*)-+++))$""$& )#"   '3"?!*H&/P)5Y,Y3<]7@W2:\7?bCHN26Q58M04K/2I-0]ADZ>BO39D'0G)2K,5Y9BR0:I'1O,5I'.J)/[:@V5;C"(E%*C"(@ &<&?$-F+4@%.208.+;.,?.-D21D21K87WED`NMP>=G87C64G;9=1/>1/9-+6*(5)'7+):-+;.,F975)'2&$." +(/"%;.1H:=,"(()(/#"-!0$"E973'%7*(8,*8,*>211%#0$#5)'.! +)(0$"0$"%)+/#!1%#2&$F:7]QO3'%," %&(,$!0)%60*.("'"    %0!;!(I)3R.8T+9]/?a1Bb.@p9Li1Cj0Bv8Kp-@p,@o,@m-@i-?e*<_'8\'7W*6W.9Y0;c:E^5?\2=[2=Z2;^;AiJNP15Q27M.2Q26O04U7;G(/H(2E%.M,6O-7N,6I'1I(1O17A&*D)-B',E*.G,0>#':#@$+@$-E)2T8AH,5N2;L09F*3G-0L43J20N65P87I10I10I10H0/S=E32O=D53A53D86A53=1/8,*5)'4(&9-+NB@7+)8,*0$")+)- !/"%>031$&+ * -"/"%1%&0$"4(&;/-2'%1%#6*(6*(:.,7+)6*(5)'2&$, +)*0$"(), +0$"4(&5)'7+)D864(&-!6*(5)'>20QGE2*%61*2-'+& #!   !*4#E*1M-6O*6S+8W,:].=g6Eh3Dn8Hi1Bj,?k,?j,?j-?p5Gi/Ah0Af1A^.=c6Bc5Bd7D`3@_1>d6C]1=_8Aa=DW3:Z6>V2:Z6>^9AQ-5O,5M*4V2$*A#,K-6U8AH)2J,6J,5I,4J-1L12L22J/0K01K01K01K01aGGW@?I33D/.D21A31A42OCAJ<:B0/H65N<;H65H54P>=`NMI:8>20?31MA?B647+)5)'6*(5)'7+)2&$0$!*##." A54,!, ."#."#1$%3&'4()5))5)'4(&6*(9-+3'%6*(5)'2&$5)'4(&;/-, ++*, =1/4(&*6*(C97NECOFELDCKDCPIHKCAPGFI?=4('8,*=2/3,&/)"2,%/*$(#1-(+($&$!  %,<&)C(.F'0U1g-?h.@e->b):b);h0B`*<^*;b->h4Eh4Ed0Aj6Ge1B`2@lBNd:EY0;^4?Y0<\2=W-8Y/:U,7[2=T-8S/9T2K+4N-7K*4N,6L,5J*1L-1P15M.2U6;O15M/3N/4O25U::L22L44I44E32B31B42L<;C10G54D21F43M;:^LKL:9H97E86?31A539-+7+);/-5)'." &, '%*&&3'%(2&$0$"5)'7+*5)(6+)5)(5)'6*(3'%3'%3'%4(&4(&2&$1%#2&$5)'2&$?31/#!)(C75MA?KA@F?>40/411BAASRRa`_edcbaa\YYYUUTML@645+(:3-3-'71*/*$(#D@;HEALJG  &.;%(E+0I+2K+2Y6>Z4=h@If;De8Cb0?`,=c/@f0Am6Ge->b(:b(:b(;j/Cm3Gw=Qt:Nk1Ek1El2Fe2Bf7Ej;Id5C\.<\.S/9J)3L.6Q9>M9*-?+.I47A,/F14K-4J&0O,6N*4O,6N+5S/9R/9Q.7X5=P-5Q/6V3;S08S08R/7N.2L00Q66N44H11E10D21C20D21E32G54J87K98ZHGH65P>=H:8B64E97MA>;/-H<:>202&$++*'&0$"(+."/$ 9.)=2-2'"9.):/*8-(C84PDBG;95)'<0.6*(/#!6*(6*(3'%4(&8,*6*(C75-!4(&, >31SKJ955WVUӵнwtsE?K98M;:L>^3B`3B\,<^*:a*;q7Il/Bj)@s1Jt2Jo-F{9R?X};T?Wo5Ij3Fj3Fr:Ml4Gh0Ci2Ev>Qk2Ai0=xBOd4@]3>__7B[3>V.9W/;Z2>V.:T,8X0204(&1%#4(&7+);/-5)'8,*=2-A80:1(6-$<3*;2)B90D;2=3-C74?319.+=1/K?=8+)3'%7+)A53<0.2&$5*'1%#'." SJIMJJUUU)))MMM///HGG655544^^^|{z2.).(".("#     %&.! 4##<)*D./S:;K02Q24U47[8^1?[,;_-=h4Dh2Bd,=c':b%9h+@e)>e+?n4Ik3Gj2Fd0Bf5Fj8Iq?Po;Lk7Hn8Jn9Jk5Dc.;c1=`2=`8CX5?N.8@"+I(0a>EQ.6R.6\9@W4;O,4M)1S+6c8D_4@\1=]2=_4@`5A\1V-9]4@`8D[2>\4=X39\8>Z7=S17O05J,1K.2@'+='+9$(@-/D23F75D63L>;D74B42D64:.+:.,;/-3(%0'$<206+)2'%6+(6+)3(&6+);0-9.*7/':2*6.&:2*>7.@80ME=A92D;7QGCA73=30NEAB853)&=41B:71(&4+(/'$)!$;41A>a3@Z,9Z+8^.^7Db9F\0>_1?e5C`0>b4@a5@[0;^6AW2C'2@)/@-0D65H>9NE?F94E41H74M?<9,)<1-5,(0*%1)%:0.5+)5,)3)&5+)8.+0&#-% 6/)5/(5.'60):4-93,?92:3,:3-ICPOO%%%00031+?>;111,**0,*tsr[[[!%60-       #-9&%F11H00H--K..O01U36V.8X-:X-:X.:`5Aa6CW,9U+7_3?Z.:Y.:X/;O)4Q-8O-7N-7P/:M,6N+6U0;X/]2=b:EV1;M+5J)3F'0V5?gDNO-7L*4M+5N,6M+5O,6T,7V+7^2>a5B]1>Z.;X,9V+7Y0T-8R+7T-9U/:U.:[5@a;F^8CcI)3H,3L37K56G43RB=N=9O;9I53\KHJ:78+(D95:1-4*'7*(4(&2%#2&$0$!4(&@314*&4-'60)93,71*@:393,3-&2,%60)93,:4-82+60)4.'4.'0,&-*&(%!(%!'$ DB@ooo```222(&42+<:8000+)(#!#60-942```421      ",0<('D..D++F++M//O/2R.5S-7S-7S-7Y3<\5?T.7V/8c;Ed=FQ+4T09P.7I)2G*2K/7I-5O2;R4\1<\1<[1W2;T/8S.7T.8V2[8B_=F\:CU3=;EEE//.*( 31)1/(:96000*('!#)")"/(&_\Znnn321        !(/! 6&%E10O:9C**Q55O23M.2N.4O.4N.3N-3Q06S28P.5U39W5;M-3I*/F+0?&+?(,B,0>)-G15S;?G-1L.4K,1T39V29Y0:c7Cc9DJ"-O*4[9CK+4E&/B$-E)2@$-<(<(A$-D(1L08R5_8?X27a;@Z5;V38Q16M.3R69H/2O7;C.1A.0=+,:*(:*)4%#6&$6&$@0/H97>2/@:382+LF?:4-5/(0*#/)"/)"93,=703-&5/(:4-5/(3-&/+$)%"#   !42.:98BBB+*).,$20'.,$874000)'&%%' (!,%"[WUzzz.--     $* /#"2$"?.-@,,@+*K32G..F,-E*-G,/K02L13G,.Q68D(+H+.K/1C)+@(*<&'8$&6$%6''<--<,,H67@+,E/0C+,H-/J+/V08a6Aj@KL$.J%/P-7B"+@!*I,6N4<: ):(D*3J08?$-B(0C-1>*+>)*>*+;&(?+,>)+?+,=)*C,.@*+G12F01D./J45K56B,-A+-P9;O8:H23I34K56I24Z=?W47^9=e>Cc;AY08^4=_4=Z1:W09fAI[8@L,4M07I.4I05?)-;((8%$6$#7%$5"!H54H65<.+70*B<51+$-' 0*#1+$-' 1+$3-&1+$2,%4.'A;44.'2,%3.(" "$!41.<;9WWW+*))'(&-+$985000*('#(!)"*# /(%UPNdcc**)       !*! -#!2&$2$"8&%<('I33Q::G10A,*E//I42I32?)(D.->)(B+*A**=(':'%6%#1#!1$"/$!7-*>2/7*(7(&C1/B.-D/-J00Y4;Z/:X-8L%/N)3P.8H(1> )I.6R:B9!)5%>&.?'/5&6&3"$`3@X,8V+6V+7V/:N)3R.9M,6H)2F,1A,,?+*@,+?+*?+*?+*A-,8)&81*?92-' 1+$-' 0*#0*#-' ,&-' 0*#3-&3-&,&,&40*+($,)%'$ @=9+($/,(FEC775! 20(970-+$::7000+))2-*3,),%"/(%0)&VPN\[[xxx,,,        %&(!+" ,!4(&@/.B/.H32A,+A-+H52M:7H63C0-B/,F30@.+>+(@-*F634%"1$ 3)%7/++$ 5/*;3.2($4($>0-;+(H63L65M*0X-7V,7[4>O+5B)@ )>(;!)4%6&:#+.0!2#/!*+#,$ ,$,% /($3+&0)$@62;.*9-)G:78,(9,):-)8,(6)&9-):-)7+'9,(=0-8,(?2.I83N94R:7U9;Q16U/8\3?^2AX+8U&4`2?[0=S*6M'3N*6L)5N17G00D.-D.-D..A++8#">('8(%4,&.(!,%0*#71*60)+%60*.("+%+%,&/)"/)",&84.8510-)-*&+($&#%"NMJOON'& FD<&$1/(;;7000*((4.+,%",%":3070-YTReddccc/..        #(0%#6*(=/-9*(E43A.-?,+;(&<*(@.,<+(B0.L;9G63>-*@0-:+(9+(2%"0$!5*'8/,5.*1(%0'$1%"4'$8)&F42I53D%)S-6gAJ]:BM+3C"+@");%:!'I285%6 &0 *+("#-'$-'$("82/:41-'%2*&8-)6+';0,0%"1'#6,(8-)7+(G86@1.I:7D52@1.J;8:+)N=:A.*T@>M55K03L.3Q09Q.8Q+5P(1b:DX2;Y4>Q.9O-8L*5L.6J14F-0D+.C*-C*,=$'@'*8%%8,(0%!* -#/&"+$.&!1*&)"& '!("' (".'#)#*%"/*(50." 2.-ᮮA@=:92&$31*<;8000*)')$ +$ +$ JD?@95UQOGGG321      !%.!4%$>.-;*)=+*J87?-,:('=+*?-,?-,?-,?-,L:9G54@/.7*(5(&<0.?310$"4(&.#!7,*4&$B10@.-3"!6%$7%$<*)?,+:!$H,0R59J-2H,1E(-?$)@%)C*/E-11-,()+!,"$!"%<442++,$%,$#1*'.+(-&#.'$:2/1)&>1/J76L:9H54=*)B0.I65<)(A.-B/->+)@-+E11A--B-.E/0A**G..K12T;=N49G,4G,5G+6J.8N2:I,4D(0F)1@#+F)1C'/:!&8#$7%%8'',,+ &#%"5--3,,$""%)!"+$$a__秧ba^IHBTRLEDA000,*(=7271**$A;4HC=OLI---/.-      %")2"!:('<*);)(A/.:(';)(?-,C10<*)G54D219'&:('E43;.,D86;/-A530$"." -!4'%3#"3! 6$#7%$5#"6$#4"!=*)B*,>#'A&*H-1I.2L15@%)B'+;!%5!-/)- ,!)) "  ##)!"-%&+#"*# )"(!)",%"3,))!0$"0=,*7&%3"!6$#6$#4#!8'&>-+?-,<+*D32A0.=+*A0/>+)@,*A,*C-.B,/C,2B)2?'1A'0E)2C&/A$-B%.>!*Q3,+;)(<*):('@.->,+;)(9'&D21E32>,+?-,D32=0.@42<0.5)'/#!0$"/#!/#!A1/0;)(9'&8&%8&%6$#<))@(*>#'B'+D)-E*.F+/@%)A&*: $6"10 ,/ "6)*'( )!"!  "%*"!&+$!2+(+$!,%";41$." . 2$"-4%#0!. 4&$6'%2#!QB@>/-=/-E64;,+5&%<,)@-*G42A..?*-;&,7 )2%3#8$5!4 5!8$>"*<(@%,42<&+0 $*3%(/#%#!2*+912     (&!OOM\\\{{{"""*)'$-' /)"1+$solQQQ000% #   $*.6&%7&%=+*8&%8&%:('?-,<*)@.-:('B0/SA@C10=+*9(&6)'6*)<0.7+)-!2&$/#!+.4""6%$G54<*)@.-8&%6#";"%?$(F+/G,0E*.D)-L15O48>$(5!10-7)+7*,'?78912#( !+#$ "' )"0)&*# -*'*# *)- ,0#!,+2%#8+)2%#8+)2%#3'%9,*7*(1$"7)&9(%@/->-,>+.7#*2&,!,/3/4 8$O2;4 <(5 /: (7'))+!$!!$ %$885332+**'''### '%##,&.(!0*$olhqpo$$#*)(*$&"   #)7)(5%$9('C21A/.8&%8&%9'&;)(;)(9'&7%$<*);)(A/.9'&8'&5(&?20<0.3'%/#!, , .!0!6$#3! 9&%9'&F437$#8&%B),L15G,0J/3D)-C(,C(,E*.A'+9!%1/1 #.!+ +!*!""! &6./+#$ &#' .'$$%+"+ + *,!=20.# 0%#8,*0%"-"0$"/#!3(&1%#,!3&#;-*F66:),.","'),27#G*306"5!26!33!B'2K3=7"+&%4+-( ! 6//2*+  "0.'*(!'&!10-..,++***)! /*%60)0*#/)#0*%3/+1.* /( 1*"$    "*5%$:*)@/.?.->-,I76<*)7%$=+*>,+K98<*);)(8&%;)(5#"6%$4'%3'%3'%2&$3'%0$"-!- 2"!9'&6$#:(':('8&%6$#9'&C+.N37B'+D)-K04J/3F+/D)-B)-:#'7!$2"-)*)#  *"#6./.&'*"#$"2+(&!!$3+(.%"+" '$:1.;2/@85,# /'$) %*!/�(%,#!5+'7+'>2.9,+1#%+!&/'.!1001224 8#H%39%I*7]?L9++*-#0'()"" !#%!    # 64,+)!,*#%#,*$%#!83,[UO5.'1+$2,%5/'C;1:2&C;12+#"   '-3##;*)C21F54M;:A/.;+*6((:('K98I76M;:A/.<*)H65:('6%#0$",#!+!1&$7+)5)'1%#1$"3#"9'&6$#:(';)(<*):('9&%=%(L15J/3C(,F+/D)-B'+B'+?&*?'+8#&1!0".!+-!#! #' 2*+,$%+#$ -*')"#(!*# ' !!&"1+)"&1+(4-*6/,JB>D:6<1.5)(- "+#&0!),!0.13 <(26"H'3L(78$4!:)0!- )&!' ) !7/05-."" &$'%*( /-%+)!*' $)#-'!+%-' 1+$*$/( 8/$:1%7/&-&     +.7$$>,+A.-D10F21C//ked:)(D10H65N<;I76>,+@.-9'&:*)e`_DDC433%! 1%$6('4&%5'&;**<**8&&<**@..:((<*+?,,D,/O48L15B'+E*.B'+@%)?$(=#'F-1=%)5#5!$;(+;*-,$$",!!/$%'-""**$)!&&( #*"!#!1,)50-JEBKFCJEBVRNF@9B>9=92<81A=5$ '"0*5.#3-$'#     #+3""7##@**E--L44J22YAA}}544D00D0/A-,J76Q=+*E32C;*->*-=),=),?+.B)-G,0L15H-1E*.H-1I.2A&*=9KJG<;9554>>=FEELLKQPOSSRQPNNMIFD?*(!%#,) /,$%#       !,2 D//G00L33^DDS99_FF}}766N99O87L55N87J32J22S;;J32F..H03R;?YNPkkk+&':%(B)-A)-@(+C*.E,0D+/C+/H03F.1C*.E*.I-1K04U:>P6:H-1Q6:J/3A&*G-0O48C(,J.2="&B'+G-09$%7&%6$#5#"7%$8&%8&%8&%5'%0#!2&$8,*<0.9-++)0)&# !'# &#,)%;84SPL<9372)3-%0'"H<97'''.- #%)*( %,4#;(5 9#=%;!4?%)1.*&'&! !%B;8%,)%IGD764@??uuuèba^*)#%#*(!$"       *0 7$$G22U>>K33Q77L22V==||866@--?//6++3((7''C))N01W::P23L.2Z;@_FJpmm;::5!$H*.H*/L-2F',L-2L.3F25,"#2#%I,0J.2M26E14.%&."#@&*B'+E*.E/2:/01%'?(,M15A&*D)-O6:2'()!!9*)A/.;)(;)(;)(:)'5'%3'%2&$:.,6-+0*)"! %""+)'(%!/.+)&")&"!,*&-+&('" "(#"!!)+2*+* 2%'"+ %  4$E'42B(31 ')!"<'+3!1-- &."$ #"+!3)'4,)HFC987ttsrrrAAA+++&&&+++;;;[[[ń$#&$#!      '/6##?))H11I00L22O55Y@@||HGG}wwihh@??+""F*+V56R12O-2]:@`CHdcc-"$H',S06P-3L)/N+1V7<{{{/*+D'+L.3N582//9$'C(,H-1[FIiefCCC+!#D+.?$(I/3{}IBBE32G54;)(:(';)(8'&3%#3'%3'%H@?zzz[[[##"%$,*#(% .+'QPNqqqOOO654;,/5'*{xy)((2(),! "?78mmm1$?$0L7@DAB-D.1/+,*B68(?32%$ '*JB@754xxx"""""!.../..---211332444__^~ "       )4""<((A++H00K11T::P77iPP|xxrsVCD^QR}zzHGG0""L-.L+,J(-T38ucfܥ522=#'T27Q.4L)/O-3ZAFDBB9"&H*/cNQLKK/!E*.E*.@&*N>@kii<:;(?%)_NQҔ?/.?-,<*)<*)=+*D219'&7)'7+)QIGwrqC;:?86^[XONH%$10''&0-'"""$!;84"dca֜VWQ01+A@<]\Zlkk(!#* /"%xvv888$*("-%&)>'2uzcW\?)2K4;-<%)4"+'%*&,/! ,')+?21B=,+:(';)(:)(4#"5'%5)(@985)':.,/$!.(",+ 77*22&""((31*""" "852~ ! !#00)"953$7,/."%wuv888!&# +#$ .#nhkjij)5"/*+++()3&(',...5&$M=;`TSGDC$$$211 #!mmkbbb&%!      '/3!!9%%B,,L44J22F,,L22U<'+yopZQRutt("#6!; $hQQ||CBB9''@.-=-+=-,H97wut@??3&%8'&@009..E67ebbGFF>45N=?9(*C57gee@67srr7559)+rooC45pmm><<+6!8 $9$<#'P;?uss5#%F13C329*([TSUUT)" ;1./--7-)6*'7+(E96B;4=:.63':7-0.#96+>;3#### '"20-###,''-#%wuu888"(%) ! -#kfhGFG%+,0++),*-!/!5"!;'&>*)I54=)(D21MCCHHH111##! "#   TSPqqq110  !    #&*1#"<++;)(:('=*)I76|yyGGG-"!5'&7+):-+MCAJHH.#!3&$NDBd`_0$ @4/\VTccc632C:70'%C=;DA@70.][[MML822QMM8+*[WWWVV+"".2"2!4#ZLOWWW& !/ !0$"2%#:0.C;981/910PHF/$ =4.wvu877?83<2+?5/H>8:0)5,$<4+A:292*:2*JC>#"",&#-3/TSS*(%+*%,+&)(#650:99*#!wuu>=>6(+,!4+-!3"&lhiHGG%**,+,-.3!6 #6!#9$$>+*<('VBAC/.L:9D<<>>>0..* "'"  !%#2+(-'#! MIGxww{{{,,+     &"(, =.-7'&7'&>,+SBBxvvggg'##," 3(&2'%`ZYPLK3'&3'%|xv71-1%E93ZQLmlk>==2-*0)'jfe,)'.'$USRffffee/)(2&$TNM___,'&.! -.C47]TVcab<<<#2&$5)'9-+?313'%2&$.# 5+&F=6URPaaa,)'0("4*#MC<:1*/' 6,%A82;2+F<5B;6#""0)'/(%B<:kkj998$" NMHBA?' trr[[["&'#pik  +lhiGGG'+0F/31203 9"&=&*;&(=+*;*)>-,>,+:)(N>=C<20@75trq-%.$3)";1+]ZXXXX$! ,&#~|{{zz)$"0)&IECʊ*" 0%#D<;}}}(&%'2$%8*,JBC2#%MDExxx100"0%#5)'6*(3'%1%#/$!=2.KA:IB=gfeGGG544+(%841NLJ4+$C:3@70E;4G?:#""' -/,HECggg<<<+*(++(YYV'%*$!lkkYXX412(#$\XYՍ'/#%3*+III#"2"-6#8!%N7;F/3>'+;&(7'&<.,9*(;,*7'&D75GA@WWW1..>453&(#$+ !7/-%&'  C?=\[[qqq-,,        "-" <.,9)(9)(D32G65daagcccbbKCB5)':.,]WUEB>+#+#1)"*"=83nmm;:91,*ecb+%",%":42uttnml(!&3,)cbaSRR$,! d^^lgf+,=11NII```522);/-5)'0$"0$"3'%7,(0&A70^WSdbaonn>:86,%F=7>5/?5.E=8xww443)# ' !2,)C@?ffevvu;94 " ,(#_^]dba`__JEF( spqگ><<+=&*<%)6#?(,:#'7 $6"$0"!4'%658.,." 1%#0$"6.,GC?.*#)$$&!#,(!;83A;8*$"7200*($)"5.+/*(62050--'$$("62/JFD' .%"6/,5-+('+ -#JA=HA?QHG3'%1%#, 5)'2&$." 1&"3("6,%<2,I?9F?:=73?95IB=6-&>3,D;58/(>4-JB=;74JDB@96%)"/)&0,(+*%+*%=<6.,%!!,)"<95IEA+&"2/*)�-*1-)0++/()+%&fee7010&(H:<.A*.C,07 #D-18!%8"%=*,:-,-" =1/9-+6*(5*(ZTSA??=834.)#' (!% )"!;43MJI666322&#    "+*-=,+:('@.-=+*6$#;*)5(&4(&2&$/#!, 8,*3'%8-*0+%-*"#!#!" #!#!-+#'!(!5.+-&##$81..'$##  *&"(%!# &"*#( $#%( $/' ,"." /#!0$"2&$C758,*7+)3($4*#6,%8.':0)9/(H>7;1*@6/A70G=6RHB:1*>4-F>8;52'!' )% (&&$-+#/-%'%*'&$%# ,&'gffLLL $'+4!R<@7!$8!%O8<:#'2 "/%#.%",".%"2)&/'$E?=lll<<<<91" CA974.F?;(   &UOM!!!+*))'$%#   &:/-0"!.<+*1;*);)(1B1/A42-!-!/#!0$"*-!+ '#)' *)!1/'.,$#"+)!$2+(4-*0)&+$!#92/3-)#"$"'%!@>:20,+($'#!$)$&!$% *%+"C853'%D867+)3'%9-+=1.6,'6,%6,&7-&9/(A81e[T7-&;1*8.'6,%TKE<3-B82=50_]\ %#31)*( '%.,$0.&&$$#  %!"977^[\ ,G047!%9"&29#&@)-3 0 -%#& '!.(%4,)3-*3.+ecb**)## !!..%)((',)!/)%' ' @;9===&&&"! 31.%#    &*/3"!4"!=,+;)(9'&7&%@311%":.+4(%3'$/# /# /%!+' 65-;:2;9187/,+#$#&%"#%1+',&"4-)3,(*$ %$0/*+*%#!"!# )&%#" # %",%=2/6+)6*(5*(." B649-+<1-:/(;0*7,&?4.A5/=2,8,&G<6:.(8,&C82~~/-,8.(?5.ME@{zz0/. 92/)"$  &#0-&*( $!'%-*"$"!! "#21,('&+%%=33$/-A/1J790C12E24.*#!*$ (",'#/)%0*&2-)841(($"" !!*+#55-))!53,.)&' !! !",*'#"   %)1! 5$#:('=*):('8&%6&$5*%;1+/%/$-#.%4*$3)#2+%*%1,&MHB@<5.*#,(!,( % 0*#5/($"+%)#)$!$"@=675." " &$$"31)'%&$B;75*(-" 7,*H=;0%#<0.5*(5)%>0*E727)#>0*?1+:,&<-'@1+=.):,&B4/F=9ZOK--=,+7%$5#"3#!1%!6+%2(!* ,","2(!.%"& ,'!72,0+%% $$& )#*$%"%2-'#&$/-%!%#%#0.'D=9+ .#">32-" 0$#1'%8-+1%". 3% 5("7)$<.(6'!?0*8)$8)$9+&8)$A3.>1,9,'9-(7,'/'!+#*"#!#%&+&*$+%.)"(#$$($ *'$*'#'$   %' "&##(!& *#,&0)#/)"81+'")&"751740$!  501       '*+1! -01 4""6&$0% 6,&2(!+"7.'1(!,#&% &!-(#+& #  #%$% 83,"$!" #! %##!*(!+%!+! )+!1&$9/-0&$1'&4)&2%!)/"4&!:-';-':,&<-(;-(5(#5(#2&!."1&".#+"%$$%!## 94.2-'("*%& $& $ $!2/,"!      !% %!&"%!% !#!DB>fd`^[X*($                 "$5'',/1! .0 2#!1'"+".%) +"+"( %! .*%*& ! !! !""'"""871 %#*)"%$41+&!$&&*!) ("')$*2&!K?:K>9=0+6)$2&!3'"8-(,"+!,"&*# )$ !!2-()$,'!'"!!(#'#!'%!      " +(%"('"" $"/-)VTQ630                &()0""*)-3*&( *"( '#""  "! ! $"#"   " !!#$$# ""$(/$ 1&!4($1&"/#-#.$!(*"'!#!"&""!$0+&(%  #!       %# 0-*OMIigd[XU)&$            "##&&!""!" !&"     #"&'* ) &#" "                 !!                          !                                                                                                                                     $"!                                                       tpclient-pywx-0.3.1.1/graphics/waiting.gif0000644000175000017500000000326510773624641016616 0ustar timtimGIF89a 58;79IGQXVWX[[\\] \_]`]Z_b`_aigcehfd bihmo hqjrknoo%r$srpwsttuzx{wv}y|zv,{|~z||6~8 A.&CK(L!!+M#,ȑ44y}IHiSПmFX;kP@ %K3 P F" B '@)A&"M&qFρk"4?ԉSMQG2hM*hSH#瞒w~Ë"JB >\@GG>B% ȑ44y}IHiSПmFX;kP@ %K3 P F" B '@)A&"M&qFρk"4?ԉSMQG2hM*hSH#瞒w~Ë"JB >\@GG>B% 瞛}Jٯ[ukkbX2@,"#Dw7Q?"[ϺX MVJ~ӦMG'Dɵ5KO~6l0\hm'@D% \^^8NimBD*^={޼y!` jGr&b6L4iܹs6БƑvt)rE$}mqO9C *J6ӊ}]fh ʕRegKgAD|=yyy6mc3 RLd ҡ SRgY@kMĺ(PJc],K@DJߥP&88#"ց bDtRLI =իz~]-k"*{wj%pyr{h.X2ڄQ***W< &ܲeK{bY"CDJq̣ (6Ika{~J^ b|W[\̔2쌣_ŲdD^^^FvF#X{M~;kŲd i S֧֭ٳ-KZ tuRs&3 DT _DDD58(޿ƿbsm5C}aڷ"W;XZZZ[nZONN{mWj>q"CHOTJUH/Ϝ9su]ay*!eZC1>~Ub"Rr Ddw8~Ey i Zi&8S "n)0~$$3ZD '۶m={j$?NDu䡇:gDU><3Hi(Zk93`oJuq)".֭[.$qb9?\ꫯ%akSt&v1$!%UJ&"jB\_ij " .1?d ̜4MWWHQرxO.Op@<e2u\ qJY kCma:s];Z&軕(ҏWi?`6n UJ#5Ei^5n'&\ zLJ} vGҫ )5وJ*O^ڑ c:3"lC{buz.3uu&eu n@ ԨQU .t2.e5. UJ} q4`)0scBns&BT,>E,xPHɻ@jkk^ZG߿ŋR7$S#W_zׯ/^dg0NWXqyf{ <HADp\DR;Zi:$nֿ)aLPJI'OED3R4R~,],fs1Ukxʵ֒؅k*,,Rc8tr2>O&%7S>a(+]2r9l6*t ;pӭOmhhXA[Rr;Y (Q@)D<|)%tE[T򦦦G^z%)y|~g^x qbEӥ݁.!k֬9۹DSLBp ,T94ðaL2 <:h?1%{FDիW{ӥ 7[fͿQi"YD` #lIY̧-݁AhU[jT6rss/ŘNYgRNkR f̔U2Ѱ[OX)5:8Kɛَ@.콏,$)%_bT-ܲttJ577J`ʼyn3)uև#4oC7f.Jnطy_cc>}.+++*.\=*c`pJ̈́)vwbADȑ#kN>=|CBzFc D6"*&Q/iuuQ:sIe+Dkq̓ME wyy)F*-%~B-QkWX/J`߾}pcjٳg߳{Ơx%a#Bl/%?gKxf"뮻^_hѧJ7[C FDiUf2(1fϟ?a wdl:`K"9sӒ%K>WJa̘1nQ=dȐ"ϙ&=OD r>:d;H;`<޼|OR̘1cyYYYonkڗ_~ugHGHO.biMHkWXQ)=@II"."QOp^) e bIjo\r-ZRHƑ|I_|S-Y3[v`~e`wGTrAm]9Rz_ns~%kXL6TRRȑ#& /=GLv+^#"I J>&fZoMe[⁔RZ=~pҍ)Z򹹹g-[nDCL3:S%"ƍ:qD mF33_py.R1|ݞ1S7K)7Kf{"yj_qoһdÆ *PSSICZk KY2ҳ rݻWn۶/vaX夗o:%4d{HO[i*8Nz Tf `H|G;w\aP 7L}vW2E˟;w* Dk>}NH>\ڭJ_&0sZXe[e˖)t}_=wt,]8kHСCǎ{kͿL$~bI{^'"򩟛!KdoN:u%"^paԨQyiҸ @Ec=v[ccsmTrK6 %5O֭[K>MQDAM?~}f3l0swgڵkLjo#oWqX:nf TD>ӛn)0C+bJT_wرc{?y䵉IY gfΜ74K ( _EZ) VCF0.NM'e 78.R0hn@hGDVi.Adт\>E )? ߿L}:p:P~HDCDiD"}'@yWzN'\IDV|E Yԉ(3F<ߪ4@NHGAd5%Vٍ?}o%9xޗTv0x"\U_bM8nwWְI"2"[ qqI(Ʋu܇mO Py Ķ4 gED˺i8i 6d2ؖ1k ~ OG|y ø>hx8C%??AU+8N^탹 ǩ׽]}^I^"W]h>oHDl+''~FqP՛JBȀd NTkm5eS`9ل6_/2a "3r@PUUɓ8^<^h+ buG:y`z9?v,N9JDTI :"rx,q0H$>:e,d|Se1 aÆ}ݧN4IM<$E+<0xXm[O.ZHǏ_n-\ ?,gRX8*LԩSƍW_SO=U 8 "˚w(-<\W%"s0t„ l2ݳgN4铚qF n.l z!uuu[10  bY>S v>/"baS>CW]uW\qo/ , eeea0HFƎK$!Ndd2iRDX,޽{I&tuuL&q] C"2E=EDU<ؿBd2 =z4> tzÞ/"lƶm(̞=3<1c0zhFQ<U7"RBYz5Wflڴ.8]]]rh$|8N-q:ew q:t( .d j8CUUÆ K/+dE࠿޳gb18XX,iB! p`0ȬYY+V|r֮]dyy\%>Llkmی?/Ν;bq8N9;$n<1MٰaCѤlH:{ڒڵ E>' QVVVzW\|>O.#b&afA'ɰ}vz-˙9s&3f`Æ lܸ|/ʣC9 555ɨQhoo' !2 1uT>y7,,! H$rE,lHZozӴ]%J֭[ ÜviL>vAKKKFF)k_Uˊ':;;/"ۇ!.ra{QVVF(q <#LHGG۶mxODrqO4:bl'%%P$xA:;;<˲8x뭷H&"PC2eʡ}cc!I4%g͇~ȪUhnn.!nmgmZRr H 7պ*)!"Q^^N"`*3f`޼yD>~faڴi|̙3z,?;8cm:AQ)>/FD0 3k,jkk)//'D0 |n VprRUUUhzA'ϗà7EjW TnM`80 /^{gۘ7o TTTPVVeYݻw]#f!ʯ_M6cǎ* \}TTTI:T4{q7`A1 ;C*b…3aÆ ;w.ӧOg.} ƠVW3իWH$f8駟ɓ, &pUWSO^=ә̍ʤBUcr`^Y]dg4$,It'˲J4wFL6;3`0Xyٿq뭷 |Iy:::HRFDT7\W~ΌF׺WsØaBp߶bT[㏳v>OX0 5k^eY$I$DAWa~UM~ު pЖ[wR&}7)'߆aӂ޿!Ͳe^|E.\Ȟ={~ "|0iiiaż;;zxj ê'7ekVhl$)@rE,| ˉb%jzbtvvfĉJhTUr\Ioijj.Nq]˗3{lDzbđ_'(L2߮B) P5!+K|z6v;<Ӽ'J=qrӓ@U, >O3k֬>{˗ݩI6-Z0"޽{9!=!`ԑ&~PXknOL@~Bn~@>;͕9.=$`f{2?殻g!Ji&W&bugOK mBL:3gRWW5}{=z)֯__K$d2bBUe˖1k^ō7kQՂXJf]$ݝ\NW8NRVG-q۝2 =thp\ /f ovryY|9uuu6Κ>  ذa7o&DvCR__O]]SLa}49 /J:&I]`q!",ZJԍut)ϼm_`vv(LWK~h/ڜ:h֗JP3" n*3N gf3f`̚5 &Ku-Dò&-˱n:VZŊ+Xf XvdÇ/3yd.r/^\r~uAawKVV=´v*ÆnU눛&جVs5(nSm-~ރ}Uç*7}mNx Byy9 >aÆQ]]Mmm- 2|>_UW֮]K[[Xb= ݥӧ㏳r>d6JpӽA,|e  uP9)ß@$Fa‰.]<jK7 hTƏ,P iWߺ/#mHwd`u_0|6l~#KU?.4T qu$_/8sWc+mTA}NUMş6s6}~aGWuOz!zwF2e 7pMMM} 90 S^˷)-7UPwiw@cՂĢ|61E"7Ԉ|*[jB4$ضm8ٳ;X|9\y]IW) ]=#*rsLY˧Ki̾W{ u:ԽO9FCM7@U[n2oa:m4]dΛ7OyJzMS^}A]ݐ2y5`w@x`ø@0EGgO4JA]>߁8:l^38d6gqolwcɴiU`KӰęw$)X,X@SSS1' y A<}Pd][xY~dz_r0҇3`)!\PB杪 ,C2AѤrX񄦿\.4@bȵ]q{5şVjʅ:SǟZf̘m<裴9 5Կ x/l<63ϟ3M?O$(9Qaoj1Z/stTRH QRHAv!c9ew*"Ig~e1n,A8fĈlٲ;vtQ~!Pᣖ5&hÔvz1N8 ./oH8F8 O1mG3u!!>(۫'+G >p.wVbeHl޼Ѹ5`3NeJn/ \|%W)q`s_wUT+|Y] YB!;(8|l'TyeSkޛ,Mt5ە,9CcTJ4qgUA@P.-86DB(_Ï|*"0 ӧ!]CYS&B4$vH*JZgm1U!r7m#j~2rATt3 | ?ɲxi!z'| !ʅn 𙉅9?2++\UH_,3 2.鯟C;lSשo|4kAFO՟. XeY'cJYhIȆs8g\!.mgu+͓>+s> ת"Rmuv]Lo R~xKI# #ueAb Reѵ`O2qY{.?~uB>j ~Kyղ~<]w}br/(}.`®-7~@_/WXUu|]=0"RSSɗ9y3Yϙ,l {>dZo*kMA^;8Лn^qYX +eg#E Hh{UwDò< \8"eJyD /c)e&#ߴI`,?}ʐ3 Jqi2)ORƗNSH?>/"+~73.,wК1#,gNa)5rX!t|̠J&RU3gPADUDd#П=⇮T8fr("AH~V0i6}9;ڔ[˴Q-[#!3 ¦ B]JGTeO3"ĉJO0cl-v835C:Uۓ*,zlw"R =Vߟ3򺨰r?ޥ$GQ  ?UʽƷ ꊮ,Yv}@DnOڶ\RS._{Uw<;]__Ҟ~B!WK+MiO(~)xg}ޢJ r{$$ߺpYvLr;|~nǒD2b~`[;Ĵ#`ŰMIpƩ~l+|&M|[^ҙл2 A`0ΫoLC.~kș ]eOR<ů#>X*X[_)ֈ*at!>zMn|铞K=g;c8 ӹ(m2Kޱ ~!#T~F^9RgUs[$2dWX$p0ihwV.ΔM{&:\DKؖs@FUNLKU5/8xCh8IENDB`tpclient-pywx-0.3.1.1/graphics/throbber.gif0000644000175000017500000000337310773624641016763 0ustar timtimGIF89a 򺺺444ėTTT! NETSCAPE2.0!, I)KͧJJ5URK(&05+/mbp z 1;$1CI* HCh`Ao"3qT5\8aBdwxG=YgwHbvA=0V\\; ;H0t%HsrY™ ,bLv|?4BvʛPu9+& 2x& k& U] vo opraT&!,{ 'e7\l-)S7@&4+`yTSL\:=Jk:;eĈ8cA8Oj@b/+:{ tyt#|- mN qK!,lI+8b̠y h*Zp=3`C`B"pX 9bPB`Z= 8>u,St"ΦOT\um|; 8~*!,xIA]GeAPb)"!s BI М V 5q((X2=,I n#&AVq5t sny\)_g|r5!,gD+8[{`&y_hI)(L "+gN8l5"LA .%@%O@8NgL+Ƀpus/ jȩjVj c7 I!,\0t p hQm6Tqmx( 6'sa@`]-lz0 _g ir!` !,s ءXP\|)pWʄQ稊G.}!*1p v;Tݩ2 X )|f%9`}0PFd~ezGw);tpclient-pywx-0.3.1.1/graphics/mousezoomin-icon24.png0000644000175000017500000000117610773624641020652 0ustar timtimPNG  IHDRw=gAMA abKGD pHYs  tIME'-ϖIDATH9hUQD(&FqbK!+("^K+-,ą4.qC"&yF#Mlrps??2Wad сf<п7`//J8E3NF7b Zzq)Mxؕ{!NNi:Uq qs~*븅_E3hiM zQ_9 -W{(}hjp} ?d|_a sաO;] =vW(:~%c!ؖwqBEe 2MQN]*؎a!vDCbҫUXuaM֏QNUU)z{ `7E+2}-MtٕgaIv[(Ov% onLA<Ճ*e|6Wħie^d^~RmK=Mj *IJe T$RL~*+l=9oL?lҀ.v2+(bEFjك 4h*ڴ(̤lQHa8>G|sgfVig{;mV _Y9n߻@$3;55YivۍxȚ6ut [4vtW<2eC1+RX>+BD4^\(qq eJwT&na]+&.֣=)&+)vTTR)2㸄 ҋGyg8ПXjY8eJ_h`&؅+RC-">HɎ7:* ,0aY񮤁}33 -=;P+u0'6]C^*Zٌ-y?3w5n!"bySIhBce2<{Mhr9oUs:2[`FeUu$m IENDB`tpclient-pywx-0.3.1.1/graphics/tp-icon-32x32.png0000644000175000017500000000414710773624641017323 0ustar timtimPNG  IHDR }JbtIME- pHYsu0u03rgAMA aIDATxW{P?c/ ,FG0c&LU:ZQG4USciMibئaL[lh뫃jLju3"F@yײvOϹVlOo~߽{^{>Jd2!5>-LR:͋6Fy6ưX,!)Fz3AKEvٶn TI*4g0NNs٠khʯzOkm9쉤w= |}` tMzNqpm0_h6ΠMZ;=YܹçҥKƍf!gZ{{X{Kg~3fٳgfL1 |QYY `E+ɱ2f&> ۂƱ14ڌX(m,H~hV&ۄ޽{/b0;;add̙3”l0E (W XjXqٲeh"8^O¼>Frz5P… ʕ+@juݻ;n^\o7Zlj:Z( :N,RdqEz~0a('mS7y+Y ?G4u4 PB-(頗0<ݎLB'`{P=Ef˳Yl <MɋEEEuz^*T1p8r-̛7 !22/+l7iG'"c>77n޼ ϟgBggDhmmM |!sA;v`pՅt"V@~A!RsrrQR~߾}HU z4P!=%>cpדIIIt@AFFACCڵnRRRj+̐\(ҵ=OQ(x@ DbNP3"2zݖ;0"łqh~>Y`n^c|NH,_k߆Mg@T!Cpf$n١ jpu(//6:vMuu5twwk6xnx)3dMeV VhvMl^Mϗߩ&JE2 .ਐ~r?iϩ7 N>fYa~W96ۢ__mĔ8[_cK@łVUk9m)}vLMME LMwWLU[1)N?tZl}q|=/Si/{޹(We0~@Dp.EK6%8QyGuÏȕkw ¹mzosMT0遙Ϡ+?c&OK@=)b3@2]:;20ųy3vש nzD'>_3cgGvßh@(&q.+I6 gl 6>{I"4=`o6IENDB`tpclient-pywx-0.3.1.1/graphics/unknown.png0000644000175000017500000001146410773624641016672 0ustar timtimPNG  IHDR>asBIT|dtEXtSoftwarewww.inkscape.org<IDATx]{P& ZBQDPE>PlmEڢ3gQZ+2کڇ2TtQ(EU:([  @Hp9g;s~ws>8c%` pہ{{{;v,=B!}}} 2 ꠦѣG v0l  aȑ~NGGTTT@QQܽ{222 //:::kz34CQQQחr`D"JHH@^=S8lܸ]*HKKCo3l ```>!HВ%Kh/aG333AwjB֮]K{ ڢ"سge7 `aa?~Lw]Ɓh/ބ]Frr2,]絶B^^B}}=z  9L0OBBxb~:%ϣ/ٴi%oaKK :}4;w.1bFiD"*++N5T#;Ы8;;V ?..ؐCOOڵ d2HIILΝ;U~-Z2&O?O joo']555͍rQUUih/!A.dB̙3`y{{R555!cccW pPCCi޽{}#_PPe?~<­DzzzܹsI7^ݢS\\\H~N7ꑓCV$QvVhhhXQfhjj"eK)a cƌ2vX}ڥ `aaƤlLM($RSS!55U%Ԕ@nbt_'$$ mkkk)D;$zCcc#466Bii)ݮOÇz=h5qqq#Ղ hσ>233IW˗/*֭[0sL8qd2 p(֓R-y!;zjԤU#W_}E{^XC毌?SW N;ݻ iK ;vP̬HW)VVVիTw:s[w^٩KJJ"᠘^}G4djjJqńL&C۷o;{{{t]鴷}=R{ mΝo$ȑ# p+ tUtIC٩qϟGj 5??3pT*EǏGaaa? @bKKKB巶Xt 3 pܿ|+WC+++t1BƜ$r`/^ ###uF"JJJ@ zCp/ڿ?tZf K.aP|@X,F666Xgee=zV2 a݂ #=5 dgg#+cǎaffF`ܹs)#ɓ vmmmXNХ`]_F كJJJMTT|(U_%V.\ p\TUUӦMW]R6 Jf̘;v5;#srrT>|ܨr={VoϟkGCxx8dddD"7o¾}ǏOy8q 0a|OZ~ d4iL m3͛6'OY //,YBM&` dgqx|j*裏@ {nn.ծwww|+,Xu_+?`kk vvv _|'q{JPPP vE3QO(w|>&޽8Sj䗦vXA/񰱩 +wy<!V=b1vZr {%@ׇD C]"7jiiQ񹱱>| ===lgbb\bwEpӧ*eή7oT褉rr9CPP{!N]]+||>ˡΝ;/͝;JϞ=#?#Ng˗/Cmm-g6mhmm|8}4TWWCmm-|: ^~ K,'''}}}ʂBBYA@@8;;TVVŋָzL Yr%JLLDF!!!A?(>1f@]W`>hkkWWWغu+iFL.zFZZ?v$1b D))) I$$JQYY~:Zbr:`p1, K%Aۇ ׯ|Ф向A{)nptn~F t_~%o j(w/ UGˤm㕇$zu ?4jXYYku@|S|FhllT ulb zBƐ#@QQPH|Kʔ+КATŭ3gT+5#@BB+ pSkii gϞH]Mɓ'2y0 _d6P(BDDx<044͛7)O tbП˗/WƥP(ТEv#477l$ɐB@o~NyER\\AEH 544 jhh X?8''a`_puuwwwJ(--b² vvvp}>d24iX[[@picc?FIR -D"ޘTD֐ yyy^^^xDx?O厥(IENDB`tpclient-pywx-0.3.1.1/graphics/mousezoomin-icon16.png0000644000175000017500000000063210773624641020647 0ustar timtimPNG  IHDRagAMA abKGD pHYs  tIME(IDAT8ҿ+q%ɏSDdh QIUѦ+))H{lݻ~}w4'@2@^aS\7q]DaxVP4#L1pyЊeĖ1 x׍Z@xLKc,61F|3U\ %h|xiߙ |$-R:ZZMC/TItb$ at" )2qH>I;#IENDB`tpclient-pywx-0.3.1.1/graphics/icon.ico0000644000175000017500000000427610773624641016114 0ustar timtim ( @PPPW)Fwww222Td neee y,8_AAAI{),  duBM  ZZZ r((( YAlnnn(/ z1R ^9C!!!999HHH!C_ 5 Ym zQ ~ q@V---~~~UUU ") N^ FuM# j \v  ^ ===jjj rW&;d$$$555DDDMMMzzz]]] ^0Pf   3V>j  vBp%+ {P \S +++///;;;FFF|||JJJpppWWWggg  )L  6777](:b Zk .;b """###%%%''')))000111:::>>>HzxxxCCCGGGoooNNNkkkQQQTTTXXX[[[  % {*E o 6667^9_XW-H[U@W3okElD#G\C7aoI|}mAA^ |ߜQS~? ff8V("5gg ѳt0] ZF$8xr <: ݊T2_Y紬zcsN.*16=М);vhpJ;9ؚ,n`ɲ:!b•uؚ>R|tqBMe8:%᪘bds|+N+8|+)J/ jJh {w:yfgOs:cLx{/4g88i&PKf8||K' fՠؠ +f˙+|͚8|8???tpclient-pywx-0.3.1.1/graphics/tp-icon.png0000644000175000017500000000142210773624641016535 0ustar timtimPNG  IHDRabKGD pHYsu0u03rtIME 73IDATx}KhSkĜGD#6` F-V8I^@t$Au piu "(j>ziiQi =Mr~'uҪ `^=`$l|px0R[{@P\n ~\pi* *)J􅂋@RJI{{;`&`&ai#X!D 1::J8fpph4JP S,LLLPV(vHX'm8XaXE.#NSTD"LMMu6 W_RWrPaL&u](eH$lIDATXõklW;>vH"Hl$TBA|/HMԢJT"Qh`A`P;q^7cױ׻^̽q'[79]͌9%f 634Ew4CI=WӻѠ d45*TK\i1m]OX]j'PϠ~iH% FFm_Z^z\z#-${@3{pO#+5cI)J8PXV担ϾSJ#>Zmo ޵O}}Gw JqLJ9#}8ʃ [8HmǒKSOImnd#O[?'Qi4P0 AC@TJ8 -]d6۱&*T/A { (-իK73clcS2RA0"* W ɂ tm.ފ `< ~C}F=g8Bt]qm~F V)VJX1#U/&:+p!?c/Ta rN,NrSn|EZFv;lA P(ov;.ty)}c_8~IDonRuQ,evA]&$|+ Ar]A tr=(.-uS./4r)5? _/jjkzxHv&y::SPfN4cy&Qmz{e{djE>ſr$ӱMV#5Ƣ|c#SCTiA [uuf  & >SuS#0`04A zÅ7" MU@kzpf fo#Bf  SY+9j!j[MpK@ff B 0,wmB @_M!ƀev5\fфAHc?Cu6&Rzʵ߶W94f @ fM['"19w9_^ɝ6;'IPgO 6<ѭ‚%lX3a0|sox2ֹ˳fJQK x4ǀ$JCo|a#j`ja27~CΝn D-)lBSWvw}9D MBC KrGϽu-Ĺh.Ϟ7vڎ IV@|!!oL]?N 3rܮDA7]8[[- "1{s~*7=7?z(cm?+%􄕲àNS [q uTnx_|VJpev$t6{]AD(,-O̔wx|s;:*sU+eEA#(ޖ0￰+qevTOYݲlxt ^s5]|^u%.K+:q>'al>o[B3#>wIENDB`tpclient-pywx-0.3.1.1/extra/0000755000175000017500000000000010773624641014002 5ustar timtimtpclient-pywx-0.3.1.1/extra/__init__.py0000644000175000017500000005320710773624641016122 0ustar timtim import string import sys import wx import wx.gizmos import wx.lib.mixins.listctrl ######################## # This fix allows me to globaly register XRC handlers ######################## import wx.xrc as xrc from wx.xrc import EmptyXmlResource as EmptyXmlResourceOrig EmptyXmlResourceOrig() xrc.ExtraHandlers = [] def XmlResourceWithHandlers(*args, **kw): if len(args)+len(kw) > 1: raise RuntimeError("Don't know what to do with all the arguments!") f = None if len(args) > 0: f = args[0] elif len(kw) > 0: f = kw['file'] res = EmptyXmlResourceOrig() for handler in xrc.ExtraHandlers: res.InsertHandler(handler()) if f != None: res.Load(f) return res xrc.XmlResourceWithHandlers = XmlResourceWithHandlers OrigXmlResource = xrc.XmlResource class MyXmlResource(OrigXmlResource): def __init__(self, *args, **kw): print '__init__', self OrigXmlResource.__init__(self, *args, **kw) def InitAllHandlers(self, *args, **kw): print "InitAllHandlers!" r = OrigXmlResource.InitAllHandlers(self, *args, **kw) for handler in xrc.ExtraHandlers: self.InsertHandler(handler()) return r xrc.XmlResource = MyXmlResource def EmptyXmlResourceWithHandlers(*args, **kwargs): res = EmptyXmlResourceOrig(*args, **kwargs) for handler in xrc.ExtraHandlers: res.InsertHandler(handler()) return res xrc.EmptyXmlResourceWithHandlers = EmptyXmlResourceWithHandlers xrc.EmptyXmlResource = EmptyXmlResourceWithHandlers import wx.gizmos from wx.gizmos import EditableListBox class EditableListBoxXmlHandler(xrc.XmlResourceHandler): def __init__(self): xrc.XmlResourceHandler.__init__(self) # Specify the styles recognized by objects of this type self.AddStyle("wxEL_ALLOW_NEW", wx.gizmos.EL_ALLOW_NEW) self.AddStyle("wxEL_ALLOW_EDIT", wx.gizmos.EL_ALLOW_EDIT) self.AddStyle("wxEL_ALLOW_DELETE", wx.gizmos.EL_ALLOW_DELETE) self.AddWindowStyles() # This method and the next one are required for XmlResourceHandlers def CanHandle(self, node): return self.IsOfClass(node, "wxEditableListBox") or self.IsOfClass(node, "EditableListBox") def DoCreateResource(self): # The simple method assumes that there is no existing # instance. Be sure of that with an assert. assert self.GetInstance() is None ctrl = EditableListBox(self.GetParentAsWindow(), self.GetID(), "", #self.GetLabel(), self.GetPosition(), self.GetSize(), self.GetStyle(), self.GetName(), ) # These two things should be done in either case: # Set standard window attributes self.SetupWindow(ctrl) # Create any child windows of this node self.CreateChildren(ctrl) return ctrl xrc.ExtraHandlers.append(EditableListBoxXmlHandler) class ListCtrlXmlHandler(xrc.XmlResourceHandler): extra_styles = [ "LC_LIST", "LC_REPORT", "LC_VIRTUAL", "LC_ICON", "LC_SMALL_ICON", "LC_ALIGN_TOP", "LC_ALIGN_LEFT", "LC_AUTOARRANGE", "LC_EDIT_LABELS", "LC_NO_HEADER", "LC_SINGLE_SEL", "LC_SORT_ASCENDING", "LC_SORT_DESCENDING", "LC_HRULES", "LC_VRULES"] def __init__(self): xrc.XmlResourceHandler.__init__(self) # Specify the styles recognized by objects of this type self.AddWindowStyles() for style in self.extra_styles: self.AddStyle("wx%s" % style, getattr(wx, style)) # This method and the next one are required for XmlResourceHandlers def CanHandle(self, node): return self.IsOfClass(node, "wxListCtrl") or self.IsOfClass(node, "ListCtrl") def DoCreateResource(self): # The simple method assumes that there is no existing # instance. Be sure of that with an assert. if self.GetInstance() is None: ctrl = wx.ListCtrl(self.GetParentAsWindow(), self.GetID(), self.GetPosition(), self.GetSize(), self.GetStyle(), name=self.GetName(), ) else: ctrl = self.GetInstance() # Now call the ctrl's Create method to actually create the window ctrl.Create(self.GetParentAsWindow(), self.GetID(), self.GetPosition(), self.GetSize(), self.GetStyle(), name = self.GetName() ) # These two things should be done in either case: # Set standard window attributes self.SetupWindow(ctrl) # Create any child windows of this node self.CreateChildren(ctrl) return ctrl xrc.ExtraHandlers.append(ListCtrlXmlHandler) class ChoiceXmlHandler(xrc.XmlResourceHandler): def __init__(self): xrc.XmlResourceHandler.__init__(self) # Specify the styles recognized by objects of this type self.AddWindowStyles() # This method and the next one are required for XmlResourceHandlers def CanHandle(self, node): return self.IsOfClass(node, "wxChoice") or self.IsOfClass(node, "Choice") def DoCreateResource(self): # The simple method assumes that there is no existing # instance. Be sure of that with an assert. if self.GetInstance() is None: ctrl = wx.Choice(self.GetParentAsWindow(), self.GetID(), self.GetPosition(), self.GetSize(), [], self.GetStyle(), name=self.GetName(), ) else: ctrl = self.GetInstance() # Now call the ctrl's Create method to actually create the window ctrl.Create(self.GetParentAsWindow(), self.GetID(), self.GetPosition(), self.GetSize(), [], self.GetStyle(), name = self.GetName() ) # These two things should be done in either case: # Set standard window attributes self.SetupWindow(ctrl) # Create any child windows of this node self.CreateChildren(ctrl) return ctrl xrc.ExtraHandlers.append(ChoiceXmlHandler) class OrderedTreeCtrlXmlHandler(xrc.XmlResourceHandler): def __init__(self): xrc.XmlResourceHandler.__init__(self) # Specify the styles recognized by objects of this type self.AddStyle("wxTR_DEFAULT_STYLE", wx.TR_DEFAULT_STYLE) self.AddStyle("wxTR_HAS_VARIABLE_ROW_HEIGHT", wx.TR_HAS_VARIABLE_ROW_HEIGHT) self.AddWindowStyles() # This method and the next one are required for XmlResourceHandlers def CanHandle(self, node): return self.IsOfClass(node, "wxOrderedTreeCtrl") or self.IsOfClass(node, "OrderedTreeCtrl") def DoCreateResource(self): # The simple method assumes that there is no existing # instance. Be sure of that with an assert. if self.GetInstance() is None: # (self, parent, id, pos, size, style, validator, name) ctrl = wx.OrderedTreeCtrl(self.GetParentAsWindow(), self.GetID(), self.GetPosition(), self.GetSize(), self.GetStyle(), name=self.GetName(), ) else: ctrl = self.GetInstance() # Now call the ctrl's Create method to actually create the window ctrl.Create(self.GetParentAsWindow(), self.GetID(), self.GetPosition(), self.GetSize(), [], self.GetStyle(), name = self.GetName() ) # These two things should be done in either case: # Set standard window attributes self.SetupWindow(ctrl) # Create any child windows of this node self.CreateChildren(ctrl) return ctrl xrc.ExtraHandlers.append(OrderedTreeCtrlXmlHandler) wx.SEARCH_CANCEL_BTN = 2**30 wx.SEARCH_SEARCH_BTN = 2**29 wx.SEARCH_MENU = 2**28 class SearchCtrlXmlHandler(xrc.XmlResourceHandler): def __init__(self): xrc.XmlResourceHandler.__init__(self) # Specify the styles recognized by objects of this type self.AddStyle("wxTE_PROCESS_ENTER", wx.TE_PROCESS_ENTER) self.AddStyle("wxSEARCH_CANCEL_BTN", wx.SEARCH_CANCEL_BTN) self.AddStyle("wxSEARCH_SEARCH_BTN", wx.SEARCH_SEARCH_BTN) self.AddStyle("wxSEARCH_MENU", wx.SEARCH_MENU) self.AddWindowStyles() # This method and the next one are required for XmlResourceHandlers def CanHandle(self, node): return self.IsOfClass(node, "wxSearchCtrl") or self.IsOfClass(node, "SearchCtrl") def DoCreateResource(self): # The simple method assumes that there is no existing # instance. Be sure of that with an assert. assert self.GetInstance() is None #__init__(self, parent, id, value, pos, size, style, validator, name) ctrl = wx.SearchCtrl(self.GetParentAsWindow(), self.GetID(), "", self.GetPosition(), self.GetSize(), name=self.GetName()) # These two things should be done in either case: # Set standard window attributes self.SetupWindow(ctrl) # Create any child windows of this node self.CreateChildren(ctrl) ctrl.ShowSearchButton(self.GetStyle()&wx.SEARCH_SEARCH_BTN != 0) ctrl.ShowCancelButton(self.GetStyle()&wx.SEARCH_CANCEL_BTN != 0) return ctrl xrc.ExtraHandlers.append(SearchCtrlXmlHandler) ######################## # This fix allows me to have tooltips on individual items rather then just the whole control. ######################## class ToolTipItemMixIn: """ This MixIn allows you to have a seperate tooltip per item in a multi-item control. """ def __init__(self): self.tooltips = {} def SetToolTipDefault(self, tooltip): """ Set the tooltip for the control when not over any items. """ if isinstance(tooltip, wx.ToolTip): tooltip = tooltip.GetTip() self.tooltips[-1] = tooltip self.SetToolTip(wx.ToolTip(tooltip)) def SetToolTipItem(self, slot, text): """ Set the tooltip for a given item. """ self.tooltips[slot] = text def GetToolTipItem(self, slot): """ Get the tooltip associated with a given item. """ if self.tooltips.has_key(slot): return self.tooltips[slot] else: return None def SetToolTipCurrent(self, slot): """ Set which tooltip should be currently displayed. """ if self.tooltips.has_key(slot): if self.GetToolTip() == None: self.SetToolTip(wx.ToolTip(self.tooltips[slot])) elif self.GetToolTip().GetTip() != self.tooltips[slot]: self.GetToolTip().SetTip(self.tooltips[slot]) wx.ChoiceOrig = wx.Choice class wxChoice(wx.Choice, ToolTipItemMixIn): """ A modified version of a wxChoice control which supports tooltips per item. """ def __init__(self, *arg, **kw): wx.ChoiceOrig.__init__(self, *arg, **kw) ToolTipItemMixIn.__init__(self) self.Bind(wx.EVT_CHOICE, self.OnSelection) def OnSelection(self, evt): """ Bind OnSelection so that we can change the tooltip when the selection changes. """ slot = self.GetSelection() self.SetToolTipCurrent(slot) wx.ComboBoxOrig = wx.ComboBox class wxComboBox(wx.ComboBox, ToolTipItemMixIn): """ A modified version of a wxComboBox control which supports tooltips per item. """ def __init__(self, *arg, **kw): wx.ComboBoxOrig.__init__(self, *arg, **kw) ToolTipItemMixIn.__init__(self) self.Bind(wx.EVT_COMBOBOX, self.OnSelection) def OnSelection(self, evt): """ Bind OnSelection so that we can change the tooltip when the selection changes. """ slot = self.GetSelection() self.SetToolTipCurrent(slot) ######################## # This fix fixes a bunch of broken stuff with the ListCtrl and adds a few more # functionality which should be default. ######################## import wx.lib.mixins.listctrl as mlc wx.ListCtrlOrig = wx.ListCtrl class wxListCtrl(wx.ListCtrlOrig, mlc.ListCtrlAutoWidthMixin, mlc.ColumnSorterMixin, ToolTipItemMixIn): """ This is a custom version of wxListCtrl which should make the list control easier to deal with, it also uses some of the default ListCtrl MixIns, including: wx.lib.mixins.listctrl.ListCtrlAutoWidthMixin wx.lib.mixins.listctrl.ColumnSorterMixin It also includes the ToolTipItemMixIn. """ def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize, *args, **kw): wx.ListCtrlOrig.__init__(self, parent, ID, pos, size, *args, **kw) mlc.ListCtrlAutoWidthMixin.__init__(self) mlc.ColumnSorterMixin.__init__(self, self.GetColumnCount()) ToolTipItemMixIn.__init__(self) self.objects = [] self.ignore = 0 self.Bind(wx.EVT_MOTION, self.OnMouseMotion) ############################################################################# # ColumnSorterMixin: This adds support for sorting then clicking the headers ############################################################################# def GetColumnSorter(self): return self.__ColumnSorter def __ColumnSorter(self, key1, key2): col = self._col ascending = self._colSortFlag[col] v1 = self.GetStringItem(key1, col) v2 = self.GetStringItem(key2, col) if not ascending: return cmp(v1, v2) else: return -cmp(v1, v2) def GetSortImages(self): # FIXME: This is a strange place to put this. # This makes sure the selected items still have focus after sorting item = self.GetNextItem(-1) while item != -1: if self.GetItemState(item, wx.LIST_STATE_SELECTED) == 0: self.SetItemState(item, 0, wx.LIST_STATE_FOCUSED) else: self.SetItemState(item, wx.LIST_STATE_FOCUSED, wx.LIST_STATE_FOCUSED) item = self.GetNextItem(item) # Update the slots as we have reorganised them slot = -1 while True: slot = self.GetNextItem(slot, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE) if slot == wx.NOT_FOUND: break self.SetItemData(slot, slot) return (-1, -1) def InsertColumn(self, *args, **kw): super(self.__class__, self).InsertColumn(*args, **kw) self.SetColumnCount(self.GetColumnCount()) def GetListCtrl(self): return self ############################################################################# ############################################################################# # This stuff makes the PyData stuff actually work and allows searching on the # pyData ############################################################################# def InsertItem(self, item): slot = wx.ListCtrlOrig.InsertItem(self, item) self._increasePyData(slot) return slot def InsertStringItem(self, slot, label): r = wx.ListCtrlOrig.InsertStringItem(self, slot, label) self._increasePyData(slot) return r def InsertImageItem(self, slot, imageIndex): r = wx.ListCtrlOrig.InsertImageItem(self, slot, imageIndex) self._increasePyData(slot) return r def InsertImageStringItem(self, slot, label, imageIndex): r = wx.ListCtrlOrig.InsertImageStringItem(self, slot, label, imageIndex) self._increasePyData(slot) return r def _increasePyData(self, slot): self.objects.insert(slot, None) self.SetItemData(slot, slot) def SetItemPyData(self, slot, data): assert slot >= 0 assert slot < len(self.objects) self.objects[slot] = data def GetItemPyData(self, slot): try: return self.objects[slot] except IOError: return None def DeleteItem(self, slot): del self.objects[slot] wx.ListCtrlOrig.DeleteItem(self, slot) def DeleteAllItems(self): self.objects = [] wx.ListCtrlOrig.DeleteAllItems(self) def FindItemByPyData(self, data): slot = -1 while True: slot = self.GetNextItem(slot, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE); if slot == wx.NOT_FOUND: return wx.NOT_FOUND if self.GetItemPyData(slot) == data: return slot def GetStringItem(self, slot, col): item = self.GetItem(slot, col) if item == wx.NOT_FOUND: return wx.NOT_FOUND else: return item.GetText() # Display individual line tooltips def OnMouseMotion(self, evt): slot = self.HitTest(evt.GetPosition())[0] self.SetToolTipCurrent(slot) # This prevents perious errors about wxPyDeadObject def _doResize(self): if hasattr(wx, 'core'): try: if not isinstance(self, wx.core._wxPyDeadObject): wx.lib.mixins.listctrl.ListCtrlAutoWidthMixin._doResize(self) except wx.core.PyDeadObjectError: pass else: wx.lib.mixins.listctrl.ListCtrlAutoWidthMixin._doResize(self) if sys.platform == "darwin": column = self.GetColumnCount()-1 if column > 0: self.SetColumnWidth(column, self.GetColumnWidth(column)-4) ############################################################################# # This stuff makes working with selected items much easier ############################################################################# def GetSelected(self): """ Get the currently selected slots. """ slots = [-1,] while True: slot = self.GetNextItem(slots[-1], wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED) if slot != wx.NOT_FOUND: slots.append(slot) else: slots = slots[1:] break slots.reverse() return slots def SetSelected(self, slots): """ Set the selection to the given slots. """ self.Freeze() # Unselect the currently selected items for slot in self.GetSelected(): self.ignore += 1 self.SetItemState(slot, 0, wx.LIST_STATE_SELECTED) for slot in slots: self.ignore += 1 self.SetItemState(slot, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED) self.Thaw() def AddSelected(self, slot): """ Make the given slot selected in addition. """ self.SetItemState(slot, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED) ######################## # This adds a TreeCtrl which orders itself by the Python Data. ######################## class OrderedTreeCtrl(wx.TreeCtrl): """ A tree control which orders itself by the Python Data. """ def __init__(self, *args, **kw): wx.TreeCtrl.__init__(self, *args, **kw) self.Bind(wx.EVT_TREE_ITEM_ACTIVATED, self.OnActivate, self) def OnActivate(self, evt): item = evt.GetItem() self.Toggle(item) def OnCompareItems(self, item1, item2): t1 = self.GetItemText(item1) t2 = self.GetItemText(item2) if t1 < t2: return -1 if t1 == t2: return 0 return 1 def GetPyData(self, item): if not item.IsOk(): return None return wx.TreeCtrl.GetItemPyData(self, item) def FindItemByData(self, pyData, compare=None, item=None): if item == None: item = self.GetRootItem() if not item.IsOk(): return None if not compare is None and compare(pyData, self.GetPyData(item)): return item elif self.GetPyData(item) == pyData: return item if self.ItemHasChildren(item): cookieo = -1 child, cookie = self.GetFirstChild(item) while cookieo != cookie: r = self.FindItemByData(pyData, compare, child) if r: return r cookieo = cookie child, cookie = self.GetNextChild(item, cookie) return None def FindAllByData(self, pyData, compare=None, item=None, r=None): if r == None: r = [] if item == None: item = self.GetRootItem() if not item.IsOk(): return None if not compare is None: if compare(pyData, self.GetPyData(item)): r.append(item) else: if self.GetPyData(item) == pyData: r.append(item) if self.ItemHasChildren(item): cookieo = -1 child, cookie = self.GetFirstChild(item) while cookieo != cookie: self.FindAllByData(pyData, compare, child, r) cookieo = cookie child, cookie = self.GetNextChild(item, cookie) return r wx.OrderedTreeCtrl = OrderedTreeCtrl ######################## # This adds a simple validator which only takes DIGITs and ALPHA characters. ######################## wx.DIGIT_ONLY = 1 wx.ALPHA_ONLY = 2 class wxSimpleValidator(wx.PyValidator): """ A simple validator which lets you only allow numbers or letters. """ def __init__(self, flag=None, pyVar=None): wx.PyValidator.__init__(self) self.flag = flag self.Bind(wx.EVT_CHAR, self.OnChar) def Clone(self): return wxSimpleValidator(self.flag) def Validate(self, win): tc = self.GetWindow() val = tc.GetValue() if self.flag == wx.ALPHA_ONLY: for x in val: if x not in string.letters: return False elif self.flag == wx.DIGIT_ONLY: try: if val != '-': long(val) return True except TypeError: return False return True def OnChar(self, event): key = event.KeyCode if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255: event.Skip() return if self.flag == wx.ALPHA_ONLY and chr(key) in string.letters: event.Skip() return if self.flag == wx.DIGIT_ONLY and chr(key) in string.digits: event.Skip() return if self.flag == wx.DIGIT_ONLY and chr(key) in '-+': event.Skip() return if not wx.Validator_IsSilent(): wx.Bell() # Returning without calling even.Skip eats the event before it # gets to the text control return wx.SimpleValidator = wxSimpleValidator ######################## # PopupWindow doesn't exist on Mac, this fakes it ######################## wx.PopupWindowOrig = wx.PopupWindow if wx.Platform == '__WXMAC__': class FakePopupWindow(wx.MiniFrame): """ A fake popup window which is used on wxPython on Mac OS X. """ def __init__(self, parent, style=None): wx.MiniFrame.__init__(self, parent, style = wx.NO_BORDER | wx.FRAME_NO_TASKBAR | wx.STAY_ON_TOP) self.Panel = wx.Panel(self) def Position(self, position, size): self.Move((position[0]+size[0], position[1]+size[1])) def SetBackgroundColour(self, colour): self.Panel.SetBackgroundColour(colour) def Window(self): return self.Panel Window = property(Window) wx.PopupWindow = FakePopupWindow else: class PopupWindow(wx.PopupWindowOrig): def Window(self): return self Window = property(Window) wx.PopupWindow = PopupWindow ######################## # Monkey Patch fancy text so it supports all forms of specifying colors... ######################## from wx.lib.fancytext import Renderer def getCurrentColor(self): font = self.fonts[-1] return font.get("color", self.defaultColor) Renderer.getCurrentColor = getCurrentColor ######################## # Assign our versions into the wx namespace ######################## wx.ListCtrl = wxListCtrl wx.Choice = wxChoice wx.ComboBox = wxComboBox wx.SimpleValidator = wxSimpleValidator from PopupCtrl import PopupCtrl wx.PopupCtrl = PopupCtrl ######################## # Figure out which AUI we should be using. ######################## if wx.VERSION_STRING < "2.8": if wx.VERSION_STRING < "2.7.2" and wx.VERSION_STRING > "2.7.0": import wx.aui as aui else: import PyAUI as aui aui.AUI_BUTTON_CUSTOM1 = aui.PaneInfo.buttonCustom1 aui.AUI_BUTTON_CUSTOM2 = aui.PaneInfo.buttonCustom2 aui.AUI_BUTTON_CUSTOM3 = aui.PaneInfo.buttonCustom3 aui.AuiManager = aui.FrameManager aui.AuiManagerEvent = aui.FrameManagerEvent aui.AuiPaneInfo = aui.PaneInfo aui.AuiFloatingPane = aui.FloatingPane else: import wx.aui as aui wx.aui = aui print "Using the following AUI", wx.aui tpclient-pywx-0.3.1.1/extra/StateTracker.py0000644000175000017500000003546110773624641016761 0ustar timtim import wx from extra.decorators import * from tp.client.ChangeList import ChangeNode # Raised when the game cache is made dirty. Contains a reference to what was updated. # -- CacheDirtyEvent # Raised when the game cache is changed. Contains a reference to what was updated. # -- CacheUpdateEvent #class StateTracker(object): class TrackerObject(object): """ Tracks the state of the selected object. Also provides a functionality to select an object. """ def __init__(self): self.oid = None self.application.gui.Binder(self.application.CacheClass.CacheDirtyEvent, self.OnCacheUpdate) self.application.gui.Binder(self.application.CacheClass.CacheUpdateEvent, self.OnCacheUpdate) self.application.gui.Binder(self.application.gui.SelectObjectEvent, self.OnSelectObject) self.application.gui.Binder(self.application.gui.PreviewObjectEvent, self.OnPreviewObject) ########################################################################## # Callbacks for various events ########################################################################## @freeze_wrapper def OnCacheUpdate(self, evt): """ Called when something changes in the cache. """ assert not self is evt.source, "Got event %s which was sent by %s which is me (%s)!" % (evt, evt.source, self) # If there was a whole cache update if evt.what is None: self.ObjectRefreshAll() # Refresh the currently selected object if not self.oid is None: self.ObjectRefresh(oid) else: self._ObjectSelect(None) @freeze_wrapper def OnSelectObject(self, evt): """ Called when something else selects an object. """ assert not self is evt.source, "Got event %s which was sent by %s which is me (%s)!" % (evt, evt.source, self) # Check that if object is not already selected if self.oid == evt.id: return self._ObjectSelect(evt.id) @freeze_wrapper def OnPreviewObject(self, evt): """ Called when something else previews an object. """ assert not self is evt.source, "Got event %s which was sent by %s which is me (%s)!" % (evt, evt.source, self) # Check that if object is not already selected if self.oid == evt.id: return self.ObjectPreview(evt.id) ########################################################################## # Methods called when state changes with an object ########################################################################## def _ObjectSelect(self, id): self.oid = id self.ObjectSelect(id) def ObjectSelect(self, id): """ Called when an object is selected. """ pass def ObjectPreview(self, id): """ Called when an object is "previewed". (By default calls ObjectSelect method). """ self._ObjectSelect(id) def ObjectRefresh(self, id, object=None): """ Refresh the selected object. If object is given then it should be used as the source of information, otherwise the cache should be used. (By default calls SelectObject.) """ if object is None: self._ObjectSelect(id) def ObjectRefreshAll(self): """ Refresh all objects (apart from the one that is selected. """ pass ########################################################################## # Methods to change the state ########################################################################## def SelectObject(self, id, forceother=False): """ Called to select an object. """ if self.oid == id and not forceother: return self.application.Post(self.application.gui.SelectObjectEvent(id), source=self) if self.oid != id: self._ObjectSelect(id) def PreviewObject(self, id): """ Called to select an object. """ if self.oid == id: return self.application.Post(self.application.gui.PreviewObjectEvent(id), source=self) self.ObjectPreview(id) def SelectNextChild(self): if not self.oid is None: #print self.application.cache.objects[self.oid].name if hasattr(self.application.cache.objects[self.oid], "contains") and self.application.cache.objects[self.oid].contains != []: #print "Contains:" #for oid in self.application.cache.objects[self.oid].contains: # print oid self.application.Post(self.application.gui.SelectObjectEvent(self.application.cache.objects[self.application.cache.objects[self.oid].contains[0]].id)) def SelectNextObject(self): """ Called to select the next object. """ if not self.oid is None: self.SelectNextSibling(self.oid) def SelectNextSibling(self, objectid): if hasattr(self.application.cache.objects[objectid], "parent"): parentid = self.application.cache.objects[objectid].parent objectfound = 0; for object in self.application.cache.objects[parentid].contains: if (object == objectid): objectfound = 1 continue if (objectfound == 1): self.application.Post(self.application.gui.SelectObjectEvent(self.application.cache.objects[object].id)) objectfound = 2 break if objectfound == 1: self.SelectNextSibling(parentid) def SelectPreviousObject(self): """ Called to select the previous object. """ if not self.oid is None: self.SelectPreviousSibling(self.oid) def SelectPreviousSibling(self, objectid): if hasattr(self.application.cache.objects[objectid], "parent"): parentid = self.application.cache.objects[objectid].parent timesthrough = 0; objectfound = -1; for object in self.application.cache.objects[parentid].contains: if (object == objectid): objectfound = timesthrough print timesthrough continue timesthrough = timesthrough + 1 if objectfound != -1: if objectfound == 0: self.application.Post(self.application.gui.SelectObjectEvent(parentid)) else: self.application.Post(self.application.gui.SelectObjectEvent(self.application.cache.objects[parentid].contains[objectfound-1])) from tp.netlib.objects import Order class TrackerObjectOrder(TrackerObject): """ Tracks the currently selected object and order. Also provides a functionality to select an object and orders. """ def __init__(self): TrackerObject.__init__(self) self.nodes = [] self.application.gui.Binder(self.application.gui.SelectOrderEvent, self.OnSelectOrder) ########################################################################## # Callbacks for various events ########################################################################## def OnCacheUpdate(self, evt): assert not self is evt.source, "Got event %s which was sent by %s which is me (%s)!" % (evt, evt.source, self) # If there was a whole cache update if evt.what is None: print self, evt, "Full cache update" self.ObjectRefreshAll() # Refresh the currently selected object if not self.oid is None: self.ObjectRefresh(self.oid) else: self._ObjectSelect(None) # Refresh the currently selected order if len(self.nodes) > 0: for node in self.nodes: self.OrderRefresh(node) return # Only interested in an CacheUpdates which are for the selected object if evt.id != self.oid: return CacheDirtyEvent, CacheUpdateEvent = self.application.cache.CacheDirtyEvent, self.application.cache.CacheUpdateEvent if evt.what == "objects": if isinstance(evt, CacheDirtyEvent): self.ObjectRefresh(evt.id, evt.change) if isinstance(evt, CacheUpdateEvent): self.ObjectRefresh(evt.id) return if evt.what == "orders": if isinstance(evt, CacheDirtyEvent): if evt.action == "create after": self.OrderInsertAfter(evt.node, evt.change) if evt.action == "create before": self.OrderInsertBefore(evt.node, evt.change) if evt.action == "change": self.OrderRefresh(evt.change) if evt.action == "remove": self.OrdersRemove(evt.nodes, True) return if isinstance(evt, CacheUpdateEvent): if evt.action in ("create before", "create after", "change"): self.OrderRefresh(evt.change) if evt.action == "remove": # Unselect any slots which are being removed leftnodes = [] for node in self.nodes: if not node in evt.nodes: leftnodes.append(node) if self.nodes != leftnodes: self._OrdersSelect(leftnodes) self.OrdersRemove(evt.nodes) return def OnSelectObject(self, evt): assert not self is evt.source, "Got event %s which was sent by %s which is me (%s)!" % (evt, evt.source, self) # Check that if object is not already selected if self.oid == evt.id: return # Clear the selected nodes self.nodes = [] self._ObjectSelect(evt.id) def _ObjectSelect(self, id): self.oid = id self.ObjectSelect(id) self._OrdersSelect([]) def OnSelectOrder(self, evt): """ Called when something else selects an order. """ assert not self is evt.source, "Got event %s which was sent by %s which is me (%s)!" % (evt, evt.source, self) # Check this order is for the currently selected object if self.oid != evt.id: return # Check if these nodes have already been selected if self.nodes == evt.nodes: return self._OrdersSelect(evt.nodes) def OnKeyUp(self, evt): print "OnKeyUp", evt, evt.GetKeyCode() if evt.GetKeyCode() == wx.WXK_ESCAPE: self.SetMode(self.GUISelect) if evt.GetKeyCode() == wx.WXK_DELETE: if len(self.nodes) == 0: return elif len(self.nodes) == 1: self.RemoveOrders(self.nodes) else: dlg = wx.MessageDialog(self, "You are about to remove multiple\norders, are you sure?", "Remove orders?", wx.OK | wx.CANCEL) if dlg.ShowModal() == wx.ID_OK: self.RemoveOrders(self.nodes) dlg.Destroy() if evt.GetKeyCode() in (60, 44): # < if len(self.nodes) > 0 and not self.nodes[0].left.left is None: if evt.ShiftDown(): self.SelectOrders([self.nodes[0].left] + self.nodes[:]) else: self.SelectOrders([self.nodes[0].left]) if len(self.nodes) == 0: d = self.application.cache.orders[self.oid] if len(d) > 0: self.SelectOrders([d.last]) if evt.GetKeyCode() in (46,): # > if len(self.nodes) > 0 and not self.nodes[-1].right is None: if evt.ShiftDown(): self.SelectOrders(self.nodes[:] + [self.nodes[-1].right]) else: self.SelectOrders([self.nodes[-1].right]) if len(self.nodes) == 0: d = self.application.cache.orders[self.oid] if len(d) > 0: self.SelectOrders([d.first]) ########################################################################## # Methods called when state changes with the order ########################################################################## def _OrdersSelect(self, nodes): """ Select an order (using nodes). """ self.nodes = nodes if self.oid != None: d = self.application.cache.orders[self.oid] def nodecmp(a, b): return cmp(d.index(a), d.index(b)) self.nodes.sort(nodecmp) self.OrdersSelect(nodes) def OrdersSelect(self, nodes): """ Select an order (using nodes). """ pass def OrderInsertAfter(self, afterme, toinsert): """ Called when a new order is inserted. """ pass def OrderInsertBefore(self, beforeme, toinsert): """ Called when a new order is inserted. """ pass def OrderRefresh(self, node, override=None): """ Refresh the selected orders (this might not be all orders). If orders is given then it should be used as the source of information, otherwise the cache should be used. """ pass def OrdersRemove(self, nodes, override=False): """ Called when an order is removed. """ pass ########################################################################## # Methods to change the state (orders) ########################################################################## def SelectOrders(self, nodes): """ Called to select orders on the current object. """ # Select orders is only valid when an object is selected assert self.oid != None if self.nodes == nodes: return # Nodes must exist in the orders cache d = self.application.cache.orders[self.oid] for node in nodes: assert isinstance(node, ChangeNode) assert node in d # Tell everyone else about the change self.application.Post(self.application.gui.SelectOrderEvent(self.oid, nodes), source=self) # Call our handler self._OrdersSelect(nodes) def InsertAfterOrder(self, order, node=None): # Insert order is only valid when an object is selected assert self.oid != None # Order must be an order, duh! assert isinstance(order, Order) if node is None: if len(self.nodes) > 0: node = self.nodes[-1] else: node = self.application.cache.orders[self.oid].last assert not node is None # Do some sanity checking d = self.application.cache.orders[self.oid] assert node in d # Make the change to the cache evt = self.application.cache.apply("orders", "create after", self.oid, node, order) # Do some sanity checking assert not evt.change is None assert evt.change in d assert node != evt.change # Tell everyone else about the change self.application.Post(evt, source=self) # Call our handler self.OrderInsertAfter(node, evt.change) return evt.change def InsertBeforeOrder(self, order, node=None): # Insert order is only valid when an object is selected assert self.oid != None # Order must be an order, duh! assert isinstance(order, Order) if node is None: if len(self.nodes) > 0: node = self.nodes[0] else: node = self.application.cache.orders[self.oid].first assert not node is None # Make the change to the cache evt = self.application.cache.apply("orders", "create before", self.oid, node, order) # Do some sanity checking assert not evt.change is None d = self.application.cache.orders[self.oid] assert evt.change in d # Tell everyone else about the change self.application.Post(evt, source=self) # Call our handler self.OrderInsertBefore(node, evt.change) return evt.change def DirtyOrder(self, order, node=None): pass # # Dirty order is only valid when an object is selected # assert self.oid != None # # Order must be an order, duh! # assert isinstance(order, Order) # # if node is None: # assert len(self.nodes) == 1 # node = self.nodes[0] # # self.application.Post(self.application.gui.DirtyOrderEvent(order), source=self) def ChangeOrder(self, order, node=None): # Change order is only valid when an object is selected assert self.oid != None # Order must be an order, duh! assert isinstance(order, Order) if node is None: assert len(self.nodes) == 1 node = self.nodes[0] evt = self.application.cache.apply("orders", "change", self.oid, node, order) # Tell everyone else about the change self.application.Post(evt, source=self) # Call our handler self.OrderRefresh(evt.change) def RemoveOrders(self, nodes=None): # Remove orders is only valid when an object is selected assert self.oid != None if nodes is None: if len(self.nodes) == 0: return nodes = self.nodes evt = self.application.cache.apply("orders", "remove", self.oid, nodes=nodes) # Tell everyone else about the change self.application.Post(evt, source=self) # Call our handler self.OrdersRemove(nodes, True) tpclient-pywx-0.3.1.1/extra/installer.patch0000644000175000017500000000131510773624641017020 0ustar timtim--- carchive.py.old 2005-03-01 08:37:42.000000000 +1030 +++ carchive.py 2005-02-22 22:14:27.000000000 +1030 @@ -261,3 +261,15 @@ if flag: raise ValueError, "Cannot open compressed archive %s in place" return CArchive(self.path, self.pkgstart+dpos, dlen) + + def openEmbeddedZlib(self, name): + """Open a CArchive of name NAME embedded within this CArchive.""" + ndx = self.toc.find(name) + if ndx == -1: + raise KeyError, "Member '%s' not found in %s" % (name, self.path) + (dpos, dlen, ulen, flag, typcd, nm) = self.toc.get(ndx) + if flag: + raise ValueError, "Cannot open compressed archive %s in place" + return archive.ZlibArchive(self.path, self.pkgstart+dpos) + + tpclient-pywx-0.3.1.1/extra/PyAUI.py0000644000175000017500000056501010773624641015312 0ustar timtim# --------------------------------------------------------------------------- # # PYAUI Library wxPython IMPLEMENTATION # # Original C++ Code From Kirix (wxAUI). You Can Find It At: # # License: wxWidgets license # # http://www.kirix.com/en/community/opensource/wxaui/about_wxaui.html # # Current wxAUI Version Tracked: 0.9.2 # # # Python Code By: # # Andrea Gavana, @ 23 Dec 2005 # Latest Revision: 30 Jun 2006, 21.00 GMT # # # PyAUI version 0.9.2 Adds: # # * Fixes For Display Glitches; # * Fixes For Other Bugs Found In Previous Versions. # # # TODO List/Caveats # # 1. Using The New Versions Of wxPython (2.6.2.1pre.20060106 Or Higher) There # Is A New Method Called wx.GetMouseState() That Gets Rid Of The Import Of # win32all or ctypes. Moreover, It Should Make PyAUI Working On All # Platforms (I Hope). # # # Development Patches: # # 1) On Windows XP, Use The Nice Sash Drawing Provided By XP While Dragging The Sash # 2) Handles wx.EVT_ACTIVATE Events For Panes # 3) Possibility To Set An Icon On Docked Panes (Don't Know How Useful It Is) # 4) Now PyAUI Saves And Loads Docking Restrictions (As LeftDockable(), TopDockable() etc...) # 5) Resizing Can Now Be Done Also In "Live Update" Or By Draing The Sash (As Usual) # 6) First Approach In The Implementation Of ModernDockArt. It Requires ctypes, And It # Still Does Not Work. If You Find A Solution, Please Contibute It Back # 7) Handles wx.EVT_CLOSE Event For Floating Panes (Thanks To DJ Gilcrease) # 8) Possibility To Draw A Sash Visual Grip, For Enhanced Visualization Of Sashes. # 9) Fixed The Mac Problem (Thanks To David Pratt) And Applied The wxGTK Patches # Suggested By Robin Dunn To Correctly Draw The Dock Hint # # For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please # Write To Me At: # # andrea.gavana@agip.it # andrea_gavan@tin.it # # Or, Obviously, To The wxPython Mailing List!!! # # with OS X support and refactoring implemented by Chris Mellon (arkanes@gmail.com) - # contact me directly or on wxPython ML for more info # # # End Of Comments # --------------------------------------------------------------------------- # """ PyAUI is an Advanced User Interface library that aims to implement "cutting-edge" interface usability and design features so developers can quickly and easily create beautiful and usable application interfaces. Vision and Design Principles PyAUI attempts to encapsulate the following aspects of the user interface: * Frame Management: Frame management provides the means to open, move and hide common controls that are needed to interact with the document, and allow these configurations to be saved into different perspectives and loaded at a later time. * Toolbars: Toolbars are a specialized subset of the frame management system and should behave similarly to other docked components. However, they also require additional functionality, such as "spring-loaded" rebar support, "chevron" buttons and end-user customizability. * Modeless Controls: Modeless controls expose a tool palette or set of options that float above the application content while allowing it to be accessed. Usually accessed by the toolbar, these controls disappear when an option is selected, but may also be "torn off" the toolbar into a floating frame of their own. * Look and Feel: Look and feel encompasses the way controls are drawn, both when shown statically as well as when they are being moved. This aspect of user interface design incorporates "special effects" such as transparent window dragging as well as frame animation. PyAUI adheres to the following principles: - Use native floating frames to obtain a native look and feel for all platforms; - Use existing wxPython code where possible, such as sizer implementation for frame management; - Use standard wxPython coding conventions. Usage: The following example shows a simple implementation that utilizes FrameManager to manage three text controls in a frame window: class MyFrame(wx.Frame): def __init__(self, parent, id=-1, title="PyAUI Test", pos=wx.DefaultPosition, size=(800, 600), style=wx.DEFAULT_FRAME_STYLE): wx.Frame.__init__(self, parent, id, title, pos, size, style) self._mgr = PyAUI.FrameManager() # notify PyAUI which frame to use self._mgr.SetFrame(self) # create several text controls text1 = wx.TextCtrl(self, -1, "Pane 1 - sample text", wx.DefaultPosition, wx.Size(200,150), wx.NO_BORDER | wx.TE_MULTILINE) text2 = wx.TextCtrl(self, -1, "Pane 2 - sample text", wx.DefaultPosition, wx.Size(200,150), wx.NO_BORDER | wx.TE_MULTILINE) text3 = wx.TextCtrl(self, -1, "Main content window", wx.DefaultPosition, wx.Size(200,150), wx.NO_BORDER | wx.TE_MULTILINE) # add the panes to the manager self._mgr.AddPane(text1, wx.LEFT, "Pane Number One") self._mgr.AddPane(text2, wx.BOTTOM, "Pane Number Two") self._mgr.AddPane(text3, wx.CENTER) # tell the manager to "commit" all the changes just made self._mgr.Update() self.Bind(wx.EVT_CLOSE, self.OnClose) def OnClose(self, event): # deinitialize the frame manager self._mgr.UnInit() self.Destroy() event.Skip() # our normal wxApp-derived class, as usual app = wx.PySimpleApp() frame = MyFrame(None) app.SetTopWindow(frame) frame.Show() app.MainLoop() What's New: PyAUI version 0.9.2 Adds: * Fixes For Display Glitches; * Fixes For Other Bugs Found In Previous Versions. License And Version: PyAUI Library Is Freeware And Distributed Under The wxPython License. Latest Revision: Andrea Gavana @ 30 Jun 2006, 21.00 GMT Version 0.9.2. """ import wx import cStringIO, zlib import time _libimported = None _newversion = False # Check For The New wxVersion: It Should Be > 2.6.2.1pre.20060102 # In Order To Let PyAUI Working On All Platforms wxver = wx.VERSION_STRING _ctypes = False if wx.Platform == "__WXMSW__": try: import ctypes import _winxptheme _ctypes = True except: _ctypes = False if hasattr(wx, "GetMouseState"): _newversion = True if wx.Platform == "__WXMSW__": try: import win32api import win32con import winxpgui _libimported = "MH" except: try: import ctypes _libimported = "ctypes" except: pass else: if wx.Platform == "__WXMSW__": try: import win32api import win32con import winxpgui _libimported = "MH" except: try: import ctypes _libimported = "ctypes" except: raise "\nERROR: At Present, On Windows Machines, You Need To Install "\ "Mark Hammond's pywin32 Extensions Or The ctypes Module, Or Download" \ "The Latest wxPython Version." else: raise "\nSorry: I Still Don't Know How To Work On GTK/MAC Platforms... " \ "Please Download The Latest wxPython Version." if wx.Platform == "__WXMAC__": try: import ctypes _carbon_dll = ctypes.cdll.LoadLibrary(r'/System/Frameworks/Carbon.framework/Carbon') except: _carbon_dll = None # Docking Styles AUI_DOCK_NONE = 0 AUI_DOCK_TOP = 1 AUI_DOCK_RIGHT = 2 AUI_DOCK_BOTTOM = 3 AUI_DOCK_LEFT = 4 AUI_DOCK_CENTER = 5 AUI_DOCK_CENTRE = AUI_DOCK_CENTER # Floating/Dragging Styles AUI_MGR_ALLOW_FLOATING = 1 AUI_MGR_ALLOW_ACTIVE_PANE = 2 AUI_MGR_TRANSPARENT_DRAG = 4 AUI_MGR_TRANSPARENT_HINT = 8 AUI_MGR_TRANSPARENT_HINT_FADE = 16 AUI_MGR_LIVE_RESIZE = 32 AUI_MGR_DEFAULT = AUI_MGR_ALLOW_FLOATING | \ AUI_MGR_TRANSPARENT_HINT | \ AUI_MGR_TRANSPARENT_HINT_FADE | \ AUI_MGR_TRANSPARENT_DRAG # Panes Customization AUI_ART_SASH_SIZE = 0 AUI_ART_CAPTION_SIZE = 1 AUI_ART_GRIPPER_SIZE = 2 AUI_ART_PANE_BORDER_SIZE = 3 AUI_ART_PANE_BUTTON_SIZE = 4 AUI_ART_BACKGROUND_COLOUR = 5 AUI_ART_SASH_COLOUR = 6 AUI_ART_ACTIVE_CAPTION_COLOUR = 7 AUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR = 8 AUI_ART_INACTIVE_CAPTION_COLOUR = 9 AUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR = 10 AUI_ART_ACTIVE_CAPTION_TEXT_COLOUR = 11 AUI_ART_INACTIVE_CAPTION_TEXT_COLOUR = 12 AUI_ART_BORDER_COLOUR = 13 AUI_ART_GRIPPER_COLOUR = 14 AUI_ART_CAPTION_FONT = 15 AUI_ART_GRADIENT_TYPE = 16 AUI_ART_DRAW_SASH_GRIP = 17 # Caption Gradient Type AUI_GRADIENT_NONE = 0 AUI_GRADIENT_VERTICAL = 1 AUI_GRADIENT_HORIZONTAL = 2 # Pane Button State AUI_BUTTON_STATE_NORMAL = 0 AUI_BUTTON_STATE_HOVER = 1 AUI_BUTTON_STATE_PRESSED = 2 # Pane Insert Level AUI_INSERT_PANE = 0 AUI_INSERT_ROW = 1 AUI_INSERT_DOCK = 2 # some built in bitmaps close_bits = '\xff\x00\x00\x00\xff\x00\x00\x00\xff\x00\x00\x00\xff\x00\x00\x00' \ '\xff\x00\x00\x00\xff\x00\x00\x00\xff\x00\x00\x00\xff\x00\x00\x00' \ '\xef\x00\x00\x00\xfb\x00\x00\x00\xcf\x00\x00\x00\xf9\x00\x00\x00' \ '\x9f\x00\x00\x00\xfc\x00\x00\x00?\x00\x00\x00\xfe\x00\x00\x00?\x00' \ '\x00\x00\xfe\x00\x00\x00\x9f\x00\x00\x00\xfc\x00\x00\x00\xcf\x00' \ '\x00\x00\xf9\x00\x00\x00\xef\x00\x00\x00\xfb\x00\x00\x00\xff\x00' \ '\x00\x00\xff\x00\x00\x00\xff\x00\x00\x00\xff\x00\x00\x00\xff\x00' \ '\x00\x00\xff\x00\x00\x00\xff\x00\x00\x00\xff\x00\x00\x00' pin_bits = '\xff\xff\xff\xff\xff\xff\x1f\xfc\xdf\xfc\xdf\xfc\xdf\xfc\xdf\xfc' \ '\xdf\xfc\x0f\xf8\x7f\xff\x7f\xff\x7f\xff\xff\xff\xff\xff\xff\xff' max_bits = '\xff\xff\xff\xff\xff\xff\x07\xf0\xf7\xf7\x07\xf0\xf7\xf7\xf7\xf7' \ '\xf7\xf7\xf7\xf7\xf7\xf7\x07\xf0\xff\xff\xff\xff\xff\xff\xff\xff' restore_bits = '\xff\xff\xff\xff\xff\xff\x1f\xf0\x1f\xf0\xdf\xf7\x07\xf4\x07\xf4' \ '\xf7\xf5\xf7\xf1\xf7\xfd\xf7\xfd\x07\xfc\xff\xff\xff\xff\xff\xff' # PyAUI Event wxEVT_AUI_PANEBUTTON = wx.NewEventType() EVT_AUI_PANEBUTTON = wx.PyEventBinder(wxEVT_AUI_PANEBUTTON, 0) def GetCloseData(): return zlib.decompress( 'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\x02 \xcc\xc1\ \x06$\xe5?\xffO\x04R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4Gy\xba8\x86X\xf4\ \x9e\r:\xcd\xc7\xa0\xc0\xe1\xf5\xfb\xbf\xff\xbb\xc2\xacb6\xdbg\xaez\xb9|\x1c\ \x9a\x82kU\x99xW\x16K\xf5\xdccS\xdad\xe9\xf3\xe0\xa4\x0f\x0f\xaf\xcb\xea\x88\ \x8bV\xd7k\x1eoN\xdf\xb2\xdd\xc8\xd0\xe7Cw2{\xdd\\uf\xfd}3\x0f\xb0\xd4=\x0ff\ \xdfr$\\\xe5\xcf\xa9\xfd3\xfa\xcdu\xa4\x7fk\xa6\x89\x03ma\xf0t\xf5sY\xe7\x94\ \xd0\x04\x00\x1714z') def GetCloseBitmap(): return wx.BitmapFromImage(GetCloseImage()) def GetCloseImage(): stream = cStringIO.StringIO(GetCloseData()) return wx.ImageFromStream(stream) def Colorize(i, color): if wx.VERSION_STRING < "2.7": i.Replace(255,255,255,123,123,123) i.Replace(0,0,0,color.Red(),color.Green(),color.Blue()) i.SetMaskColour(123,123,123) else: i.Replace(0,0,0,123,123,123) i.Replace(255,255,255,color.Red(),color.Green(),color.Blue()) i.SetMaskColour(123,123,123) def GetRestoreImage(color): i = wx.ImageFromBitmap(wx.BitmapFromBits(restore_bits, 16, 16, 1)) Colorize(i, color) return i def GetMaximizeImage(color): i = wx.ImageFromBitmap(wx.BitmapFromBits(max_bits, 16, 16, 1)) Colorize(i, color) return i def GetPinImage(color): i = wx.ImageFromBitmap(wx.BitmapFromBits(pin_bits, 16, 16, 1)) Colorize(i, color) return i def StepColour(c, percent): """ StepColour() it a utility function that simply darkens a color by the specified percentage. """ r = c.Red() g = c.Green() b = c.Blue() return wx.Colour(min((r*percent)/100, 255), min((g*percent)/100, 255), min((b*percent)/100, 255)) def LightContrastColour(c): amount = 120 # if the color is especially dark, then # make the contrast even lighter if c.Red() < 128 and c.Green() < 128 and c.Blue() < 128: amount = 160 return StepColour(c, amount) def BitmapFromBits(color, type=0): """ BitmapFromBits() is a utility function that creates a masked bitmap from raw bits (XBM format). """ if type == 0: # Close Bitmap img = GetCloseImage() elif type == 1: # this should be GetClosePin()... but what the hell is a "pin"? img = GetPinImage(color) elif type == 2: img = GetMaximizeImage(color) elif type == 3: img = GetRestoreImage(color) img.Replace(255, 255, 255, 123, 123, 123) img.Replace(0, 0, 0, color.Red(), color.Green(), color.Blue()) return img.ConvertToBitmap() def DrawGradientRectangle(dc, rect, start_color, end_color, direction): rd = end_color.Red() - start_color.Red() gd = end_color.Green() - start_color.Green() bd = end_color.Blue() - start_color.Blue() if direction == AUI_GRADIENT_VERTICAL: high = rect.GetHeight() - 1 else: high = rect.GetWidth() - 1 for ii in xrange(high+1): r = start_color.Red() + ((ii*rd*100)/high)/100 g = start_color.Green() + ((ii*gd*100)/high)/100 b = start_color.Blue() + ((ii*bd*100)/high)/100 p = wx.Pen(wx.Colour(r, g, b)) dc.SetPen(p) if direction == AUI_GRADIENT_VERTICAL: dc.DrawLine(rect.x, rect.y+ii, rect.x+rect.width, rect.y+ii) else: dc.DrawLine(rect.x+ii, rect.y, rect.x+ii, rect.y+rect.height) class DockInfo: def __init__(self): self.dock_direction = 0 self.dock_layer = 0 self.dock_row = 0 self.size = 0 self.min_size = 0 self.resizable = True self.fixed = False self.toolbar = False self.rect = wx.Rect() self.panes = [] def IsOk(self): return (self.dock_direction != 0 and [True] or [False])[0] def IsHorizontal(self): return ((self.dock_direction == AUI_DOCK_TOP or \ self.dock_direction == AUI_DOCK_BOTTOM) and \ [True] or [False])[0] def IsVertical(self): return ((self.dock_direction == AUI_DOCK_LEFT or \ self.dock_direction == AUI_DOCK_RIGHT or \ self.dock_direction == AUI_DOCK_CENTER) and [True] or [False])[0] class DockUIPart: typeCaption = 0 typeGripper = 1 typeDock = 2 typeDockSizer = 3 typePane = 4 typePaneSizer = 5 typeBackground = 6 typePaneBorder = 7 typePaneButton = 8 def __init__(self): self.orientation = wx.VERTICAL self.type = 0 self.rect = wx.Rect() class PaneButton: def __init__(self, button_id): self.button_id = button_id # event declarations/classes class FrameManagerEvent(wx.PyCommandEvent): def __init__(self, eventType, id=1): wx.PyCommandEvent.__init__(self, eventType, id) self.pane = None self.button = 0 def SetPane(self, p): self.pane = p def SetButton(self, b): self.button = b def GetPane(self): return self.pane def GetButton(self): return self.button # -- DefaultDockArt class implementation -- # # DefaultDockArt is an art provider class which does all of the drawing for # FrameManager. This allows the library caller to customize the dock art # (probably by deriving from this class), or to completely replace all drawing # with custom dock art. The active dock art class can be set via # FrameManager.SetDockArt() class DefaultDockArt: def __init__(self): base_color = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE) darker1_color = StepColour(base_color, 85) darker2_color = StepColour(base_color, 70) darker3_color = StepColour(base_color, 60) darker4_color = StepColour(base_color, 50) darker5_color = StepColour(base_color, 40) self._active_caption_colour = LightContrastColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT)) self._active_caption_gradient_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHT) self._active_caption_text_colour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT) self._inactive_caption_colour = StepColour(darker1_color, 80) self._inactive_caption_gradient_colour = darker1_color self._inactive_caption_text_colour = wx.BLACK sash_color = base_color caption_color = darker1_color paneborder_color = darker2_color selectbutton_color = base_color selectbuttonpen_color = darker3_color self._sash_brush = wx.Brush(base_color) self._background_brush = wx.Brush(base_color) self._border_pen = wx.Pen(darker2_color) self._gripper_brush = wx.Brush(base_color) self._gripper_pen1 = wx.Pen(darker5_color) self._gripper_pen2 = wx.Pen(darker3_color) self._gripper_pen3 = wx.WHITE_PEN self._caption_font = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False) self._inactive_close_bitmap = BitmapFromBits(self._inactive_caption_text_colour, 0) self._inactive_pin_bitmap = BitmapFromBits(self._inactive_caption_text_colour, 1) self._inactive_max_bitmap = BitmapFromBits(self._inactive_caption_text_colour, 2) self._inactive_restore_bitmap = BitmapFromBits(self._inactive_caption_text_colour, 3) self._active_close_bitmap = BitmapFromBits(self._active_caption_text_colour, 0) self._active_pin_bitmap = BitmapFromBits(self._active_caption_text_colour, 1) self._active_max_bitmap = BitmapFromBits(self._active_caption_text_colour, 2) self._active_restore_bitmap = BitmapFromBits(self._active_caption_text_colour, 3) # default metric values self._sash_size = 4 self._caption_size = 17 self._border_size = 1 self._button_size = 14 self._gripper_size = 9 self._gradient_type = AUI_GRADIENT_VERTICAL self._draw_sash = False def GetMetric(self, id): if id == AUI_ART_SASH_SIZE: return self._sash_size elif id == AUI_ART_CAPTION_SIZE: return self._caption_size elif id == AUI_ART_GRIPPER_SIZE: return self._gripper_size elif id == AUI_ART_PANE_BORDER_SIZE: return self._border_size elif id == AUI_ART_PANE_BUTTON_SIZE: return self._button_size elif id == AUI_ART_GRADIENT_TYPE: return self._gradient_type elif id == AUI_ART_DRAW_SASH_GRIP: return self._draw_sash else: raise "\nERROR: Invalid Metric Ordinal. " def SetMetric(self, id, new_val): if id == AUI_ART_SASH_SIZE: self._sash_size = new_val elif id == AUI_ART_CAPTION_SIZE: self._caption_size = new_val elif id == AUI_ART_GRIPPER_SIZE: self._gripper_size = new_val elif id == AUI_ART_PANE_BORDER_SIZE: self._border_size = new_val elif id == AUI_ART_PANE_BUTTON_SIZE: self._button_size = new_val elif id == AUI_ART_GRADIENT_TYPE: self._gradient_type = new_val elif id == AUI_ART_DRAW_SASH_GRIP: self._draw_sash = new_val else: raise "\nERROR: Invalid Metric Ordinal. " def GetColor(self, id): if id == AUI_ART_BACKGROUND_COLOUR: return self._background_brush.GetColour() elif id == AUI_ART_SASH_COLOUR: return self._sash_brush.GetColour() elif id == AUI_ART_INACTIVE_CAPTION_COLOUR: return self._inactive_caption_colour elif id == AUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR: return self._inactive_caption_gradient_colour elif id == AUI_ART_INACTIVE_CAPTION_TEXT_COLOUR: return self._inactive_caption_text_colour elif id == AUI_ART_ACTIVE_CAPTION_COLOUR: return self._active_caption_colour elif id == AUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR: return self._active_caption_gradient_colour elif id == AUI_ART_ACTIVE_CAPTION_TEXT_COLOUR: return self._active_caption_text_colour elif id == AUI_ART_BORDER_COLOUR: return self._border_pen.GetColour() elif id == AUI_ART_GRIPPER_COLOUR: return self._gripper_brush.GetColour() else: raise "\nERROR: Invalid Metric Ordinal. " def SetColor(self, id, colour): if id == AUI_ART_BACKGROUND_COLOUR: self._background_brush.SetColour(colour) elif id == AUI_ART_SASH_COLOUR: self._sash_brush.SetColour(colour) elif id == AUI_ART_INACTIVE_CAPTION_COLOUR: self._inactive_caption_colour = colour elif id == AUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR: self._inactive_caption_gradient_colour = colour elif id == AUI_ART_INACTIVE_CAPTION_TEXT_COLOUR: self._inactive_caption_text_colour = colour elif id == AUI_ART_ACTIVE_CAPTION_COLOUR: self._active_caption_colour = colour elif id == AUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR: self._active_caption_gradient_colour = colour elif id == AUI_ART_ACTIVE_CAPTION_TEXT_COLOUR: self._active_caption_text_colour = colour elif id == AUI_ART_BORDER_COLOUR: self._border_pen.SetColour(colour) elif id == AUI_ART_GRIPPER_COLOUR: self._gripper_brush.SetColour(colour) self._gripper_pen1.SetColour(StepColour(colour, 40)) self._gripper_pen2.SetColour(StepColour(colour, 60)) else: raise "\nERROR: Invalid Metric Ordinal. " GetColour = GetColor SetColour = SetColor def SetFont(self, id, font): if id == AUI_ART_CAPTION_FONT: self._caption_font = font def GetFont(self, id): if id == AUI_ART_CAPTION_FONT: return self._caption_font return wx.NoneFont def DrawSash(self, dc, orient, rect): dc.SetPen(wx.TRANSPARENT_PEN) dc.SetBrush(self._sash_brush) dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) draw_sash = self.GetMetric(AUI_ART_DRAW_SASH_GRIP) if draw_sash: self.DrawSashGripper(dc, orient, rect) def DrawBackground(self, dc, orient, rect): dc.SetPen(wx.TRANSPARENT_PEN) dc.SetBrush(self._background_brush) dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) def DrawBorder(self, dc, rect, pane): drect = wx.Rect() drect.x = rect.x drect.y = rect.y drect.width = rect.width drect.height = rect.height dc.SetPen(self._border_pen) dc.SetBrush(wx.TRANSPARENT_BRUSH) border_width = self.GetMetric(AUI_ART_PANE_BORDER_SIZE) if pane.IsToolbar(): for ii in xrange(0, border_width): dc.SetPen(wx.WHITE_PEN) dc.DrawLine(drect.x, drect.y, drect.x+drect.width, drect.y) dc.DrawLine(drect.x, drect.y, drect.x, drect.y+drect.height) dc.SetPen(self._border_pen) dc.DrawLine(drect.x, drect.y+drect.height-1, drect.x+drect.width, drect.y+drect.height-1) dc.DrawLine(drect.x+drect.width-1, drect.y, drect.x+drect.width-1, drect.y+drect.height) drect.Deflate(1, 1) else: for ii in xrange(0, border_width): dc.DrawRectangle(drect.x, drect.y, drect.width, drect.height) drect.Deflate(1, 1) def DrawCaptionBackground(self, dc, rect, active): if self._gradient_type == AUI_GRADIENT_NONE: if active: dc.SetBrush(wx.Brush(self._active_caption_colour)) else: dc.SetBrush(wx.Brush(self._inactive_caption_colour)) dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) else: if active: DrawGradientRectangle(dc, rect, self._active_caption_colour, self._active_caption_gradient_colour, self._gradient_type) else: DrawGradientRectangle(dc, rect, self._inactive_caption_colour, self._inactive_caption_gradient_colour, self._gradient_type) def DrawIcon(self, dc, rect, pane): # Draw the icon centered vertically if pane.icon.Ok(): dc.DrawBitmap(pane.icon, rect.x+2, rect.y+(rect.height-pane.icon.GetHeight())/2, True) def DrawCaption(self, dc, text, rect, pane): dc.SetPen(wx.TRANSPARENT_PEN) dc.SetFont(self._caption_font) self.DrawCaptionBackground(dc, rect, ((pane.state & PaneInfo.optionActive) and \ [True] or [False])[0]) if pane.state & PaneInfo.optionActive: dc.SetTextForeground(self._active_caption_text_colour) else: dc.SetTextForeground(self._inactive_caption_text_colour) w, h = dc.GetTextExtent("ABCDEFHXfgkj") dc.SetClippingRegion(rect.x, rect.y, rect.width, rect.height) caption_offset = 0 if pane.icon: caption_offset += pane.icon.GetWidth() + 3 self.DrawIcon(dc, rect, pane) dc.DrawText(text, rect.x+3+caption_offset, rect.y+(rect.height/2)-(h/2)-1) dc.DestroyClippingRegion() def DrawGripper(self, dc, rect, pane): dc.SetPen(wx.TRANSPARENT_PEN) dc.SetBrush(self._gripper_brush) dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) if not pane.HasGripperTop(): y = 5 while 1: dc.SetPen(self._gripper_pen1) dc.DrawPoint(rect.x+3, rect.y+y) dc.SetPen(self._gripper_pen2) dc.DrawPoint(rect.x+3, rect.y+y+1) dc.DrawPoint(rect.x+4, rect.y+y) dc.SetPen(self._gripper_pen3) dc.DrawPoint(rect.x+5, rect.y+y+1) dc.DrawPoint(rect.x+5, rect.y+y+2) dc.DrawPoint(rect.x+4, rect.y+y+2) y = y + 4 if y > rect.GetHeight() - 5: break else: x = 5 while 1: dc.SetPen(self._gripper_pen1) dc.DrawPoint(rect.x+x, rect.y+3) dc.SetPen(self._gripper_pen2) dc.DrawPoint(rect.x+x+1, rect.y+3) dc.DrawPoint(rect.x+x, rect.y+4) dc.SetPen(self._gripper_pen3) dc.DrawPoint(rect.x+x+1, rect.y+5) dc.DrawPoint(rect.x+x+2, rect.y+5) dc.DrawPoint(rect.x+x+2, rect.y+4) x = x + 4 if x > rect.GetWidth() - 5: break def DrawPaneButton(self, dc, button, button_state, rect, pane): drect = wx.Rect() drect.x = rect.x drect.y = rect.y drect.width = rect.width drect.height = rect.height if button_state == AUI_BUTTON_STATE_PRESSED: drect.x = drect.x + 1 drect.y = drect.y + 1 if button_state in [AUI_BUTTON_STATE_HOVER, AUI_BUTTON_STATE_PRESSED]: if pane.state & PaneInfo.optionActive: dc.SetBrush(wx.Brush(StepColour(self._active_caption_colour, 120))) dc.SetPen(wx.Pen(StepColour(self._active_caption_colour, 70))) else: dc.SetBrush(wx.Brush(StepColour(self._inactive_caption_colour, 120))) dc.SetPen(wx.Pen(StepColour(self._inactive_caption_colour, 70))) # draw the background behind the button dc.DrawRectangle(drect.x, drect.y, 15, 15) bmp = None if button == PaneInfo.buttonClose: if pane.state & PaneInfo.optionActive: bmp = self._active_close_bitmap else: bmp = self._inactive_close_bitmap elif button == PaneInfo.buttonPin: if pane.state & PaneInfo.optionActive: bmp = self._active_pin_bitmap else: bmp = self._inactive_pin_bitmap elif button == PaneInfo.buttonMaximize: if not pane.IsMaximized(): if pane.state & PaneInfo.optionActive: bmp = self._active_max_bitmap else: bmp = self._inactive_max_bitmap else: if pane.state & PaneInfo.optionActive: bmp = self._active_restore_bitmap else: bmp = self._inactive_restore_bitmap # draw the button itself dc.DrawBitmap(bmp, drect.x, drect.y, True) def DrawSashGripper(self, dc, orient, rect): dc.SetBrush(self._gripper_brush) if orient == wx.HORIZONTAL: # horizontal sash x = rect.x + int((1.0/4.0)*rect.width) xend = rect.x + int((3.0/4.0)*rect.width) y = rect.y + (rect.height/2) - 1 while 1: dc.SetPen(self._gripper_pen3) dc.DrawRectangle(x, y, 2, 2) dc.SetPen(self._gripper_pen2) dc.DrawPoint(x+1, y+1) x = x + 5 if x >= xend: break else: y = rect.y + int((1.0/4.0)*rect.height) yend = rect.y + int((3.0/4.0)*rect.height) x = rect.x + (rect.width/2) - 1 while 1: dc.SetPen(self._gripper_pen3) dc.DrawRectangle(x, y, 2, 2) dc.SetPen(self._gripper_pen2) dc.DrawPoint(x+1, y+1) y = y + 5 if y >= yend: break if _ctypes: class RECT(ctypes.Structure): _fields_ = [('left', ctypes.c_ulong),('top', ctypes.c_ulong),('right', ctypes.c_ulong),('bottom', ctypes.c_ulong)] def dump(self): return map(int, (self.left, self.top, self.right, self.bottom)) class SIZE(ctypes.Structure): _fields_ = [('x', ctypes.c_long),('y', ctypes.c_long)] class ModernDockArt(DefaultDockArt): def __init__(self, win): DefaultDockArt.__init__(self) self.usingTheme = False self.win = win self.lib = ctypes.windll.LoadLibrary("uxtheme.dll") # Get the size of a small close button (themed) hwnd = self.win.GetHandle() hTheme = self.lib.GetWindowTheme(hwnd) self.hTheme = _winxptheme.OpenThemeData(hwnd, "Window") self.usingTheme = True dc = wx.ClientDC(self.win) hdc = dc.GetHDC() sz = SIZE() self.lib.GetThemePartSize(self.hTheme.handle, hdc, 19, 1, None, 1, ctypes.byref(sz)) self._button_size = sz.x # We only highlight the active pane with the caption text being in bold. # So we do not want a special colour for active elements. self._active_caption_colour = self._inactive_caption_colour self._active_close_bitmap = self._inactive_close_bitmap del dc def DrawCaption(self, dc, text, rect, pane): dc.SetPen(wx.TRANSPARENT_PEN) self.DrawCaptionBackground(dc, rect, ((pane.state & PaneInfo.optionActive) and \ [True] or [False])[0]) self._caption_font.SetWeight(wx.FONTWEIGHT_BOLD) dc.SetFont(self._caption_font) dc.SetTextForeground(self._active_caption_text_colour) w, h = dc.GetTextExtent("ABCDEFHXfgkj") dc.SetClippingRegion(rect.x, rect.y, rect.width, rect.height) caption_offset = 0 if pane.icon: caption_offset += pane.icon.GetWidth() + 3 self.DrawIcon(dc, rect, pane) dc.DrawText(text, rect.x+3+caption_offset, rect.y+(rect.height/2)-(h/2)-1) dc.DestroyClippingRegion() def DrawCaptionBackground(self, dc, rect, active): dc.SetBrush(self._background_brush) dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height) if self.usingTheme: rectangle = wx.Rect() rectangle.x = rect.x rectangle.y = rect.y rectangle.width = rect.width rectangle.height = rect.height rectangle.x = rectangle.x - 1 rectangle.y = rectangle.y - 1 rectangle.width += 2 rectangle.height += 2 rc = RECT(rectangle.x, rectangle.y, rectangle.width, rectangle.height) if active: _winxptheme.DrawThemeBackground(self.hTheme, dc.GetHDC(), 5, 1, (rectangle.x, rectangle.y, rectangle.width, rectangle.height), None) else: _winxptheme.DrawThemeBackground(self.hTheme, dc.GetHDC(), 5, 2, (rectangle.x, rectangle.y, rectangle.width, rectangle.height), None) else: wx.RendererNative.Get().DrawHeaderButton(self.win, dc, rect, wx.CONTROL_FOCUSED) def DrawPaneButton(self, dc, button, button_state, rect, pane): if self.usingTheme: # Get the real button position (compensating for borders) drect = wx.Rect(rect.x, rect.y, self._button_size, self._button_size) # Draw the themed close button rc = RECT(drect.x, drect.y, drect.width, drect.height) state = 4 # CBS_DISABLED if pane.state & PaneInfo.optionActive: if button_state == AUI_BUTTON_STATE_NORMAL: state = 1 # CBS_NORMAL elif button_state == AUI_BUTTON_STATE_HOVER: state = 2 # CBS_HOT elif button_state == AUI_BUTTON_STATE_PRESSED: state = 3 # CBS_PUSHED else: raise "\nERROR: Unknown State." else: # inactive pane if button_state == AUI_BUTTON_STATE_NORMAL: state = 5 # CBS_NORMAL elif button_state == AUI_BUTTON_STATE_HOVER: state = 6 # CBS_HOT elif button_state == AUI_BUTTON_STATE_PRESSED: state = 7 # CBS_PUSHED else: raise "\nERROR: Unknown State." _winxptheme.DrawThemeBackground(self.hTheme, dc.GetHDC(), 19, state, (drect.x, drect.y, drect.width, drect.height), None) else: # Fallback to default closebutton if themes are not enabled DefaultDockArt.DrawPaneButton(self, dc, button, button_state, rect, pane) # -- PaneInfo class implementation -- # # PaneInfo specifies all the parameters for a pane. These parameters specify where # the pane is on the screen, whether it is docked or floating, or hidden. In addition, # these parameters specify the pane's docked position, floating position, preferred # size, minimum size, caption text among many other parameters. class PaneInfo(object): optionFloating = 2**0 optionHidden = 2**1 optionLeftDockable = 2**2 optionRightDockable = 2**3 optionTopDockable = 2**4 optionBottomDockable = 2**5 optionFloatable = 2**6 optionMovable = 2**7 optionResizable = 2**8 optionPaneBorder = 2**9 optionCaption = 2**10 optionGripper = 2**11 optionDestroyOnClose = 2**12 optionToolbar = 2**13 optionActive = 2**14 optionGripperTop = 2**15 buttonClose = 2**24 buttonFloatClose = 2**25 buttonMaximize = 2**26 buttonMinimize = 2**27 buttonPin = 2**28 buttonCustom1 = 2**29 buttonCustom2 = 2**30 buttonCustom3 = 2**31 actionPane = 2**32 # used internally stateHiddenSaved = 2**16 stateMaximized = 2**17 def __init__(self): self.window = None self.frame = None self.state = 0 self.dock_direction = AUI_DOCK_LEFT self.dock_layer = 0 self.dock_row = 0 self.dock_pos = 0 self.floating_pos = wx.Point(-1, -1) self.floating_size = wx.Size(-1, -1) self.best_size = wx.Size(-1, -1) self._best_size = wx.Size(-1, -1) self.min_size = wx.Size(-1, -1) self.max_size = wx.Size(-1, -1) self.dock_proportion = 0 self.caption = "" self.buttons = [] self.name = "" self.icon = None self.rect = wx.Rect() self.DefaultPane() def dock_direction_get(self): if self.IsMaximized(): return AUI_DOCK_CENTER else: return self._dock_direction def dock_direction_set(self, value): self._dock_direction = value dock_direction = property(dock_direction_get, dock_direction_set) def IsOk(self): """ IsOk() returns True if the PaneInfo structure is valid. """ return (self.window != None and [True] or [False])[0] def IsMaximized(self): """ IsMaximized() returns True if the pane is maximized. """ return self.HasFlag(self.stateMaximized) def IsFixed(self): """ IsFixed() returns True if the pane cannot be resized. """ return not self.HasFlag(self.optionResizable) def IsResizable(self): """ IsResizeable() returns True if the pane can be resized. """ return self.HasFlag(self.optionResizable) def IsShown(self): """ IsShown() returns True if the pane should be drawn on the screen. """ return not self.HasFlag(self.optionHidden) def IsFloating(self): """ IsFloating() returns True if the pane is floating. """ return self.HasFlag(self.optionFloating) def IsDocked(self): """ IsDocked() returns True if the pane is docked. """ return not self.HasFlag(self.optionFloating) def IsToolbar(self): """ IsToolbar() returns True if the pane contains a toolbar. """ return self.HasFlag(self.optionToolbar) def IsTopDockable(self): """ IsTopDockable() returns True if the pane can be docked at the top of the managed frame. """ return self.HasFlag(self.optionTopDockable) def IsBottomDockable(self): """ IsBottomDockable() returns True if the pane can be docked at the bottom of the managed frame. """ return self.HasFlag(self.optionBottomDockable) def IsLeftDockable(self): """ IsLeftDockable() returns True if the pane can be docked at the left of the managed frame. """ return self.HasFlag(self.optionLeftDockable) def IsRightDockable(self): """ IsRightDockable() returns True if the pane can be docked at the right of the managed frame. """ return self.HasFlag(self.optionRightDockable) def IsDockable(self): """ IsDockable() returns True if the pane can be docked. """ return self.IsTopDockable() or self.IsBottomDockable() or self.IsLeftDockable() or \ self.IsRightDockable() def IsFloatable(self): """ IsFloatable() returns True if the pane can be undocked and displayed as a floating window. """ return self.HasFlag(self.optionFloatable) def IsMovable(self): """ IsMoveable() returns True if the docked frame can be undocked or moved to another dock position. """ return self.HasFlag(self.optionMovable) def HasCaption(self): """ HasCaption() returns True if the pane displays a caption. """ return self.HasFlag(self.optionCaption) def HasGripper(self): """ HasGripper() returns True if the pane displays a gripper. """ return self.HasFlag(self.optionGripper) def HasBorder(self): """ HasBorder() returns True if the pane displays a border. """ return self.HasFlag(self.optionPaneBorder) def HasCloseButton(self): """ HasCloseButton() returns True if the pane displays a button to close the pane. """ return self.HasFlag(self.buttonClose) def HasMaximizeButton(self): """ HasMaximizeButton() returns True if the pane displays a button to maximize the pane. """ return self.HasFlag(self.buttonMaximize) def HasMinimizeButton(self): """ HasMinimizeButton() returns True if the pane displays a button to minimize the pane. """ return self.HasFlag(self.buttonMinimize) def HasPinButton(self): """ HasPinButton() returns True if the pane displays a button to float the pane. """ return self.HasFlag(self.buttonPin) def HasGripperTop(self): return self.HasFlag(self.optionGripperTop) def Window(self, w): self.window = w return self def Name(self, n): """ Name() sets the name of the pane so it can be referenced in lookup functions. """ self.name = n return self def Caption(self, c): """ Caption() sets the caption of the pane. """ self.caption = c return self def Left(self): """ Left() sets the pane dock position to the left side of the frame. """ self.dock_direction = AUI_DOCK_LEFT return self def Right(self): """ Right() sets the pane dock position to the right side of the frame. """ self.dock_direction = AUI_DOCK_RIGHT return self def Top(self): """ Top() sets the pane dock position to the top of the frame. """ self.dock_direction = AUI_DOCK_TOP return self def Bottom(self): """ Bottom() sets the pane dock position to the bottom of the frame. """ self.dock_direction = AUI_DOCK_BOTTOM return self def Center(self): """ Center() sets the pane to the center position of the frame. """ self.dock_direction = AUI_DOCK_CENTER return self def Centre(self): """ Centre() sets the pane to the center position of the frame. """ self.dock_direction = AUI_DOCK_CENTRE return self def Direction(self, direction): """ Direction() determines the direction of the docked pane. """ self.dock_direction = direction return self def Layer(self, layer): """ Layer() determines the layer of the docked pane. """ self.dock_layer = layer return self def Row(self, row): """ Row() determines the row of the docked pane. """ self.dock_row = row return self def Position(self, pos): """ Position() determines the position of the docked pane. """ self.dock_pos = pos return self def MinSize(self, arg1=None, arg2=None): """ MinSize() sets the minimum size of the pane. """ if isinstance(arg1, wx.Size): ret = self.MinSize1(arg1) else: ret = self.MinSize2(arg1, arg2) return ret def MinSize1(self, size): self.min_size = size return self def MinSize2(self, x, y): self.min_size.Set(x,y) return self def MaxSize(self, arg1=None, arg2=None): """ MaxSize() sets the maximum size of the pane. """ if isinstance(arg1, wx.Size): ret = self.MaxSize1(arg1) else: ret = self.MaxSize2(arg1, arg2) return ret def MaxSize1(self, size): self.max_size = size return self def MaxSize2(self, x, y): self.max_size.Set(x,y) return self def BestSize(self, arg1=None, arg2=None): """ BestSize() sets the ideal size for the pane. """ if isinstance(arg1, wx.Size): ret = self.BestSize1(arg1) else: ret = self.BestSize2(arg1, arg2) return ret def BestSize1(self, size): self.best_size = size return self def BestSize2(self, x, y): self.best_size.Set(x,y) return self def FloatingPosition(self, pos): """ FloatingPosition() sets the position of the floating pane. """ self.floating_pos = pos return self def FloatingSize(self, size): """ FloatingSize() sets the size of the floating pane. """ self.floating_size = size return self def Maximize(self): """ Maximized() makes the pane take up the full area.""" return self.SetFlag(self.stateMaximized, True) def Restore(self): """ Restore() reverse of Maximize.""" return self.SetFlag(self.stateMaximized, False) def Fixed(self): """ Fixed() forces a pane to be fixed size so that it cannot be resized. """ return self.SetFlag(self.optionResizable, False) def Resizable(self, resizable=True): """ Resizable() allows a pane to be resizable if resizable is True, and forces it to be a fixed size if resizeable is False. """ return self.SetFlag(self.optionResizable, resizable) def Dock(self): """ Dock() indicates that a pane should be docked. """ return self.SetFlag(self.optionFloating, False) def Float(self): """ Float() indicates that a pane should be floated. """ return self.SetFlag(self.optionFloating, True) def Hide(self): """ Hide() indicates that a pane should be hidden. """ return self.SetFlag(self.optionHidden, True) def Show(self, show=True): """ Show() indicates that a pane should be shown. """ return self.SetFlag(self.optionHidden, not show) def CaptionVisible(self, visible=True): """ CaptionVisible() indicates that a pane caption should be visible. """ return self.SetFlag(self.optionCaption, visible) def PaneBorder(self, visible=True): """ PaneBorder() indicates that a border should be drawn for the pane. """ return self.SetFlag(self.optionPaneBorder, visible) def Gripper(self, visible=True): """ Gripper() indicates that a gripper should be drawn for the pane. """ return self.SetFlag(self.optionGripper, visible) def GripperTop(self, attop=True): """ GripperTop() indicates that a gripper should be drawn for the pane. """ return self.SetFlag(self.optionGripperTop, attop) def CloseButton(self, visible=True): """ CloseButton() indicates that a close button should be drawn for the pane. """ return self.SetFlag(self.buttonClose, visible) def MaximizeButton(self, visible=True): """ MaximizeButton() indicates that a maximize button should be drawn for the pane. """ return self.SetFlag(self.buttonMaximize, visible) def MinimizeButton(self, visible=True): """ MinimizeButton() indicates that a minimize button should be drawn for the pane. """ return self return self.SetFlag(self.buttonMinimize, visible) def PinButton(self, visible=True): """ PinButton() indicates that a pin button should be drawn for the pane. """ return self.SetFlag(self.buttonPin, visible) def DestroyOnClose(self, b=True): """ DestroyOnClose() indicates whether a pane should be destroyed when it is closed. """ return self.SetFlag(self.optionDestroyOnClose, b) def TopDockable(self, b=True): """ TopDockable() indicates whether a pane can be docked at the top of the frame. """ return self.SetFlag(self.optionTopDockable, b) def BottomDockable(self, b=True): """ BottomDockable() indicates whether a pane can be docked at the bottom of the frame. """ return self.SetFlag(self.optionBottomDockable, b) def LeftDockable(self, b=True): """ LeftDockable() indicates whether a pane can be docked on the left of the frame. """ return self.SetFlag(self.optionLeftDockable, b) def RightDockable(self, b=True): """ RightDockable() indicates whether a pane can be docked on the right of the frame. """ return self.SetFlag(self.optionRightDockable, b) def Floatable(self, b=True): """ Floatable() indicates whether a frame can be floated. """ return self.SetFlag(self.optionFloatable, b) def Movable(self, b=True): """ Movable() indicates whether a frame can be moved. """ return self.SetFlag(self.optionMovable, b) def Dockable(self, b=True): return self.TopDockable(b).BottomDockable(b).LeftDockable(b).RightDockable(b) def DefaultPane(self): """ DefaultPane() specifies that the pane should adopt the default pane settings. """ state = self.state state |= self.optionTopDockable | self.optionBottomDockable | \ self.optionLeftDockable | self.optionRightDockable | \ self.optionFloatable | self.optionMovable | self.optionResizable | \ self.optionCaption | self.optionPaneBorder | self.buttonClose self.state = state return self def CentrePane(self): """ CentrePane() specifies that the pane should adopt the default center pane settings. """ return self.CenterPane() def CenterPane(self): """ CenterPane() specifies that the pane should adopt the default center pane settings. """ self.state = 0 return self.Center().PaneBorder().Resizable() def ToolbarPane(self): """ ToolbarPane() specifies that the pane should adopt the default toolbar pane settings. """ self.DefaultPane() state = self.state state |= (self.optionToolbar | self.optionGripper) state &= ~(self.optionResizable | self.optionCaption) if self.dock_layer == 0: self.dock_layer = 10 self.state = state return self def SetIcon(self, icon): self.icon = icon return self def SetFlag(self, flag, option_state): """ SetFlag() turns the property given by flag on or off with the option_state parameter. """ state = self.state if option_state: state |= flag else: state &= ~flag self.state = state return self def HasFlag(self, flag): """ HasFlag() returns True if the the property specified by flag is active for the pane. """ return (self.state & flag and [True] or [False])[0] NonePaneInfo = PaneInfo() # -- FloatingPane class implementation -- # # FloatingPane implements a frame class with some special functionality # which allows the library to sense when the frame move starts, is active, # and completes. Note that it contains it's own FrameManager instance, # which, in the future, would allow for nested managed frames. # For now, with wxMSW, the wx.MiniFrame window is used, but on wxGTK, wx.Frame if wx.Platform == "__WXGTK__": class FloatingPaneBaseClass(wx.Frame): def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=0): wx.Frame.__init__(self, parent, id, title, pos, size, style) else: class FloatingPaneBaseClass(wx.MiniFrame): def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=0): wx.MiniFrame.__init__(self, parent, id, title, pos, size, style) if wx.Platform == "__WXMAC__": self.MacSetMetalAppearance(True) class FloatingPane(FloatingPaneBaseClass): def __init__(self, parent, owner_mgr, id=wx.ID_ANY, title="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.RESIZE_BORDER | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.FRAME_NO_TASKBAR | wx.FRAME_FLOAT_ON_PARENT | wx.CLIP_CHILDREN, resizeborder=0): if not resizeborder: style = style & ~wx.RESIZE_BORDER FloatingPaneBaseClass.__init__(self, parent, id, title, pos, size, style) self._owner_mgr = owner_mgr self._moving = False self._last_rect = wx.Rect() self._mgr = FrameManager(None) self._mgr.SetFrame(self) self._mousedown = False self.SetExtraStyle(wx.WS_EX_PROCESS_IDLE) self.Bind(wx.EVT_CLOSE, self.OnClose) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_MOVE, self.OnMoveEvent) self.Bind(wx.EVT_MOVING, self.OnMoveEvent) self.Bind(wx.EVT_IDLE, self.OnIdle) self.Bind(wx.EVT_ACTIVATE, self.OnActivate) def CopyAttributes(self, pane, contained_pane): contained_pane.name = pane.name contained_pane.caption = pane.caption contained_pane.window = pane.window contained_pane.frame = pane.frame contained_pane.state = pane.state contained_pane.dock_direction = pane.dock_direction contained_pane.dock_layer = pane.dock_layer contained_pane.dock_row = pane.dock_row contained_pane.dock_pos = pane.dock_pos contained_pane.best_size = pane.best_size contained_pane.min_size = pane.min_size contained_pane.max_size = pane.max_size contained_pane.floating_pos = pane.floating_pos contained_pane.floating_size = pane.floating_size contained_pane.dock_proportion = pane.dock_proportion contained_pane.buttons = pane.buttons contained_pane.rect = pane.rect return contained_pane def SetPaneWindow(self, pane): self._pane_window = pane.window self._pane_window.Reparent(self) contained_pane = PaneInfo() contained_pane = self.CopyAttributes(pane, contained_pane) contained_pane.Dock().Center().Show(). \ CaptionVisible(False). \ PaneBorder(False). \ Layer(0).Row(0).Position(0) indx = self._owner_mgr._panes.index(pane) self._owner_mgr._panes[indx] = pane self._mgr.AddPane(self._pane_window, contained_pane) self._mgr.Update() if pane.min_size.IsFullySpecified(): tmp = self.GetSize() self.GetSizer().SetSizeHints(self) self.SetSize(tmp) self.SetTitle(pane.caption) if pane.floating_size != wx.DefaultSize: self.SetSize(pane.floating_size) self._owner_mgr._panes[indx] = pane else: size = pane.best_size if size == wx.DefaultSize: size = pane.min_size if size == wx.DefaultSize: size = self._pane_window.GetSize() if pane.HasGripper(): if pane.HasGripperTop(): size.y += self._owner_mgr._art.GetMetric(AUI_ART_GRIPPER_SIZE) else: size.x += self._owner_mgr._art.GetMetric(AUI_ART_GRIPPER_SIZE) pane.floating_size = size self._owner_mgr._panes[indx] = pane self.SetClientSize(size) def OnSize(self, event): self._owner_mgr.OnFloatingPaneResized(self._pane_window, event.GetSize()) def OnClose(self, event): e = FrameManagerEvent(wxEVT_AUI_PANEBUTTON) e.SetPane(self._owner_mgr.GetPane(self._pane_window)) e.SetButton(PaneInfo.buttonFloatClose) self._owner_mgr.ProcessMgrEvent(e) def OnMoveEvent(self, event): win_rect = self.GetRect() # skip the first move event if self._last_rect.IsEmpty(): self._last_rect = win_rect return # prevent frame redocking during resize if self._last_rect.GetSize() != win_rect.GetSize(): self._last_rect = win_rect return self._last_rect = win_rect if not self.IsMouseDown(): return if not self._moving: self.OnMoveStart() self._moving = True self.OnMoving(event.GetRect()) def IsMouseDown(self): if _newversion: ms = wx.GetMouseState() return ms.leftDown else: if wx.Platform == "__WXMSW__": if _libimported == "MH": return ((win32api.GetKeyState(win32con.VK_LBUTTON) & (1<<15))\ and [True] or [False])[0] elif _libimported == "ctypes": return ((ctypes.windll.user32.GetKeyState(1) & (1<<15)) and \ [True] or [False])[0] def OnIdle(self, event): if self._moving: if not self.IsMouseDown(): self._moving = False self.OnMoveFinished() else: event.RequestMore() event.Skip() def OnMoveStart(self): # notify the owner manager that the pane has started to move self._owner_mgr.OnFloatingPaneMoveStart(self._pane_window) def OnMoving(self, window_rect): # notify the owner manager that the pane is moving self._owner_mgr.OnFloatingPaneMoving(self._pane_window) def OnMoveFinished(self): # notify the owner manager that the pane has finished moving self._owner_mgr.OnFloatingPaneMoved(self._pane_window) def OnActivate(self, event): self._owner_mgr.OnFloatingPaneActivate(self._pane_window, event.GetActive()) # -- static utility functions -- def PaneCreateStippleBitmap(): data = [0, 0, 0, 192, 192, 192, 192, 192, 192, 0, 0, 0] img = wx.EmptyImage(2, 2) counter = 0 for ii in xrange(2): for jj in xrange(2): img.SetRGB(ii, jj, data[counter], data[counter+1], data[counter+2]) counter = counter + 3 return img.ConvertToBitmap() def DrawResizeHint(dc, rect): if wx.Platform == "__WXMSW__" and wx.App.GetComCtl32Version() >= 600: # Draw the nice XP style splitter dc.SetPen(wx.TRANSPARENT_PEN) dc.SetBrush(wx.BLACK_BRUSH) dc.SetLogicalFunction(wx.INVERT) dc.DrawRectangleRect(rect) else: stipple = PaneCreateStippleBitmap() brush = wx.BrushFromBitmap(stipple) dc.SetBrush(brush) dc.SetPen(wx.TRANSPARENT_PEN) dc.SetLogicalFunction(wx.XOR) dc.DrawRectangleRect(rect) def CopyDocksAndPanes(src_docks, src_panes): """ CopyDocksAndPanes() - this utility function creates shallow copies of the dock and pane info. DockInfo's usually contain pointers to PaneInfo classes, thus this function is necessary to reliably reconstruct that relationship in the new dock info and pane info arrays. """ dest_docks = src_docks dest_panes = src_panes for ii in xrange(len(dest_docks)): dock = dest_docks[ii] for jj in xrange(len(dock.panes)): for kk in xrange(len(src_panes)): if dock.panes[jj] == src_panes[kk]: dock.panes[jj] = dest_panes[kk] return dest_docks, dest_panes def CopyDocksAndPanes2(src_docks, src_panes): """ CopyDocksAndPanes2() - this utility function creates full copies of the dock and pane info. DockInfo's usually contain pointers to PaneInfo classes, thus this function is necessary to reliably reconstruct that relationship in the new dock info and pane info arrays. """ dest_docks = [] for ii in xrange(len(src_docks)): dest_docks.append(DockInfo()) dest_docks[ii].dock_direction = src_docks[ii].dock_direction dest_docks[ii].dock_layer = src_docks[ii].dock_layer dest_docks[ii].dock_row = src_docks[ii].dock_row dest_docks[ii].size = src_docks[ii].size dest_docks[ii].min_size = src_docks[ii].min_size dest_docks[ii].resizable = src_docks[ii].resizable dest_docks[ii].fixed = src_docks[ii].fixed dest_docks[ii].toolbar = src_docks[ii].toolbar dest_docks[ii].panes = src_docks[ii].panes dest_docks[ii].rect = src_docks[ii].rect dest_panes = [] for ii in xrange(len(src_panes)): dest_panes.append(PaneInfo()) dest_panes[ii].name = src_panes[ii].name dest_panes[ii].caption = src_panes[ii].caption dest_panes[ii].window = src_panes[ii].window dest_panes[ii].frame = src_panes[ii].frame dest_panes[ii].state = src_panes[ii].state dest_panes[ii].dock_direction = src_panes[ii].dock_direction dest_panes[ii].dock_layer = src_panes[ii].dock_layer dest_panes[ii].dock_row = src_panes[ii].dock_row dest_panes[ii].dock_pos = src_panes[ii].dock_pos dest_panes[ii].best_size = src_panes[ii].best_size dest_panes[ii].min_size = src_panes[ii].min_size dest_panes[ii].max_size = src_panes[ii].max_size dest_panes[ii].floating_pos = src_panes[ii].floating_pos dest_panes[ii].floating_size = src_panes[ii].floating_size dest_panes[ii].dock_proportion = src_panes[ii].dock_proportion dest_panes[ii].buttons = src_panes[ii].buttons dest_panes[ii].rect = src_panes[ii].rect dest_panes[ii].icon = src_panes[ii].icon for ii in xrange(len(dest_docks)): dock = dest_docks[ii] for jj in xrange(len(dock.panes)): for kk in xrange(len(src_panes)): if dock.panes[jj] == src_panes[kk]: dock.panes[jj] = dest_panes[kk] dest_docks[ii] = dock return dest_docks, dest_panes def GetMaxLayer(docks, dock_direction): """ GetMaxLayer() is an internal function which returns the highest layer inside the specified dock. """ max_layer = 0 for dock in docks: if dock.dock_direction == dock_direction and dock.dock_layer > max_layer and not dock.fixed: max_layer = dock.dock_layer return max_layer def GetMaxRow(panes, direction, layer): """ GetMaxRow() is an internal function which returns the highest layer inside the specified dock. """ max_row = 0 for pane in panes: if pane.dock_direction == direction and pane.dock_layer == layer and \ pane.dock_row > max_row: max_row = pane.dock_row return max_row def DoInsertDockLayer(panes, dock_direction, dock_layer): """ DoInsertDockLayer() is an internal function that inserts a new dock layer by incrementing all existing dock layer values by one. """ for ii in xrange(len(panes)): pane = panes[ii] if not pane.IsFloating() and pane.dock_direction == dock_direction and pane.dock_layer >= dock_layer: pane.dock_layer = pane.dock_layer + 1 panes[ii] = pane return panes def DoInsertDockRow(panes, dock_direction, dock_layer, dock_row): """ DoInsertDockRow() is an internal function that inserts a new dock row by incrementing all existing dock row values by one. """ for ii in xrange(len(panes)): pane = panes[ii] if not pane.IsFloating() and pane.dock_direction == dock_direction and \ pane.dock_layer == dock_layer and pane.dock_row >= dock_row: pane.dock_row = pane.dock_row + 1 panes[ii] = pane return panes def DoInsertPane(panes, dock_direction, dock_layer, dock_row, dock_pos): for ii in xrange(len(panes)): pane = panes[ii] if not pane.IsFloating() and pane.dock_direction == dock_direction and \ pane.dock_layer == dock_layer and pane.dock_row == dock_row and \ pane.dock_pos >= dock_pos: pane.dock_pos = pane.dock_pos + 1 panes[ii] = pane return panes def FindDocks(docks, dock_direction, dock_layer=-1, dock_row=-1, arr=[]): """ FindDocks() is an internal function that returns a list of docks which meet the specified conditions in the parameters and returns a sorted array (sorted by layer and then row). """ begin_layer = dock_layer end_layer = dock_layer begin_row = dock_row end_row = dock_row dock_count = len(docks) max_row = 0 max_layer = 0 # discover the maximum dock layer and the max row for ii in xrange(dock_count): max_row = max(max_row, docks[ii].dock_row) max_layer = max(max_layer, docks[ii].dock_layer) # if no dock layer was specified, search all dock layers if dock_layer == -1: begin_layer = 0 end_layer = max_layer # if no dock row was specified, search all dock row if dock_row == -1: begin_row = 0 end_row = max_row arr = [] for layer in xrange(begin_layer, end_layer+1): for row in xrange(begin_row, end_row+1): for ii in xrange(dock_count): d = docks[ii] if dock_direction == -1 or dock_direction == d.dock_direction: if d.dock_layer == layer and d.dock_row == row: arr.append(d) return arr def FindPaneInDock(dock, window): """ FindPaneInDock() looks up a specified window pointer inside a dock. If found, the corresponding PaneInfo pointer is returned, otherwise None. """ for p in dock.panes: if p.window == window: return p return None def RemovePaneFromDocks(docks, pane, exc=None): """ RemovePaneFromDocks() removes a pane window from all docks with a possible exception specified by parameter "except". """ for ii in xrange(len(docks)): d = docks[ii] if d == exc: continue pi = FindPaneInDock(d, pane.window) if pi: d.panes.remove(pi) docks[ii] = d return docks def RenumberDockRows(docks): """ RenumberDockRows() takes a dock and assigns sequential numbers to existing rows. Basically it takes out the gaps so if a dock has rows with numbers 0, 2, 5, they will become 0, 1, 2. """ for ii in xrange(len(docks)): dock = docks[ii] dock.dock_row = ii for jj in xrange(len(dock.panes)): dock.panes[jj].dock_row = ii docks[ii] = dock return docks def SetActivePane(panes, active_pane): for ii in xrange(len(panes)): pane = panes[ii] if pane.window == active_pane: if not pane.state & PaneInfo.optionActive: pane.state |= PaneInfo.optionActive e = wx.ActivateEvent(wx.wxEVT_ACTIVATE, True) # Generate an activation event for pane.window.ProcessEvent(e) # the pane that becomes activated pane.window.SetFocus() # and transfer focus to activated pane else: if pane.state & PaneInfo.optionActive: pane.state &= ~PaneInfo.optionActive # Generate a deactivation event for e = wx.ActivateEvent(wx.wxEVT_ACTIVATE, False) # the pane that becomes deactivated pane.window.ProcessEvent(e) panes[ii] = pane return panes def KillActivePane(panes): for ii in xrange(len(panes)): pane = panes[ii] if pane.state & PaneInfo.optionActive: pane.state &= ~PaneInfo.optionActive # Generate a deactivation event for e = wx.ActivateEvent(wx.wxEVT_ACTIVATE, False) # the pane that becomes deactivated pane.window.ProcessEvent(e) panes[ii] = pane return panes def PaneSortFunc(p1, p2): """ This function is used to sort panes by dock position. """ return (p1.dock_pos < p2.dock_pos and [-1] or [1])[0] def EscapeDelimiters(s): """ EscapeDelimiters() changes "" into "\" and "|" into "\|" in the input string. This is an internal functions which is used for saving perspectives. """ result = s.replace(";", "\\") result = result.replace("|", "|\\") return result actionNone = 0 actionResize = 1 actionClickButton = 2 actionClickCaption = 3 actionDragToolbarPane = 4 actionDragFloatingPane = 5 auiInsertRowPixels = 10 auiNewRowPixels = 40 auiLayerInsertPixels = 40 auiLayerInsertOffset = 5 # -- FrameManager class implementation -- # # FrameManager manages the panes associated with it for a particular wx.Frame, # using a pane's PaneInfo information to determine each pane's docking and # floating behavior. FrameManager uses wxPython's sizer mechanism to plan the # layout of each frame. It uses a replaceable dock art class to do all drawing, # so all drawing is localized in one area, and may be customized depending on an # applications' specific needs. # # FrameManager works as follows: The programmer adds panes to the class, or makes # changes to existing pane properties (dock position, floating state, show state, etc.). # To apply these changes, FrameManager's Update() function is called. This batch # processing can be used to avoid flicker, by modifying more than one pane at a time, # and then "committing" all of the changes at once by calling Update(). # # Panes can be added quite easily: # # text1 = wx.TextCtrl(self, -1) # text2 = wx.TextCtrl(self, -1) # self._mgr.AddPane(text1, wx.LEFT, "Pane Caption") # self._mgr.AddPane(text2, wx.BOTTOM, "Pane Caption") # self._mgr.Update() # # Later on, the positions can be modified easily. The following will float an # existing pane in a tool window: # self._mgr.GetPane(text1).Float() # Layers, Rows and Directions, Positions # Inside PyAUI, the docking layout is figured out by checking several pane parameters. # Four of these are important for determining where a pane will end up. # # Direction - Each docked pane has a direction, Top, Bottom, Left, Right, or Center. # This is fairly self-explanatory. The pane will be placed in the location specified # by this variable. # # Position - More than one pane can be placed inside of a "dock." Imagine to panes # being docked on the left side of a window. One pane can be placed over another. # In proportionally managed docks, the pane position indicates it's sequential position, # starting with zero. So, in our scenario with two panes docked on the left side, the # top pane in the dock would have position 0, and the second one would occupy position 1. # # Row - A row can allow for two docks to be placed next to each other. One of the most # common places for this to happen is in the toolbar. Multiple toolbar rows are allowed, # the first row being in row 0, and the second in row 1. Rows can also be used on # vertically docked panes. # # Layer - A layer is akin to an onion. Layer 0 is the very center of the managed pane. # Thus, if a pane is in layer 0, it will be closest to the center window (also sometimes # known as the "content window"). Increasing layers "swallow up" all layers of a lower # value. This can look very similar to multiple rows, but is different because all panes # in a lower level yield to panes in higher levels. The best way to understand layers # is by running the PyAUI sample (PyAUIDemo.py). class FrameManager(wx.EvtHandler): def __init__(self, frame=None, flags=None): """ Default Class Constructor. frame specifies the wx.Frame which should be managed. flags specifies options which allow the frame management behavior to be modified. """ wx.EvtHandler.__init__(self) self._action = actionNone self._last_mouse_move = wx.Point() self._hover_button = None self._art = DefaultDockArt() self._hint_wnd = None self._action_window = None self._last_hint = wx.Rect() self._hint_fadetimer = wx.Timer() self._hintshown = False if flags is None: flags = AUI_MGR_DEFAULT self._flags = flags self._active_pane = None self._has_maximized = False if frame: self.SetFrame(frame) self._panes = [] self._docks = [] self._uiparts = [] self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_SET_CURSOR, self.OnSetCursor) self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) self.Bind(wx.EVT_MOTION, self.OnMotion) self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveWindow) self.Bind(wx.EVT_TIMER, self.OnHintFadeTimer) self.Bind(wx.EVT_CHILD_FOCUS, self.OnChildFocus) self.Bind(wx.EVT_ACTIVATE, self.OnActivate) self.Bind(EVT_AUI_PANEBUTTON, self.OnPaneButton) def GetPaneByWidget(self, window): """ This version of GetPane() looks up a pane based on a 'pane window', see below comment for more info. """ for p in self._panes: if p.window == window: return p return NonePaneInfo def GetPaneByName(self, name): """ This version of GetPane() looks up a pane based on a 'pane name', see below comment for more info. """ for p in self._panes: if p.name == name: return p return NonePaneInfo def GetPane(self, item): """ GetPane() looks up a PaneInfo structure based on the supplied window pointer. Upon failure, GetPane() returns an empty PaneInfo, a condition which can be checked by calling PaneInfo.IsOk(). The pane info's structure may then be modified. Once a pane's info is modified, FrameManager.Update() must be called to realize the changes in the UI. AG: Added To Handle 2 Different Versions Of GetPane() For wxPython/Python. """ if isinstance(item, type("")): return self.GetPaneByName(item) else: return self.GetPaneByWidget(item) def GetAllPanes(self): """ GetAllPanes() returns a reference to all the pane info structures. """ return self._panes def HitTest(self, x, y): """ HitTest() is an internal function which determines which UI item the specified coordinates are over (x,y) specify a position in client coordinates. """ result = None for item in self._uiparts: # we are not interested in typeDock, because this space # isn't used to draw anything, just for measurements # besides, the entire dock area is covered with other # rectangles, which we are interested in. if item.type == DockUIPart.typeDock: continue # if we already have a hit on a more specific item, we are not # interested in a pane hit. If, however, we don't already have # a hit, returning a pane hit is necessary for some operations if (item.type == DockUIPart.typePane or \ item.type == DockUIPart.typePaneBorder) and result: continue # if the point is inside the rectangle, we have a hit if item.rect.Inside((x, y)): result = item return result # SetFlags() and GetFlags() allow the owner to set various # options which are global to FrameManager def SetFlags(self, flags): """ SetFlags() is used to specify FrameManager's settings flags. flags specifies options which allow the frame management behavior to be modified. """ self._flags = flags def GetFlags(self): """ GetFlags() returns the current manager's flags. """ return self._flags def SetFrame(self, frame): """ SetFrame() is usually called once when the frame manager class is being initialized. "frame" specifies the frame which should be managed by the frame manager. """ if not frame: raise "\nERROR: Specified Frame Must Be Non-Null. " self._frame = frame self._frame.PushEventHandler(self) # if the owner is going to manage an MDI parent frame, # we need to add the MDI client window as the default # center pane if isinstance(frame, wx.MDIParentFrame): mdi_frame = frame client_window = mdi_frame.GetClientWindow() if not client_window: raise "\nERROR: MDI Client Window Is Null. " self.AddPane(client_window, PaneInfo().Name("mdiclient"). CenterPane().PaneBorder(False)) SetManagedWindow = SetFrame def GetFrame(self): """ GetFrame() returns the frame pointer being managed by FrameManager. """ return self._frame def UnInit(self): """ UnInit() must be called, usually in the destructor of the frame class. If it is not called, usually this will result in a crash upon program exit. """ self._frame.RemoveEventHandler(self) def GetArtProvider(self): """ GetArtProvider() returns the current art provider being used. """ return self._art def ProcessMgrEvent(self, event): # first, give the owner frame a chance to override if self._frame: if self._frame.ProcessEvent(event): return self.ProcessEvent(event) def CanMakeWindowsTransparent(self): if wx.Platform == "__WXMSW__": version = wx.GetOsDescription() found = version.find("XP") >= 0 or version.find("2000") >= 0 or version.find("NT") >= 0 return found and _libimported elif wx.Platform == "__WXMAC__" and _carbon_dll: return True else: return False # on supported windows systems (Win2000 and greater), this function # will make a frame window transparent by a certain amount def MakeWindowTransparent(self, wnd, amount): if wnd.GetSize() == (0, 0): return # this API call is not in all SDKs, only the newer ones, so # we will runtime bind this if wx.Platform == "__WXMSW__": hwnd = wnd.GetHandle() if not hasattr(self, "_winlib"): if _libimported == "MH": self._winlib = win32api.LoadLibrary("user32") elif _libimported == "ctypes": self._winlib = ctypes.windll.user32 if _libimported == "MH": pSetLayeredWindowAttributes = win32api.GetProcAddress(self._winlib, "SetLayeredWindowAttributes") if pSetLayeredWindowAttributes == None: return exstyle = win32api.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) if 0 == (exstyle & 0x80000): win32api.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, exstyle | 0x80000) winxpgui.SetLayeredWindowAttributes(hwnd, 0, amount, 2) elif _libimported == "ctypes": style = self._winlib.GetWindowLongA(hwnd, 0xffffffecL) style |= 0x00080000 self._winlib.SetWindowLongA(hwnd, 0xffffffecL, style) self._winlib.SetLayeredWindowAttributes(hwnd, 0, amount, 2) elif wx.Platform == "__WXMAC__" and _carbon_dll: handle = _carbon_dll.GetControlOwner(wnd.GetHandle()) if amount == 0: amnt = float(0) else: amnt = float(amount)/255.0 #convert from the 0-255 amount to the float that Carbon wants _carbon_dll.SetWindowAlpha(handle, ctypes.c_float(amnt)) else: #shouldn't be called, but just in case... return def SetArtProvider(self, art_provider): """ SetArtProvider() instructs FrameManager to use the specified art provider for all drawing calls. This allows plugable look-and-feel features. """ # delete the last art provider, if any del self._art # assign the new art provider self._art = art_provider def AddPane(self, window, arg1=None, arg2=None): """ AddPane() tells the frame manager to start managing a child window. There are two versions of this function. The first verison allows the full spectrum of pane parameter possibilities (AddPane1). The second version is used for simpler user interfaces which do not require as much configuration (AddPane2). In wxPython, simply call AddPane. """ if type(arg1) == type(1): # This Is Addpane2 if arg1 is None: arg1 = wx.LEFT if arg2 is None: arg2 = "" return self.AddPane2(window, arg1, arg2) else: return self.AddPane1(window, arg1) def AddPane1(self, window, pane_info): # check if the pane has a valid window if not window: return False # check if the pane already exists if self.GetPane(pane_info.window).IsOk(): return False if isinstance(window, wx.ToolBar): window.SetBestFittingSize() self._panes.append(pane_info) pinfo = self._panes[-1] # set the pane window pinfo.window = window # if the pane's name identifier is blank, create a random string if len(pinfo.name) == 0 or pinfo.name == "": pinfo.name = ("%s%08x%08x%08x")%(pinfo.window.GetName(), time.time(), time.clock(), len(self._panes)) # set initial proportion (if not already set) if pinfo.dock_proportion == 0: pinfo.dock_proportion = 100000 pinfo.buttons = [] if pinfo.HasMaximizeButton(): button = PaneButton(None) button.button_id = PaneInfo.buttonMaximize pinfo.buttons.append(button) if pinfo.HasPinButton(): button = PaneButton(None) button.button_id = PaneInfo.buttonPin pinfo.buttons.append(button) if pinfo.HasCloseButton(): button = PaneButton(None) button.button_id = PaneInfo.buttonClose pinfo.buttons.append(button) if pinfo.best_size == wx.DefaultSize and pinfo.window: pinfo.best_size = pinfo.window.GetClientSize() if isinstance(pinfo.window, wx.ToolBar): # GetClientSize() doesn't get the best size for # a toolbar under some newer versions of wxWidgets, # so use GetBestSize() pinfo.best_size = pinfo.window.GetBestSize() # for some reason, wxToolBar::GetBestSize() is returning # a size that is a pixel shy of the correct amount. # I believe this to be the correct action, until # wxToolBar::GetBestSize() is fixed. Is this assumption # correct? pinfo.best_size.y = pinfo.best_size.y + 1 # this is needed for Win2000 to correctly fill toolbar backround # it should probably be repeated once system colour change happens if wx.Platform == "__WXMSW__" and pinfo.window.UseBgCol(): pinfo.window.SetBackgroundColour(self.GetArtProvider().GetColour(AUI_ART_BACKGROUND_COLOUR)) if pinfo.min_size != wx.DefaultSize: if pinfo.best_size.x < pinfo.min_size.x: pinfo.best_size.x = pinfo.min_size.x if pinfo.best_size.y < pinfo.min_size.y: pinfo.best_size.y = pinfo.min_size.y self._panes[-1] = pinfo return True def AddPane2(self, window, direction, caption): pinfo = PaneInfo() pinfo.Caption(caption) if direction == wx.TOP: pinfo.Top() elif direction == wx.BOTTOM: pinfo.Bottom() elif direction == wx.LEFT: pinfo.Left() elif direction == wx.RIGHT: pinfo.Right() elif direction == wx.CENTER: pinfo.CenterPane() return self.AddPane(window, pinfo) def InsertPane(self, window, pane_info, insert_level=AUI_INSERT_PANE): """ InsertPane() is used to insert either a previously unmanaged pane window into the frame manager, or to insert a currently managed pane somewhere else. InsertPane() will push all panes, rows, or docks aside and insert the window into the position specified by insert_location. Because insert_location can specify either a pane, dock row, or dock layer, the insert_level parameter is used to disambiguate this. The parameter insert_level can take a value of AUI_INSERT_PANE, AUI_INSERT_ROW or AUI_INSERT_DOCK. """ # shift the panes around, depending on the insert level if insert_level == AUI_INSERT_PANE: self._panes = DoInsertPane(self._panes, pane_info.dock_direction, pane_info.dock_layer, pane_info.dock_row, pane_info.dock_pos) elif insert_level == AUI_INSERT_ROW: self._panes = DoInsertDockRow(self._panes, pane_info.dock_direction, pane_info.dock_layer, pane_info.dock_row) elif insert_level == AUI_INSERT_DOCK: self._panes = DoInsertDockLayer(self._panes, pane_info.dock_direction, pane_info.dock_layer) # if the window already exists, we are basically just moving/inserting the # existing window. If it doesn't exist, we need to add it and insert it existing_pane = self.GetPane(window) indx = self._panes.index(existing_pane) if not existing_pane.IsOk(): return self.AddPane(window, pane_info) else: if pane_info.IsFloating(): existing_pane.Float() if pane_info.floating_pos != wx.DefaultPosition: existing_pane.FloatingPosition(pane_info.floating_pos) if pane_info.floating_size != wx.DefaultSize: existing_pane.FloatingSize(pane_info.floating_size) else: # if the new pane is docked then we should undo maximize self.RestoreMaximizedPane() existing_pane.Direction(pane_info.dock_direction) existing_pane.Layer(pane_info.dock_layer) existing_pane.Row(pane_info.dock_row) existing_pane.Position(pane_info.dock_pos) self._panes[indx] = existing_pane return True def DetachPane(self, window): """ DetachPane() tells the FrameManager to stop managing the pane specified by window. The window, if in a floated frame, is reparented to the frame managed by FrameManager. """ for p in self._panes: if p.window == window: if p.frame: # we have a floating frame which is being detached. We need to # reparent it to m_frame and destroy the floating frame # reduce flicker p.window.SetSize(1,1) p.frame.Show(False) # reparent to self._frame and destroy the pane p.window.Reparent(self._frame) p.frame.SetSizer(None) p.frame.Destroy() p.frame = None self._panes.remove(p) return True return False def MaximizePane(self, pane_info): """\ """ for p in self._panes: if not p.IsToolbar(): p.Restore() # save hidden state p.SetFlag(p.stateHiddenSaved, p.HasFlag(p.optionHidden)) # hide the pane, because only the newly # maximized pane should show p.Hide() # mark ourselves maximized pane_info.Maximize() pane_info.Show() self._has_maximized = True # last, show the window if pane_info.window and not pane_info.window.IsShown(): pane_info.window.Show(True) def RestorePane(self, pane_info): # restore all the panes for p in self._panes: if not p.IsToolbar(): p.SetFlag(p.optionHidden, p.HasFlag(p.stateHiddenSaved)) # mark ourselves non-maximized pane_info.Restore() self._has_maximized = False # last, show the window if pane_info.window and not pane_info.window.IsShown(): pane_info.window.Show(True) def RestoreMaximizedPane(self): # restore all the panes for p in self._panes: if p.IsMaximized(): self.RestorePane(p) break def SavePerspective(self): """ SavePerspective() saves all pane information as a single string. This string may later be fed into LoadPerspective() to restore all pane settings. This save and load mechanism allows an exact pane configuration to be saved and restored at a later time. """ result = "layout1|" pane_count = len(self._panes) for pane_i in xrange(pane_count): pane = self._panes[pane_i] result = result + "name=" + EscapeDelimiters(pane.name) + ";" result = result + "caption=" + EscapeDelimiters(pane.caption) + ";" result = result + "state=%u;"%pane.state result = result + "dir=%d;"%pane.dock_direction result = result + "layer=%d;"%pane.dock_layer result = result + "row=%d;"%pane.dock_row result = result + "pos=%d;"%pane.dock_pos result = result + "prop=%d;"%pane.dock_proportion result = result + "bestw=%d;"%pane.best_size.x result = result + "besth=%d;"%pane.best_size.y result = result + "minw=%d;"%pane.min_size.x result = result + "minh=%d;"%pane.min_size.y result = result + "maxw=%d;"%pane.max_size.x result = result + "maxh=%d;"%pane.max_size.y result = result + "floatx=%d;"%pane.floating_pos.x result = result + "floaty=%d;"%pane.floating_pos.y result = result + "floatw=%d;"%pane.floating_size.x result = result + "floath=%d;"%pane.floating_size.y result = result + "topdock=%d;"%pane.IsTopDockable() result = result + "leftdock=%d;"%pane.IsLeftDockable() result = result + "rightdock=%d;"%pane.IsRightDockable() result = result + "bottomdock=%d"%pane.IsBottomDockable() result = result + "|" dock_count = len(self._docks) for dock_i in xrange(dock_count): dock = self._docks[dock_i] result = result + ("dock_size(%d,%d,%d)=%d|")%(dock.dock_direction, dock.dock_layer, dock.dock_row, dock.size) return result def LoadPerspective(self, layout, update=True): """ LoadPerspective() loads a layout which was saved with SavePerspective() If the "update" flag parameter is True, the GUI will immediately be updated. """ input = layout # check layout string version indx = input.index("|") part = input[0:indx] input = input[indx+1:] part = part.strip() if part != "layout1": return False olddocks = self._docks[:] oldpanes = self._panes[:] # mark all panes currently managed as docked and hidden pane_count = len(self._panes) for pane_i in xrange(pane_count): pane = self._panes[pane_i] pane.Dock().Hide() self._panes[pane_i] = pane # clear out the dock array this will be reconstructed self._docks = [] # replace escaped characters so we can # split up the string easily input = input.replace("\\|", "\a") input = input.replace("\\", "\b") input = input.split("|") for line in input: if line.startswith("dock_size"): indx = line.index("=") size = int(line[indx+1:]) indx1 = line.index("(") indx2 = line.index(")") line2 = line[indx1+1:indx2] vals = line2.split(",") dir = int(vals[0]) layer = int(vals[1]) row = int(vals[2]) dock = DockInfo() dock.dock_direction = dir dock.dock_layer = layer dock.dock_row = row dock.size = size self._docks.append(dock) elif line.startswith("name"): newline = line.split(";") pane = PaneInfo() for newl in newline: myline = newl.strip() vals = myline.split("=") val_name = vals[0] value = vals[1] if val_name == "name": pane.name = value elif val_name == "caption": pane.caption = value elif val_name == "state": pane.state = int(value) elif val_name == "dir": pane.dock_direction = int(value) elif val_name == "layer": pane.dock_layer = int(value) elif val_name == "row": pane.dock_row = int(value) elif val_name == "pos": pane.dock_pos = int(value) elif val_name == "prop": pane.dock_proportion = int(value) elif val_name == "bestw": pane.best_size.x = int(value) elif val_name == "besth": pane.best_size.y = int(value) pane.best_size = wx.Size(pane.best_size.x, pane.best_size.y) elif val_name == "minw": pane.min_size.x = int(value) elif val_name == "minh": pane.min_size.y = int(value) pane.min_size = wx.Size(pane.min_size.x, pane.min_size.y) elif val_name == "maxw": pane.max_size.x = int(value) elif val_name == "maxh": pane.max_size.y = int(value) pane.max_size = wx.Size(pane.max_size.x, pane.max_size.y) elif val_name == "floatx": pane.floating_pos.x = int(value) elif val_name == "floaty": pane.floating_pos.y = int(value) pane.floating_pos = wx.Point(pane.floating_pos.x, pane.floating_pos.y) elif val_name == "floatw": pane.floating_size.x = int(value) elif val_name == "floath": pane.floating_size.y = int(value) pane.floating_size = wx.Size(pane.floating_size.x, pane.floating_size.y) elif val_name == "topdock": pane.TopDockable(int(value)) elif val_name == "leftdock": pane.LeftDockable(int(value)) elif val_name == "rightdock": pane.RightDockable(int(value)) elif val_name == "bottomdock": pane.BottomDockable(int(value)) else: raise "\nERROR: Bad Perspective String." # replace escaped characters so we can # split up the string easily pane.name = pane.name.replace("\a", "|") pane.name = pane.name.replace("\b", ";") pane.caption = pane.caption.replace("\a", "|") pane.caption = pane.caption.replace("\b", ";") p = self.GetPane(pane.name) if not p.IsOk(): # the pane window couldn't be found # in the existing layout return False indx = self._panes.index(p) pane.window = p.window pane.frame = p.frame pane.buttons = p.buttons self._panes[indx] = pane if update: self.Update() return True def GetPanePositionsAndSizes(self, dock): """ Returns all the panes positions and sizes. """ caption_size = self._art.GetMetric(AUI_ART_CAPTION_SIZE) pane_border_size = self._art.GetMetric(AUI_ART_PANE_BORDER_SIZE) gripper_size = self._art.GetMetric(AUI_ART_GRIPPER_SIZE) positions = [] sizes = [] action_pane = -1 pane_count = len(dock.panes) # find the pane marked as our action pane for pane_i in xrange(pane_count): pane = dock.panes[pane_i] if pane.state & PaneInfo.actionPane: action_pane = pane_i # set up each panes default position, and # determine the size (width or height, depending # on the dock's orientation) of each pane for pane in dock.panes: positions.append(pane.dock_pos) size = 0 if pane.HasBorder(): size = size + pane_border_size*2 if dock.IsHorizontal(): if pane.HasGripper() and not pane.HasGripperTop(): size = size + gripper_size size = size + pane.best_size.x else: if pane.HasGripper() and pane.HasGripperTop(): size = size + gripper_size if pane.HasCaption(): size = size + caption_size size = size + pane.best_size.y sizes.append(size) # if there is no action pane, just return the default # positions (as specified in pane.pane_pos) if action_pane == -1: return positions, sizes offset = 0 for pane_i in xrange(action_pane-1, -1, -1): amount = positions[pane_i+1] - (positions[pane_i] + sizes[pane_i]) if amount >= 0: offset = offset + amount else: positions[pane_i] -= -amount offset = offset + sizes[pane_i] # if the dock mode is fixed, make sure none of the panes # overlap we will bump panes that overlap offset = 0 for pane_i in xrange(action_pane, pane_count): amount = positions[pane_i] - offset if amount >= 0: offset = offset + amount else: positions[pane_i] += -amount offset = offset + sizes[pane_i] return positions, sizes def LayoutAddPane(self, cont, dock, pane, uiparts, spacer_only): sizer_item = wx.SizerItem() caption_size = self._art.GetMetric(AUI_ART_CAPTION_SIZE) gripper_size = self._art.GetMetric(AUI_ART_GRIPPER_SIZE) pane_border_size = self._art.GetMetric(AUI_ART_PANE_BORDER_SIZE) pane_button_size = self._art.GetMetric(AUI_ART_PANE_BUTTON_SIZE) # find out the orientation of the item (orientation for panes # is the same as the dock's orientation) if dock.IsHorizontal(): orientation = wx.HORIZONTAL else: orientation = wx.VERTICAL # this variable will store the proportion # value that the pane will receive pane_proportion = pane.dock_proportion horz_pane_sizer = wx.BoxSizer(wx.HORIZONTAL) vert_pane_sizer = wx.BoxSizer(wx.VERTICAL) if pane.HasGripper(): part = DockUIPart() if pane.HasGripperTop(): sizer_item = vert_pane_sizer.Add((1, gripper_size), 0, wx.EXPAND) else: sizer_item = horz_pane_sizer.Add((gripper_size, 1), 0, wx.EXPAND) part.type = DockUIPart.typeGripper part.dock = dock part.pane = pane part.button = None part.orientation = orientation part.cont_sizer = horz_pane_sizer part.sizer_item = sizer_item uiparts.append(part) if pane.HasCaption(): # create the caption sizer part = DockUIPart() caption_sizer = wx.BoxSizer(wx.HORIZONTAL) sizer_item = caption_sizer.Add((1, caption_size), 1, wx.EXPAND) part.type = DockUIPart.typeCaption part.dock = dock part.pane = pane part.button = None part.orientation = orientation part.cont_sizer = vert_pane_sizer part.sizer_item = sizer_item caption_part_idx = len(uiparts) uiparts.append(part) # add pane buttons to the caption for button in pane.buttons: sizer_item = caption_sizer.Add((pane_button_size, caption_size), 0, wx.EXPAND) part = DockUIPart() part.type = DockUIPart.typePaneButton part.dock = dock part.pane = pane part.button = button part.orientation = orientation part.cont_sizer = caption_sizer part.sizer_item = sizer_item uiparts.append(part) # add the caption sizer sizer_item = vert_pane_sizer.Add(caption_sizer, 0, wx.EXPAND) uiparts[caption_part_idx].sizer_item = sizer_item # add the pane window itself if spacer_only: sizer_item = vert_pane_sizer.Add((1, 1), 1, wx.EXPAND) else: sizer_item = vert_pane_sizer.Add(pane.window, 1, wx.EXPAND) vert_pane_sizer.SetItemMinSize(pane.window, (1, 1)) part = DockUIPart() part.type = DockUIPart.typePane part.dock = dock part.pane = pane part.button = None part.orientation = orientation part.cont_sizer = vert_pane_sizer part.sizer_item = sizer_item uiparts.append(part) # determine if the pane should have a minimum size if the pane is # non-resizable (fixed) then we must set a minimum size. Alternitavely, # if the pane.min_size is set, we must use that value as well min_size = pane.min_size if pane.IsFixed(): if min_size == wx.DefaultSize: min_size = pane.best_size pane_proportion = 0 if min_size != wx.DefaultSize: vert_pane_sizer.SetItemMinSize( len(vert_pane_sizer.GetChildren())-1, (min_size.x, min_size.y)) # add the verticle sizer (caption, pane window) to the # horizontal sizer (gripper, verticle sizer) horz_pane_sizer.Add(vert_pane_sizer, 1, wx.EXPAND) # finally, add the pane sizer to the dock sizer if pane.HasBorder(): # allowing space for the pane's border sizer_item = cont.Add(horz_pane_sizer, pane_proportion, wx.EXPAND | wx.ALL, pane_border_size) part = DockUIPart() part.type = DockUIPart.typePaneBorder part.dock = dock part.pane = pane part.button = None part.orientation = orientation part.cont_sizer = cont part.sizer_item = sizer_item uiparts.append(part) else: sizer_item = cont.Add(horz_pane_sizer, pane_proportion, wx.EXPAND) return uiparts def LayoutAddDock(self, cont, dock, uiparts, spacer_only): sizer_item = wx.SizerItem() part = DockUIPart() sash_size = self._art.GetMetric(AUI_ART_SASH_SIZE) orientation = (dock.IsHorizontal() and [wx.HORIZONTAL] or [wx.VERTICAL])[0] # resizable bottom and right docks have a sash before them if not self._has_maximized and not dock.fixed and (dock.dock_direction == AUI_DOCK_BOTTOM or \ dock.dock_direction == AUI_DOCK_RIGHT): sizer_item = cont.Add((sash_size, sash_size), 0, wx.EXPAND) part.type = DockUIPart.typeDockSizer part.orientation = orientation part.dock = dock part.pane = None part.button = None part.cont_sizer = cont part.sizer_item = sizer_item uiparts.append(part) # create the sizer for the dock dock_sizer = wx.BoxSizer(orientation) # add each pane to the dock has_maximized_pane = False pane_count = len(dock.panes) if dock.fixed: # figure out the real pane positions we will # use, without modifying the each pane's pane_pos member pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock) offset = 0 for pane_i in xrange(pane_count): pane = dock.panes[pane_i] pane_pos = pane_positions[pane_i] if pane.IsMaximized(): has_maximized_pane = True amount = pane_pos - offset if amount > 0: if dock.IsVertical(): sizer_item = dock_sizer.Add((1, amount), 0, wx.EXPAND) else: sizer_item = dock_sizer.Add((amount, 1), 0, wx.EXPAND) part = DockUIPart() part.type = DockUIPart.typeBackground part.dock = dock part.pane = None part.button = None part.orientation = (orientation==wx.HORIZONTAL and \ [wx.VERTICAL] or [wx.HORIZONTAL])[0] part.cont_sizer = dock_sizer part.sizer_item = sizer_item uiparts.append(part) offset = offset + amount uiparts = self.LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only) offset = offset + pane_sizes[pane_i] # at the end add a very small stretchable background area sizer_item = dock_sizer.Add((1, 1), 1, wx.EXPAND) part = DockUIPart() part.type = DockUIPart.typeBackground part.dock = dock part.pane = None part.button = None part.orientation = orientation part.cont_sizer = dock_sizer part.sizer_item = sizer_item uiparts.append(part) else: for pane_i in xrange(pane_count): pane = dock.panes[pane_i] if pane.IsMaximized(): has_maximized_pane = True # if this is not the first pane being added, # we need to add a pane sizer if not self._has_maximized and pane_i > 0: sizer_item = dock_sizer.Add((sash_size, sash_size), 0, wx.EXPAND) part = DockUIPart() part.type = DockUIPart.typePaneSizer part.dock = dock part.pane = dock.panes[pane_i-1] part.button = None part.orientation = (orientation==wx.HORIZONTAL and \ [wx.VERTICAL] or [wx.HORIZONTAL])[0] part.cont_sizer = dock_sizer part.sizer_item = sizer_item uiparts.append(part) uiparts = self.LayoutAddPane(dock_sizer, dock, pane, uiparts, spacer_only) if dock.dock_direction == AUI_DOCK_CENTER: sizer_item = cont.Add(dock_sizer, 1, wx.EXPAND) else: sizer_item = cont.Add(dock_sizer, 0, wx.EXPAND) part = DockUIPart() part.type = DockUIPart.typeDock part.dock = dock part.pane = None part.button = None part.orientation = orientation part.cont_sizer = cont part.sizer_item = sizer_item uiparts.append(part) if dock.IsHorizontal(): cont.SetItemMinSize(dock_sizer, (0, dock.size)) else: cont.SetItemMinSize(dock_sizer, (dock.size, 0)) # top and left docks have a sash after them if not self._has_maximized and not dock.fixed and (dock.dock_direction == AUI_DOCK_TOP or \ dock.dock_direction == AUI_DOCK_LEFT): sizer_item = cont.Add((sash_size, sash_size), 0, wx.EXPAND) part = DockUIPart() part.type = DockUIPart.typeDockSizer part.dock = dock part.pane = None part.button = None part.orientation = orientation part.cont_sizer = cont part.sizer_item = sizer_item uiparts.append(part) return uiparts def LayoutAll(self, panes, docks, uiparts, spacer_only=False, oncheck=True): container = wx.BoxSizer(wx.VERTICAL) pane_border_size = self._art.GetMetric(AUI_ART_PANE_BORDER_SIZE) caption_size = self._art.GetMetric(AUI_ART_CAPTION_SIZE) cli_size = self._frame.GetClientSize() # empty all docks out for ii in xrange(len(docks)): docks[ii].panes = [] dock_count = len(docks) # iterate through all known panes, filing each # of them into the appropriate dock. If the # pane does not exist in the dock, add it for p in panes: # find any docks in this layer arr = FindDocks(docks, p.dock_direction, p.dock_layer, p.dock_row) if len(arr) > 0: dock = arr[0] else: # dock was not found, so we need to create a new one d = DockInfo() d.dock_direction = p.dock_direction d.dock_layer = p.dock_layer d.dock_row = p.dock_row docks.append(d) dock = docks[-1] if p.IsDocked() and p.IsShown(): # remove the pane from any existing docks except this one docks = RemovePaneFromDocks(docks, p, dock) # pane needs to be added to the dock, # if it doesn't already exist if not FindPaneInDock(dock, p.window): dock.panes.append(p) else: # remove the pane from any existing docks docks = RemovePaneFromDocks(docks, p) # remove any empty docks for ii in xrange(len(docks)-1, -1, -1): if len(docks[ii].panes) == 0: docks.pop(ii) dock_count = len(docks) # configure the docks further for ii in xrange(len(docks)): dock = docks[ii] dock_pane_count = len(dock.panes) # sort the dock pane array by the pane's # dock position (dock_pos), in ascending order dock.panes.sort(PaneSortFunc) # for newly created docks, set up their initial size if dock.size == 0: size = 0 for jj in xrange(dock_pane_count): pane = dock.panes[jj] pane_size = pane.best_size if pane_size == wx.DefaultSize: pane_size = pane.min_size if pane_size == wx.DefaultSize: pane_size = pane.window.GetSize() if dock.IsHorizontal(): size = max(pane_size.y, size) else: size = max(pane_size.x, size) # add space for the border (two times), but only # if at least one pane inside the dock has a pane border for jj in xrange(dock_pane_count): if dock.panes[jj].HasBorder(): size = size + pane_border_size*2 break # if pane is on the top or bottom, add the caption height, # but only if at least one pane inside the dock has a caption if dock.IsHorizontal(): for jj in xrange(dock_pane_count): if dock.panes[jj].HasCaption(): size = size + caption_size break # new dock's size may not be more than 1/3 of the frame size if dock.IsHorizontal(): size = min(size, cli_size.y/3) else: size = min(size, cli_size.x/3) if size < 10: size = 10 dock.size = size # determine the dock's minimum size plus_border = False plus_caption = False dock_min_size = 0 for jj in xrange(dock_pane_count): pane = dock.panes[jj] if pane.min_size != wx.DefaultSize: if pane.HasBorder(): plus_border = True if pane.HasCaption(): plus_caption = True if dock.IsHorizontal(): if pane.min_size.y > dock_min_size: dock_min_size = pane.min_size.y else: if pane.min_size.x > dock_min_size: dock_min_size = pane.min_size.x if plus_border: dock_min_size = dock_min_size + pane_border_size*2 if plus_caption and dock.IsHorizontal(): dock_min_size = dock_min_size + caption_size dock.min_size = dock_min_size # if the pane's current size is less than it's # minimum, increase the dock's size to it's minimum if dock.size < dock.min_size: dock.size = dock.min_size # determine the dock's mode (fixed or proportional) # determine whether the dock has only toolbars action_pane_marked = False dock.fixed = True dock.toolbar = True for jj in xrange(dock_pane_count): pane = dock.panes[jj] if not pane.IsFixed(): dock.fixed = False if not pane.IsToolbar(): dock.toolbar = False if pane.state & PaneInfo.actionPane: action_pane_marked = True # if the dock mode is proportional and not fixed-pixel, # reassign the dock_pos to the sequential 0, 1, 2, 3 # e.g. remove gaps like 1, 2, 30, 500 if not dock.fixed: for jj in xrange(dock_pane_count): pane = dock.panes[jj] pane.dock_pos = jj dock.panes[jj] = pane # if the dock mode is fixed, and none of the panes # are being moved right now, make sure the panes # do not overlap each other. If they do, we will # adjust the panes' positions if dock.fixed and not action_pane_marked: pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock) offset = 0 for jj in xrange(dock_pane_count): pane = dock.panes[jj] pane.dock_pos = pane_positions[jj] amount = pane.dock_pos - offset if amount >= 0: offset = offset + amount else: pane.dock_pos += -amount offset = offset + pane_sizes[jj] dock.panes[jj] = pane if oncheck: self._docks[ii] = dock # discover the maximum dock layer max_layer = 0 for ii in xrange(dock_count): max_layer = max(max_layer, docks[ii].dock_layer) # clear out uiparts uiparts = [] # create a bunch of box sizers, # from the innermost level outwards. cont = None middle = None if oncheck: docks = self._docks for layer in xrange(max_layer+1): # find any docks in this layer arr = FindDocks(docks, -1, layer, -1) # if there aren't any, skip to the next layer if len(arr) == 0: continue old_cont = cont # create a container which will hold this layer's # docks (top, bottom, left, right) cont = wx.BoxSizer(wx.VERTICAL) # find any top docks in this layer arr = FindDocks(docks, AUI_DOCK_TOP, layer, -1, arr) arr = RenumberDockRows(arr) if len(arr) > 0: for row in xrange(len(arr)): uiparts = self.LayoutAddDock(cont, arr[row], uiparts, spacer_only) # fill out the middle layer (which consists # of left docks, content area and right docks) middle = wx.BoxSizer(wx.HORIZONTAL) # find any left docks in this layer arr = FindDocks(docks, AUI_DOCK_LEFT, layer, -1, arr) arr = RenumberDockRows(arr) if len(arr) > 0: for row in xrange(len(arr)): uiparts = self.LayoutAddDock(middle, arr[row], uiparts, spacer_only) # add content dock (or previous layer's sizer # to the middle if not old_cont: # find any center docks arr = FindDocks(docks, AUI_DOCK_CENTER, -1, -1, arr) if len(arr) > 0: for row in xrange(len(arr)): uiparts = self.LayoutAddDock(middle, arr[row], uiparts, spacer_only) elif not self._has_maximized: # there are no center docks, add a background area sizer_item = middle.Add((1, 1), 1, wx.EXPAND) part = DockUIPart() part.type = DockUIPart.typeBackground part.pane = None part.dock = None part.button = None part.cont_sizer = middle part.sizer_item = sizer_item uiparts.append(part) else: middle.Add(old_cont, 1, wx.EXPAND) # find any right docks in this layer arr = FindDocks(docks, AUI_DOCK_RIGHT, layer, -1, arr) arr = RenumberDockRows(arr) if len(arr) > 0: for row in xrange(len(arr)-1, -1, -1): uiparts = self.LayoutAddDock(middle, arr[row], uiparts, spacer_only) cont.Add(middle, 1, wx.EXPAND) # find any bottom docks in this layer arr = FindDocks(docks, AUI_DOCK_BOTTOM, layer, -1, arr) arr = RenumberDockRows(arr) if len(arr) > 0: for row in xrange(len(arr)-1, -1, -1): uiparts = self.LayoutAddDock(cont, arr[row], uiparts, spacer_only) if not cont: # no sizer available, because there are no docks, # therefore we will create a simple background area cont = wx.BoxSizer(wx.VERTICAL) sizer_item = cont.Add((1, 1), 1, wx.EXPAND) part = DockUIPart() part.type = DockUIPart.typeBackground part.pane = None part.dock = None part.button = None part.cont_sizer = middle part.sizer_item = sizer_item uiparts.append(part) if oncheck: self._uiparts = uiparts self._docks = docks container.Add(cont, 1, wx.EXPAND) if oncheck: return container else: return container, panes, docks, uiparts def Update(self): """ Update() updates the layout. Whenever changes are made to one or more panes, this function should be called. It is the external entry point for running the layout engine. """ pane_count = len(self._panes) # delete old sizer first self._frame.SetSizer(None) # destroy floating panes which have been # redocked or are becoming non-floating for ii in xrange(pane_count): p = self._panes[ii] if not p.IsFloating() and p.frame: # because the pane is no longer in a floating, we need to # reparent it to self._frame and destroy the floating frame # reduce flicker p.window.SetSize((1, 1)) p.frame.Show(False) # reparent to self._frame and destroy the pane p.window.Reparent(self._frame) p.frame.SetSizer(None) p.frame.Destroy() p.frame = None self._panes[ii] = p # create a layout for all of the panes sizer = self.LayoutAll(self._panes, self._docks, self._uiparts, False) # hide or show panes as necessary, # and float panes as necessary pane_count = len(self._panes) for ii in xrange(pane_count): p = self._panes[ii] if p.IsFloating(): if p.frame == None: # we need to create a frame for this # pane, which has recently been floated resizeborder = 1 if p.IsFixed(): resizeborder = 0 frame = FloatingPane(self._frame, self, -1, "", p.floating_pos, p.floating_size, resizeborder=resizeborder) # on MSW, if the owner desires transparent dragging, and # the dragging is happening right now, then the floating # window should have this style by default if self._action == actionDragFloatingPane and self.UseTransparentDrag(): self.MakeWindowTransparent(frame, 150) frame.SetPaneWindow(p) p.frame = frame if p.IsShown(): frame.Show() else: # frame already exists, make sure it's position # and size reflect the information in PaneInfo if p.frame.GetPosition() != p.floating_pos: p.frame.SetDimensions(p.floating_pos.x, p.floating_pos.y, -1, -1, wx.SIZE_USE_EXISTING) p.frame.Show(p.IsShown()) else: p.window.Show(p.IsShown()) # if "active panes" are no longer allowed, clear # any optionActive values from the pane states if self._flags & AUI_MGR_ALLOW_ACTIVE_PANE == 0: p.state &= ~PaneInfo.optionActive self._panes[ii] = p old_pane_rects = [] for ii in xrange(pane_count): r = wx.Rect() p = self._panes[ii] if p.window and p.IsShown() and p.IsDocked(): r = p.rect old_pane_rects.append(r) # apply the new sizer self._frame.SetSizer(sizer) self._frame.SetAutoLayout(False) self.DoFrameLayout() # now that the frame layout is done, we need to check # the new pane rectangles against the old rectangles that # we saved a few lines above here. If the rectangles have # changed, the corresponding panes must also be updated for ii in xrange(pane_count): p = self._panes[ii] if p.window and p.IsShown() and p.IsDocked(): if p.rect != old_pane_rects[ii]: p.window.Refresh() p.window.Update() self.Repaint() def DoFrameLayout(self): """ DoFrameLayout() is an internal function which invokes wxSizer.Layout on the frame's main sizer, then measures all the various UI items and updates their internal rectangles. This should always be called instead of calling self._frame.Layout() directly """ self._frame.Layout() for ii in xrange(len(self._uiparts)): part = self._uiparts[ii] # get the rectangle of the UI part # originally, this code looked like this: # part.rect = wx.Rect(part.sizer_item.GetPosition(), # part.sizer_item.GetSize()) # this worked quite well, with one exception: the mdi # client window had a "deferred" size variable # that returned the wrong size. It looks like # a bug in wx, because the former size of the window # was being returned. So, we will retrieve the part's # rectangle via other means part.rect = part.sizer_item.GetRect() flag = part.sizer_item.GetFlag() border = part.sizer_item.GetBorder() if flag & wx.TOP: part.rect.y -= border part.rect.height += border if flag & wx.LEFT: part.rect.x -= border part.rect.width += border if flag & wx.BOTTOM: part.rect.height += border if flag & wx.RIGHT: part.rect.width += border if part.type == DockUIPart.typeDock: part.dock.rect = part.rect if part.type == DockUIPart.typePane: part.pane.rect = part.rect self._uiparts[ii] = part def GetPanePart(self, wnd): """ GetPanePart() looks up the pane border UI part of the pane specified. This allows the caller to get the exact rectangle of the pane in question, including decorations like caption and border. """ for ii in xrange(len(self._uiparts)): part = self._uiparts[ii] if part.type == DockUIPart.typePaneBorder and \ part.pane and part.pane.window == wnd: return part for ii in xrange(len(self._uiparts)): part = self._uiparts[ii] if part.type == DockUIPart.typePane and \ part.pane and part.pane.window == wnd: return part return None def GetDockPixelOffset(self, test): """ GetDockPixelOffset() is an internal function which returns a dock's offset in pixels from the left side of the window (for horizontal docks) or from the top of the window (for vertical docks). This value is necessary for calculating fixel-pane/toolbar offsets when they are dragged. """ # the only way to accurately calculate the dock's # offset is to actually run a theoretical layout docks, panes = CopyDocksAndPanes2(self._docks, self._panes) panes.append(test) sizer, panes, docks, uiparts = self.LayoutAll(panes, docks, [], True, False) client_size = self._frame.GetClientSize() sizer.SetDimension(0, 0, client_size.x, client_size.y) sizer.Layout() for ii in xrange(len(uiparts)): part = uiparts[ii] pos = part.sizer_item.GetPosition() size = part.sizer_item.GetSize() part.rect = wx.Rect(pos[0], pos[1], size[0], size[1]) if part.type == DockUIPart.typeDock: part.dock.rect = part.rect sizer.Destroy() for ii in xrange(len(docks)): dock = docks[ii] if test.dock_direction == dock.dock_direction and \ test.dock_layer == dock.dock_layer and \ test.dock_row == dock.dock_row: if dock.IsVertical(): return dock.rect.y else: return dock.rect.x return 0 def ProcessDockResult(self, target, new_pos): """ ProcessDockResult() is a utility function used by DoDrop() - it checks if a dock operation is allowed, the new dock position is copied into the target info. If the operation was allowed, the function returns True. """ allowed = False if new_pos.dock_direction == AUI_DOCK_TOP: allowed = target.IsTopDockable() elif new_pos.dock_direction == AUI_DOCK_BOTTOM: allowed = target.IsBottomDockable() elif new_pos.dock_direction == AUI_DOCK_LEFT: allowed = target.IsLeftDockable() elif new_pos.dock_direction == AUI_DOCK_RIGHT: allowed = target.IsRightDockable() if allowed: target = new_pos return allowed, target def DoDrop(self, docks, panes, target, pt, offset=wx.Point(0,0)): """ DoDrop() is an important function. It basically takes a mouse position, and determines where the panes new position would be. If the pane is to be dropped, it performs the drop operation using the specified dock and pane arrays. By specifying copy dock and pane arrays when calling, a "what-if" scenario can be performed, giving precise coordinates for drop hints. """ cli_size = self._frame.GetClientSize() drop = PaneInfo() drop.name = target.name drop.caption = target.caption drop.window = target.window drop.frame = target.frame drop.state = target.state drop.dock_direction = target.dock_direction drop.dock_layer = target.dock_layer drop.dock_row = target.dock_row drop.dock_pos = target.dock_pos drop.best_size = target.best_size drop.min_size = target.min_size drop.max_size = target.max_size drop.floating_pos = target.floating_pos drop.floating_size = target.floating_size drop.dock_proportion = target.dock_proportion drop.buttons = target.buttons drop.rect = target.rect drop.icon = target.icon # The result should always be shown drop.Show() # Check to see if the pane has been dragged outside of the window # (or near to the outside of the window), if so, dock it along the edge layer_insert_offset = auiLayerInsertOffset if target.IsToolbar(): layer_insert_offset = 0 if pt.x < layer_insert_offset and \ pt.x > layer_insert_offset-auiLayerInsertPixels: new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_LEFT), GetMaxLayer(docks, AUI_DOCK_BOTTOM)), GetMaxLayer(docks, AUI_DOCK_TOP)) + 1 drop.Dock().Left().Layer(new_layer).Row(0). \ Position(pt.y - self.GetDockPixelOffset(drop) - offset.y) return self.ProcessDockResult(target, drop) elif pt.y < layer_insert_offset and \ pt.y > layer_insert_offset-auiLayerInsertPixels: new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_TOP), GetMaxLayer(docks, AUI_DOCK_LEFT)), GetMaxLayer(docks, AUI_DOCK_RIGHT)) + 1 drop.Dock().Top().Layer(new_layer).Row(0). \ Position(pt.x - self.GetDockPixelOffset(drop) - offset.x) return self.ProcessDockResult(target, drop) elif pt.x >= cli_size.x - layer_insert_offset and \ pt.x < cli_size.x - layer_insert_offset + auiLayerInsertPixels: new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_RIGHT), GetMaxLayer(docks, AUI_DOCK_TOP)), GetMaxLayer(docks, AUI_DOCK_BOTTOM)) + 1 drop.Dock().Right().Layer(new_layer).Row(0). \ Position(pt.y - self.GetDockPixelOffset(drop) - offset.y) return self.ProcessDockResult(target, drop) elif pt.y >= cli_size.y - layer_insert_offset and \ pt.y < cli_size.y - layer_insert_offset + auiLayerInsertPixels: new_layer = max(max(GetMaxLayer(docks, AUI_DOCK_BOTTOM), GetMaxLayer(docks, AUI_DOCK_LEFT)), GetMaxLayer(docks, AUI_DOCK_RIGHT)) + 1 drop.Dock().Bottom().Layer(new_layer).Row(0). \ Position(pt.x - self.GetDockPixelOffset(drop) - offset.x) return self.ProcessDockResult(target, drop) part = self.HitTest(pt.x, pt.y) if drop.IsToolbar(): if not part or not part.dock: return False, target # calculate the offset from where the dock begins # to the point where the user dropped the pane dock_drop_offset = 0 if part.dock.IsHorizontal(): dock_drop_offset = pt.x - part.dock.rect.x - offset.x else: dock_drop_offset = pt.y - part.dock.rect.y - offset.y # toolbars may only be moved in and to fixed-pane docks, # otherwise we will try to float the pane. Also, the pane # should float if being dragged over center pane windows if not part.dock.fixed or part.dock.dock_direction == AUI_DOCK_CENTER: if (self._flags & AUI_MGR_ALLOW_FLOATING) and (drop.IsFloatable() or (\ part.dock.dock_direction != AUI_DOCK_CENTER and \ part.dock.dock_direction != AUI_DOCK_NONE)): drop.Float() return self.ProcessDockResult(target, drop) drop.Dock(). \ Direction(part.dock.dock_direction). \ Layer(part.dock.dock_layer). \ Row(part.dock.dock_row). \ Position(dock_drop_offset) if pt.y < part.dock.rect.y + 2 and len(part.dock.panes) > 1: row = drop.dock_row panes = DoInsertDockRow(panes, part.dock.dock_direction, part.dock.dock_layer, part.dock.dock_row) drop.dock_row = row if pt.y > part.dock.rect.y + part.dock.rect.height - 2 and \ len(part.dock.panes) > 1: panes = DoInsertDockRow(panes, part.dock.dock_direction, part.dock.dock_layer, part.dock.dock_row+1) drop.dock_row = part.dock.dock_row + 1 return self.ProcessDockResult(target, drop) if not part: return False, target if part.type == DockUIPart.typePaneBorder or \ part.type == DockUIPart.typeCaption or \ part.type == DockUIPart.typeGripper or \ part.type == DockUIPart.typePaneButton or \ part.type == DockUIPart.typePane or \ part.type == DockUIPart.typePaneSizer or \ part.type == DockUIPart.typeDockSizer or \ part.type == DockUIPart.typeBackground: if part.type == DockUIPart.typeDockSizer: if len(part.dock.panes) != 1: return False, target part = self.GetPanePart(part.dock.panes[0].window) if not part: return False, target # If a normal frame is being dragged over a toolbar, insert it # along the edge under the toolbar, but over all other panes. # (this could be done much better, but somehow factoring this # calculation with the one at the beginning of this function) if part.dock and (hasattr(part.dock, "toolbar") and part.dock.toolbar): layer = 0 if part.dock.dock_direction == AUI_DOCK_LEFT: layer = max(max(GetMaxLayer(docks, AUI_DOCK_LEFT), GetMaxLayer(docks, AUI_DOCK_BOTTOM)), GetMaxLayer(docks, AUI_DOCK_TOP)) elif part.dock.dock_direction == AUI_DOCK_TOP: layer = max(max(GetMaxLayer(docks, AUI_DOCK_TOP), GetMaxLayer(docks, AUI_DOCK_LEFT)), GetMaxLayer(docks, AUI_DOCK_RIGHT)) elif part.dock.dock_direction == AUI_DOCK_RIGHT: layer = max(max(GetMaxLayer(docks, AUI_DOCK_RIGHT), GetMaxLayer(docks, AUI_DOCK_TOP)), GetMaxLayer(docks, AUI_DOCK_BOTTOM)) elif part.dock.dock_direction == AUI_DOCK_BOTTOM: layer = max(max(GetMaxLayer(docks, AUI_DOCK_BOTTOM), GetMaxLayer(docks, AUI_DOCK_LEFT)), GetMaxLayer(docks, AUI_DOCK_RIGHT)) panes = DoInsertDockRow(panes, part.dock.dock_direction, layer, 0) drop.Dock(). \ Direction(part.dock.dock_direction). \ Layer(layer).Row(0).Position(0) return self.ProcessDockResult(target, drop) if not part.pane: return False, target part = self.GetPanePart(part.pane.window) if not part: return False, target insert_dock_row = False insert_row = part.pane.dock_row insert_dir = part.pane.dock_direction insert_layer = part.pane.dock_layer if part.pane.dock_direction == AUI_DOCK_TOP: if pt.y >= part.rect.y and \ pt.y < part.rect.y+auiInsertRowPixels: insert_dock_row = True elif part.pane.dock_direction == AUI_DOCK_BOTTOM: if pt.y > part.rect.y+part.rect.height-auiInsertRowPixels and \ pt.y <= part.rect.y + part.rect.height: insert_dock_row = True elif part.pane.dock_direction == AUI_DOCK_LEFT: if pt.x >= part.rect.x and \ pt.x < part.rect.x+auiInsertRowPixels: insert_dock_row = True elif part.pane.dock_direction == AUI_DOCK_RIGHT: if pt.x > part.rect.x+part.rect.width-auiInsertRowPixels and \ pt.x <= part.rect.x+part.rect.width: insert_dock_row = True elif part.pane.dock_direction == AUI_DOCK_CENTER: # "new row pixels" will be set to the default, but # must never exceed 20% of the window size new_row_pixels_x = auiNewRowPixels new_row_pixels_y = auiNewRowPixels if new_row_pixels_x > part.rect.width*20/100: new_row_pixels_x = part.rect.width*20/100 if new_row_pixels_y > part.rect.height*20/100: new_row_pixels_y = part.rect.height*20/100 # determine if the mouse pointer is in a location that # will cause a new row to be inserted. The hot spot positions # are along the borders of the center pane insert_layer = 0 insert_dock_row = True if pt.x >= part.rect.x and \ pt.x < part.rect.x+new_row_pixels_x: insert_dir = AUI_DOCK_LEFT elif pt.y >= part.rect.y and \ pt.y < part.rect.y+new_row_pixels_y: insert_dir = AUI_DOCK_TOP elif pt.x >= part.rect.x + part.rect.width-new_row_pixels_x and \ pt.x < part.rect.x + part.rect.width: insert_dir = AUI_DOCK_RIGHT elif pt.y >= part.rect.y+ part.rect.height-new_row_pixels_y and \ pt.y < part.rect.y + part.rect.height: insert_dir = AUI_DOCK_BOTTOM else: return False, target insert_row = GetMaxRow(panes, insert_dir, insert_layer) + 1 if insert_dock_row: panes = DoInsertDockRow(panes, insert_dir, insert_layer, insert_row) drop.Dock().Direction(insert_dir). \ Layer(insert_layer). \ Row(insert_row). \ Position(0) return self.ProcessDockResult(target, drop) # determine the mouse offset and the pane size, both in the # direction of the dock itself, and perpendicular to the dock if part.orientation == wx.VERTICAL: offset = pt.y - part.rect.y size = part.rect.GetHeight() else: offset = pt.x - part.rect.x size = part.rect.GetWidth() drop_position = part.pane.dock_pos # if we are in the top/left part of the pane, # insert the pane before the pane being hovered over if offset <= size/2: drop_position = part.pane.dock_pos panes = DoInsertPane(panes, part.pane.dock_direction, part.pane.dock_layer, part.pane.dock_row, part.pane.dock_pos) # if we are in the bottom/right part of the pane, # insert the pane before the pane being hovered over if offset > size/2: drop_position = part.pane.dock_pos+1 panes = DoInsertPane(panes, part.pane.dock_direction, part.pane.dock_layer, part.pane.dock_row, part.pane.dock_pos+1) drop.Dock(). \ Direction(part.dock.dock_direction). \ Layer(part.dock.dock_layer). \ Row(part.dock.dock_row). \ Position(drop_position) return self.ProcessDockResult(target, drop) return False, target def UseTransparentHint(self): return (self._flags & AUI_MGR_TRANSPARENT_HINT) and self.CanMakeWindowsTransparent() def OnHintFadeTimer(self, event): #sanity check if not self.UseTransparentHint(): return if not self._hint_wnd or self._hint_fadeamt >= 50: self._hint_fadetimer.Stop() return self._hint_fadeamt = self._hint_fadeamt + 5 self.MakeWindowTransparent(self._hint_wnd, self._hint_fadeamt) def ShowHint(self, rect): self._hintshown = True if self.UseTransparentHint(): if wx.Platform == "__WXMSW__": if self._last_hint == rect: return self._last_hint = rect initial_fade = 50 if self._flags & AUI_MGR_TRANSPARENT_HINT_FADE: initial_fade = 0 if self._hint_wnd == None: pt = rect.GetPosition() size = rect.GetSize() self._hint_wnd = wx.Frame(self._frame, -1, "", pt, size, wx.FRAME_TOOL_WINDOW | wx.FRAME_FLOAT_ON_PARENT | wx.FRAME_NO_TASKBAR | wx.NO_BORDER) self.MakeWindowTransparent(self._hint_wnd, initial_fade) self._hint_wnd.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)) self._hint_wnd.Show() # if we are dragging a floating pane, set the focus # back to that floating pane (otherwise it becomes unfocused) if self._action == actionDragFloatingPane and self._action_window: self._action_window.SetFocus() else: pt = rect.GetPosition() size = rect.GetSize() self.MakeWindowTransparent(self._hint_wnd, initial_fade) self._hint_wnd.SetDimensions(pt.x, pt.y, rect.width, rect.height) if self._flags & AUI_MGR_TRANSPARENT_HINT_FADE: # start fade in timer self._hint_fadeamt = 0 self._hint_fadetimer.SetOwner(self, 101) self._hint_fadetimer.Start(5) return elif wx.Platform == "__WXMAC__": if self._last_hint == rect: return #same rect, already shown, no-op if self._flags & AUI_MGR_TRANSPARENT_HINT_FADE: initial_fade = 0 else: initial_fade = 80 if not self._hint_wnd: self._hint_wnd = wx.MiniFrame(self._frame, style=wx.FRAME_FLOAT_ON_PARENT|wx.FRAME_TOOL_WINDOW |wx.CAPTION#|wx.FRAME_SHAPED #without wxCAPTION + wx.FRAME_TOOL_WINDOW, the hint window #gets focus & dims the main frames toolbar, which is both wrong #and distracting. #wx.CAPTION + wx.FRAME_TOOL_WINDOW cures the focus problem, #but then it draws the caption. Adding wx.FRAME_SHAPED takes #care of that, but then SetRect doesn't work to size - need to #create a bitmap or mask or something. ) #can't set the background of a wx.Frame in OSX p = wx.Panel(self._hint_wnd) #the caption color is a light silver thats really hard to see #especially transparent. See if theres some other system #setting that is more appropriate, or just extend the art provider #to cover this #p.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)) p.SetBackgroundColour(wx.BLUE) self.MakeWindowTransparent(self._hint_wnd, initial_fade) self._hint_wnd.SetRect(rect) self._hint_wnd.Show() if self._action == actionDragFloatingPane and self._action_window: self._action_window.SetFocus() if self._flags & AUI_MGR_TRANSPARENT_HINT_FADE: # start fade in timer self._hint_fadeamt = 0 self._hint_fadetimer.SetOwner(self, 101) self._hint_fadetimer.Start(5) return if self._last_hint != rect: # remove the last hint rectangle self._last_hint = rect self._frame.Refresh() self._frame.Update() screendc = wx.ScreenDC() clip = wx.Region(1, 1, 10000, 10000) # clip all floating windows, so we don't draw over them for pane in self._panes: if pane.IsFloating() and pane.frame.IsShown(): recta = pane.frame.GetRect() if wx.Platform == "__WXGTK__": # wxGTK returns the client size, not the whole frame size width, height = pane.frame.ClientToScreen((0,0)) - pane.frame.GetPosition() recta.width = recta.width + width recta.height = recta.height + height recta.Inflate(5, 5) #endif clip.SubtractRect(recta) screendc.SetClippingRegionAsRegion(clip) screendc.SetBrush(wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION))) screendc.SetPen(wx.TRANSPARENT_PEN) screendc.DrawRectangle(rect.x, rect.y, 5, rect.height) screendc.DrawRectangle(rect.x+5, rect.y, rect.width-10, 5) screendc.DrawRectangle(rect.x+rect.width-5, rect.y, 5, rect.height) screendc.DrawRectangle(rect.x+5, rect.y+rect.height-5, rect.width-10, 5) def HideHint(self): self._hintshown = False # hides a transparent window hint (currently wxMSW only) if self.UseTransparentHint(): if self._hint_wnd: self._hint_fadetimer.Stop() #self._hint_wnd.Destroy() self.MakeWindowTransparent(self._hint_wnd, 0) self._last_hint = wx.Rect() return # hides a painted hint by redrawing the frame window if not self._last_hint.IsEmpty(): self._frame.Refresh() self._frame.Update() self._last_hint = wx.Rect() def DrawHintRect(self, pane_window, pt, offset): """ DrawHintRect() draws a drop hint rectangle. First calls DoDrop() to determine the exact position the pane would be at were if dropped. If the pame would indeed become docked at the specified drop point, DrawHintRect() then calls ShowHint() to indicate this drop rectangle. "pane_window" is the window pointer of the pane being dragged, pt is the mouse position, in client coordinates. """ # we need to paint a hint rectangle to find out the exact hint rectangle, # we will create a new temporary layout and then measure the resulting # rectangle we will create a copy of the docking structures (self._docks) # so that we don't modify the real thing on screen rect = wx.Rect() pane = self.GetPane(pane_window) attrs = self.GetAttributes(pane) hint = PaneInfo() hint = self.SetAttributes(hint, attrs) if hint.name != "__HINT__": self._oldname = hint.name hint.name = "__HINT__" if not hint.IsOk(): hint.name = self._oldname return docks, panes = CopyDocksAndPanes2(self._docks, self._panes) # remove any pane already there which bears the same window # this happens when you are moving a pane around in a dock for ii in xrange(len(panes)): if panes[ii].window == pane_window: docks = RemovePaneFromDocks(docks, panes[ii]) panes.pop(ii) break # find out where the new pane would be allow, hint = self.DoDrop(docks, panes, hint, pt, offset) if not allow: self.HideHint() return panes.append(hint) sizer, panes, docks, uiparts = self.LayoutAll(panes, docks, [], True, False) client_size = self._frame.GetClientSize() sizer.SetDimension(0, 0, client_size.x, client_size.y) sizer.Layout() for ii in xrange(len(uiparts)): part = uiparts[ii] if part.type == DockUIPart.typePaneBorder and \ part.pane and part.pane.name == "__HINT__": pos = part.sizer_item.GetPosition() size = part.sizer_item.GetSize() rect = wx.Rect(pos[0], pos[1], size[0], size[1]) break sizer.Destroy() if rect.IsEmpty(): self.HideHint() return # actually show the hint rectangle on the screen rect.x, rect.y = self._frame.ClientToScreen((rect.x, rect.y)) self.ShowHint(rect) def GetAttributes(self, pane): attrs = [] attrs.extend([pane.window, pane.frame, pane.state, pane.dock_direction, pane.dock_layer, pane.dock_pos, pane.dock_row, pane.dock_proportion, pane.floating_pos, pane.floating_size, pane.best_size, pane.min_size, pane.max_size, pane.caption, pane.name, pane.buttons, pane.rect]) return attrs def SetAttributes(self, pane, attrs): pane.window = attrs[0] pane.frame = attrs[1] pane.state = attrs[2] pane.dock_direction = attrs[3] pane.dock_layer = attrs[4] pane.dock_pos = attrs[5] pane.dock_row = attrs[6] pane.dock_proportion = attrs[7] pane.floating_pos = attrs[8] pane.floating_size = attrs[9] pane.best_size = attrs[10] pane.min_size = attrs[11] pane.max_size = attrs[12] pane.caption = attrs[13] pane.name = attrs[14] pane.buttons = attrs[15] pane.rect = attrs[16] return pane def UseTransparentDrag(self): if self._flags & AUI_MGR_TRANSPARENT_DRAG: return self.CanMakeWindowsTransparent() else: return False def OnFloatingPaneMoveStart(self, wnd): # try to find the pane pane = self.GetPane(wnd) if not pane.IsOk(): raise "\nERROR: Pane Window Not Found" if self.UseTransparentDrag() and pane.IsDockable(): self.MakeWindowTransparent(pane.frame, 150) def OnFloatingPaneMoving(self, wnd): # try to find the pane pane = self.GetPane(wnd) if not pane.IsOk(): raise "\nERROR: Pane Window Not Found" pt = wx.GetMousePosition() client_pt = self._frame.ScreenToClient(pt) # calculate the offset from the upper left-hand corner # of the frame to the mouse pointer frame_pos = pane.frame.GetPosition() action_offset = wx.Point(pt[0]-frame_pos.x, pt[1]-frame_pos.y) ## # no hint for toolbar floating windows ## if pane.IsToolbar() and self._action == actionDragFloatingPane: ## ## oldname = pane.name ## indx = self._panes.index(pane) ## hint = pane ## docks, panes = CopyDocksAndPanes2(self._docks, self._panes) ## ## # find out where the new pane would be ## ret, hint = self.DoDrop(docks, panes, hint, client_pt) ## ## if not ret: ## return ## ## if hint.IsFloating(): ## return ## ## pane = hint ## pane.name = oldname ## ## self._panes[indx] = pane ## self._action = actionDragToolbarPane ## self._action_window = pane.window ## ## self.Update() ## ## return # if a key modifier is pressed while dragging the frame, # don't dock the window if wx.GetKeyState(wx.WXK_CONTROL) or wx.GetKeyState(wx.WXK_ALT): self.HideHint() return if pane.IsDockable(): self.DrawHintRect(wnd, client_pt, action_offset) # reduces flicker self._frame.Update() def OnFloatingPaneMoved(self, wnd): # try to find the pane pane = self.GetPane(wnd) if not pane.IsOk(): raise "\nERROR: Pane Window Not Found" pt = wx.GetMousePosition() client_pt = self._frame.ScreenToClient(pt) indx = self._panes.index(pane) # calculate the offset from the upper left-hand corner # of the frame to the mouse pointer frame_pos = pane.frame.GetPosition() action_offset = wx.Point(pt[0]-frame_pos.x, pt[1]-frame_pos.y) # if a key modifier is pressed while dragging the frame, # don't dock the window if wx.GetKeyState(wx.WXK_CONTROL) or wx.GetKeyState(wx.WXK_ALT): self.HideHint() return if not pane.IsToolbar() and pane.IsDockable() and not self._hintshown: if not pane.IsFloating(): pane.Float() pane.floating_pos = pane.frame.GetPosition() self._panes[indx] = pane if self.UseTransparentDrag(): self.MakeWindowTransparent(pane.frame, 255) # do the drop calculation allow, pane = self.DoDrop(self._docks, self._panes, pane, client_pt, action_offset) # if the pane is still floating, update it's floating # position (that we store) if pane.IsFloating(): pane.floating_pos = pane.frame.GetPosition() if self.UseTransparentDrag(): self.MakeWindowTransparent(pane.frame, 255) elif self._has_maximized: self.RestoreMaximizedPane() if not pane.IsToolbar() and pane.IsDockable(): pane.name = self._oldname self._panes[indx] = pane self.Update() self.HideHint() def OnFloatingPaneResized(self, wnd, size): # try to find the pane pane = self.GetPane(wnd) if not pane.IsOk(): raise "\nERROR: Pane Window Not Found" indx = self._panes.index(pane) pane.floating_size = size self._panes[indx] = pane def OnFloatingPaneClosed(self, wnd): # try to find the pane pane = self.GetPane(wnd) if not pane.IsOk(): raise "\nERROR: Pane Window Not Found" indx = self._panes.index(pane) # reparent the pane window back to us and # prepare the frame window for destruction pane.window.Show(False) pane.window.Reparent(self._frame) pane.frame = None pane.Hide() self._panes[indx] = pane def OnFloatingPaneActivate(self, wnd, state): if self.GetFlags() & AUI_MGR_ALLOW_ACTIVE_PANE: # try to find the pane pane = self.GetPane(wnd) if not pane.IsOk(): raise "\nERROR: Pane Window Not Found" if state: self._panes = SetActivePane(self._panes, wnd) else: self._panes = KillActivePane(self._panes) self.Repaint() def Render(self, dc): """ Render() draws all of the pane captions, sashes, backgrounds, captions, grippers, pane borders and buttons. It renders the entire user interface. """ for part in self._uiparts: # don't draw hidden pane items if part.sizer_item and not part.sizer_item.IsShown(): continue if part.type == DockUIPart.typeDockSizer or \ part.type == DockUIPart.typePaneSizer: self._art.DrawSash(dc, part.orientation, part.rect) elif part.type == DockUIPart.typeBackground: self._art.DrawBackground(dc, part.orientation, part.rect) elif part.type == DockUIPart.typeCaption: self._art.DrawCaption(dc, part.pane.caption, part.rect, part.pane) elif part.type == DockUIPart.typeGripper: self._art.DrawGripper(dc, part.rect, part.pane) elif part.type == DockUIPart.typePaneBorder: self._art.DrawBorder(dc, part.rect, part.pane) elif part.type == DockUIPart.typePaneButton: self._art.DrawPaneButton(dc, part.button.button_id, AUI_BUTTON_STATE_NORMAL, part.rect, part.pane) def Repaint(self, dc=None): w, h = self._frame.GetClientSize() # figure out which dc to use if one # has been specified, use it, otherwise # make a client dc client_dc = None if not dc: client_dc = wx.ClientDC(self._frame) dc = client_dc # if the frame has a toolbar, the client area # origin will not be (0,0). pt = self._frame.GetClientAreaOrigin() if pt.x != 0 or pt.y != 0: dc.SetDeviceOrigin(pt.x, pt.y) # render all the items self.Render(dc) # if we created a client_dc, delete it if client_dc: del client_dc def OnPaint(self, event): dc = wx.PaintDC(self._frame) if wx.Platform == "__WXMAC__": # Macs paint optimizations clip the area we need to paint a log # of the time, this is a dirty hack to always paint everything self.Repaint(None) else: self.Repaint(dc) def OnEraseBackground(self, event): if wx.Platform == "__WXMAC__": event.Skip() def OnSize(self, event): if self._frame: self.DoFrameLayout() wx.CallAfter(self.Repaint) if not isinstance(self._frame, wx.MDIParentFrame): event.Skip() def OnSetCursor(self, event): # determine cursor part = self.HitTest(event.GetX(), event.GetY()) cursor = None if part: if part.type == DockUIPart.typeDockSizer or \ part.type == DockUIPart.typePaneSizer: # a dock may not be resized if it has a single # pane which is not resizable if part.type == DockUIPart.typeDockSizer and part.dock and \ len(part.dock.panes) == 1 and part.dock.panes[0].IsFixed(): return # panes that may not be resized do not get a sizing cursor if part.pane and part.pane.IsFixed(): return if part.orientation == wx.VERTICAL: cursor = wx.StockCursor(wx.CURSOR_SIZEWE) else: cursor = wx.StockCursor(wx.CURSOR_SIZENS) elif part.type == DockUIPart.typeGripper: cursor = wx.StockCursor(wx.CURSOR_SIZING) if cursor is not None: event.SetCursor(cursor) def UpdateButtonOnScreen(self, button_ui_part, event): hit_test = self.HitTest(event.GetX(), event.GetY()) state = AUI_BUTTON_STATE_NORMAL if hit_test == button_ui_part: if event.LeftDown(): state = AUI_BUTTON_STATE_PRESSED else: state = AUI_BUTTON_STATE_HOVER else: if event.LeftDown(): state = AUI_BUTTON_STATE_HOVER # now repaint the button with hover state cdc = wx.ClientDC(self._frame) # if the frame has a toolbar, the client area # origin will not be (0,0). pt = self._frame.GetClientAreaOrigin() if pt.x != 0 or pt.y != 0: cdc.SetDeviceOrigin(pt.x, pt.y) self._art.DrawPaneButton(cdc, button_ui_part.button.button_id, state, button_ui_part.rect, hit_test.pane) def OnLeftDown(self, event): part = self.HitTest(event.GetX(), event.GetY()) if part: #if part.dock and part.dock.dock_direction == AUI_DOCK_CENTER: # return if part.type == DockUIPart.typeDockSizer or \ part.type == DockUIPart.typePaneSizer: # a dock may not be resized if it has a single # pane which is not resizable if part.type == DockUIPart.typeDockSizer and part.dock and \ len(part.dock.panes) == 1 and part.dock.panes[0].IsFixed(): return # panes that may not be resized should be ignored here if part.pane and part.pane.IsFixed(): return self._action = actionResize self._action_part = part self._action_hintrect = wx.Rect() self._action_start = wx.Point(event.GetX(), event.GetY()) self._action_offset = wx.Point(event.GetX() - part.rect.x, event.GetY() - part.rect.y) self._frame.CaptureMouse() elif part.type == DockUIPart.typePaneButton: self._action = actionClickButton self._action_part = part self._action_start = wx.Point(event.GetX(), event.GetY()) self._frame.CaptureMouse() self.UpdateButtonOnScreen(part, event) elif part.type == DockUIPart.typeCaption or \ part.type == DockUIPart.typeGripper: if self.GetFlags() & AUI_MGR_ALLOW_ACTIVE_PANE: # set the caption as active self._panes = SetActivePane(self._panes, part.pane.window) self.Repaint() self._action = actionClickCaption self._action_part = part self._action_start = wx.Point(event.GetX(), event.GetY()) self._action_offset = wx.Point(event.GetX() - part.rect.x, event.GetY() - part.rect.y) self._frame.CaptureMouse() if wx.Platform != "__WXMAC__": event.Skip() def OnLeftUp(self, event): if self._action == actionResize: self._frame.ReleaseMouse() if not self._flags & AUI_MGR_LIVE_RESIZE: # get rid of the hint rectangle dc = wx.ScreenDC() DrawResizeHint(dc, self._action_hintrect) self.ResizeDock(wx.Point(event.GetX(), event.GetY())) elif self._action == actionClickButton: self._hover_button = None self._frame.ReleaseMouse() self.UpdateButtonOnScreen(self._action_part, event) # make sure we're still over the item that was originally clicked if self._action_part == self.HitTest(event.GetX(), event.GetY()): # fire button-click event e = FrameManagerEvent(wxEVT_AUI_PANEBUTTON) e.SetPane(self._action_part.pane) e.SetButton(self._action_part.button.button_id) self.ProcessMgrEvent(e) elif self._action == actionClickCaption: self._frame.ReleaseMouse() elif self._action == actionDragFloatingPane: self._frame.ReleaseMouse() elif self._action == actionDragToolbarPane: self._frame.ReleaseMouse() pane = self.GetPane(self._action_window) if not pane.IsOk(): raise "\nERROR: Pane Window Not Found" # save the new positions docks = FindDocks(self._docks, pane.dock_direction, pane.dock_layer, pane.dock_row) if len(docks) == 1: dock = docks[0] pane_positions, pane_sizes = self.GetPanePositionsAndSizes(dock) dock_pane_count = len(dock.panes) for ii in xrange(dock_pane_count): dock.panes[ii].dock_pos = pane_positions[ii] pane.state &= ~PaneInfo.actionPane indx = self._panes.index(pane) self._panes[indx] = pane self.Update() else: event.Skip() self._action = actionNone self._last_mouse_move = wx.Point() # see comment in OnMotion() def OnMotion(self, event): # sometimes when Update() is called from inside this method, # a spurious mouse move event is generated this check will make # sure that only real mouse moves will get anywhere in this method # this appears to be a bug somewhere, and I don't know where the # mouse move event is being generated. only verified on MSW mouse_pos = event.GetPosition() if self._last_mouse_move == mouse_pos: return self._last_mouse_move = mouse_pos if self._action == actionResize: pos = self._action_part.rect.GetPosition() if self._action_part.orientation == wx.HORIZONTAL: pos.y = max(0, mouse_pos.y - self._action_offset.y) pos.y = min(pos.y, self._frame.GetClientSize().y - self._action_part.rect.GetSize().y) else: pos.x = max(0, mouse_pos.x - self._action_offset.x) pos.x = min(pos.x, self._frame.GetClientSize().x - self._action_part.rect.GetSize().x) mypos = self._frame.ClientToScreen(pos) mysize = self._action_part.rect.GetSize() rect = wx.Rect(mypos[0], mypos[1], mysize[0], mysize[1]) # is it the same as the old rectangle? if self._action_hintrect == rect: # heck, yes, no need to draw again, it will only bring about flicker event.Skip() return if self._flags & AUI_MGR_LIVE_RESIZE: if not self._action_hintrect.IsEmpty() and self._action_hintrect != rect: self.ResizeDock(wx.Point(event.GetX(), event.GetY())); # The part pointer does not seem to survive the relayout # so we have to reacquire it here for it to be valid # at the next motion event self._action_part = self.HitTest(event.GetX(), event.GetY()) self._action_hintrect = rect else: # otherwise draw the hint dc = wx.ScreenDC() if not self._action_hintrect.IsEmpty() and self._action_hintrect != rect: DrawResizeHint(dc, self._action_hintrect) DrawResizeHint(dc, rect) self._action_hintrect = rect elif self._action == actionClickCaption: drag_x_threshold = wx.SystemSettings_GetMetric(wx.SYS_DRAG_X) drag_y_threshold = wx.SystemSettings_GetMetric(wx.SYS_DRAG_Y) # caption has been clicked. we need to check if the mouse # is now being dragged. if it is, we need to change the # mouse action to 'drag' if abs(mouse_pos.x - self._action_start.x) > drag_x_threshold or \ abs(mouse_pos.y - self._action_start.y) > drag_y_threshold: pane_info = self._action_part.pane indx = self._panes.index(pane_info) if not pane_info.IsToolbar(): if self._flags & AUI_MGR_ALLOW_FLOATING and \ pane_info.IsFloatable(): self._action = actionDragFloatingPane # set initial float position pt = self._frame.ClientToScreen(event.GetPosition()) pane_info.floating_pos = wx.Point(pt.x - self._action_offset.x, pt.y - self._action_offset.y) # float the window if pane_info.IsMaximized(): self.RestorePane(pane_info) pane_info.Float() self._panes[indx] = pane_info self.Update() self._action_window = pane_info.frame # action offset is used here to make it feel "natural" to the user # to drag a docked pane and suddenly have it become a floating frame. # Sometimes, however, the offset where the user clicked on the docked # caption is bigger than the width of the floating frame itself, so # in that case we need to set the action offset to a sensible value frame_size = self._action_window.GetSize() if frame_size.x <= self._action_offset.x: self._action_offset.x = 30 else: self._action = actionDragToolbarPane self._action_window = pane_info.window elif self._action == actionDragFloatingPane: pt = self._frame.ClientToScreen(event.GetPosition()) if self._action_window: self._action_window.Move((pt.x - self._action_offset.x, pt.y - self._action_offset.y)) elif self._action == actionDragToolbarPane: pane = self.GetPane(self._action_window) if not pane.IsOk(): raise "\nERROR: Pane Window Not Found" indx = self._panes.index(pane) pane.state |= PaneInfo.actionPane pt = event.GetPosition() ret, pane = self.DoDrop(self._docks, self._panes, pane, pt, self._action_offset) if not ret: return # if DoDrop() decided to float the pane, set up # the floating pane's initial position if pane.IsFloating(): pt = self._frame.ClientToScreen(event.GetPosition()) pane.floating_pos = wx.Point(pt.x - self._action_offset.x, pt.y - self._action_offset.y) self._panes[indx] = pane # this will do the actiual move operation # in the case that the pane has been floated, # this call will create the floating pane # and do the reparenting self.Update() # if the pane has been floated, change the mouse # action actionDragFloatingPane so that subsequent # EVT_MOTION() events will move the floating pane if pane.IsFloating(): pane.state &= ~PaneInfo.actionPane self._action = actionDragFloatingPane self._action_window = pane.frame self._panes[indx] = pane else: part = self.HitTest(event.GetX(), event.GetY()) if part and part.type == DockUIPart.typePaneButton: if part != self._hover_button: # make the old button normal if self._hover_button: self.UpdateButtonOnScreen(self._hover_button, event) # mouse is over a button, so repaint the # button in hover mode self.UpdateButtonOnScreen(part, event) self._hover_button = part else: if self._hover_button: self._hover_button = None self.Repaint() else: event.Skip() def ResizeDock(self, pos): # resize the dock or the pane if self._action_part and self._action_part.type == DockUIPart.typeDockSizer: rect = self._action_part.dock.rect new_pos = wx.Point(pos.x - self._action_offset.x, pos.y - self._action_offset.y) if self._action_part.dock.dock_direction == AUI_DOCK_LEFT: self._action_part.dock.size = new_pos.x - rect.x elif self._action_part.dock.dock_direction == AUI_DOCK_TOP: self._action_part.dock.size = new_pos.y - rect.y elif self._action_part.dock.dock_direction == AUI_DOCK_RIGHT: self._action_part.dock.size = rect.x + rect.width - \ new_pos.x - \ self._action_part.rect.GetWidth() elif self._action_part.dock.dock_direction == AUI_DOCK_BOTTOM: self._action_part.dock.size = rect.y + rect.height - \ new_pos.y - \ self._action_part.rect.GetHeight() self.Update() self.Repaint(None) elif self._action_part and \ self._action_part.type == DockUIPart.typePaneSizer: dock = self._action_part.dock pane = self._action_part.pane total_proportion = 0 dock_pixels = 0 new_pixsize = 0 caption_size = self._art.GetMetric(AUI_ART_CAPTION_SIZE) pane_border_size = self._art.GetMetric(AUI_ART_PANE_BORDER_SIZE) sash_size = self._art.GetMetric(AUI_ART_SASH_SIZE) new_pos = wx.Point(pos.x - self._action_offset.x, pos.y - self._action_offset.y) # determine the pane rectangle by getting the pane part pane_part = self.GetPanePart(pane.window) if not pane_part: raise "\nERROR: Pane border part not found -- shouldn't happen" # determine the new pixel size that the user wants # this will help us recalculate the pane's proportion if dock.IsHorizontal(): new_pixsize = new_pos.x - pane_part.rect.x else: new_pixsize = new_pos.y - pane_part.rect.y # determine the size of the dock, based on orientation if dock.IsHorizontal(): dock_pixels = dock.rect.GetWidth() else: dock_pixels = dock.rect.GetHeight() # determine the total proportion of all resizable panes, # and the total size of the dock minus the size of all # the fixed panes dock_pane_count = len(dock.panes) pane_position = -1 for ii in xrange(dock_pane_count): p = dock.panes[ii] if p.window == pane.window: pane_position = ii # while we're at it, subtract the pane sash # width from the dock width, because this would # skew our proportion calculations if ii > 0: dock_pixels = dock_pixels - sash_size # also, the whole size (including decorations) of # all fixed panes must also be subtracted, because they # are not part of the proportion calculation if p.IsFixed(): if dock.IsHorizontal(): dock_pixels = dock_pixels - p.best_size.x else: dock_pixels = dock_pixels - p.best_size.y else: total_proportion = total_proportion + p.dock_proportion # find a pane in our dock to 'steal' space from or to 'give' # space to -- this is essentially what is done when a pane is # resized the pane should usually be the first non-fixed pane # to the right of the action pane borrow_pane = -1 for ii in xrange(pane_position+1, dock_pane_count): p = dock.panes[ii] if not p.IsFixed(): borrow_pane = ii break # demand that the pane being resized is found in this dock # (this assert really never should be raised) if pane_position == -1: raise "\nERROR: Pane not found in dock" # prevent division by zero if dock_pixels == 0 or total_proportion == 0 or borrow_pane == -1: self._action = actionNone return # calculate the new proportion of the pane new_proportion = new_pixsize*total_proportion/dock_pixels # default minimum size min_size = 0 # check against the pane's minimum size, if specified. please note # that this is not enough to ensure that the minimum size will # not be violated, because the whole frame might later be shrunk, # causing the size of the pane to violate it's minimum size if pane.min_size.IsFullySpecified(): min_size = 0 if pane.HasBorder(): min_size = min_size + pane_border_size*2 # calculate minimum size with decorations (border,caption) if pane_part.orientation == wx.VERTICAL: min_size = min_size + pane.min_size.y if pane.HasCaption(): min_size = min_size + caption_size else: min_size = min_size + pane.min_size.x # for some reason, an arithmatic error somewhere is causing # the proportion calculations to always be off by 1 pixel # for now we will add the 1 pixel on, but we really should # determine what's causing this. min_size = min_size + 1 min_proportion = min_size*total_proportion/dock_pixels if new_proportion < min_proportion: new_proportion = min_proportion prop_diff = new_proportion - pane.dock_proportion # borrow the space from our neighbor pane to the # right or bottom (depending on orientation) dock.panes[borrow_pane].dock_proportion -= prop_diff pane.dock_proportion = new_proportion indxd = self._docks.index(dock) indxp = self._panes.index(pane) self._docks[indxd] = dock self._panes[indxp] = pane # repaint self.Update() self.Repaint(None) def OnLeaveWindow(self, event): if self._hover_button: self._hover_button = None self.Repaint() def OnChildFocus(self, event): # when a child pane has it's focus set, we should change the # pane's active state to reflect this. (this is only true if # active panes are allowed by the owner) if self.GetFlags() & AUI_MGR_ALLOW_ACTIVE_PANE: if self.GetPane(event.GetWindow()).IsOk(): self._panes = SetActivePane(self._panes, event.GetWindow()) self.Repaint() event.Skip() # OnActivate() is an event handler that gets called when # the frame managed by the frame manager gets activated / deactivated def OnActivate(self, event): for pane in self._panes: # Loop through all valid panes and check if one of them was activated # before, if so, "reactivate" it if event.GetActive() and (pane.state & PaneInfo.optionActive): # Only send to the pane that was active before e = wx.ActivateEvent(wx.wxEVT_ACTIVATE, True) # the pane that was last activated pane.window.ProcessEvent(e) event.Skip() # let other handlers also process this message def OnPaneButton(self, event): """ OnPaneButton() is an event handler that is called when a pane button has been pressed. """ pane = event.pane indx = self._panes.index(pane) import math if event.button == PaneInfo.buttonClose: pane.Hide() self._panes[indx] = pane self.Update() elif event.button == PaneInfo.buttonMaximize and not pane.IsMaximized(): self.MaximizePane(pane) self.Update() elif event.button == PaneInfo.buttonMaximize and pane.IsMaximized(): self.RestorePane(pane) self.Update() elif event.button == PaneInfo.buttonFloatClose: if not pane.IsOk(): raise "\nERROR: Pane Window Not Found" indx = self._panes.index(pane) # reparent the pane window back to us and # prepare the frame window for destruction pane.window.Show(False) pane.window.Reparent(self._frame) pane.Hide() pane.frame.Destroy() pane.frame._mgr.UnInit() pane.frame = None self._panes[indx] = pane self.Update() elif event.button == PaneInfo.buttonPin: if self._flags & AUI_MGR_ALLOW_FLOATING and pane.IsFloatable(): pane.Float() self._panes[indx] = pane self.Update() tpclient-pywx-0.3.1.1/extra/decorators.py0000644000175000017500000000271110773624641016522 0ustar timtim from tp.client.decorator import decorator @decorator def freeze_wrapper(func, self, *args, **kw): """ This decorator calls Freeze before calling the function, and then thaw after. """ frozen = False try: if hasattr(self, "Freeze"): frozen = True self.Freeze() return func(self, *args, **kw) finally: if frozen: self.Thaw() import wx @decorator def onlyshown(func, self, evt, *args, **kw): """ This decorator prevents a callback being called unless the window that it is on is shown. """ if not self.IsShown(): print "WARNING: %s called when %s was not shown!" % (func, self) # FIXME: Hack for Mac OS X's crap if isinstance(evt, wx.Event): if hasattr(self, "application"): self.application.gui.current.AddPendingEvent(evt) return return func(self, evt, *args, **kw) def onlyenabled(attribute): """ This decorator prevents a callback being called unless the given wxWindow is enabled. """ @decorator def onlyenabled_decorator(func, self, *args, **kw): """ This decorator prevents a callback being called unless the given wxWindow is enabled. """ try: tocheck = getattr(self, attribute) if not tocheck.IsEnabled(): print "WARNING: %s called when %s on %s was not enabled!" % (func, tocheck, self) return except AttributeError, e: print "ERROR: Was unable to check enable state of %s when calling %s (%s)" % (attribute, func, e) return func(self, *args, **kw) return onlyenabled_decorator tpclient-pywx-0.3.1.1/extra/GIFAnimationCtrl.py0000644000175000017500000001107010773624641017445 0ustar timtim import os import wx try: import Image import PngImagePlugin import GifImagePlugin import JpegImagePlugin Image._initialized=2 def pil2wx(pil,alpha=True): if alpha: image = wx.EmptyImage(*pil.size) image.SetData( pil.convert( "RGB").tostring() ) image.SetAlphaData(pil.convert("RGBA").tostring()[3::4]) else: image = wx.EmptyImage(*pil.size) image.SetData( pil.convert( "RGB").tostring() ) return image class ImagePanel(wx.Panel): def __init__(self, parent, id, *args, **kw): wx.Panel.__init__(self, parent, id, *args, **kw) self.bitmap = None self.background = None self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnErase) self.Bind(wx.EVT_PAINT, self.OnPaint) def display(self, image): if wx.Platform == '__WXMSW__' and self.IsShown(): if self.background is None: dc = wx.ClientDC(self) dc.Clear() color = dc.GetPixel(0, 0) self.background = (wx.Pen(wx.Color(*color)), wx.Brush(wx.Color(*color))) bitmap = image.ConvertToBitmap() self.bitmap = wx.EmptyBitmap(*self.GetSize()) dc = wx.MemoryDC(self.bitmap) dc.SetPen(self.background[0]) dc.SetBrush(self.background[1]) dc.DrawRectangle(0, 0, *self.GetSize()) dc.DrawBitmap(bitmap, 0,0) else: self.bitmap = image.ConvertToBitmap() self.Refresh(True) def OnPaint(self, evt): dc = wx.PaintDC(self) if self.bitmap: dc.DrawBitmap(self.bitmap, 0,0) def OnErase(self, evt): return True class GIFAnimationCtrl(ImagePanel): def __init__(self, parent, id=-1, file="", *args, **kw): ImagePanel.__init__(self, parent, id, *args, **kw) self.timer = wx.Timer(self, -1) self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer) def Play(self): if hasattr(self, "gif"): #print "Starting Animation" self.timer.Start(self.delay) else: raise IOError("No file loaded...") def Stop(self): #print "Stoping Animation" self.timer.Stop() def LoadFile(self, file): #print "Loading File", file self.gif = Image.open(file) if not self.gif.info.has_key('duration') or self.gif.info['duration'] == 0: self.delay = 100 else: self.delay = self.gif.info['duration'] self.frames = [] # Frame Cache self.alldone = False # Have we cached all the frames? self.current = 0 self.SetSize(wx.Size(*self.gif.size)) def OnTimer(self, evt): self.display(self.NextFrame()) def NextFrame(self): if not self.alldone: try: self.gif.seek(len(self.frames)) self.frames.append(pil2wx(self.gif, True)) except EOFError: # No more frames left self.alldone = True i = self.frames[self.current % len(self.frames)] self.current += 1 return i except ImportError, e: from wx.animate import GIFAnimationCtrl print e def LoadFile(self, file): dc = wx.ClientDC(self) dc.Clear() del dc if not file.endswith(".gif"): new = file[:file.rfind('.')]+'.gif' if os.path.exists(new): print "Using low quality version", new + ". Install PIL for better version." file = new else: print "Unable to display file", file + ". Install PIL to have it displayed." return GIFAnimationCtrl.__LoadFile(self, file) GIFAnimationCtrl.__LoadFile = GIFAnimationCtrl.LoadFile GIFAnimationCtrl.LoadFile = LoadFile import wx.xrc as xrc class GIFAnimationCtrlXmlHandler(xrc.XmlResourceHandler): def __init__(self): xrc.XmlResourceHandler.__init__(self) # Specify the styles recognized by objects of this type self.AddWindowStyles() # This method and the next one are required for XmlResourceHandlers def CanHandle(self, node): return self.IsOfClass(node, "wxGIFAnimationCtrl") or self.IsOfClass(node, "GIFAnimationCtrl") def DoCreateResource(self): # The simple method assumes that there is no existing # instance. Be sure of that with an assert. assert self.GetInstance() is None ctrl = GIFAnimationCtrl(self.GetParentAsWindow(), self.GetID(), "", self.GetPosition(), self.GetSize(), self.GetStyle(), self.GetName(), ) # These two things should be done in either case: # Set standard window attributes self.SetupWindow(ctrl) # Create any child windows of this node self.CreateChildren(ctrl) return ctrl xrc.ExtraHandlers.append(GIFAnimationCtrlXmlHandler) if __name__ == "__main__": a = wx.App() class Frame(wx.Frame): def __init__(self, parent, id, title): wx.Frame.__init__(self, None, id, title, wx.DefaultPosition, wx.Size(500, 400)) self.panel = GIFAnimationCtrl(self, -1) self.panel.LoadFile("barren1.gif") self.panel.Play() f = Frame(a, -1, "Testing") f.Show() a.MainLoop() tpclient-pywx-0.3.1.1/extra/Opener.py0000644000175000017500000002637310773624641015617 0ustar timtim#!/usr/bin/env python """ Title: Cross-platform startfile and mailto functions Submitter: Antonio Valentino (other recipes) Last Updated: 2007/04/01 Version no: 1.0 Category: System http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/511443 Utilities for opening files or URLs in the registered default application and for sending e-mail using the user's preferred composer. """ __version__ = '1.0' __all__ = ['open', 'mailto'] import os import sys import webbrowser import subprocess from email.Utils import encode_rfc2231 _controllers = {} _open = None class BaseController(object): '''Base class for open program controllers.''' def __init__(self, name): self.name = name def open(self, filename): raise NotImplementedError class Controller(BaseController): '''Controller for a generic open program.''' def __init__(self, *args): super(Controller, self).__init__(os.path.basename(args[0])) self.args = list(args) def _invoke(self, cmdline): if sys.platform[:3] == 'win': closefds = False startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW else: closefds = True startupinfo = None if (os.environ.get('DISPLAY') or sys.platform[:3] == 'win' or sys.platform == 'darwin'): inout = file(os.devnull, 'r+') else: # for TTY programs, we need stdin/out inout = None # if possible, put the child precess in separate process group, # so keyboard interrupts don't affect child precess as well as # Python setsid = getattr(os, 'setsid', None) if not setsid: setsid = getattr(os, 'setpgrp', None) pipe = subprocess.Popen(cmdline, stdin=inout, stdout=inout, stderr=inout, close_fds=closefds, preexec_fn=setsid, startupinfo=startupinfo) # It is assumed that this kind of tools (gnome-open, kfmclient, # exo-open, xdg-open and open for OSX) immediately exit after lauching # the specific application returncode = pipe.wait() if hasattr(self, 'fixreturncode'): returncode = self.fixreturncode(returncode) return not returncode def open(self, filename): if isinstance(filename, basestring): cmdline = self.args + [filename] else: # assume it is a sequence cmdline = self.args + filename try: return self._invoke(cmdline) except OSError: return False # Platform support for Windows if sys.platform[:3] == 'win': class Start(BaseController): '''Controller for the win32 start progam through os.startfile.''' def open(self, filename): try: os.startfile(filename) except WindowsError: # [Error 22] No application is associated with the specified # file for this operation: '' return False else: return True _controllers['windows-default'] = Start('windows') _open = _controllers['windows-default'].open # Platform support for MacOS elif sys.platform == 'darwin': _controllers['open']= Controller('open') _open = _controllers['open'].open # Platform support for Unix else: import commands # @WARNING: use the private API of the webbrowser module from webbrowser import _iscommand class KfmClient(Controller): '''Controller for the KDE kfmclient program.''' def __init__(self, kfmclient='kfmclient'): super(KfmClient, self).__init__(kfmclient, 'exec') self.kde_version = self.detect_kde_version() def detect_kde_version(self): kde_version = None try: info = commands.getoutput('kde-config --version') for line in info.splitlines(): if line.startswith('KDE'): kde_version = line.split(':')[-1].strip() break except (OSError, RuntimeError): pass return kde_version def fixreturncode(self, returncode): if returncode is not None and self.kde_version > '3.5.4': return returncode else: return os.EX_OK def detect_desktop_environment(): '''Checks for known desktop environments Return the desktop environments name, lowercase (kde, gnome, xfce) or "generic" ''' desktop_environment = 'generic' if os.environ.get('KDE_FULL_SESSION') == 'true': desktop_environment = 'kde' elif os.environ.get('GNOME_DESKTOP_SESSION_ID'): desktop_environment = 'gnome' else: try: info = commands.getoutput('xprop -root _DT_SAVE_MODE') if ' = "xfce4"' in info: desktop_environment = 'xfce' except (OSError, RuntimeError): pass return desktop_environment def register_X_controllers(): if _iscommand('kfmclient'): _controllers['kde-open'] = KfmClient() for command in ('gnome-open', 'exo-open', 'xdg-open'): if _iscommand(command): _controllers[command] = Controller(command) def get(): controllers_map = { \ 'gnome': 'gnome-open', 'kde': 'kde-open', 'xfce': 'exo-open', } desktop_environment = detect_desktop_environment() try: controller_name = controllers_map[desktop_environment] return _controllers[controller_name].open except KeyError: if _controllers.has_key('xdg-open'): return _controllers['xdg-open'].open else: return webbrowser.open if os.environ.get("DISPLAY"): register_X_controllers() _open = get() def open(filename): '''Open a file or an URL in the registered default application.''' return _open(filename) def _fix_addersses(**kwargs): for headername in ('address', 'to', 'cc', 'bcc'): try: headervalue = kwargs[headername] if not headervalue: del kwargs[headername] continue elif not isinstance(headervalue, basestring): # assume it is a sequence headervalue = ','.join(headervalue) except KeyError: pass except TypeError: raise TypeError('string or sequence expected for "%s", ' \ '%s found' % (headername, type(headervalue).__name__)) else: translation_map = {'%': '%25', '&': '%26', '?': '%3F'} for char, replacement in translation_map.items(): headervalue = headervalue.replace(char, replacement) kwargs[headername] = headervalue return kwargs def mailto_format(**kwargs): # @TODO: implement utf8 option kwargs = _fix_addersses(**kwargs) parts = [] for headername in ('to', 'cc', 'bcc', 'subject', 'body', 'attach'): if kwargs.has_key(headername): headervalue = kwargs[headername] if not headervalue: continue if headername in ('address', 'to', 'cc', 'bcc'): parts.append('%s=%s' % (headername, headervalue)) else: headervalue = encode_rfc2231(headervalue) # @TODO: check parts.append('%s=%s' % (headername, headervalue)) mailto_string = 'mailto:%s' % kwargs.get('address', '') if parts: mailto_string = '%s?%s' % (mailto_string, '&'.join(parts)) return mailto_string def mailto(address, to=None, cc=None, bcc=None, subject=None, body=None, attach=None): '''Send an e-mail using the user's preferred composer. Open the user's preferred e-mail composer in order to send a mail to address(es) that must follow the syntax of RFC822. Multiple addresses may be provided (for address, cc and bcc parameters) as separate arguments. All parameters provided are used to prefill corresponding fields in the user's e-mail composer. The user will have the opportunity to change any of this information before actually sending the e-mail. address - specify the destination recipient cc - specify a recipient to be copied on the e-mail bcc - specify a recipient to be blindly copied on the e-mail subject - specify a subject for the e-mail body - specify a body for the e-mail. Since the user will be able to make changes before actually sending the e-mail, this can be used to provide the user with a template for the e-mail text may contain linebreaks attach - specify an attachment for the e-mail. file must point to an existing file ''' mailto_string = mailto_format(**locals()) return open(mailto_string) if __name__ == '__main__': from optparse import OptionParser version = '%%prog %s' % __version__ usage = ( '\n\n%prog FILENAME [FILENAME(s)] -- for opening files' '\n\n%prog -m [OPTIONS] ADDRESS [ADDRESS(es)] -- for sending e-mails' ) parser = OptionParser(usage=usage, version=version, description=__doc__) parser.add_option('-m', '--mailto', dest='mailto_mode', default=False, \ action='store_true', help='set mailto mode. ' 'If not set any other option is ignored') parser.add_option('--cc', dest='cc', help='specify a recipient to be ' 'copied on the e-mail') parser.add_option('--bcc', dest='bcc', help='specify a recipient to be ' 'blindly copied on the e-mail') parser.add_option('--subject', dest='subject', help='specify a subject for the e-mail') parser.add_option('--body', dest='body', help='specify a body for the ' 'e-mail. Since the user will be able to make changes ' 'before actually sending the e-mail, this can be used ' 'to provide the user with a template for the e-mail ' 'text may contain linebreaks') parser.add_option('--attach', dest='attach', help='specify an attachment ' 'for the e-mail. file must point to an existing file') (options, args) = parser.parse_args() if not args: parser.print_usage() parser.exit(1) if options.mailto_mode: if not mailto(args, None, options.cc, options.bcc, options.subject, options.body, options.attach): sys.exit('Unable to open the e-mail client') else: for name in ('cc', 'bcc', 'subject', 'body', 'attach'): if getattr(options, name): parser.error('The "cc", "bcc", "subject", "body" and "attach" ' 'options are only accepten in mailto mode') success = False for arg in args: if not open(arg): print 'Unable to open "%s"' % arg else: success = True sys.exit(success) tpclient-pywx-0.3.1.1/extra/PopupCtrl.py0000644000175000017500000000441610773624641016311 0ustar timtim import wx from wx.lib.popupctl import * # Tried to use wxPopupWindow but the control misbehaves on MSW class PopupDialog(wx.Dialog): def __init__(self,parent,content = None): wx.Dialog.__init__(self,parent,-1,'', style = wx.BORDER_SIMPLE|wx.STAY_ON_TOP) self.ctrl = parent self.win = wx.Window(self,-1,pos = (0,0),style = 0) if content: self.SetContent(content) def SetContent(self,content): self.content = content self.content.Reparent(self.win) self.content.Show(True) def Display(self): self.ctrl.FormatContent() self.win.SetClientSize(self.content.GetSize()) self.SetSize(self.win.GetSize()) pos = self.ctrl.ClientToScreen( (0,0) ) dSize = wx.GetDisplaySize() selfSize = self.GetSize() tcSize = self.ctrl.GetSize() pos.x -= (selfSize.width - tcSize.width) / 2 if pos.x + selfSize.width > dSize.width: pos.x = dSize.width - selfSize.width if pos.x < 0: pos.x = 0 pos.y += tcSize.height if pos.y + selfSize.height > dSize.height: pos.y = dSize.height - selfSize.height if pos.y < 0: pos.y = 0 self.Move(pos) self.ShowModal() class PopupCtrl(wx.PyControl): def __init__(self, *args, **kwargs): wx.PyControl.__init__(self, *args, **kwargs) self.control = None self.content = None self.pop = None self.Bind(wx.EVT_SIZE, self.OnSize) def OnSize(self, evt): if not self.control is None: self.control.SetSize(self.GetClientSize()) def SetPopupCtrl(self, control): self.control = control self.control.Reparent(self) self.OnSize(None) self.control.Bind(wx.EVT_LEFT_UP, self.OnButton) def SetPopupContent(self,content): if not self.pop: self.content = content self.content.Show(False) else: self.pop.SetContent(content) def OnButton(self,evt): self.PopUp() def FormatContent(self): pass def PopUp(self): if not self.pop: if self.content: self.pop = PopupDialog(self,self.content) del self.content else: print 'No Content to pop' if self.pop: self.pop.Display() def PopDown(self): if self.pop: self.pop.EndModal(True) def Enable(self,flag): wx.PyControl.Enable(self,flag) self.control.Enable(flag) def __getattr__(self, value): if hasattr(self.control, value): return getattr(self.control, value) raise AttributeError("No such attribute " + value) tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/0000755000175000017500000000000010773624641016562 5ustar timtimtpclient-pywx-0.3.1.1/extra/wxFloatCanvas/__init__.py0000644000175000017500000000723010773624641020675 0ustar timtim""" This is the floatcanvas package. It provides two primary modules, and a support module. FloatCanvas.py contains the main FloatCanvas class, and its supporting classes. NavCanvas.py contains a wrapper for the FloatCanvas that provides the canvas and a toolbar with tools that allow you to navigate the canvas (zooming, panning, etc.) Resources.py is a module that contains a few resources required by the FloatCanvas (icons, etc) The FloatCanvas is a high level window for drawing maps and anything else in an arbitrary coordinate system. The goal is to provide a convenient way to draw stuff on the screen without having to deal with handling OnPaint events, converting to pixel coordinates, knowing about wxWindows brushes, pens, and colors, etc. It also provides virtually unlimited zooming and scrolling I am using it for two things: 1) general purpose drawing in floating point coordinates 2) displaying map data in Lat-long coordinates If the projection is set to None, it will draw in general purpose floating point coordinates. If the projection is set to 'FlatEarth', it will draw a FlatEarth projection, centered on the part of the map that you are viewing. You can also pass in your own projection function. It is double buffered, so re-draws after the window is uncovered by something else are very quick. It relies on NumPy, which is needed for speed (maybe, I haven't profiled properly) and convenience. Bugs and Limitations: Lots: patches, fixes welcome For Map drawing: It ignores the fact that the world is, in fact, a sphere, so it will do strange things if you are looking at stuff near the poles or the date line. so far I don't have a need to do that, so I havn't bothered to add any checks for that yet. Zooming: I have set no zoom limits. What this means is that if you zoom in really far, you can get integer overflows, and get weird results. It doesn't seem to actually cause any problems other than weird output, at least when I have run it. Speed: I have done a couple of things to improve speed in this app. The one thing I have done is used NumPy Arrays to store the coordinates of the points of the objects. This allowed me to use array oriented functions when doing transformations, and should provide some speed improvement for objects with a lot of points (big polygons, polylines, pointsets). The real slowdown comes when you have to draw a lot of objects, because you have to call the wx.DC.DrawSomething call each time. This is plenty fast for tens of objects, OK for hundreds of objects, but pretty darn slow for thousands of objects. If you are zoomed in, it checks the Bounding box of an object before drawing it. This makes it a great deal faster when there are a lot of objects and you are zoomed in so that only a few are shown. Mouse Events: There are a full set of custom mouse events. They are just like the regular mouse events, but include an extra attribute: Event.GetCoords(), that returns the (x,y) position in world coordinates, as a length-2 NumPy vector of Floats. There are also a full set of bindings to mouse events on objects, so that you can specify a given function be called when an object is clicked, mouse-over'd, etc. See the Demo for what it can do, and how to use it. Copyright: Christopher Barker License: Same as the version of wxPython you are using it with. TRAC site for some docs and updates: http://morticia.cs.dal.ca/FloatCanvas/ SVN for latest code: svn://morticia.cs.dal.ca/FloatCanvas Mailing List: http://mail.mithis.com/cgi-bin/mailman/listinfo/floatcanvas Check for updates or answers to questions, send me an email. Please let me know if you're using this!!! Contact me at: Chris.Barker@noaa.gov """ __version__ = "0.9.18" tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/Utilities/0000755000175000017500000000000010773624641020535 5ustar timtimtpclient-pywx-0.3.1.1/extra/wxFloatCanvas/Utilities/BBoxTest.py0000755000175000017500000002640610773624641022614 0ustar timtim#!/usr/bin/env python """ Test code for the BBox Object """ import unittest from BBox import * class testCreator(unittest.TestCase): def testCreates(self): B = BBox(((0,0),(5,5))) self.failUnless(isinstance(B, BBox)) def testType(self): B = N.array(((0,0),(5,5))) self.failIf(isinstance(B, BBox)) def testDataType(self): B = BBox(((0,0),(5,5))) self.failUnless(B.dtype == N.float) def testShape(self): B = BBox((0,0,5,5)) self.failUnless(B.shape == (2,2)) def testShape2(self): self.failUnlessRaises(ValueError, BBox, (0,0,5) ) def testShape3(self): self.failUnlessRaises(ValueError, BBox, (0,0,5,6,7) ) def testArrayConstruction(self): A = N.array(((4,5),(10,12)), N.float_) B = BBox(A) self.failUnless(isinstance(B, BBox)) def testMinMax(self): self.failUnlessRaises(ValueError, BBox, (0,0,-1,6) ) def testMinMax2(self): self.failUnlessRaises(ValueError, BBox, (0,0,1,-6) ) def testMinMax(self): # OK to have a zero-sized BB B = BBox(((0,0),(0,5))) self.failUnless(isinstance(B, BBox)) def testMinMax2(self): # OK to have a zero-sized BB B = BBox(((10.0,-34),(10.0,-34.0))) self.failUnless(isinstance(B, BBox)) def testMinMax3(self): # OK to have a tiny BB B = BBox(((0,0),(1e-20,5))) self.failUnless(isinstance(B, BBox)) def testMinMax4(self): # Should catch tiny difference self.failUnlessRaises(ValueError, BBox, ((0,0), (-1e-20,5)) ) class testAsBBox(unittest.TestCase): def testPassThrough(self): B = BBox(((0,0),(5,5))) C = asBBox(B) self.failUnless(B is C) def testPassThrough2(self): B = (((0,0),(5,5))) C = asBBox(B) self.failIf(B is C) def testPassArray(self): # Different data type A = N.array( (((0,0),(5,5))) ) C = asBBox(A) self.failIf(A is C) def testPassArray2(self): # same data type -- should be a view A = N.array( (((0,0),(5,5))), N.float_ ) C = asBBox(A) A[0,0] = -10 self.failUnless(C[0,0] == A[0,0]) class testIntersect(unittest.TestCase): def testSame(self): B = BBox(((-23.5, 456),(56, 532.0))) C = BBox(((-23.5, 456),(56, 532.0))) self.failUnless(B.Overlaps(C) ) def testUpperLeft(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (0, 12),(10, 32.0) ) ) self.failUnless(B.Overlaps(C) ) def testUpperRight(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (12, 12),(25, 32.0) ) ) self.failUnless(B.Overlaps(C) ) def testLowerRight(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (12, 5),(25, 15) ) ) self.failUnless(B.Overlaps(C) ) def testLowerLeft(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (-10, 5),(8.5, 15) ) ) self.failUnless(B.Overlaps(C) ) def testBelow(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (-10, 5),(8.5, 9.2) ) ) self.failIf(B.Overlaps(C) ) def testAbove(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (-10, 25.001),(8.5, 32) ) ) self.failIf(B.Overlaps(C) ) def testLeft(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (4, 8),(4.95, 32) ) ) self.failIf(B.Overlaps(C) ) def testRight(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (17.1, 8),(17.95, 32) ) ) self.failIf(B.Overlaps(C) ) def testInside(self): B = BBox( ( (-15, -25),(-5, -10) ) ) C = BBox( ( (-12, -22), (-6, -8) ) ) self.failUnless(B.Overlaps(C) ) def testOutside(self): B = BBox( ( (-15, -25),(-5, -10) ) ) C = BBox( ( (-17, -26), (3, 0) ) ) self.failUnless(B.Overlaps(C) ) def testTouch(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (15, 8),(17.95, 32) ) ) self.failUnless(B.Overlaps(C) ) def testCorner(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (15, 25),(17.95, 32) ) ) self.failUnless(B.Overlaps(C) ) def testZeroSize(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (15, 25),(15, 25) ) ) self.failUnless(B.Overlaps(C) ) def testZeroSize2(self): B = BBox( ( (5, 10),(5, 10) ) ) C = BBox( ( (15, 25),(15, 25) ) ) self.failIf(B.Overlaps(C) ) def testZeroSize3(self): B = BBox( ( (5, 10),(5, 10) ) ) C = BBox( ( (0, 8),(10, 12) ) ) self.failUnless(B.Overlaps(C) ) def testZeroSize4(self): B = BBox( ( (5, 1),(10, 25) ) ) C = BBox( ( (8, 8),(8, 8) ) ) self.failUnless(B.Overlaps(C) ) class testEquality(unittest.TestCase): def testSame(self): B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) ) C = BBox( ( (1.0, 2.0), (5.0, 10.0) ) ) self.failUnless(B == C) def testIdentical(self): B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) ) self.failUnless(B == B) def testNotSame(self): B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) ) C = BBox( ( (1.0, 2.0), (5.0, 10.1) ) ) self.failIf(B == C) def testWithArray(self): B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) ) C = N.array( ( (1.0, 2.0), (5.0, 10.0) ) ) self.failUnless(B == C) def testWithArray2(self): B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) ) C = N.array( ( (1.0, 2.0), (5.0, 10.0) ) ) self.failUnless(C == B) def testWithArray2(self): B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) ) C = N.array( ( (1.01, 2.0), (5.0, 10.0) ) ) self.failIf(C == B) class testInside(unittest.TestCase): def testSame(self): B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) ) C = BBox( ( (1.0, 2.0), (5.0, 10.0) ) ) self.failUnless(B.Inside(C)) def testPoint(self): B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) ) C = BBox( ( (3.0, 4.0), (3.0, 4.0) ) ) self.failUnless(B.Inside(C)) def testPointOutside(self): B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) ) C = BBox( ( (-3.0, 4.0), (0.10, 4.0) ) ) self.failIf(B.Inside(C)) def testUpperLeft(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (0, 12),(10, 32.0) ) ) self.failIf(B.Inside(C) ) def testUpperRight(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (12, 12),(25, 32.0) ) ) self.failIf(B.Inside(C) ) def testLowerRight(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (12, 5),(25, 15) ) ) self.failIf(B.Inside(C) ) def testLowerLeft(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (-10, 5),(8.5, 15) ) ) self.failIf(B.Inside(C) ) def testBelow(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (-10, 5),(8.5, 9.2) ) ) self.failIf(B.Inside(C) ) def testAbove(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (-10, 25.001),(8.5, 32) ) ) self.failIf(B.Inside(C) ) def testLeft(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (4, 8),(4.95, 32) ) ) self.failIf(B.Inside(C) ) def testRight(self): B = BBox( ( (5, 10),(15, 25) ) ) C = BBox( ( (17.1, 8),(17.95, 32) ) ) self.failIf(B.Inside(C) ) class testFromPoints(unittest.TestCase): def testCreate(self): Pts = N.array( ((5,2), (3,4), (1,6), ), N.float_ ) B = fromPoints(Pts) #B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) ) self.failUnless(B[0,0] == 1.0 and B[0,1] == 2.0 and B[1,0] == 5.0 and B[1,1] == 6.0 ) def testCreateInts(self): Pts = N.array( ((5,2), (3,4), (1,6), ) ) B = fromPoints(Pts) self.failUnless(B[0,0] == 1.0 and B[0,1] == 2.0 and B[1,0] == 5.0 and B[1,1] == 6.0 ) def testSinglePoint(self): Pts = N.array( (5,2), N.float_ ) B = fromPoints(Pts) self.failUnless(B[0,0] == 5.0 and B[0,1] == 2.0 and B[1,0] == 5.0 and B[1,1] == 2.0 ) def testListTuples(self): Pts = [ (3, 6.5), (13, 43.2), (-4.32, -4), (65, -23), (-0.0001, 23.432), ] B = fromPoints(Pts) self.failUnless(B[0,0] == -4.32 and B[0,1] == -23.0 and B[1,0] == 65.0 and B[1,1] == 43.2 ) class testMerge(unittest.TestCase): A = BBox( ((-23.5, 456), (56, 532.0)) ) B = BBox( ((-20.3, 460), (54, 465 )) )# B should be completely inside A C = BBox( ((-23.5, 456), (58, 540.0)) )# up and to the right or A D = BBox( ((-26.5, 12), (56, 532.0)) ) def testInside(self): C = self.A.copy() C.Merge(self.B) self.failUnless(C == self.A) def testFullOutside(self): C = self.B.copy() C.Merge(self.A) self.failUnless(C == self.A) def testUpRight(self): A = self.A.copy() A.Merge(self.C) self.failUnless(A[0] == self.A[0] and A[1] == self.C[1]) def testDownLeft(self): A = self.A.copy() A.Merge(self.D) self.failUnless(A[0] == self.D[0] and A[1] == self.A[1]) class testWidthHeight(unittest.TestCase): B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) ) def testWidth(self): self.failUnless(self.B.Width == 4.0) def testWidth(self): self.failUnless(self.B.Height == 8.0) def attemptSetWidth(self): self.B.Width = 6 def attemptSetHeight(self): self.B.Height = 6 def testSetW(self): self.failUnlessRaises(AttributeError, self.attemptSetWidth) def testSetH(self): self.failUnlessRaises(AttributeError, self.attemptSetHeight) class testCenter(unittest.TestCase): B = BBox( ( (1.0, 2.0), (5.0, 10.0) ) ) def testCenter(self): print self.B.Center self.failUnless( (self.B.Center == (3.0, 6.0)).all() ) def attemptSetCenter(self): self.B.Center = (6, 5) def testSetCenter(self): self.failUnlessRaises(AttributeError, self.attemptSetCenter) class testBBarray(unittest.TestCase): BBarray = N.array( ( ((-23.5, 456), (56, 532.0)), ((-20.3, 460), (54, 465 )), ((-23.5, 456), (58, 540.0)), ((-26.5, 12), (56, 532.0)), ), dtype=N.float) BB = asBBox( ((-26.5, 12.), ( 58. , 540.)) ) def testJoin(self): BB = fromBBArray(self.BBarray) self.failUnless(BB == self.BB, "Wrong BB was created. It was:\n%s \nit should have been:\n%s"%(BB, self.BB)) if __name__ == "__main__": unittest.main() tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/Utilities/__init__.py0000644000175000017500000000007710773624641022652 0ustar timtim""" __init__ for the floatcanvas Utilities package """ pass tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/Utilities/BBox.py0000755000175000017500000001213110773624641021742 0ustar timtim#!/usr/bin/env python """ A Bounding Box object and assorted utilities , subclassed from a numpy array """ import numpy as N class BBox(N.ndarray): """ A Bounding Box object: Takes Data as an array. Data is any python sequence that can be turned into a 2x2 numpy array of floats: [[MinX, MinY ], [MaxX, MaxY ]] It is a subclass of numpy.ndarray, so for the most part it can be used as an array, and arrays that fit the above description can be used in its place. Usually created by the factory functions: asBBox and fromPoints """ def __new__(subtype, data): """ Takes Data as an array. Data is any python sequence that can be turned into a 2x2 numpy array of floats: [[MinX, MinY ], [MaxX, MaxY ]] You don't usually call this directly. BBox objects are created with the factory functions: asBBox and fromPoints """ arr = N.array(data, N.float) arr.shape = (2,2) if arr[0,0] > arr[1,0] or arr[0,1] > arr[1,1]: # note: zero sized BB OK. raise ValueError("BBox values not aligned: \n minimum values must be less that maximum values") return N.ndarray.__new__(BBox, shape=arr.shape, dtype=arr.dtype, buffer=arr) def Overlaps(self, BB): """ Overlap(BB): Tests if the given Bounding Box overlaps with this one. Returns True is the Bounding boxes overlap, False otherwise If they are just touching, returns True """ if ( (self[1,0] >= BB[0,0]) and (self[0,0] <= BB[1,0]) and (self[1,1] >= BB[0,1]) and (self[0,1] <= BB[1,1]) ): return True else: return False def Inside(self, BB): """ Inside(BB): Tests if the given Bounding Box is entirely inside this one. Returns True if it is entirely inside, or touching the border. Returns False otherwise """ if ( (BB[0,0] >= self[0,0]) and (BB[1,0] <= self[1,0]) and (BB[0,1] >= self[0,1]) and (BB[1,1] <= self[1,1]) ): return True else: return False def Merge(self, BB): """ Joins this bounding box with the one passed in, maybe making this one bigger """ if BB[0,0] < self[0,0]: self[0,0] = BB[0,0] if BB[0,1] < self[0,1]: self[0,1] = BB[0,1] if BB[1,0] > self[1,0]: self[1,0] = BB[1,0] if BB[1,1] > self[1,1]: self[1,1] = BB[1,1] def _getWidth(self): return self[1,0] - self[0,0] def _getHeight(self): return self[1,1] - self[0,1] Width = property(_getWidth) Height = property(_getHeight) def _getCenter(self): return self.sum(0) / 2.0 Center = property(_getCenter) ### This could be used for a make BB from a bunch of BBs #~ def _getboundingbox(bboxarray): # lrk: added this #~ # returns the bounding box of a bunch of bounding boxes #~ upperleft = N.minimum.reduce(bboxarray[:,0]) #~ lowerright = N.maximum.reduce(bboxarray[:,1]) #~ return N.array((upperleft, lowerright), N.float) #~ _getboundingbox = staticmethod(_getboundingbox) ## Save the ndarray __eq__ for internal use. Array__eq__ = N.ndarray.__eq__ def __eq__(self, BB): """ __eq__(BB) The equality operator A == B if and only if all the entries are the same """ return N.all(self.Array__eq__(BB)) def asBBox(data): """ returns a BBox object. If object is a BBox, it is returned unaltered If object is a numpy array, a BBox object is returned that shares a view of the data with that array """ if isinstance(data, BBox): return data arr = N.asarray(data, N.float) return N.ndarray.__new__(BBox, shape=arr.shape, dtype=arr.dtype, buffer=arr) def fromPoints(Points): """ fromPoints (Points). reruns the bounding box of the set of points in Points. Points can be any python object that can be turned into a numpy NX2 array of Floats. If a single point is passed in, a zero-size Bounding Box is returned. """ Points = N.asarray(Points, N.float).reshape(-1,2) arr = N.vstack( (Points.min(0), Points.max(0)) ) return N.ndarray.__new__(BBox, shape=arr.shape, dtype=arr.dtype, buffer=arr) def fromBBArray(BBarray): """ Builds a BBox object from an array of Bounding Boxes. The resulting Bounding Box encompases all the included BBs. The BBarray is in the shape: (Nx2x2) where BBarray[n] is a 2x2 array that represents a BBox """ #upperleft = N.minimum.reduce(BBarray[:,0]) #lowerright = N.maximum.reduce(BBarray[:,1]) # BBarray = N.asarray(BBarray, N.float).reshape(-1,2) # arr = N.vstack( (BBarray.min(0), BBarray.max(0)) ) BBarray = N.asarray(BBarray, N.float).reshape(-1,2,2) arr = N.vstack( (BBarray[:,0,:].min(0), BBarray[:,1,:].max(0)) ) return asBBox(arr) #return asBBox( (upperleft, lowerright) ) * 2 tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/Utilities/GUI.py0000644000175000017500000000641510773624641021541 0ustar timtim""" Part of the floatcanvas.Utilities package. This module contains assorted GUI-related utilities that can be used with FloatCanvas So far, they are: RubberBandBox: used to draw a RubberBand Box on the screen """ import wx from floatcanvas import FloatCanvas class RubberBandBox: """ Class to provide a rubber band box that can be drawn on a Window """ def __init__(self, Canvas, CallBack, Tol=5): """ To initialize: RubberBandBox(Canvas, CallBack) Canvas: the FloatCanvas you want the Rubber band box to be used on CallBack: is the method you want called when the mouse is released. That method will be called, passing in a rect parameter, where rect is: (Point, WH) of the rect in world coords. Tol: The tolerance for the smallest rectangle allowed. defaults to 5. In pixels Methods: Enable() : Enables the Rubber Band Box (Binds the events) Disable() : Enables the Rubber Band Box (Unbinds the events) Attributes: CallBack: The callback function, if it's replaced you need to call Enable() again. """ self.Canvas = Canvas self.CallBack = CallBack self.Tol = Tol self.Drawing = False self.RBRect = None self.StartPointWorld = None return None def Enable(self): """ Called when you want the rubber band box to be enabled """ # bind events: self.Canvas.Bind(FloatCanvas.EVT_MOTION, self.OnMove ) self.Canvas.Bind(FloatCanvas.EVT_LEFT_DOWN, self.OnLeftDown) self.Canvas.Bind(FloatCanvas.EVT_LEFT_UP, self.OnLeftUp ) def Disable(self): """ Called when you don't want the rubber band box to be enabled """ # unbind events: self.Canvas.Unbind(FloatCanvas.EVT_MOTION) self.Canvas.Unbind(FloatCanvas.EVT_LEFT_DOWN) self.Canvas.Unbind(FloatCanvas.EVT_LEFT_UP) def OnMove(self, event): if self.Drawing: x, y = self.StartPoint Cornerx, Cornery = event.GetPosition() w, h = ( Cornerx - x, Cornery - y) if abs(w) > self.Tol and abs(h) > self.Tol: # draw the RB box dc = wx.ClientDC(self.Canvas) dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH)) dc.SetBrush(wx.TRANSPARENT_BRUSH) dc.SetLogicalFunction(wx.XOR) if self.RBRect: dc.DrawRectangle(*self.RBRect) self.RBRect = (x, y, w, h ) dc.DrawRectangle(*self.RBRect) event.Skip() # skip so that other events can catch these def OnLeftDown(self, event): # Start drawing self.Drawing = True self.StartPoint = event.GetPosition() self.StartPointWorld = event.Coords def OnLeftUp(self, event): # Stop Drawing if self.Drawing: self.Drawing = False if self.RBRect: WH = event.Coords - self.StartPointWorld wx.CallAfter(self.CallBack, (self.StartPointWorld, WH)) self.RBRect = None self.StartPointWorld = None tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/Utilities/Colors.py0000755000175000017500000000366710773624641022367 0ustar timtim#!/usr/bin/env python """ Colors.py Assorted stuff for Colrsd support. At the moment, only a single item: CatagoricalColor1: A list of colors that are distict. """ ## Categorical 12-step scheme, after ColorBrewer 11-step Paired Scheme ## From: http://geography.uoregon.edu/datagraphics/color_scales.htm # CategoricalColor1 = [ (255, 191, 127), # (255, 127, 0), # (255, 255, 153), # (255, 255, 50), # (178, 255, 140), # ( 50, 255, 0), # (165, 237, 255), # (25, 178, 255), # (204, 191, 255), # (101, 76, 255), # (255, 153, 191), # (229, 25, 50), # ] CategoricalColor1 = [ (229, 25, 50), (101, 76, 255), ( 50, 255, 0), (255, 127, 0), (255, 255, 50), (255, 153, 191), (25, 178, 255), (178, 255, 140), (255, 191, 127), (204, 191, 255), (165, 237, 255), (255, 255, 153), ] if __name__ == "__main__": import wx # tiny test app class TestFrame(wx.Frame): def __init__(self, *args, **kwargs): wx.Frame.__init__(self, *args, **kwargs) Sizer = wx.BoxSizer(wx.VERTICAL) Sizer.Add(wx.StaticText(self, label="CategoricalColor"), 0, wx.ALL, 5) for c in CategoricalColor1: w = wx.Window(self, size=(100, 20)) w.SetBackgroundColour(wx.Colour(*c)) Sizer.Add(w, 0, wx.ALL, 5) self.SetSizerAndFit(Sizer) self.Show() A = wx.App(False) F = TestFrame(None) A.MainLoop() tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/GUIMode.py0000644000175000017500000003265310773624641020376 0ustar timtim#!/usr/bin/env python """ Module that holds the GUI modes used by FloatCanvas Note that this can only be imported after a wx.App() has been created. This approach was inpired by Christian Blouin, who also wrote the initial version of the code. """ import wx ## fixme: events should live in their own module, so all of FloatCanvas ## wouldn't have to be imported here. import FloatCanvas, Resources import numpy as N ## create all the Cursors, so they don't need to be created each time. if "wxMac" in wx.PlatformInfo: # use 16X16 cursors for wxMac HandCursor = wx.CursorFromImage(Resources.getHand16Image()) GrabHandCursor = wx.CursorFromImage(Resources.getGrabHand16Image()) img = Resources.getMagPlus16Image() img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 6) img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 6) MagPlusCursor = wx.CursorFromImage(img) img = Resources.getMagMinus16Image() img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 6) img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 6) MagMinusCursor = wx.CursorFromImage(img) else: # use 24X24 cursors for GTK and Windows HandCursor = wx.CursorFromImage(Resources.getHandImage()) GrabHandCursor = wx.CursorFromImage(Resources.getGrabHandImage()) img = Resources.getMagPlusImage() img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 9) img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 9) MagPlusCursor = wx.CursorFromImage(img) img = Resources.getMagMinusImage() img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_X, 9) img.SetOptionInt(wx.IMAGE_OPTION_CUR_HOTSPOT_Y, 9) MagMinusCursor = wx.CursorFromImage(img) class GUIBase: """ Basic Mouse mode and baseclass for other GUImode. This one does nothing with any event """ def __init__(self, parent): self.parent = parent Cursor = wx.NullCursor # Handlers def OnLeftDown(self, event): pass def OnLeftUp(self, event): pass def OnLeftDouble(self, event): pass def OnRightDown(self, event): pass def OnRightUp(self, event): pass def OnRightDouble(self, event): pass def OnMiddleDown(self, event): pass def OnMiddleUp(self, event): pass def OnMiddleDouble(self, event): pass def OnWheel(self, event): pass def OnMove(self, event): pass def UpdateScreen(self): """ Update gets called if the screen has been repainted in the middle of a zoom in so the Rubber Band Box can get updated """ pass class GUIMouse(GUIBase): """ Mouse mode checks for a hit test, and if nothing is hit, raises a FloatCanvas mouse event for each event. """ Cursor = wx.NullCursor # Handlers def OnLeftDown(self, event): EventType = FloatCanvas.EVT_FC_LEFT_DOWN if not self.parent.HitTest(event, EventType): self.parent._RaiseMouseEvent(event, EventType) def OnLeftUp(self, event): EventType = FloatCanvas.EVT_FC_LEFT_UP if not self.parent.HitTest(event, EventType): self.parent._RaiseMouseEvent(event, EventType) def OnLeftDouble(self, event): EventType = FloatCanvas.EVT_FC_LEFT_DCLICK if not self.parent.HitTest(event, EventType): self.parent._RaiseMouseEvent(event, EventType) def OnMiddleDown(self, event): EventType = FloatCanvas.EVT_FC_MIDDLE_DOWN if not self.parent.HitTest(event, EventType): self.parent._RaiseMouseEvent(event, EventType) def OnMiddleUp(self, event): EventType = FloatCanvas.EVT_FC_MIDDLE_UP if not self.parent.HitTest(event, EventType): self.parent._RaiseMouseEvent(event, EventType) def OnMiddleDouble(self, event): EventType = FloatCanvas.EVT_FC_MIDDLE_DCLICK if not self.parent.HitTest(event, EventType): self.parent._RaiseMouseEvent(event, EventType) def OnRightDown(self, event): EventType = FloatCanvas.EVT_FC_RIGHT_DOWN if not self.parent.HitTest(event, EventType): self.parent._RaiseMouseEvent(event, EventType) def OnRightUp(self, event): EventType = FloatCanvas.EVT_FC_RIGHT_UP if not self.parent.HitTest(event, EventType): self.parent._RaiseMouseEvent(event, EventType) def OnRightDouble(self, event): EventType = FloatCanvas.EVT_FC_RIGHT_DCLICK if not self.parent.HitTest(event, EventType): self.parent._RaiseMouseEvent(event, EventType) def OnWheel(self, event): EventType = FloatCanvas.EVT_FC_MOUSEWHEEL self.parent._RaiseMouseEvent(event, EventType) def OnMove(self, event): ## The Move event always gets raised, even if there is a hit-test self.parent.MouseOverTest(event) self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION) class GUIMove(GUIBase): Cursor = HandCursor GrabCursor = GrabHandCursor def __init__(self, parent): GUIBase.__init__(self, parent) self.StartMove = None self.PrevMoveXY = None def OnLeftDown(self, event): self.parent.SetCursor(self.GrabCursor) self.parent.CaptureMouse() self.StartMove = N.array( event.GetPosition() ) self.PrevMoveXY = (0,0) def OnLeftUp(self, event): if self.StartMove is not None: StartMove = self.StartMove EndMove = N.array(event.GetPosition()) DiffMove = StartMove-EndMove if N.sum(DiffMove**2) > 16: self.parent.MoveImage(DiffMove, 'Pixel') self.StartMove = None self.parent.SetCursor(self.Cursor) def OnMove(self, event): # Allways raise the Move event. self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION) if event.Dragging() and event.LeftIsDown() and not self.StartMove is None: xy1 = N.array( event.GetPosition() ) wh = self.parent.PanelSize xy_tl = xy1 - self.StartMove dc = wx.ClientDC(self.parent) dc.BeginDrawing() x1,y1 = self.PrevMoveXY x2,y2 = xy_tl w,h = self.parent.PanelSize ##fixme: This sure could be cleaner! if x2 > x1 and y2 > y1: xa = xb = x1 ya = yb = y1 wa = w ha = y2 - y1 wb = x2- x1 hb = h elif x2 > x1 and y2 <= y1: xa = x1 ya = y1 wa = x2 - x1 ha = h xb = x1 yb = y2 + h wb = w hb = y1 - y2 elif x2 <= x1 and y2 > y1: xa = x1 ya = y1 wa = w ha = y2 - y1 xb = x2 + w yb = y1 wb = x1 - x2 hb = h - y2 + y1 elif x2 <= x1 and y2 <= y1: xa = x2 + w ya = y1 wa = x1 - x2 ha = h xb = x1 yb = y2 + h wb = w hb = y1 - y2 dc.SetPen(wx.TRANSPARENT_PEN) dc.SetBrush(self.parent.BackgroundBrush) dc.DrawRectangle(xa, ya, wa, ha) dc.DrawRectangle(xb, yb, wb, hb) self.PrevMoveXY = xy_tl if self.parent._ForeDrawList: dc.DrawBitmapPoint(self.parent._ForegroundBuffer,xy_tl) else: dc.DrawBitmapPoint(self.parent._Buffer,xy_tl) dc.EndDrawing() def OnWheel(self, event): """ By default, zoom in/out by a 0.1 factor per Wheel event. """ if event.GetWheelRotation() < 0: self.parent.Zoom(0.9) else: self.parent.Zoom(1.1) class GUIMouseAndMove(GUIMouse, GUIMove): def __init__(self, parent): GUIMouse.__init__(self, parent) GUIMove.__init__(self, parent) def OnKeyUp(self, event): # FIXME: Check these on non-qwerty keyboards ZoomOut = (61, 388) ZoomIn = (45, 390) pos = event.GetPosition() size = self.parent.GetSize() center = size[0]/2, size[1]/2 move = center[0]-pos[0], center[1]-pos[1] if event.UnicodeKey in ZoomIn: self.parent.Zoom(0.90, event.GetPosition(), 'Pixel', False) self.parent.MoveImage(move, 'Pixel') return True elif event.UnicodeKey in ZoomOut: self.parent.Zoom(1.10, event.GetPosition(), 'Pixel', False) self.parent.MoveImage(move, 'Pixel') return True Up = (315, 87, 332) Left = (314, 328, 65) Down = (317, 326, 83) Right = (316, 330, 68) if event.UnicodeKey in Left: self.parent.MoveImage((-40, 0), 'Pixel') elif event.UnicodeKey in Right: self.parent.MoveImage((40, 0), 'Pixel') elif event.UnicodeKey in Up: self.parent.MoveImage((0, -40), 'Pixel') elif event.UnicodeKey in Down: self.parent.MoveImage((0, 40), 'Pixel') return True def OnLeftDown(self, event): EventType = FloatCanvas.EVT_FC_LEFT_DOWN if not self.parent.HitTest(event, EventType): GUIMove.OnLeftDown(self, event) def OnLeftUp(self, event): if self.StartMove is None: GUIMouse.OnLeftUp(self, event) else: GUIMove.OnLeftUp(self, event) def OnLeftDouble(self, event): EventType = FloatCanvas.EVT_FC_LEFT_DCLICK if not self.parent.HitTest(event, EventType): self.parent.Zoom(1.0,event.GetPosition(),"Pixel") # self.parent._RaiseMouseEvent(event, EventType) def OnMove(self, event): if self.StartMove is None: GUIMouse.OnMove(self, event) else: GUIMove.OnMove(self, event) class GUIZoomIn(GUIBase): Cursor = MagPlusCursor def __init__(self, parent): GUIBase.__init__(self, parent) self.StartRBBox = None self.PrevRBBox = None def OnLeftDown(self, event): self.StartRBBox = N.array( event.GetPosition() ) self.PrevRBBox = None self.parent.CaptureMouse() def OnLeftUp(self, event): #if self.parent.HasCapture(): # self.parent.ReleaseMouse() if event.LeftUp() and not self.StartRBBox is None: self.PrevRBBox = None EndRBBox = event.GetPosition() StartRBBox = self.StartRBBox # if mouse has moved less that ten pixels, don't use the box. if ( abs(StartRBBox[0] - EndRBBox[0]) > 10 and abs(StartRBBox[1] - EndRBBox[1]) > 10 ): EndRBBox = self.parent.PixelToWorld(EndRBBox) StartRBBox = self.parent.PixelToWorld(StartRBBox) BB = N.array(((min(EndRBBox[0],StartRBBox[0]), min(EndRBBox[1],StartRBBox[1])), (max(EndRBBox[0],StartRBBox[0]), max(EndRBBox[1],StartRBBox[1]))),N.float_) self.parent.ZoomToBB(BB) else: Center = self.parent.PixelToWorld(StartRBBox) self.parent.Zoom(1.5,Center) self.StartRBBox = None def OnMove(self, event): # Allways raise the Move event. self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION) if event.Dragging() and event.LeftIsDown() and not (self.StartRBBox is None): xy0 = self.StartRBBox xy1 = N.array( event.GetPosition() ) wh = abs(xy1 - xy0) wh[0] = max(wh[0], int(wh[1]*self.parent.AspectRatio)) wh[1] = int(wh[0] / self.parent.AspectRatio) xy_c = (xy0 + xy1) / 2 dc = wx.ClientDC(self.parent) dc.BeginDrawing() dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH)) dc.SetBrush(wx.TRANSPARENT_BRUSH) dc.SetLogicalFunction(wx.XOR) if self.PrevRBBox: dc.DrawRectanglePointSize(*self.PrevRBBox) self.PrevRBBox = ( xy_c - wh/2, wh ) dc.DrawRectanglePointSize( *self.PrevRBBox ) dc.EndDrawing() def UpdateScreen(self): """ Update gets called if the screen has been repainted in the middle of a zoom in so the Rubber Band Box can get updated """ if self.PrevRBBox is not None: dc = wx.ClientDC(self.parent) dc.SetPen(wx.Pen('WHITE', 2, wx.SHORT_DASH)) dc.SetBrush(wx.TRANSPARENT_BRUSH) dc.SetLogicalFunction(wx.XOR) dc.DrawRectanglePointSize(*self.PrevRBBox) def OnRightDown(self, event): self.parent.Zoom(1/1.5, event.GetPosition(), centerCoords="pixel") def OnWheel(self, event): if event.GetWheelRotation() < 0: self.parent.Zoom(0.9) else: self.parent.Zoom(1.1) class GUIZoomOut(GUIBase): Cursor = MagMinusCursor def OnLeftDown(self, event): self.parent.Zoom(1/1.5, event.GetPosition(), centerCoords="Pixel") def OnRightDown(self, event): self.parent.Zoom(1.5, event.GetPosition(), centerCoords="Pixel") def OnWheel(self, event): if event.GetWheelRotation() < 0: self.parent.Zoom(0.9) else: self.parent.Zoom(1.1) def OnMove(self, event): # Allways raise the Move event. self.parent._RaiseMouseEvent(event,FloatCanvas.EVT_FC_MOTION) tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/PieChart.py0000644000175000017500000001303210773624641020632 0ustar timtimimport wx ## import a local version of FloatCanvas from extra.wxFloatCanvas import FloatCanvas from extra.wxFloatCanvas.Utilities import BBox from extra.wxFloatCanvas.Utilities import Colors import numpy as N from math import * XYObjectMixin = FloatCanvas.XYObjectMixin LineOnlyMixin = FloatCanvas.LineOnlyMixin DrawObject = FloatCanvas.DrawObject class PieChart(XYObjectMixin, LineOnlyMixin, DrawObject): """ This is DrawObject for a pie chart You can pass in a bunch of values, and it will draw a pie chart for you, and it will make the chart, scaling the size of each "slice" to match your values. The parameters are: XY : The (x,y) coords of the center of the chart Diameter : The diamter of the chart in worls coords, unless you set "Scaled" to False, in which case it's in pixel coords. Values : sequence of values you want to make the chart of. FillColors=None : sequence of colors you want the slices. If None, it will choose (no guarantee youll like them!) FillStyles=None : Fill style you want ("Solid", "Hash", etc) LineColor = None : Color of lines separating the slices LineStyle = "Solid" : style of lines separating the slices LineWidth = 1 : With of lines separating the slices Scaled = True : Do you want the pie to scale when zooming? or stay the same size in pixels? InForeground = False: Should it be on the foreground? """ ##fixme: this should be a longer and better designed set. ## Maybe one from: http://geography.uoregon.edu/datagraphics/color_scales.htm DefaultColorList = Colors.CategoricalColor1 #["Red", "Green", "Blue", "Purple", "Yellow", "Cyan"] def __init__(self, XY, Diameter, Values, FillColors=None, FillStyles=None, LineColor = None, LineStyle = "Solid", LineWidth = 1, Scaled = True, InForeground = False): DrawObject.__init__(self, InForeground) self.XY = N.asarray(XY, N.float).reshape( (2,) ) self.Diameter = Diameter self.Values = N.asarray(Values, dtype=N.float).reshape((-1,1)) if FillColors is None: FillColors = self.DefaultColorList[:len(Values)] if FillStyles is None: FillStyles = ['Solid'] * len(FillColors) self.FillColors = FillColors self.FillStyles = FillStyles self.LineColor = LineColor self.LineStyle = LineStyle self.Scaled = Scaled self.InForeground = InForeground self.SetPen(LineColor, LineStyle, LineWidth) self.SetBrushes() self.CalculatePoints() def SetFillColors(self, FillColors): self.FillColors = FillColors self.SetBrushes() def SetFillStyles(self, FillStyles): self.FillStyles = FillStyles self.SetBrushed() def SetValues(self, Values): Values = N.asarray(Values, dtype=N.float).reshape((-1,1)) self.Values = Values self.CalculatePoints() def CalculatePoints(self): # add the zero point to start Values = N.vstack( ( (0,), self.Values) ) self.Angles = 270 - 360. * Values.cumsum()/Values.sum() self.CalcBoundingBox() def SetBrushes(self): self.Brushes = [] for FillColor, FillStyle in zip(self.FillColors, self.FillStyles): if FillColor is None or FillStyle is None: self.Brush = wx.TRANSPARENT_BRUSH else: self.Brushes.append(self.BrushList.setdefault( (FillColor, FillStyle), wx.Brush( FillColor, self.FillStyleList[FillStyle] ) ) ) def CalcBoundingBox(self): if self.Scaled: self.BoundingBox = BBox.asBBox( ((self.XY-self.Diameter),(self.XY+self.Diameter)) ) else: self.BoundingBox = BBox.asBBox((self.XY, self.XY)) if self._Canvas: self._Canvas.BoundingBoxDirty = True def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): CenterXY = WorldToPixel(self.XY) if self.Scaled: Diameter = ScaleWorldToPixel( (self.Diameter,self.Diameter) )[0] else: Diameter = self.Diameter dc.SetPen(self.Pen) PreviousEndXY = (0,0) for i, brush in enumerate(self.Brushes): dc.SetBrush( brush ) Radius = Diameter/2 ToAngle = self.toRAD(self.Angles[i+1]) FromAngle = self.toRAD(self.Angles[i]) EndXY = CenterXY + (Radius * cos(ToAngle), Radius * sin(ToAngle)) if not (PreviousEndXY[0] == 0 and PreviousEndXY[1] == 0): StartXY = PreviousEndXY else: StartXY = CenterXY + (Radius * cos(FromAngle), Radius * sin(FromAngle)) PreviousEndXY = EndXY dc.DrawArc(StartXY[0], StartXY[1], EndXY[0], EndXY[1], CenterXY[0], CenterXY[1]) if HTdc and self.HitAble: if self.Scaled: radius = (ScaleWorldToPixel(self.Diameter)/2)[0]# just the x-coord else: radius = self.Diameter/2 HTdc.SetPen(self.HitPen) HTdc.SetBrush(self.HitBrush) HTdc.DrawCirclePoint(CenterXY, radius) def toRAD(self, deg): return pi*deg/180.0 tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/NavCanvas.py0000644000175000017500000000614610773624641021023 0ustar timtim""" A Panel that includes the FloatCanvas and Navigation controls """ import wx import FloatCanvas, Resources class NavCanvas(wx.Panel): """ NavCanvas.py This is a high level window that encloses the FloatCanvas in a panel and adds a Navigation toolbar. """ def __init__(self, parent, id = wx.ID_ANY, size = wx.DefaultSize, **kwargs): # The rest just get passed into FloatCanvas wx.Panel.__init__(self, parent, id, size=size) self.BuildToolbar() ## Create the vertical sizer for the toolbar and Panel box = wx.BoxSizer(wx.VERTICAL) box.Add(self.ToolBar, 0, wx.ALL | wx.ALIGN_LEFT | wx.GROW, 4) self.Canvas = FloatCanvas.FloatCanvas(self, **kwargs) box.Add(self.Canvas, 1, wx.GROW) self.SetSizerAndFit(box) import GUIMode # here so that it doesn't get imported before wx.App() self.GUIZoomIn = GUIMode.GUIZoomIn(self.Canvas) self.GUIZoomOut = GUIMode.GUIZoomOut(self.Canvas) self.GUIMove = GUIMode.GUIMove(self.Canvas) self.GUIMouse = GUIMode.GUIMouse(self.Canvas) # default to Mouse mode self.ToolBar.ToggleTool(self.PointerTool.GetId(), True) self.Canvas.SetMode(self.GUIMouse) return None def BuildToolbar(self): tb = wx.ToolBar(self) self.ToolBar = tb tb.SetToolBitmapSize((24,24)) self.PointerTool = tb.AddRadioTool(wx.ID_ANY, bitmap=Resources.getPointerBitmap(), shortHelp = "Pointer") self.Bind(wx.EVT_TOOL, lambda evt : self.SetMode(Mode=self.GUIMouse), self.PointerTool) self.ZoomInTool = tb.AddRadioTool(wx.ID_ANY, bitmap=Resources.getMagPlusBitmap(), shortHelp = "Zoom In") self.Bind(wx.EVT_TOOL, lambda evt : self.SetMode(Mode=self.GUIZoomIn), self.ZoomInTool) self.ZoomOutTool = tb.AddRadioTool(wx.ID_ANY, bitmap=Resources.getMagMinusBitmap(), shortHelp = "Zoom Out") self.Bind(wx.EVT_TOOL, lambda evt : self.SetMode(Mode=self.GUIZoomOut), self.ZoomOutTool) self.MoveTool = tb.AddRadioTool(wx.ID_ANY, bitmap=Resources.getHandBitmap(), shortHelp = "Move") self.Bind(wx.EVT_TOOL, lambda evt : self.SetMode(Mode=self.GUIMove), self.MoveTool) tb.AddSeparator() self.ZoomButton = wx.Button(tb, label="Zoom To Fit") tb.AddControl(self.ZoomButton) self.ZoomButton.Bind(wx.EVT_BUTTON, self.ZoomToFit) tb.Realize() ## fixme: remove this when the bug is fixed! wx.CallAfter(self.HideShowHack) # this required on wxPython 2.8.3 on OS-X return tb def HideShowHack(self): ##fixme: remove this when the bug is fixed! """ Hack to hide and show button on toolbar to get around OS-X bug on wxPython2.8 on OS-X """ self.ZoomButton.Hide() self.ZoomButton.Show() def SetMode(self, Mode): self.Canvas.SetMode(Mode) def ZoomToFit(self,Event): self.Canvas.ZoomToBB() self.Canvas.SetFocus() # Otherwise the focus stays on the Button, and wheel events are lost. tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/PolygonStatic.py0000644000175000017500000000251210773624641021733 0ustar timtim import numpy as N from FloatCanvas import Polygon, XYObjectMixin class PolygonStatic(Polygon, XYObjectMixin): """\ Draws a polygon which always has the same pixel size. """ CalcBoundingBox = XYObjectMixin.CalcBoundingBox def __init__(self, XY, Points, Color="Black", InForeground=False, Offset=(0,0), **kw): xy = N.array(XY, N.float) xy.shape = (2,) self.XY = xy Polygon.__init__(self, Points, LineColor=Color, FillColor=Color, InForeground=InForeground, **kw) self.SetOffset(Offset) def SetOffset(self, Offset): self.Offset = N.array(Offset, N.float_) self.Offset.shape = (2,) # Make sure it is a length 2 vector def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel = None, HTdc=None): print "Drawing Arrow!" Points = self.Points + self.Offset + WorldToPixel(self.XY) dc.SetPen(self.Pen) dc.SetBrush(self.Brush) dc.DrawPolygon(Points) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.SetBrush(self.HitBrush) HTdc.DrawPolygon(Points) class PolygonArrow(PolygonStatic): def __init__(self, XY, *args, **kw): kw['LineWidth'] = 1 PolygonStatic.__init__(self, XY, [(0,0), (-5,-10), (0, -8), (5,-10)], *args, **kw) class PolygonShip(PolygonStatic): def __init__(self, XY, *args, **kw): kw['LineWidth'] = 1 PolygonStatic.__init__(self, XY, [(0,0), (3,0), (0,4), (0,2), (-3,0)], *args, **kw) tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/RelativePoint.py0000644000175000017500000000607410773624641021730 0ustar timtim import numpy as N from FloatCanvas import Point, PointSet class RelativePoint(Point): """\ Relative Point is a point which also has a *pixel* offset. This is useful for Icons where you want a point to be at the same location as another graphic but a different offset. """ def __init__(self, XY, Color = "Black", Diameter = 1, InForeground = False, Offset=(0,0)): Point.__init__(self, XY, Color, Diameter, InForeground = False) self.SetOffset(Offset) def SetOffset(self, Offset): self.Offset = N.array(Offset, N.float_) self.Offset.shape = (2,) # Make sure it is a length 2 vector def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): dc.SetPen(self.Pen) xy = WorldToPixel(self.XY) + self.Offset if self.Diameter <= 1: dc.DrawPoint(xy[0], xy[1]) else: dc.SetBrush(self.Brush) radius = int(round(self.Diameter/2)) dc.DrawCircle(xy[0],xy[1], radius) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) if self.Diameter <= 1: HTdc.DrawPoint(xy[0], xy[1]) else: HTdc.SetBrush(self.HitBrush) HTdc.DrawCircle(xy[0],xy[1], radius) class RelativePointSet(PointSet): def __init__(self, Points, Color = "Black", Diameter = 1, InForeground = False, Offsets=None): PointSet.__init__(self, Points, Color, Diameter, InForeground) self.SetOffsets(Offsets) def SetOffsets(self, Offsets): self.Offsets = N.array(Offsets, N.float_) if len(self.Offsets) != len(self.Points): raise TypeError('The offset list must be the same length as the number of points') def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): dc.SetPen(self.Pen) Points = WorldToPixel(self.Points)+self.Offsets if self.Diameter <= 1: dc.DrawPointList(Points) elif self.Diameter <= 2: self.DrawD2(dc, Points) else: dc.SetBrush(self.Brush) radius = int(round(self.Diameter/2)) ##fixme: I really should add a DrawCircleList to wxPython if len(Points) > 100: xy = Points xywh = N.concatenate((xy-radius, N.ones(xy.shape) * self.Diameter ), 1 ) dc.DrawEllipseList(xywh) else: for xy in Points: dc.DrawCircle(xy[0],xy[1], radius) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.SetBrush(self.HitBrush) if self.Diameter <= 1: HTdc.DrawPointList(Points) elif self.Diameter <= 2: self.DrawD2(HTdc, Points) else: if len(Points) > 100: xy = Points xywh = N.concatenate((xy-radius, N.ones(xy.shape) * self.Diameter ), 1 ) HTdc.DrawEllipseList(xywh) else: for xy in Points: HTdc.DrawCircle(xy[0],xy[1], radius) tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/FloatCanvas.py0000644000175000017500000032474410773624641021353 0ustar timtim#!/usr/bin/env python from __future__ import division try: import numpy as N except ImportError: raise ImportError("I could not import numpy") from time import clock import wx from Utilities import BBox ## A global variable to hold the Pixels per inch that wxWindows thinks is in use ## This is used for scaling fonts. ## This can't be computed on module __init__, because a wx.App might not have initialized yet. global FontScale ## Custom Exceptions: class FloatCanvasError(Exception): pass ## Create all the mouse events EVT_FC_ENTER_WINDOW = wx.NewEventType() EVT_FC_LEAVE_WINDOW = wx.NewEventType() EVT_FC_LEFT_DOWN = wx.NewEventType() EVT_FC_LEFT_UP = wx.NewEventType() EVT_FC_LEFT_DCLICK = wx.NewEventType() EVT_FC_MIDDLE_DOWN = wx.NewEventType() EVT_FC_MIDDLE_UP = wx.NewEventType() EVT_FC_MIDDLE_DCLICK = wx.NewEventType() EVT_FC_RIGHT_DOWN = wx.NewEventType() EVT_FC_RIGHT_UP = wx.NewEventType() EVT_FC_RIGHT_DCLICK = wx.NewEventType() EVT_FC_MOTION = wx.NewEventType() EVT_FC_MOUSEWHEEL = wx.NewEventType() ## these two are for the hit-test stuff, I never make them real Events ## fixme: could I use the PyEventBinder for the Object events too? EVT_FC_ENTER_OBJECT = wx.NewEventType() EVT_FC_LEAVE_OBJECT = wx.NewEventType() ##Create all mouse event binding objects EVT_LEFT_DOWN = wx.PyEventBinder(EVT_FC_LEFT_DOWN) EVT_LEFT_UP = wx.PyEventBinder(EVT_FC_LEFT_UP) EVT_LEFT_DCLICK = wx.PyEventBinder(EVT_FC_LEFT_DCLICK) EVT_MIDDLE_DOWN = wx.PyEventBinder(EVT_FC_MIDDLE_DOWN) EVT_MIDDLE_UP = wx.PyEventBinder(EVT_FC_MIDDLE_UP) EVT_MIDDLE_DCLICK = wx.PyEventBinder(EVT_FC_MIDDLE_DCLICK) EVT_RIGHT_DOWN = wx.PyEventBinder(EVT_FC_RIGHT_DOWN) EVT_RIGHT_UP = wx.PyEventBinder(EVT_FC_RIGHT_UP) EVT_RIGHT_DCLICK = wx.PyEventBinder(EVT_FC_RIGHT_DCLICK) EVT_MOTION = wx.PyEventBinder(EVT_FC_MOTION) EVT_ENTER_WINDOW = wx.PyEventBinder(EVT_FC_ENTER_WINDOW) EVT_LEAVE_WINDOW = wx.PyEventBinder(EVT_FC_LEAVE_WINDOW) EVT_MOUSEWHEEL = wx.PyEventBinder(EVT_FC_MOUSEWHEEL) class _MouseEvent(wx.PyCommandEvent): """! This event class takes a regular wxWindows mouse event as a parameter, and wraps it so that there is access to all the original methods. This is similar to subclassing, but you can't subclass a wxWindows event The goal is to be able to it just like a regular mouse event. It adds the method: GetCoords() , which returns and (x,y) tuple in world coordinates. Another difference is that it is a CommandEvent, which propagates up the window hierarchy until it is handled. """ def __init__(self, EventType, NativeEvent, WinID, Coords = None): wx.PyCommandEvent.__init__(self) self.SetEventType( EventType ) self._NativeEvent = NativeEvent self.Coords = Coords def GetCoords(self): return self.Coords def __getattr__(self, name): return getattr(self._NativeEvent, name) def _cycleidxs(indexcount, maxvalue, step): """! Utility function used by _colorGenerator """ if indexcount == 0: yield () else: for idx in xrange(0, maxvalue, step): for tail in _cycleidxs(indexcount - 1, maxvalue, step): yield (idx, ) + tail def _colorGenerator(): """! Generates a series of unique colors used to do hit-tests with the Hit Test bitmap """ depth = wx.GetDisplayDepth() ## ##there have been problems with 16 bbp displays, to I'm disabling this for now. ## if depth == 16: ## print "Warning: There have been problems with hit-testing on 16bbp displays" ## step = 8 if depth >= 24: step = 1 else: msg= ["ColorGenerator does not work with depth = %s" % depth] msg.append("It is required for hit testing -- binding events to mouse") msg.append("actions on objects on the Canvas.") msg.append("Please set your display to 24bit") msg.append("Alternatively, the code could be adapted to 16 bit if that's required") raise FloatCanvasError(msg) return _cycleidxs(indexcount=3, maxvalue=256, step=step) class DrawObject: """! This is the base class for all the objects that can be drawn. One must subclass from this (and an assortment of Mixins) to create a new DrawObject. \note This class contain a series of static dictionaries: * BrushList * PenList * FillStyleList * LineStyleList Is this still necessary? """ def __init__(self, InForeground = False, IsVisible = True): """! \param InForeground (bool) \param IsVisible (Bool) """ self.InForeground = InForeground self.DrawOrder = 0 self._Canvas = None self.HitColor = None self.CallBackFuncs = {} ## these are the defaults self.HitAble = False self.HitLine = True self.HitFill = True self.MinHitLineWidth = 3 self.HitLineWidth = 3 ## this gets re-set by the subclasses if necessary self.Brush = None self.Pen = None self.FillStyle = "Solid" self.Visible = IsVisible # I pre-define all these as class variables to provide an easier # interface, and perhaps speed things up by caching all the Pens # and Brushes, although that may not help, as I think wx now # does that on it's own. Send me a note if you know! BrushList = { ( None,"Transparent") : wx.TRANSPARENT_BRUSH, ("Blue","Solid") : wx.BLUE_BRUSH, ("Green","Solid") : wx.GREEN_BRUSH, ("White","Solid") : wx.WHITE_BRUSH, ("Black","Solid") : wx.BLACK_BRUSH, ("Grey","Solid") : wx.GREY_BRUSH, ("MediumGrey","Solid") : wx.MEDIUM_GREY_BRUSH, ("LightGrey","Solid") : wx.LIGHT_GREY_BRUSH, ("Cyan","Solid") : wx.CYAN_BRUSH, ("Red","Solid") : wx.RED_BRUSH } PenList = { (None,"Transparent",1) : wx.TRANSPARENT_PEN, ("Green","Solid",1) : wx.GREEN_PEN, ("White","Solid",1) : wx.WHITE_PEN, ("Black","Solid",1) : wx.BLACK_PEN, ("Grey","Solid",1) : wx.GREY_PEN, ("MediumGrey","Solid",1) : wx.MEDIUM_GREY_PEN, ("LightGrey","Solid",1) : wx.LIGHT_GREY_PEN, ("Cyan","Solid",1) : wx.CYAN_PEN, ("Red","Solid",1) : wx.RED_PEN } FillStyleList = { "Transparent" : wx.TRANSPARENT, "Solid" : wx.SOLID, "BiDiagonalHatch": wx.BDIAGONAL_HATCH, "CrossDiagHatch" : wx.CROSSDIAG_HATCH, "FDiagonal_Hatch": wx.FDIAGONAL_HATCH, "CrossHatch" : wx.CROSS_HATCH, "HorizontalHatch": wx.HORIZONTAL_HATCH, "VerticalHatch" : wx.VERTICAL_HATCH } LineStyleList = { "Solid" : wx.SOLID, "Transparent": wx.TRANSPARENT, "Dot" : wx.DOT, "LongDash" : wx.LONG_DASH, "ShortDash" : wx.SHORT_DASH, "DotDash" : wx.DOT_DASH, } # def BBFromPoints(self, Points): # """! # Calculates a Bounding box from a set of points (NX2 array of coordinates) # \param Points (array?) # """ # # ## fixme: this could be done with array.min() and vstack() in numpy. # ## This could use the Utilities.BBox module now. # #return N.array( (N.minimum.reduce(Points), # # N.maximum.reduce(Points) ), # # ) # return BBox.fromPoints(Points) def Bind(self, Event, CallBackFun): ##fixme: Way too much Canvas Manipulation here! self.CallBackFuncs[Event] = CallBackFun self.HitAble = True self._Canvas.UseHitTest = True if self.InForeground and self._Canvas._ForegroundHTBitmap is None: self._Canvas.MakeNewForegroundHTBitmap() elif self._Canvas._HTBitmap is None: self._Canvas.MakeNewHTBitmap() if not self.HitColor: if not self._Canvas.HitColorGenerator: self._Canvas.HitColorGenerator = _colorGenerator() self._Canvas.HitColorGenerator.next() # first call to prevent the background color from being used. self.HitColor = self._Canvas.HitColorGenerator.next() self.SetHitPen(self.HitColor,self.HitLineWidth) self.SetHitBrush(self.HitColor) # put the object in the hit dict, indexed by it's color if not self._Canvas.HitDict: self._Canvas.MakeHitDict() self._Canvas.HitDict[Event][self.HitColor] = (self) # put the object in the hit dict, indexed by it's color def UnBindAll(self): ## fixme: this only removes one from each list, there could be more. if self._Canvas.HitDict: for Event in self._Canvas.HitDict.itervalues(): try: del Event[self.HitColor] except KeyError: pass self.HitAble = False def SetBrush(self,FillColor,FillStyle): if FillColor is None or FillStyle is None: self.Brush = wx.TRANSPARENT_BRUSH ##fixme: should I really re-set the style? self.FillStyle = "Transparent" else: self.Brush = self.BrushList.setdefault( (FillColor,FillStyle), wx.Brush(FillColor,self.FillStyleList[FillStyle] ) ) def SetPen(self,LineColor,LineStyle,LineWidth): if (LineColor is None) or (LineStyle is None): self.Pen = wx.TRANSPARENT_PEN self.LineStyle = 'Transparent' else: self.Pen = self.PenList.setdefault( (LineColor,LineStyle,LineWidth), wx.Pen(LineColor,LineWidth,self.LineStyleList[LineStyle]) ) def SetHitBrush(self,HitColor): if not self.HitFill: self.HitBrush = wx.TRANSPARENT_BRUSH else: self.HitBrush = self.BrushList.setdefault( (HitColor,"solid"), wx.Brush(HitColor,self.FillStyleList["Solid"] ) ) def SetHitPen(self,HitColor,LineWidth): if not self.HitLine: self.HitPen = wx.TRANSPARENT_PEN else: self.HitPen = self.PenList.setdefault( (HitColor, "solid", self.HitLineWidth), wx.Pen(HitColor, self.HitLineWidth, self.LineStyleList["Solid"]) ) ## Just to make sure that they will always be there ## the appropriate ones should be overridden in the subclasses def SetColor(self, Color): pass def SetLineColor(self, LineColor): pass def SetLineStyle(self, LineStyle): pass def SetLineWidth(self, LineWidth): pass def SetFillColor(self, FillColor): pass def SetFillStyle(self, FillStyle): pass def PutInBackground(self): if self._Canvas and self.InForeground: self._Canvas._ForeDrawList.remove(self) self._Canvas._DrawList.append(self) self._Canvas._BackgroundDirty = True self.InForeground = False def PutInForeground(self): if self._Canvas and (not self.InForeground): self._Canvas._ForeDrawList.append(self) self._Canvas._DrawList.remove(self) self._Canvas._BackgroundDirty = True self.InForeground = True def Hide(self): """! \brief Make an object hidden. """ self.Visible = False def Show(self): """! \brief Make an object visible on the canvas. """ self.Visible = True class Group(DrawObject): """ A group of other FloatCanvas Objects Not all DrawObject methods may apply here. In particular, you can't Bind events to a group. Note that if an object is in more than one group, it will get drawn more than once. """ def __init__(self, ObjectList=[], InForeground = False, IsVisible = True): self.ObjectList = list(ObjectList) DrawObject.__init__(self, InForeground, IsVisible) self.CalcBoundingBox() def AddObject(self, obj): self.ObjectList.append(obj) self.BoundingBox.Merge(obj.BoundingBox) def AddObjects(self, Objects): for o in Objects: self.AddObject(o) def CalcBoundingBox(self): if self.ObjectList: BB = BBox.asBBox(self.ObjectList[0].BoundingBox) for obj in self.ObjectList[1:]: BB.Merge(obj.BoundingBox) else: BB = None self.BoundingBox = BB def SetColor(self, Color): for o in self.ObjectList: o.SetColor(Color) def SetLineColor(self, Color): for o in self.ObjectList: o.SetLineColor(Color) def SetLineStyle(self, LineStyle): for o in self.ObjectList: o.SetLineStyle(LineStyle) def SetLineWidth(self, LineWidth): for o in self.ObjectList: o.SetLineWidth(LineWidth) def SetFillColor(self, Color): for o in self.ObjectList: o.SetFillColor(Color) def SetFillStyle(self, FillStyle): for o in self.ObjectList: o.SetFillStyle(FillStyle) def Move(self, Delta): for obj in self.ObjectList: obj.Move(Delta) def Bind(self, Event, CallBackFun): ## slight variation on DrawObject Bind Method: ## fixme: There is a lot of repeated code from the DrawObject method, but ## it all needs a l ot of cleaning up anyway. self.CallBackFuncs[Event] = CallBackFun self.HitAble = True self._Canvas.UseHitTest = True if self.InForeground and self._Canvas._ForegroundHTBitmap is None: self._Canvas.MakeNewForegroundHTBitmap() elif self._Canvas._HTBitmap is None: self._Canvas.MakeNewHTBitmap() if not self.HitColor: if not self._Canvas.HitColorGenerator: self._Canvas.HitColorGenerator = _colorGenerator() self._Canvas.HitColorGenerator.next() # first call to prevent the background color from being used. # Set all contained objects to the same Hit color: self.HitColor = self._Canvas.HitColorGenerator.next() for obj in self.ObjectList: obj.SetHitPen(self.HitColor, self.HitLineWidth) obj.SetHitBrush(self.HitColor) obj.HitAble = True # put the object in the hit dict, indexed by it's color if not self._Canvas.HitDict: self._Canvas.MakeHitDict() self._Canvas.HitDict[Event][self.HitColor] = (self) # put the object in the hit dict, indexed by it's color def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel = None, HTdc=None): for obj in self.ObjectList: obj._Draw(dc, WorldToPixel, ScaleWorldToPixel, HTdc) class ColorOnlyMixin: """ Mixin class for objects that have just one color, rather than a fill color and line color """ def SetColor(self, Color): self.SetPen(Color,"Solid",1) self.SetBrush(Color,"Solid") SetFillColor = SetColor # Just to provide a consistant interface class LineOnlyMixin: """ Mixin class for objects that have just one color, rather than a fill color and line color """ def SetLineColor(self, LineColor): self.LineColor = LineColor self.SetPen(LineColor,self.LineStyle,self.LineWidth) SetColor = SetLineColor# so that it will do somethign reasonable def SetLineStyle(self, LineStyle): self.LineStyle = LineStyle self.SetPen(self.LineColor,LineStyle,self.LineWidth) def SetLineWidth(self, LineWidth): self.LineWidth = LineWidth self.SetPen(self.LineColor,self.LineStyle,LineWidth) class LineAndFillMixin(LineOnlyMixin): """ Mixin class for objects that have both a line and a fill color and style. """ def SetFillColor(self, FillColor): self.FillColor = FillColor self.SetBrush(FillColor, self.FillStyle) def SetFillStyle(self, FillStyle): self.FillStyle = FillStyle self.SetBrush(self.FillColor,FillStyle) def SetUpDraw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc): dc.SetPen(self.Pen) dc.SetBrush(self.Brush) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.SetBrush(self.HitBrush) return ( WorldToPixel(self.XY), ScaleWorldToPixel(self.WH) ) class XYObjectMixin: """ This is a mixin class that provides some methods suitable for use with objects that have a single (x,y) coordinate pair. """ def Move(self, Delta ): """ Move(Delta): moves the object by delta, where delta is a (dx,dy) pair. Ideally a Numpy array of shape (2,) """ Delta = N.asarray(Delta, N.float) self.XY += Delta self.BoundingBox += Delta if self._Canvas: self._Canvas.BoundingBoxDirty = True def CalcBoundingBox(self): ## This may get overwritten in some subclasses self.BoundingBox = N.array( (self.XY, self.XY), N.float ) self.BoundingBox = BBox.asBBox((self.XY, self.XY)) def SetPoint(self, xy): xy = N.array(xy, N.float) xy.shape = (2,) self.XY = xy self.CalcBoundingBox() if self._Canvas: self._Canvas.BoundingBoxDirty = True class PointsObjectMixin: """ This is a mixin class that provides some methods suitable for use with objects that have a set of (x,y) coordinate pairs. """ def Move(self, Delta): """ Move(Delta): moves the object by delta, where delta is an (dx, dy) pair. Ideally a Numpy array of shape (2,) """ Delta = N.asarray(Delta, N.float) Delta.shape = (2,) self.Points += Delta self.BoundingBox += Delta if self._Canvas: self._Canvas.BoundingBoxDirty = True def CalcBoundingBox(self): self.BoundingBox = BBox.fromPoints(self.Points) if self._Canvas: self._Canvas.BoundingBoxDirty = True def SetPoints(self, Points, copy = True): """ Sets the coordinates of the points of the object to Points (NX2 array). By default, a copy is made, if copy is set to False, a reference is used, iff Points is a NumPy array of Floats. This allows you to change some or all of the points without making any copies. For example: Points = Object.Points Points += (5,10) # shifts the points 5 in the x dir, and 10 in the y dir. Object.SetPoints(Points, False) # Sets the points to the same array as it was """ if copy: self.Points = N.array(Points, N.float) self.Points.shape = (-1,2) # Make sure it is a NX2 array, even if there is only one point else: self.Points = N.asarray(Points, N.float) self.CalcBoundingBox() class Polygon(PointsObjectMixin, LineAndFillMixin, DrawObject): """ The Polygon class takes a list of 2-tuples, or a NX2 NumPy array of point coordinates. so that Points[N][0] is the x-coordinate of point N and Points[N][1] is the y-coordinate or Points[N,0] is the x-coordinate of point N and Points[N,1] is the y-coordinate for arrays. The other parameters specify various properties of the Polygon, and should be self explanatory. """ def __init__(self, Points, LineColor = "Black", LineStyle = "Solid", LineWidth = 1, FillColor = None, FillStyle = "Solid", InForeground = False): DrawObject.__init__(self, InForeground) self.Points = N.array(Points ,N.float) # this DOES need to make a copy self.CalcBoundingBox() self.LineColor = LineColor self.LineStyle = LineStyle self.LineWidth = LineWidth self.FillColor = FillColor self.FillStyle = FillStyle self.HitLineWidth = max(LineWidth,self.MinHitLineWidth) self.SetPen(LineColor,LineStyle,LineWidth) self.SetBrush(FillColor,FillStyle) def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel = None, HTdc=None): Points = WorldToPixel(self.Points)#.tolist() dc.SetPen(self.Pen) dc.SetBrush(self.Brush) dc.DrawPolygon(Points) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.SetBrush(self.HitBrush) HTdc.DrawPolygon(Points) class Line(PointsObjectMixin, LineOnlyMixin, DrawObject,): """ The Line class takes a list of 2-tuples, or a NX2 NumPy Float array of point coordinates. It will draw a straight line if there are two points, and a polyline if there are more than two. """ def __init__(self,Points, LineColor = "Black", LineStyle = "Solid", LineWidth = 1, InForeground = False): DrawObject.__init__(self, InForeground) self.Points = N.array(Points,N.float) self.CalcBoundingBox() self.LineColor = LineColor self.LineStyle = LineStyle self.LineWidth = LineWidth self.SetPen(LineColor,LineStyle,LineWidth) self.HitLineWidth = max(LineWidth,self.MinHitLineWidth) def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): Points = WorldToPixel(self.Points) dc.SetPen(self.Pen) dc.DrawLines(Points) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.DrawLines(Points) class Spline(Line): def __init__(self, *args, **kwargs): Line.__init__(self, *args, **kwargs) def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): Points = WorldToPixel(self.Points) dc.SetPen(self.Pen) dc.DrawSpline(Points) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.DrawSpline(Points) class Arrow(XYObjectMixin, LineOnlyMixin, DrawObject): """ Arrow(XY, # coords of origin of arrow (x,y) Length, # length of arrow in pixels theta, # angle of arrow in degrees: zero is straight up # +angle is to the right LineColor = "Black", LineStyle = "Solid", LineWidth = 1, ArrowHeadSize = 4, # size of arrowhead in pixels ArrowHeadAngle = 45, # angle of arrow head in degrees InForeground = False): It will draw an arrow , starting at the point, (X,Y) pointing in direction, theta. """ def __init__(self, XY, Length, Direction, LineColor = "Black", LineStyle = "Solid", LineWidth = 2, # pixels ArrowHeadSize = 8, # pixels ArrowHeadAngle = 30, # degrees InForeground = False): DrawObject.__init__(self, InForeground) self.XY = N.array(XY, N.float) self.XY.shape = (2,) # Make sure it is a length 2 vector self.Length = Length self.Direction = float(Direction) self.ArrowHeadSize = ArrowHeadSize self.ArrowHeadAngle = float(ArrowHeadAngle) self.CalcArrowPoints() self.CalcBoundingBox() self.LineColor = LineColor self.LineStyle = LineStyle self.LineWidth = LineWidth self.SetPen(LineColor,LineStyle,LineWidth) ##fixme: How should the HitTest be drawn? self.HitLineWidth = max(LineWidth,self.MinHitLineWidth) def SetDirection(self, Direction): self.Direction = float(Direction) self.CalcArrowPoints() def SetLength(self, Length): self.Length = Length self.CalcArrowPoints() def SetLengthDirection(self, Length, Direction): self.Direction = float(Direction) self.Length = Length self.CalcArrowPoints() ## def CalcArrowPoints(self): ## L = self.Length ## S = self.ArrowHeadSize ## phi = self.ArrowHeadAngle * N.pi / 360 ## theta = (self.Direction-90.0) * N.pi / 180 ## ArrowPoints = N.array( ( (0, L, L - S*N.cos(phi),L, L - S*N.cos(phi) ), ## (0, 0, S*N.sin(phi), 0, -S*N.sin(phi) ) ), ## N.float ) ## RotationMatrix = N.array( ( ( N.cos(theta), -N.sin(theta) ), ## ( N.sin(theta), N.cos(theta) ) ), ## N.float ## ) ## ArrowPoints = N.matrixmultiply(RotationMatrix, ArrowPoints) ## self.ArrowPoints = N.transpose(ArrowPoints) def CalcArrowPoints(self): L = self.Length S = self.ArrowHeadSize phi = self.ArrowHeadAngle * N.pi / 360 theta = (270 - self.Direction) * N.pi / 180 AP = N.array( ( (0,0), (0,0), (N.cos(theta - phi), -N.sin(theta - phi) ), (0,0), (N.cos(theta + phi), -N.sin(theta + phi) ), ), N.float ) AP *= S shift = (-L*N.cos(theta), L*N.sin(theta) ) AP[1:,:] += shift self.ArrowPoints = AP def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): dc.SetPen(self.Pen) xy = WorldToPixel(self.XY) ArrowPoints = xy + self.ArrowPoints dc.DrawLines(ArrowPoints) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.DrawLines(ArrowPoints) class ArrowLine(PointsObjectMixin, LineOnlyMixin, DrawObject): """ ArrowLine(Points, # coords of points LineColor = "Black", LineStyle = "Solid", LineWidth = 1, ArrowHeadSize = 4, # in pixels ArrowHeadAngle = 45, InForeground = False): It will draw a set of arrows from point to point. It takes a list of 2-tuples, or a NX2 NumPy Float array of point coordinates. """ def __init__(self, Points, LineColor = "Black", LineStyle = "Solid", LineWidth = 1, # pixels ArrowHeadSize = 8, # pixels ArrowHeadAngle = 30, # degrees InForeground = False): DrawObject.__init__(self, InForeground) self.Points = N.asarray(Points,N.float) self.Points.shape = (-1,2) # Make sure it is a NX2 array, even if there is only one point self.ArrowHeadSize = ArrowHeadSize self.ArrowHeadAngle = float(ArrowHeadAngle) self.CalcArrowPoints() self.CalcBoundingBox() self.LineColor = LineColor self.LineStyle = LineStyle self.LineWidth = LineWidth self.SetPen(LineColor,LineStyle,LineWidth) self.HitLineWidth = max(LineWidth,self.MinHitLineWidth) def CalcArrowPoints(self): S = self.ArrowHeadSize phi = self.ArrowHeadAngle * N.pi / 360 Points = self.Points n = Points.shape[0] self.ArrowPoints = N.zeros((n-1, 3, 2), N.float) for i in xrange(n-1): dx, dy = self.Points[i] - self.Points[i+1] theta = N.arctan2(dy, dx) AP = N.array( ( (N.cos(theta - phi), -N.sin(theta-phi)), (0,0), (N.cos(theta + phi), -N.sin(theta + phi)) ), N.float ) self.ArrowPoints[i,:,:] = AP self.ArrowPoints *= S def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): Points = WorldToPixel(self.Points) ArrowPoints = Points[1:,N.newaxis,:] + self.ArrowPoints dc.SetPen(self.Pen) dc.DrawLines(Points) for arrow in ArrowPoints: dc.DrawLines(arrow) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.DrawLines(Points) for arrow in ArrowPoints: HTdc.DrawLines(arrow) class PointSet(PointsObjectMixin, ColorOnlyMixin, DrawObject): """ The PointSet class takes a list of 2-tuples, or a NX2 NumPy array of point coordinates. If Points is a sequence of tuples: Points[N][0] is the x-coordinate of point N and Points[N][1] is the y-coordinate. If Points is a NumPy array: Points[N,0] is the x-coordinate of point N and Points[N,1] is the y-coordinate for arrays. Each point will be drawn the same color and Diameter. The Diameter is in screen pixels, not world coordinates. The hit-test code does not distingish between the points, you will only know that one of the points got hit, not which one. You can use PointSet.FindClosestPoint(WorldPoint) to find out which one In the case of points, the HitLineWidth is used as diameter. """ def __init__(self, Points, Color = "Black", Diameter = 1, InForeground = False): DrawObject.__init__(self,InForeground) self.Points = N.array(Points,N.float) self.Points.shape = (-1,2) # Make sure it is a NX2 array, even if there is only one point self.CalcBoundingBox() self.Diameter = Diameter self.HitLineWidth = min(self.MinHitLineWidth, Diameter) self.SetColor(Color) def SetDiameter(self,Diameter): self.Diameter = Diameter def FindClosestPoint(self, XY): """ Returns the index of the closest point to the point, XY, given in World coordinates. It's essentially random which you get if there are more than one that are the same. This can be used to figure out which point got hit in a mouse binding callback, for instance. It's a lot faster that using a lot of separate points. """ d = self.Points - XY return N.argmin(N.hypot(d[:,0],d[:,1])) def DrawD2(self, dc, Points): # A Little optimization for a diameter2 - point dc.DrawPointList(Points) dc.DrawPointList(Points + (1,0)) dc.DrawPointList(Points + (0,1)) dc.DrawPointList(Points + (1,1)) def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): dc.SetPen(self.Pen) Points = WorldToPixel(self.Points) if self.Diameter <= 1: dc.DrawPointList(Points) elif self.Diameter <= 2: self.DrawD2(dc, Points) else: dc.SetBrush(self.Brush) radius = int(round(self.Diameter/2)) ##fixme: I really should add a DrawCircleList to wxPython if len(Points) > 100: xy = Points xywh = N.concatenate((xy-radius, N.ones(xy.shape) * self.Diameter ), 1 ) dc.DrawEllipseList(xywh) else: for xy in Points: dc.DrawCircle(xy[0],xy[1], radius) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.SetBrush(self.HitBrush) if self.Diameter <= 1: HTdc.DrawPointList(Points) elif self.Diameter <= 2: self.DrawD2(HTdc, Points) else: if len(Points) > 100: xy = Points xywh = N.concatenate((xy-radius, N.ones(xy.shape) * self.Diameter ), 1 ) HTdc.DrawEllipseList(xywh) else: for xy in Points: HTdc.DrawCircle(xy[0],xy[1], radius) class Point(XYObjectMixin, ColorOnlyMixin, DrawObject): """ The Point class takes a 2-tuple, or a (2,) NumPy array of point coordinates. The Diameter is in screen points, not world coordinates, So the Bounding box is just the point, and doesn't include the Diameter. The HitLineWidth is used as diameter for the Hit Test. """ def __init__(self, XY, Color = "Black", Diameter = 1, InForeground = False): DrawObject.__init__(self, InForeground) self.XY = N.array(XY, N.float) self.XY.shape = (2,) # Make sure it is a length 2 vector self.CalcBoundingBox() self.SetColor(Color) self.Diameter = Diameter self.HitLineWidth = self.MinHitLineWidth def SetDiameter(self,Diameter): self.Diameter = Diameter def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): dc.SetPen(self.Pen) xy = WorldToPixel(self.XY) if self.Diameter <= 1: dc.DrawPoint(xy[0], xy[1]) else: dc.SetBrush(self.Brush) radius = int(round(self.Diameter/2)) dc.DrawCircle(xy[0],xy[1], radius) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) if self.Diameter <= 1: HTdc.DrawPoint(xy[0], xy[1]) else: HTdc.SetBrush(self.HitBrush) HTdc.DrawCircle(xy[0],xy[1], radius) class SquarePoint(XYObjectMixin, ColorOnlyMixin, DrawObject): """ The SquarePoint class takes a 2-tuple, or a (2,) NumPy array of point coordinates. It produces a square dot, centered on Point The Size is in screen points, not world coordinates, so the Bounding box is just the point, and doesn't include the Size. The HitLineWidth is used as diameter for the Hit Test. """ def __init__(self, Point, Color = "Black", Size = 4, InForeground = False): DrawObject.__init__(self, InForeground) self.XY = N.array(Point, N.float) self.XY.shape = (2,) # Make sure it is a length 2 vector self.CalcBoundingBox() self.SetColor(Color) self.Size = Size self.HitLineWidth = self.MinHitLineWidth def SetSize(self,Size): self.Size = Size def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): Size = self.Size dc.SetPen(self.Pen) xc,yc = WorldToPixel(self.XY) if self.Size <= 1: dc.DrawPoint(xc, yc) else: x = xc - Size/2.0 y = yc - Size/2.0 dc.SetBrush(self.Brush) dc.DrawRectangle(x, y, Size, Size) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) if self.Size <= 1: HTdc.DrawPoint(xc, xc) else: HTdc.SetBrush(self.HitBrush) HTdc.DrawRectangle(x, y, Size, Size) class RectEllipse(XYObjectMixin, LineAndFillMixin, DrawObject): def __init__(self, XY, WH, LineColor = "Black", LineStyle = "Solid", LineWidth = 1, FillColor = None, FillStyle = "Solid", InForeground = False): DrawObject.__init__(self,InForeground) self.SetShape(XY, WH) self.LineColor = LineColor self.LineStyle = LineStyle self.LineWidth = LineWidth self.FillColor = FillColor self.FillStyle = FillStyle self.HitLineWidth = max(LineWidth,self.MinHitLineWidth) self.SetPen(LineColor,LineStyle,LineWidth) self.SetBrush(FillColor,FillStyle) def SetShape(self, XY, WH): self.XY = N.array( XY, N.float) self.XY.shape = (2,) self.WH = N.array( WH, N.float) self.WH.shape = (2,) self.CalcBoundingBox() def CalcBoundingBox(self): # you need this in case Width or Height are negative corners = N.array((self.XY, (self.XY + self.WH) ), N.float) self.BoundingBox = BBox.fromPoints(corners) if self._Canvas: self._Canvas.BoundingBoxDirty = True class Rectangle(RectEllipse): def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): ( XY, WH ) = self.SetUpDraw(dc, WorldToPixel, ScaleWorldToPixel, HTdc) dc.DrawRectanglePointSize(XY, WH) if HTdc and self.HitAble: HTdc.DrawRectanglePointSize(XY, WH) class Ellipse(RectEllipse): def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): ( XY, WH ) = self.SetUpDraw(dc, WorldToPixel, ScaleWorldToPixel, HTdc) dc.DrawEllipsePointSize(XY, WH) if HTdc and self.HitAble: HTdc.DrawEllipsePointSize(XY, WH) class Circle(Ellipse): ## fixme: this should probably be use the DC.DrawCircle! def __init__(self, XY, Diameter, **kwargs): self.Center = N.array(XY, N.float) Diameter = float(Diameter) RectEllipse.__init__(self , self.Center - Diameter/2.0, (Diameter, Diameter), **kwargs) def SetDiameter(self, Diameter): Diameter = float(Diameter) XY = self.Center - (Diameter/2.0) self.SetShape(XY, (Diameter, Diameter) ) class TextObjectMixin(XYObjectMixin): """ A mix in class that holds attributes and methods that are needed by the Text objects """ ## I'm caching fonts, because on GTK, getting a new font can take a ## while. However, it gets cleared after every full draw as hanging ## on to a bunch of large fonts takes a massive amount of memory. FontList = {} LayoutFontSize = 16 # font size used for calculating layout def SetFont(self, Size, Family, Style, Weight, Underlined, FaceName): self.Font = self.FontList.setdefault( (Size, Family, Style, Weight, Underlined, FaceName), #wx.FontFromPixelSize((0.45*Size,Size), # this seemed to give a decent height/width ratio on Windows wx.Font(Size, Family, Style, Weight, Underlined, FaceName) ) def SetColor(self, Color): self.Color = Color def SetBackgroundColor(self, BackgroundColor): self.BackgroundColor = BackgroundColor def SetText(self, String): """ Re-sets the text displayed by the object In the case of the ScaledTextBox, it will re-do the layout as appropriate Note: only tested with the ScaledTextBox """ self.String = String self.LayoutText() def LayoutText(self): """ A dummy method to re-do the layout of the text. A derived object needs to override this if required. """ pass ## store the function that shift the coords for drawing text. The ## "c" parameter is the correction for world coordinates, rather ## than pixel coords as the y axis is reversed ## pad is the extra space around the text ## if world = 1, the vertical shift is done in y-up coordinates ShiftFunDict = {'tl': lambda x, y, w, h, world=0, pad=0: (x + pad, y + pad - 2*world*pad), 'tc': lambda x, y, w, h, world=0, pad=0: (x - w/2, y + pad - 2*world*pad), 'tr': lambda x, y, w, h, world=0, pad=0: (x - w - pad, y + pad - 2*world*pad), 'cl': lambda x, y, w, h, world=0, pad=0: (x + pad, y - h/2 + world*h), 'cc': lambda x, y, w, h, world=0, pad=0: (x - w/2, y - h/2 + world*h), 'cr': lambda x, y, w, h, world=0, pad=0: (x - w - pad, y - h/2 + world*h), 'bl': lambda x, y, w, h, world=0, pad=0: (x + pad, y - h + 2*world*h - pad + world*2*pad) , 'bc': lambda x, y, w, h, world=0, pad=0: (x - w/2, y - h + 2*world*h - pad + world*2*pad) , 'br': lambda x, y, w, h, world=0, pad=0: (x - w - pad, y - h + 2*world*h - pad + world*2*pad)} class Text(TextObjectMixin, DrawObject, ): """ This class creates a text object, placed at the coordinates, x,y. the "Position" argument is a two charactor string, indicating where in relation to the coordinates the string should be oriented. The first letter is: t, c, or b, for top, center and bottom The second letter is: l, c, or r, for left, center and right The position refers to the position relative to the text itself. It defaults to "tl" (top left). Size is the size of the font in pixels, or in points for printing (if it ever gets implimented). Those will be the same, If you assume 72 PPI. Family: Font family, a generic way of referring to fonts without specifying actual facename. One of: wx.DEFAULT: Chooses a default font. wx.DECORATIVE: A decorative font. wx.ROMAN: A formal, serif font. wx.SCRIPT: A handwriting font. wx.SWISS: A sans-serif font. wx.MODERN: A fixed pitch font. NOTE: these are only as good as the wxWindows defaults, which aren't so good. Style: One of wx.NORMAL, wx.SLANT and wx.ITALIC. Weight: One of wx.NORMAL, wx.LIGHT and wx.BOLD. Underlined: The value can be True or False. At present this may have an an effect on Windows only. Alternatively, you can set the kw arg: Font, to a wx.Font, and the above will be ignored. The size is fixed, and does not scale with the drawing. The hit-test is done on the entire text extent """ def __init__(self,String, xy, Size = 14, Color = "Black", BackgroundColor = None, Family = wx.MODERN, Style = wx.NORMAL, Weight = wx.NORMAL, Underlined = False, Position = 'tl', InForeground = False, Font = None): DrawObject.__init__(self,InForeground) self.String = String # Input size in in Pixels, compute points size from FontScaleinfo. # fixme: for printing, we'll have to do something a little different self.Size = Size * FontScale self.Color = Color self.BackgroundColor = BackgroundColor if not Font: FaceName = '' else: FaceName = Font.GetFaceName() Family = Font.GetFamily() Size = Font.GetPointSize() Style = Font.GetStyle() Underlined = Font.GetUnderlined() Weight = Font.GetWeight() self.SetFont(Size, Family, Style, Weight, Underlined, FaceName) self.BoundingBox = BBox.asBBox((xy, xy)) self.XY = N.asarray(xy) self.XY.shape = (2,) (self.TextWidth, self.TextHeight) = (None, None) self.ShiftFun = self.ShiftFunDict[Position] def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): XY = WorldToPixel(self.XY) dc.SetFont(self.Font) dc.SetTextForeground(self.Color) if self.BackgroundColor: dc.SetBackgroundMode(wx.SOLID) dc.SetTextBackground(self.BackgroundColor) else: dc.SetBackgroundMode(wx.TRANSPARENT) if self.TextWidth is None or self.TextHeight is None: (self.TextWidth, self.TextHeight) = dc.GetTextExtent(self.String) XY = self.ShiftFun(XY[0], XY[1], self.TextWidth, self.TextHeight) dc.DrawTextPoint(self.String, XY) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.SetBrush(self.HitBrush) HTdc.DrawRectanglePointSize(XY, (self.TextWidth, self.TextHeight) ) class ScaledText(TextObjectMixin, DrawObject, ): """ This class creates a text object that is scaled when zoomed. It is placed at the coordinates, x,y. the "Position" argument is a two charactor string, indicating where in relation to the coordinates the string should be oriented. The first letter is: t, c, or b, for top, center and bottom The second letter is: l, c, or r, for left, center and right The position refers to the position relative to the text itself. It defaults to "tl" (top left). Size is the size of the font in world coordinates. Family: Font family, a generic way of referring to fonts without specifying actual facename. One of: wx.DEFAULT: Chooses a default font. wx.DECORATI: A decorative font. wx.ROMAN: A formal, serif font. wx.SCRIPT: A handwriting font. wx.SWISS: A sans-serif font. wx.MODERN: A fixed pitch font. NOTE: these are only as good as the wxWindows defaults, which aren't so good. Style: One of wx.NORMAL, wx.SLANT and wx.ITALIC. Weight: One of wx.NORMAL, wx.LIGHT and wx.BOLD. Underlined: The value can be True or False. At present this may have an an effect on Windows only. Alternatively, you can set the kw arg: Font, to a wx.Font, and the above will be ignored. The size of the font you specify will be ignored, but the rest of its attributes will be preserved. The size will scale as the drawing is zoomed. Bugs/Limitations: As fonts are scaled, the do end up a little different, so you don't get exactly the same picture as you scale up and doen, but it's pretty darn close. On wxGTK1 on my Linux system, at least, using a font of over about 3000 pts. brings the system to a halt. It's the Font Server using huge amounts of memory. My work around is to max the font size to 3000 points, so it won't scale past there. GTK2 uses smarter font drawing, so that may not be an issue in future versions, so feel free to test. Another smarter way to do it would be to set a global zoom limit at that point. The hit-test is done on the entire text extent. This could be made optional, but I haven't gotten around to it. """ def __init__(self, String, XY, Size, Color = "Black", BackgroundColor = None, Family = wx.MODERN, Style = wx.NORMAL, Weight = wx.NORMAL, Underlined = False, Position = 'tl', Font = None, InForeground = False): DrawObject.__init__(self,InForeground) self.String = String self.XY = N.array( XY, N.float) self.XY.shape = (2,) self.Size = Size self.Color = Color self.BackgroundColor = BackgroundColor self.Family = Family self.Style = Style self.Weight = Weight self.Underlined = Underlined if not Font: self.FaceName = '' else: self.FaceName = Font.GetFaceName() self.Family = Font.GetFamily() self.Style = Font.GetStyle() self.Underlined = Font.GetUnderlined() self.Weight = Font.GetWeight() # Experimental max font size value on wxGTK2: this works OK on # my system. If it's a lot larger, there is a crash, with the # message: # # The application 'FloatCanvasDemo.py' lost its # connection to the display :0.0; most likely the X server was # shut down or you killed/destroyed the application. # # Windows and OS-X seem to be better behaved in this regard. # They may not draw it, but they don't crash either! self.MaxFontSize = 1000 self.ShiftFun = self.ShiftFunDict[Position] self.CalcBoundingBox() def LayoutText(self): # This will be called when the text is re-set # nothing much to be done here self.CalcBoundingBox() def CalcBoundingBox(self): ## this isn't exact, as fonts don't scale exactly. dc = wx.MemoryDC() bitmap = wx.EmptyBitmap(1, 1) dc.SelectObject(bitmap) #wxMac needs a Bitmap selected for GetTextExtent to work. DrawingSize = 40 # pts This effectively determines the resolution that the BB is computed to. ScaleFactor = float(self.Size) / DrawingSize self.SetFont(DrawingSize, self.Family, self.Style, self.Weight, self.Underlined, self.FaceName) dc.SetFont(self.Font) (w,h) = dc.GetTextExtent(self.String) w = w * ScaleFactor h = h * ScaleFactor x, y = self.ShiftFun(self.XY[0], self.XY[1], w, h, world = 1) self.BoundingBox = BBox.asBBox(((x, y-h ),(x + w, y))) def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): (X,Y) = WorldToPixel( (self.XY) ) # compute the font size: Size = abs( ScaleWorldToPixel( (self.Size, self.Size) )[1] ) # only need a y coordinate length ## Check to see if the font size is large enough to blow up the X font server ## If so, limit it. Would it be better just to not draw it? ## note that this limit is dependent on how much memory you have, etc. Size = min(Size, self.MaxFontSize) self.SetFont(Size, self.Family, self.Style, self.Weight, self.Underlined, self.FaceName) dc.SetFont(self.Font) dc.SetTextForeground(self.Color) if self.BackgroundColor: dc.SetBackgroundMode(wx.SOLID) dc.SetTextBackground(self.BackgroundColor) else: dc.SetBackgroundMode(wx.TRANSPARENT) (w,h) = dc.GetTextExtent(self.String) # compute the shift, and adjust the coordinates, if neccesary # This had to be put in here, because it changes with Zoom, as # fonts don't scale exactly. xy = self.ShiftFun(X, Y, w, h) dc.DrawTextPoint(self.String, xy) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.SetBrush(self.HitBrush) HTdc.DrawRectanglePointSize(xy, (w, h) ) class ScaledTextBox(TextObjectMixin, DrawObject): """ This class creates a TextBox object that is scaled when zoomed. It is placed at the coordinates, x,y. If the Width parameter is defined, the text will be wrapped to the width given. A Box can be drawn around the text, be specifying: LineWidth and/or FillColor A space(margin) can be put all the way around the text, be specifying: the PadSize argument in world coordinates. The spacing between lines can be adjusted with the: LineSpacing argument. The "Position" argument is a two character string, indicating where in relation to the coordinates the Box should be oriented. -The first letter is: t, c, or b, for top, center and bottom. -The second letter is: l, c, or r, for left, center and right The position refers to the position relative to the text itself. It defaults to "tl" (top left). Size is the size of the font in world coordinates. Family: Font family, a generic way of referring to fonts without specifying actual facename. One of: wx.DEFAULT: Chooses a default font. wx.DECORATIVE: A decorative font. wx.ROMAN: A formal, serif font. wx.SCRIPT: A handwriting font. wx.SWISS: A sans-serif font. wx.MODERN: A fixed pitch font. NOTE: these are only as good as the wxWindows defaults, which aren't so good. Style: One of wx.NORMAL, wx.SLANT and wx.ITALIC. Weight: One of wx.NORMAL, wx.LIGHT and wx.BOLD. Underlined: The value can be True or False. At present this may have an an effect on Windows only. Alternatively, you can set the kw arg: Font, to a wx.Font, and the above will be ignored. The size of the font you specify will be ignored, but the rest of its attributes will be preserved. The size will scale as the drawing is zoomed. Bugs/Limitations: As fonts are scaled, they do end up a little different, so you don't get exactly the same picture as you scale up and down, but it's pretty darn close. On wxGTK1 on my Linux system, at least, using a font of over about 1000 pts. brings the system to a halt. It's the Font Server using huge amounts of memory. My work around is to max the font size to 1000 points, so it won't scale past there. GTK2 uses smarter font drawing, so that may not be an issue in future versions, so feel free to test. Another smarter way to do it would be to set a global zoom limit at that point. The hit-test is done on the entire box. This could be made optional, but I haven't gotten around to it. """ def __init__(self, String, Point, Size, Color = "Black", BackgroundColor = None, LineColor = 'Black', LineStyle = 'Solid', LineWidth = 1, Width = None, PadSize = None, Family = wx.MODERN, Style = wx.NORMAL, Weight = wx.NORMAL, Underlined = False, Position = 'tl', Alignment = "left", Font = None, LineSpacing = 1.0, InForeground = False): DrawObject.__init__(self,InForeground) self.XY = N.array(Point, N.float) self.Size = Size self.Color = Color self.BackgroundColor = BackgroundColor self.LineColor = LineColor self.LineStyle = LineStyle self.LineWidth = LineWidth self.Width = Width if PadSize is None: # the default is just a little bit of padding self.PadSize = Size/10.0 else: self.PadSize = float(PadSize) self.Family = Family self.Style = Style self.Weight = Weight self.Underlined = Underlined self.Alignment = Alignment.lower() self.LineSpacing = float(LineSpacing) self.Position = Position if not Font: self.FaceName = '' else: self.FaceName = Font.GetFaceName() self.Family = Font.GetFamily() self.Style = Font.GetStyle() self.Underlined = Font.GetUnderlined() self.Weight = Font.GetWeight() # Experimental max font size value on wxGTK2: this works OK on # my system. If it's a lot larger, there is a crash, with the # message: # # The application 'FloatCanvasDemo.py' lost its # connection to the display :0.0; most likely the X server was # shut down or you killed/destroyed the application. # # Windows and OS-X seem to be better behaved in this regard. # They may not draw it, but they don't crash either! self.MaxFontSize = 1000 self.ShiftFun = self.ShiftFunDict[Position] self.String = String self.LayoutText() self.CalcBoundingBox() self.SetPen(LineColor,LineStyle,LineWidth) self.SetBrush(BackgroundColor, "Solid") def WrapToWidth(self): dc = wx.MemoryDC() bitmap = wx.EmptyBitmap(1, 1) dc.SelectObject(bitmap) #wxMac needs a Bitmap selected for GetTextExtent to work. DrawingSize = self.LayoutFontSize # pts This effectively determines the resolution that the BB is computed to. ScaleFactor = float(self.Size) / DrawingSize Width = (self.Width - 2*self.PadSize) / ScaleFactor #Width to wrap to self.SetFont(DrawingSize, self.Family, self.Style, self.Weight, self.Underlined, self.FaceName) dc.SetFont(self.Font) NewStrings = [] for s in self.Strings: #beginning = True text = s.split(" ") text.reverse() LineLength = 0 NewText = text[-1] del text[-1] while text: w = dc.GetTextExtent(' ' + text[-1])[0] if LineLength + w <= Width: NewText += ' ' NewText += text[-1] LineLength = dc.GetTextExtent(NewText)[0] else: NewStrings.append(NewText) NewText = text[-1] LineLength = dc.GetTextExtent(text[-1])[0] del text[-1] NewStrings.append(NewText) self.Strings = NewStrings def ReWrap(self, Width): self.Width = Width self.LayoutText() def LayoutText(self): """ Calculates the positions of the words of text. This isn't exact, as fonts don't scale exactly. To help this, the position of each individual word is stored separately, so that the general layout stays the same in world coordinates, as the fonts scale. """ self.Strings = self.String.split("\n") if self.Width: self.WrapToWidth() dc = wx.MemoryDC() bitmap = wx.EmptyBitmap(1, 1) dc.SelectObject(bitmap) #wxMac needs a Bitmap selected for GetTextExtent to work. DrawingSize = self.LayoutFontSize # pts This effectively determines the resolution that the BB is computed to. ScaleFactor = float(self.Size) / DrawingSize self.SetFont(DrawingSize, self.Family, self.Style, self.Weight, self.Underlined, self.FaceName) dc.SetFont(self.Font) TextHeight = dc.GetTextExtent("X")[1] SpaceWidth = dc.GetTextExtent(" ")[0] LineHeight = TextHeight * self.LineSpacing LineWidths = N.zeros((len(self.Strings),), N.float) y = 0 Words = [] AllLinePoints = [] for i, s in enumerate(self.Strings): LineWidths[i] = 0 LineWords = s.split(" ") LinePoints = N.zeros((len(LineWords),2), N.float) for j, word in enumerate(LineWords): if j > 0: LineWidths[i] += SpaceWidth Words.append(word) LinePoints[j] = (LineWidths[i], y) w = dc.GetTextExtent(word)[0] LineWidths[i] += w y -= LineHeight AllLinePoints.append(LinePoints) TextWidth = N.maximum.reduce(LineWidths) self.Words = Words if self.Width is None: BoxWidth = TextWidth * ScaleFactor + 2*self.PadSize else: # use the defined Width BoxWidth = self.Width Points = N.zeros((0,2), N.float) for i, LinePoints in enumerate(AllLinePoints): ## Scale to World Coords. LinePoints *= (ScaleFactor, ScaleFactor) if self.Alignment == 'left': LinePoints[:,0] += self.PadSize elif self.Alignment == 'center': LinePoints[:,0] += (BoxWidth - LineWidths[i]*ScaleFactor)/2.0 elif self.Alignment == 'right': LinePoints[:,0] += (BoxWidth - LineWidths[i]*ScaleFactor-self.PadSize) Points = N.concatenate((Points, LinePoints)) BoxHeight = -(Points[-1,1] - (TextHeight * ScaleFactor)) + 2*self.PadSize #(x,y) = self.ShiftFun(self.XY[0], self.XY[1], BoxWidth, BoxHeight, world=1) Points += (0, -self.PadSize) self.Points = Points self.BoxWidth = BoxWidth self.BoxHeight = BoxHeight self.CalcBoundingBox() def CalcBoundingBox(self): """ Calculates the Bounding Box """ w, h = self.BoxWidth, self.BoxHeight x, y = self.ShiftFun(self.XY[0], self.XY[1], w, h, world=1) self.BoundingBox = BBox.asBBox(((x, y-h ),(x + w, y))) def GetBoxRect(self): wh = (self.BoxWidth, self.BoxHeight) xy = (self.BoundingBox[0,0], self.BoundingBox[1,1]) return (xy, wh) def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): xy, wh = self.GetBoxRect() Points = self.Points + xy Points = WorldToPixel(Points) xy = WorldToPixel(xy) wh = ScaleWorldToPixel(wh) * (1,-1) # compute the font size: Size = abs( ScaleWorldToPixel( (self.Size, self.Size) )[1] ) # only need a y coordinate length ## Check to see if the font size is large enough to blow up the X font server ## If so, limit it. Would it be better just to not draw it? ## note that this limit is dependent on how much memory you have, etc. Size = min(Size, self.MaxFontSize) self.SetFont(Size, self.Family, self.Style, self.Weight, self.Underlined, self.FaceName) dc.SetFont(self.Font) dc.SetTextForeground(self.Color) dc.SetBackgroundMode(wx.TRANSPARENT) # Draw The Box if (self.LineStyle and self.LineColor) or self.BackgroundColor: dc.SetBrush(self.Brush) dc.SetPen(self.Pen) dc.DrawRectanglePointSize(xy , wh) # Draw the Text dc.DrawTextList(self.Words, Points) # Draw the hit box. if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.SetBrush(self.HitBrush) HTdc.DrawRectanglePointSize(xy, wh) class Bitmap(TextObjectMixin, DrawObject, ): """ This class creates a bitmap object, placed at the coordinates, x,y. the "Position" argument is a two charactor string, indicating where in relation to the coordinates the bitmap should be oriented. The first letter is: t, c, or b, for top, center and bottom The second letter is: l, c, or r, for left, center and right The position refers to the position relative to the text itself. It defaults to "tl" (top left). The size is fixed, and does not scale with the drawing. """ def __init__(self,Bitmap,XY, Position = 'tl', InForeground = False): DrawObject.__init__(self,InForeground) if type(Bitmap) == wx._gdi.Bitmap: self.Bitmap = Bitmap elif type(Bitmap) == wx._core.Image: self.Bitmap = wx.BitmapFromImage(Bitmap) # Note the BB is just the point, as the size in World coordinates is not fixed self.BoundingBox = BBox.asBBox( (XY,XY) ) self.XY = XY (self.Width, self.Height) = self.Bitmap.GetWidth(), self.Bitmap.GetHeight() self.ShiftFun = self.ShiftFunDict[Position] def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): XY = WorldToPixel(self.XY) XY = self.ShiftFun(XY[0], XY[1], self.Width, self.Height) dc.DrawBitmapPoint(self.Bitmap, XY, True) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.SetBrush(self.HitBrush) HTdc.DrawRectanglePointSize(XY, (self.Width, self.Height) ) class ScaledBitmap(TextObjectMixin, DrawObject, ): """ This class creates a bitmap object, placed at the coordinates, XY, of Height, H, in World coorsinates. The width is calculated from the aspect ratio of the bitmap. the "Position" argument is a two charactor string, indicating where in relation to the coordinates the bitmap should be oriented. The first letter is: t, c, or b, for top, center and bottom The second letter is: l, c, or r, for left, center and right The position refers to the position relative to the text itself. It defaults to "tl" (top left). The size scales with the drawing """ def __init__(self, Bitmap, XY, Height, Position = 'tl', InForeground = False): DrawObject.__init__(self,InForeground) if type(Bitmap) == wx._gdi.Bitmap: self.Image = Bitmap.ConvertToImage() elif type(Bitmap) == wx._core.Image: self.Image = Bitmap self.XY = XY self.Height = Height (self.bmpWidth, self.bmpHeight) = self.Image.GetWidth(), self.Image.GetHeight() self.Width = self.bmpWidth / self.bmpHeight * Height self.ShiftFun = self.ShiftFunDict[Position] self.CalcBoundingBox() self.ScaledBitmap = None self.ScaledHeight = None def CalcBoundingBox(self): ## this isn't exact, as fonts don't scale exactly. w, h = self.Width, self.Height x, y = self.ShiftFun(self.XY[0], self.XY[1], w, h, world = 1) self.BoundingBox = BBox.asBBox( ( (x, y-h ), (x + w, y) ) ) def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): XY = WorldToPixel(self.XY) H = ScaleWorldToPixel(self.Height)[0] W = H * (self.bmpWidth / self.bmpHeight) if (self.ScaledBitmap is None) or (H <> self.ScaledHeight) : self.ScaledHeight = H Img = self.Image.Scale(W, H) self.ScaledBitmap = wx.BitmapFromImage(Img) XY = self.ShiftFun(XY[0], XY[1], W, H) dc.DrawBitmapPoint(self.ScaledBitmap, XY, True) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.SetBrush(self.HitBrush) HTdc.DrawRectanglePointSize(XY, (W, H) ) class ScaledBitmap2(TextObjectMixin, DrawObject, ): """ An alternative scaled bitmap that only scaled the required amount of the main bitmap when zoomed in: EXPERIMENTAL! """ def __init__(self, Bitmap, XY, Height, Width=None, Position = 'tl', InForeground = False): DrawObject.__init__(self,InForeground) if type(Bitmap) == wx._gdi.Bitmap: self.Image = Bitmap.ConvertToImage() elif type(Bitmap) == wx._core.Image: self.Image = Bitmap self.XY = N.array(XY, N.float) self.Height = Height (self.bmpWidth, self.bmpHeight) = self.Image.GetWidth(), self.Image.GetHeight() self.bmpWH = N.array((self.bmpWidth, self.bmpHeight), N.int32) ## fixme: this should all accommodate different scales for X and Y if Width is None: self.BmpScale = float(self.bmpHeight) / Height self.Width = self.bmpWidth / self.BmpScale self.WH = N.array((self.Width, Height), N.float) ##fixme: should this have a y = -1 to shift to y-up? self.BmpScale = self.bmpWH / self.WH print "bmpWH:", self.bmpWH print "Width, Height:", self.WH print "self.BmpScale", self.BmpScale self.ShiftFun = self.ShiftFunDict[Position] self.CalcBoundingBox() self.ScaledBitmap = None # cache of the last existing scaled bitmap def CalcBoundingBox(self): ## this isn't exact, as fonts don't scale exactly. w,h = self.Width, self.Height x, y = self.ShiftFun(self.XY[0], self.XY[1], w, h, world = 1) self.BoundingBox = BBox.asBBox( ((x, y-h ), (x + w, y)) ) def WorldToBitmap(self, Pw): """ computes bitmap coords from World coords """ delta = Pw - self.XY Pb = delta * self.BmpScale Pb *= (1, -1) ##fixme: this may only works for Yup projection! ## and may only work for top left position return Pb.astype(N.int_) def _DrawEntireBitmap(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc): """ this is pretty much the old code Scales and Draws the entire bitmap. """ XY = WorldToPixel(self.XY) H = ScaleWorldToPixel(self.Height)[0] W = H * (self.bmpWidth / self.bmpHeight) if (self.ScaledBitmap is None) or (self.ScaledBitmap[0] != (0, 0, self.bmpWidth, self.bmpHeight, W, H) ): #if True: #fixme: (self.ScaledBitmap is None) or (H <> self.ScaledHeight) : self.ScaledHeight = H print "Scaling to:", W, H Img = self.Image.Scale(W, H) bmp = wx.BitmapFromImage(Img) self.ScaledBitmap = ((0, 0, self.bmpWidth, self.bmpHeight , W, H), bmp)# this defines the cached bitmap else: print "Using Cached bitmap" bmp = self.ScaledBitmap[1] XY = self.ShiftFun(XY[0], XY[1], W, H) dc.DrawBitmapPoint(bmp, XY, True) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.SetBrush(self.HitBrush) HTdc.DrawRectanglePointSize(XY, (W, H) ) def _DrawSubBitmap(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc): """ Subsets just the part of the bitmap that is visible then scales and draws that. """ BBworld = BBox.asBBox(self._Canvas.ViewPortBB) BBbitmap = BBox.fromPoints(self.WorldToBitmap(BBworld)) XYs = WorldToPixel(self.XY) # figure out subimage: # fixme: this should be able to be done more succinctly! if BBbitmap[0,0] < 0: Xb = 0 elif BBbitmap[0,0] > self.bmpWH[0]: # off the bitmap Xb = 0 else: Xb = BBbitmap[0,0] XYs[0] = 0 # draw at origin if BBbitmap[0,1] < 0: Yb = 0 elif BBbitmap[0,1] > self.bmpWH[1]: # off the bitmap Yb = 0 ShouldDraw = False else: Yb = BBbitmap[0,1] XYs[1] = 0 # draw at origin if BBbitmap[1,0] < 0: #off the screen -- This should never happen! Wb = 0 elif BBbitmap[1,0] > self.bmpWH[0]: Wb = self.bmpWH[0] - Xb else: Wb = BBbitmap[1,0] - Xb if BBbitmap[1,1] < 0: # off the screen -- This should never happen! Hb = 0 ShouldDraw = False elif BBbitmap[1,1] > self.bmpWH[1]: Hb = self.bmpWH[1] - Yb else: Hb = BBbitmap[1,1] - Yb FullHeight = ScaleWorldToPixel(self.Height)[0] scale = FullHeight / self.bmpWH[1] Ws = int(scale * Wb + 0.5) # add the 0.5 to round Hs = int(scale * Hb + 0.5) if (self.ScaledBitmap is None) or (self.ScaledBitmap[0] != (Xb, Yb, Wb, Hb, Ws, Ws) ): Img = self.Image.GetSubImage(wx.Rect(Xb, Yb, Wb, Hb)) Img.Rescale(Ws, Hs) bmp = wx.BitmapFromImage(Img) self.ScaledBitmap = ((Xb, Yb, Wb, Hb, Ws, Ws), bmp)# this defines the cached bitmap #XY = self.ShiftFun(XY[0], XY[1], W, H) #fixme: get the shiftfun working! else: print "Using cached bitmap" ##fixme: The cached bitmap could be used if the one needed is the same scale, but ## a subset of the cached one. bmp = self.ScaledBitmap[1] dc.DrawBitmapPoint(bmp, XYs, True) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.SetBrush(self.HitBrush) HTdc.DrawRectanglePointSize(XYs, (Ws, Hs) ) def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): BBworld = BBox.asBBox(self._Canvas.ViewPortBB) ## first see if entire bitmap is displayed: if BBworld.Inside(self.BoundingBox): print "Drawing entire bitmap with old code" self._DrawEntireBitmap(dc , WorldToPixel, ScaleWorldToPixel, HTdc) return None elif BBworld.Overlaps(self.BoundingBox): #BBbitmap = BBox.fromPoints(self.WorldToBitmap(BBworld)) print "Drawing a sub-bitmap" self._DrawSubBitmap(dc , WorldToPixel, ScaleWorldToPixel, HTdc) else: print "Not Drawing -- no part of image is showing" class DotGrid: """ An example of a Grid Object -- it is set on teh FloatCAnvas with one of: FloatCanvas.GridUnder = Grid FloatCanvas.GridOver = Grid It will be drawn every time, regardless of the viewport. In its _Draw method, it computes what to draw, given the ViewPortBB of the Canvas it's being drawn on. """ def __init__(self, Spacing, Size = 2, Color = "Black", Cross=False, CrossThickness = 1): self.Spacing = N.array(Spacing, N.float) self.Spacing.shape = (2,) self.Size = Size self.Color = Color self.Cross = Cross self.CrossThickness = CrossThickness def CalcPoints(self, Canvas): ViewPortBB = Canvas.ViewPortBB Spacing = self.Spacing minx, miny = N.floor(ViewPortBB[0] / Spacing) * Spacing maxx, maxy = N.ceil(ViewPortBB[1] / Spacing) * Spacing ##fixme: this could use vstack or something with numpy x = N.arange(minx, maxx+Spacing[0], Spacing[0]) # making sure to get the last point y = N.arange(miny, maxy+Spacing[1], Spacing[1]) # an extra is OK Points = N.zeros((len(y), len(x), 2), N.float) x.shape = (1,-1) y.shape = (-1,1) Points[:,:,0] += x Points[:,:,1] += y Points.shape = (-1,2) return Points def _Draw(self, dc, Canvas): Points = self.CalcPoints(Canvas) Points = Canvas.WorldToPixel(Points) dc.SetPen(wx.Pen(self.Color,self.CrossThickness)) if self.Cross: # Use cross shaped markers #Horizontal lines LinePoints = N.concatenate((Points + (self.Size,0),Points + (-self.Size,0)),1) dc.DrawLineList(LinePoints) # Vertical Lines LinePoints = N.concatenate((Points + (0,self.Size),Points + (0,-self.Size)),1) dc.DrawLineList(LinePoints) pass else: # use dots ## Note: this code borrowed from Pointset -- itreally shouldn't be repeated here!. if self.Size <= 1: dc.DrawPointList(Points) elif self.Size <= 2: dc.DrawPointList(Points + (0,-1)) dc.DrawPointList(Points + (0, 1)) dc.DrawPointList(Points + (1, 0)) dc.DrawPointList(Points + (-1,0)) else: dc.SetBrush(wx.Brush(self.Color)) radius = int(round(self.Size/2)) ##fixme: I really should add a DrawCircleList to wxPython if len(Points) > 100: xy = Points xywh = N.concatenate((xy-radius, N.ones(xy.shape) * self.Size ), 1 ) dc.DrawEllipseList(xywh) else: for xy in Points: dc.DrawCircle(xy[0],xy[1], radius) #--------------------------------------------------------------------------- class FloatCanvas(wx.Panel): """ FloatCanvas.py This is a high level window for drawing maps and anything else in an arbitrary coordinate system. The goal is to provide a convenient way to draw stuff on the screen without having to deal with handling OnPaint events, converting to pixel coordinates, knowing about wxWindows brushes, pens, and colors, etc. It also provides virtually unlimited zooming and scrolling I am using it for two things: 1) general purpose drawing in floating point coordinates 2) displaying map data in Lat-long coordinates If the projection is set to None, it will draw in general purpose floating point coordinates. If the projection is set to 'FlatEarth', it will draw a FlatEarth projection, centered on the part of the map that you are viewing. You can also pass in your own projection function. It is double buffered, so re-draws after the window is uncovered by something else are very quick. It relies on NumPy, which is needed for speed (maybe, I havn't profiled it) Bugs and Limitations: Lots: patches, fixes welcome For Map drawing: It ignores the fact that the world is, in fact, a sphere, so it will do strange things if you are looking at stuff near the poles or the date line. so far I don't have a need to do that, so I havn't bothered to add any checks for that yet. Zooming: I have set no zoom limits. What this means is that if you zoom in really far, you can get integer overflows, and get wierd results. It doesn't seem to actually cause any problems other than wierd output, at least when I have run it. Speed: I have done a couple of things to improve speed in this app. The one thing I have done is used NumPy Arrays to store the coordinates of the points of the objects. This allowed me to use array oriented functions when doing transformations, and should provide some speed improvement for objects with a lot of points (big polygons, polylines, pointsets). The real slowdown comes when you have to draw a lot of objects, because you have to call the wx.DC.DrawSomething call each time. This is plenty fast for tens of objects, OK for hundreds of objects, but pretty darn slow for thousands of objects. The solution is to be able to pass some sort of object set to the DC directly. I've used DC.DrawPointList(Points), and it helped a lot with drawing lots of points. I havn't got a LineSet type object, so I havn't used DC.DrawLineList yet. I'd like to get a full set of DrawStuffList() methods implimented, and then I'd also have a full set of Object sets that could take advantage of them. I hope to get to it some day. Mouse Events: At this point, there are a full set of custom mouse events. They are just like the regular mouse events, but include an extra attribute: Event.GetCoords(), that returns the (x,y) position in world coordinates, as a length-2 NumPy vector of Floats. Copyright: Christopher Barker License: Same as the version of wxPython you are using it with Please let me know if you're using this!!! Contact me at: Chris.Barker@noaa.gov """ def __init__(self, parent, id = -1, size = wx.DefaultSize, ProjectionFun = None, BackgroundColor = "WHITE", Debug = False): wx.Panel.__init__( self, parent, id, wx.DefaultPosition, size) self.ComputeFontScale() self.InitAll() self.BackgroundBrush = wx.Brush(BackgroundColor,wx.SOLID) self.Debug = Debug wx.EVT_PAINT(self, self.OnPaint) wx.EVT_SIZE(self, self.OnSize) wx.EVT_LEFT_DOWN(self, self.LeftDownEvent) wx.EVT_LEFT_UP(self, self.LeftUpEvent) wx.EVT_LEFT_DCLICK(self, self.LeftDoubleClickEvent) wx.EVT_MIDDLE_DOWN(self, self.MiddleDownEvent) wx.EVT_MIDDLE_UP(self, self.MiddleUpEvent) wx.EVT_MIDDLE_DCLICK(self, self.MiddleDoubleClickEvent) wx.EVT_RIGHT_DOWN(self, self.RightDownEvent) wx.EVT_RIGHT_UP(self, self.RightUpEvent) wx.EVT_RIGHT_DCLICK(self, self.RightDoubleCLickEvent) wx.EVT_MOTION(self, self.MotionEvent) wx.EVT_MOUSEWHEEL(self, self.WheelEvent) wx.EVT_KEY_DOWN(self, self.KeyDownEvent) wx.EVT_KEY_UP(self, self.KeyUpEvent) ## CHB: I'm leaving these out for now. #wx.EVT_ENTER_WINDOW(self, self. ) #wx.EVT_LEAVE_WINDOW(self, self. ) self.SetProjectionFun(ProjectionFun) self.GUIMode = None # timer to give a delay when re-sizing so that buffers aren't re-built too many times. self.SizeTimer = wx.PyTimer(self.OnSizeTimer) self.InitializePanel() self.MakeNewBuffers() # self.CreateCursors() def ComputeFontScale(self): ## A global variable to hold the scaling from pixel size to point size. global FontScale dc = wx.ScreenDC() dc.SetFont(wx.Font(16, wx.ROMAN, wx.NORMAL, wx.NORMAL)) E = dc.GetTextExtent("X") FontScale = 16/E[1] del dc def InitAll(self): """ InitAll() sets everything in the Canvas to default state. It can be used to reset the Canvas """ self.HitColorGenerator = None self.UseHitTest = False self.NumBetweenBlits = 500 ## create the Hit Test Dicts: self.HitDict = None self._HTdc = None self._DrawList = [] self._ForeDrawList = [] self._ForegroundBuffer = None self.BoundingBox = None self.BoundingBoxDirty = False self.MinScale = None self.MaxScale = None self.ViewPortCenter= N.array( (0,0), N.float) self.SetProjectionFun(None) self.MapProjectionVector = N.array( (1,1), N.float) # No Projection to start! self.TransformVector = N.array( (1,-1), N.float) # default Transformation self.Scale = 1 self.ObjectUnderMouse = None self.GridUnder = None self.GridOver = None self._BackgroundDirty = True def SetProjectionFun(self,ProjectionFun): if ProjectionFun == 'FlatEarth': self.ProjectionFun = self.FlatEarthProjection elif callable(ProjectionFun): self.ProjectionFun = ProjectionFun elif ProjectionFun is None: self.ProjectionFun = lambda x=None: N.array( (1,1), N.float) else: raise FloatCanvasError('Projectionfun must be either:' ' "FlatEarth", None, or a callable object ' '(function, for instance) that takes the ' 'ViewPortCenter and returns a MapProjectionVector') def FlatEarthProjection(self, CenterPoint): MaxLatitude = 75 # these were determined essentially arbitrarily MinLatitude = -75 Lat = min(CenterPoint[1],MaxLatitude) Lat = max(Lat,MinLatitude) return N.array((N.cos(N.pi*Lat/180),1),N.float) def SetMode(self, Mode): ''' Set the GUImode to any of the availble mode. ''' # Set mode self.GUIMode = Mode #self.GUIMode.SetCursor() self.SetCursor(self.GUIMode.Cursor) def MakeHitDict(self): ##fixme: Should this just be None if nothing has been bound? self.HitDict = {EVT_FC_LEFT_DOWN: {}, EVT_FC_LEFT_UP: {}, EVT_FC_LEFT_DCLICK: {}, EVT_FC_MIDDLE_DOWN: {}, EVT_FC_MIDDLE_UP: {}, EVT_FC_MIDDLE_DCLICK: {}, EVT_FC_RIGHT_DOWN: {}, EVT_FC_RIGHT_UP: {}, EVT_FC_RIGHT_DCLICK: {}, EVT_FC_ENTER_OBJECT: {}, EVT_FC_LEAVE_OBJECT: {}, } def _RaiseMouseEvent(self, Event, EventType): """ This is called in various other places to raise a Mouse Event """ pt = self.PixelToWorld( Event.GetPosition() ) evt = _MouseEvent(EventType, Event, self.GetId(), pt) self.GetEventHandler().ProcessEvent(evt) if wx.__version__ >= "2.8" and wx.Platform == "__WXMAC__": HitTestBitmapDepth = 32 #print "Using hit test code for 2.8" def GetHitTestColor(self, xy): if self._ForegroundHTBitmap: pdata = wx.AlphaPixelData(self._ForegroundHTBitmap) else: pdata = wx.AlphaPixelData(self._HTBitmap) if not pdata: raise RuntimeError("Trouble Accessing Hit Test bitmap") pacc = pdata.GetPixels() pacc.MoveTo(pdata, xy[0], xy[1]) return pacc.Get()[:3] else: HitTestBitmapDepth = 24 #print "using pre-2.8 hit test code" def GetHitTestColor(self, xy ): dc = wx.MemoryDC() if self._ForegroundHTBitmap: dc.SelectObject(self._ForegroundHTBitmap) else: dc.SelectObject(self._HTBitmap) hitcolor = dc.GetPixelPoint( xy ) return hitcolor.Get() def HitTest(self, event, HitEvent): if self.HitDict: # check if there are any objects in the dict for this event if self.HitDict[ HitEvent ]: xy = event.GetPosition() color = self.GetHitTestColor( xy ) if color in self.HitDict[ HitEvent ]: Object = self.HitDict[ HitEvent ][color] ## Add the hit coords to the Object Object.HitCoords = self.PixelToWorld( xy ) Object.HitCoordsPixel = xy Object.CallBackFuncs[HitEvent](Object) return True return False def MouseOverTest(self, event): ##fixme: Can this be cleaned up? if (self.HitDict and (self.HitDict[EVT_FC_ENTER_OBJECT ] or self.HitDict[EVT_FC_LEAVE_OBJECT ] ) ): xy = event.GetPosition() color = self.GetHitTestColor( xy ) OldObject = self.ObjectUnderMouse ObjectCallbackCalled = False if color in self.HitDict[ EVT_FC_ENTER_OBJECT ]: Object = self.HitDict[ EVT_FC_ENTER_OBJECT][color] if (OldObject is None): try: Object.CallBackFuncs[EVT_FC_ENTER_OBJECT](Object) ObjectCallbackCalled = True except KeyError: pass # this means the enter event isn't bound for that object elif OldObject == Object: # the mouse is still on the same object pass ## Is the mouse on a differnt object as it was... elif not (Object == OldObject): # call the leave object callback try: OldObject.CallBackFuncs[EVT_FC_LEAVE_OBJECT](OldObject) ObjectCallbackCalled = True except KeyError: pass # this means the leave event isn't bound for that object try: Object.CallBackFuncs[EVT_FC_ENTER_OBJECT](Object) ObjectCallbackCalled = True except KeyError: pass # this means the enter event isn't bound for that object ## set the new object under mouse self.ObjectUnderMouse = Object elif color in self.HitDict[ EVT_FC_LEAVE_OBJECT ]: Object = self.HitDict[ EVT_FC_LEAVE_OBJECT][color] self.ObjectUnderMouse = Object else: # no objects under mouse bound to mouse-over events self.ObjectUnderMouse = None if OldObject: try: OldObject.CallBackFuncs[EVT_FC_LEAVE_OBJECT](OldObject) ObjectCallbackCalled = True except KeyError: pass # this means the leave event isn't bound for that object return ObjectCallbackCalled return False ## fixme: There is a lot of repeated code here ## Is there a better way? def LeftDoubleClickEvent(self, event): if self.GUIMode: self.GUIMode.OnLeftDouble(event) event.Skip() def MiddleDownEvent(self, event): if self.GUIMode: self.GUIMode.OnMiddleDown(event) event.Skip() def MiddleUpEvent(self, event): if self.GUIMode: self.GUIMode.OnMiddleUp(event) event.Skip() def MiddleDoubleClickEvent(self, event): if self.GUIMode: self.GUIMode.OnMiddleDouble(event) event.Skip() def RightDoubleCLickEvent(self, event): if self.GUIMode: self.GUIMode.OnRightDouble(event) event.Skip() def WheelEvent(self, event): if self.GUIMode: self.GUIMode.OnWheel(event) event.Skip() def LeftDownEvent(self, event): if self.GUIMode: self.GUIMode.OnLeftDown(event) event.Skip() def LeftUpEvent(self, event): if self.HasCapture(): self.ReleaseMouse() if self.GUIMode: self.GUIMode.OnLeftUp(event) event.Skip() def MotionEvent(self, event): if self.GUIMode: self.GUIMode.OnMove(event) event.Skip() def RightDownEvent(self, event): if self.GUIMode: self.GUIMode.OnRightDown(event) event.Skip() def RightUpEvent(self, event): if self.GUIMode: self.GUIMode.OnRightUp(event) event.Skip() def KeyDownEvent(self, event): if self.GUIMode and hasattr(self.GUIMode, 'OnKeyDown'): self.GUIMode.OnKeyDown(event) event.Skip() def KeyUpEvent(self, event): if self.GUIMode and hasattr(self.GUIMode, 'OnKeyUp'): self.GUIMode.OnKeyUp(event) event.Skip() def MakeNewBuffers(self): self._BackgroundDirty = True # Make new offscreen bitmap: self._Buffer = wx.EmptyBitmap(*self.PanelSize) if self._ForeDrawList: self._ForegroundBuffer = wx.EmptyBitmap(*self.PanelSize) if self.UseHitTest: self.MakeNewHTBitmap() else: self._ForegroundHTBitmap = None else: self._ForegroundBuffer = None self._ForegroundHTBitmap = None if self.UseHitTest: self.MakeNewHTBitmap() else: self._HTBitmap = None self._ForegroundHTBitmap = None def MakeNewHTBitmap(self): """ Off screen Bitmap used for Hit tests on background objects """ self._HTBitmap = wx.EmptyBitmap(self.PanelSize[0], self.PanelSize[1], depth=self.HitTestBitmapDepth) def MakeNewForegroundHTBitmap(self): ## Note: the foreground and backround HT bitmaps are in separate functions ## so that they can be created separate --i.e. when a foreground is ## added after the backgound is drawn """ Off screen Bitmap used for Hit tests on foreground objects """ self._ForegroundHTBitmap = wx.EmptyBitmap(self.PanelSize[0], self.PanelSize[1], depth=self.HitTestBitmapDepth) def OnSize(self, event=None): self.InitializePanel() self.SizeTimer.Start(50, oneShot=True) def OnSizeTimer(self, event=None): self.MakeNewBuffers() self.Draw() def InitializePanel(self): self.PanelSize = self.GetClientSizeTuple() if self.PanelSize == (0,0): ## OS-X sometimes gives a Size event when the panel is size (0,0) self.PanelSize = (2,2) self.PanelSize = N.array(self.PanelSize, N.int32) self.HalfPanelSize = self.PanelSize / 2 # lrk: added for speed in WorldToPixel if self.PanelSize[0] == 0 or self.PanelSize[1] == 0: self.AspectRatio = 1.0 else: self.AspectRatio = float(self.PanelSize[0]) / self.PanelSize[1] def OnPaint(self, event): dc = wx.PaintDC(self) if self._ForegroundBuffer: dc.DrawBitmap(self._ForegroundBuffer,0,0) else: dc.DrawBitmap(self._Buffer,0,0) def Draw(self, Force=False): """ Canvas.Draw(Force=False) Re-draws the canvas. Note that the buffer will not be re-drawn unless something has changed. If you change a DrawObject directly, then the canvas will not know anything has changed. In this case, you can force a re-draw by passing int True for the Force flag: Canvas.Draw(Force=True) There is a main buffer set up to double buffer the screen, so you can get quick re-draws when the window gets uncovered. If there are any objects in self._ForeDrawList, then the background gets drawn to a new buffer, and the foreground objects get drawn on top of it. The final result if blitted to the screen, and stored for future Paint events. This is done so that you can have a complicated background, but have something changing on the foreground, without having to wait for the background to get re-drawn. This can be used to support simple animation, for instance. """ if N.sometrue(self.PanelSize <= 2 ): # it's possible for this to get called before being properly initialized. return if self.Debug: start = clock() ScreenDC = wx.ClientDC(self) ViewPortWorld = N.array(( self.PixelToWorld((0,0)), self.PixelToWorld(self.PanelSize) ) ) self.ViewPortBB = N.array( ( N.minimum.reduce(ViewPortWorld), N.maximum.reduce(ViewPortWorld) ) ) #self.ViewPortWorld = ViewPortWorld dc = wx.MemoryDC() dc.SelectObject(self._Buffer) if self._BackgroundDirty or Force: dc.SetBackground(self.BackgroundBrush) dc.Clear() if self._HTBitmap is not None: HTdc = wx.MemoryDC() HTdc.SelectObject(self._HTBitmap) HTdc.Clear() else: HTdc = None if self.GridUnder is not None: self.GridUnder._Draw(dc, self) self._DrawObjects(dc, self._DrawList, ScreenDC, self.ViewPortBB, HTdc) self._BackgroundDirty = False del HTdc if self._ForeDrawList: ## If an object was just added to the Foreground, there might not yet be a buffer if self._ForegroundBuffer is None: self._ForegroundBuffer = wx.EmptyBitmap(self.PanelSize[0], self.PanelSize[1]) dc = wx.MemoryDC() ## I got some strange errors (linewidths wrong) if I didn't make a new DC here dc.SelectObject(self._ForegroundBuffer) dc.DrawBitmap(self._Buffer,0,0) if self._ForegroundHTBitmap is not None: ForegroundHTdc = wx.MemoryDC() ForegroundHTdc.SelectObject( self._ForegroundHTBitmap) ForegroundHTdc.Clear() if self._HTBitmap is not None: #Draw the background HT buffer to the foreground HT buffer ForegroundHTdc.DrawBitmap(self._HTBitmap, 0, 0) else: ForegroundHTdc = None self._DrawObjects(dc, self._ForeDrawList, ScreenDC, self.ViewPortBB, ForegroundHTdc) if self.GridOver is not None: self.GridOver._Draw(dc, self) ScreenDC.Blit(0, 0, self.PanelSize[0],self.PanelSize[1], dc, 0, 0) # If the canvas is in the middle of a zoom or move, # the Rubber Band box needs to be re-drawn ##fixme: maybe GUIModes should never be None, and rather have a Do-nothing GUI-Mode. if self.GUIMode is not None: self.GUIMode.UpdateScreen() if self.Debug: print "Drawing took %f seconds of CPU time"%(clock()-start) ## Clear the font cache. If you don't do this, the X font server ## starts to take up Massive amounts of memory This is mostly a ## problem with very large fonts, that you get with scaled text ## when zoomed in. DrawObject.FontList = {} def _ShouldRedraw(DrawList, ViewPortBB): # lrk: adapted code from BBCheck # lrk: Returns the objects that should be redrawn ## fixme: should this check be moved into the object? ## also: a BB object would make this cleaner too BB2 = ViewPortBB redrawlist = [] for Object in DrawList: BB1 = Object.BoundingBox ## note: this could use the Utilities.BBCheck function ## butthis saves a function call if (BB1[1,0] > BB2[0,0] and BB1[0,0] < BB2[1,0] and BB1[1,1] > BB2[0,1] and BB1[0,1] < BB2[1,1]): redrawlist.append(Object) #return redrawlist ##fixme: disabled this!!!! return redrawlist _ShouldRedraw = staticmethod(_ShouldRedraw) def MoveImage(self,shift,CoordType): """ move the image in the window. shift is an (x,y) tuple, specifying the amount to shift in each direction It can be in any of three coordinates: Panel, Pixel, World, specified by the CoordType parameter Panel coordinates means you want to shift the image by some fraction of the size of the displaed image Pixel coordinates means you want to shift the image by some number of pixels World coordinates mean you want to shift the image by an amount in Floating point world coordinates """ shift = N.asarray(shift,N.float) if CoordType == 'Panel':# convert from panel coordinates shift = shift * N.array((-1,1),N.float) *self.PanelSize/self.TransformVector elif CoordType == 'Pixel': # convert from pixel coordinates shift = shift/self.TransformVector elif CoordType == 'World': # No conversion pass else: raise FloatCanvasError('CoordType must be either "Panel", "Pixel", or "World"') self.ViewPortCenter = self.ViewPortCenter + shift self.MapProjectionVector = self.ProjectionFun(self.ViewPortCenter) self.TransformVector = N.array((self.Scale,-self.Scale),N.float) * self.MapProjectionVector self._BackgroundDirty = True self.Draw() def Zoom(self, factor, center = None, centerCoords="World", DrawFlag=True): """ Zoom(factor, center) changes the amount of zoom of the image by factor. If factor is greater than one, the image gets larger. If factor is less than one, the image gets smaller. center is a tuple of (x,y) coordinates of the center of the viewport, after zooming. If center is not given, the center will stay the same. centerCoords is a flag indicating whether the center given is in pixel or world coords. Options are: "World" or "Pixel" """ self.Scale = self.Scale*factor if not center is None: if centerCoords == "Pixel": center = self.PixelToWorld( center ) elif centerCoords == "World": center = N.array(center,N.float) else: raise FloatCanvasError('centerCoords must be either "Pixel", or "World"') self.ViewPortCenter = center self.SetToNewScale(DrawFlag) def ZoomToBB(self, NewBB=None, DrawFlag=True): """ Zooms the image to the bounding box given, or to the bounding box of all the objects on the canvas, if none is given. """ if NewBB is not None: BoundingBox = NewBB else: if self.BoundingBoxDirty: self._ResetBoundingBox() BoundingBox = self.BoundingBox if BoundingBox is not None: self.ViewPortCenter = N.array(((BoundingBox[0,0]+BoundingBox[1,0])/2, (BoundingBox[0,1]+BoundingBox[1,1])/2 ),N.float_) self.MapProjectionVector = self.ProjectionFun(self.ViewPortCenter) # Compute the new Scale BoundingBox = BoundingBox*self.MapProjectionVector # this does need to make a copy! try: self.Scale = min(abs(self.PanelSize[0] / (BoundingBox[1,0]-BoundingBox[0,0])), abs(self.PanelSize[1] / (BoundingBox[1,1]-BoundingBox[0,1])) )*0.95 except ZeroDivisionError: # this will happen if the BB has zero width or height try: #width == 0 self.Scale = (self.PanelSize[0] / (BoundingBox[1,0]-BoundingBox[0,0]))*0.95 except ZeroDivisionError: try: # height == 0 self.Scale = (self.PanelSize[1] / (BoundingBox[1,1]-BoundingBox[0,1]))*0.95 except ZeroDivisionError: #zero size! (must be a single point) self.Scale = 1 if DrawFlag: self._BackgroundDirty = True else: # Reset the shifting and scaling to defaults when there is no BB self.ViewPortCenter= N.array( (0,0), N.float) self.Scale= 1 self.SetToNewScale(DrawFlag=DrawFlag) def SetToNewScale(self, DrawFlag=True): Scale = self.Scale if self.MinScale is not None: Scale = max(Scale, self.MinScale) if self.MaxScale is not None: Scale = min(Scale, self.MaxScale) self.MapProjectionVector = self.ProjectionFun(self.ViewPortCenter) self.TransformVector = N.array((Scale,-Scale),N.float) * self.MapProjectionVector self.Scale = Scale self._BackgroundDirty = True if DrawFlag: self.Draw() def RemoveObjects(self, Objects): for Object in Objects: self.RemoveObject(Object, ResetBB=False) self.BoundingBoxDirty = True def RemoveObject(self, Object, ResetBB = True): ##fixme: Using the list.remove method is kind of slow if Object.InForeground: self._ForeDrawList.remove(Object) if not self._ForeDrawList: self._ForegroundBuffer = None self._ForegroundHTdc = None else: self._DrawList.remove(Object) self._BackgroundDirty = True if ResetBB: self.BoundingBoxDirty = True def ClearAll(self, ResetBB=True): """ ClearAll(ResetBB=True) Removes all DrawObjects from the Canvas If ResetBB is set to False, the original bounding box will remain """ self._DrawList = [] self._ForeDrawList = [] self._BackgroundDirty = True self.HitColorGenerator = None self.UseHitTest = False if ResetBB: self._ResetBoundingBox() self.MakeNewBuffers() self.HitDict = None def _ResetBoundingBox(self): if self._DrawList or self._ForeDrawList: bblist = [] for (i, obj) in enumerate(self._DrawList): bblist.append(obj.BoundingBox) for (j, obj) in enumerate(self._ForeDrawList): bblist.append(obj.BoundingBox) self.BoundingBox = BBox.fromBBArray(bblist) else: self.BoundingBox = None self.ViewPortCenter= N.array( (0,0), N.float) self.TransformVector = N.array( (1,-1), N.float) self.MapProjectionVector = N.array( (1,1), N.float) self.Scale = 1 self.BoundingBoxDirty = False def PixelToWorld(self, Points): """ Converts coordinates from Pixel coordinates to world coordinates. Points is a tuple of (x,y) coordinates, or a list of such tuples, or a NX2 Numpy array of x,y coordinates. """ return (((N.asarray(Points, N.float) - (self.PanelSize/2))/self.TransformVector) + self.ViewPortCenter) def WorldToPixel(self,Coordinates): """ This function will get passed to the drawing functions of the objects, to transform from world to pixel coordinates. Coordinates should be a NX2 array of (x,y) coordinates, or a 2-tuple, or sequence of 2-tuples. """ #Note: this can be called by users code for various reasons, so N.asarray is needed. return (((N.asarray(Coordinates,N.float) - self.ViewPortCenter)*self.TransformVector)+ (self.HalfPanelSize)).astype('i') def ScaleWorldToPixel(self,Lengths): """ This function will get passed to the drawing functions of the objects, to Change a length from world to pixel coordinates. Lengths should be a NX2 array of (x,y) coordinates, or a 2-tuple, or sequence of 2-tuples. """ return ( (N.asarray(Lengths, N.float)*self.TransformVector) ).astype('i') def ScalePixelToWorld(self,Lengths): """ This function computes a pair of x.y lengths, to change then from pixel to world coordinates. Lengths should be a NX2 array of (x,y) coordinates, or a 2-tuple, or sequence of 2-tuples. """ return (N.asarray(Lengths,N.float) / self.TransformVector) def AddObject(self, obj): # put in a reference to the Canvas, so remove and other stuff can work obj._Canvas = self if obj.InForeground: self._ForeDrawList.append(obj) self.UseForeground = True else: self._DrawList.append(obj) self._BackgroundDirty = True def DrawOrder(a, b): try: return cmp(a.DrawOrder, b.DrawOrder) except AttributeError: return 1 self._DrawList.sort(DrawOrder) self.BoundingBoxDirty = True return True def AddObjects(self, Objects): for Object in Objects: self.AddObject(Object) def _DrawObjects(self, dc, DrawList, ScreenDC, ViewPortBB, HTdc = None): """ This is a convenience function; This function takes the list of objects and draws them to specified device context. """ dc.SetBackground(self.BackgroundBrush) dc.BeginDrawing() #i = 0 PanelSize0, PanelSize1 = self.PanelSize # for speed WorldToPixel = self.WorldToPixel # for speed ScaleWorldToPixel = self.ScaleWorldToPixel # for speed Blit = ScreenDC.Blit # for speed NumBetweenBlits = self.NumBetweenBlits # for speed for i, Object in enumerate(self._ShouldRedraw(DrawList, ViewPortBB)): if Object.Visible: Object._Draw(dc, WorldToPixel, ScaleWorldToPixel, HTdc) if (i+1) % NumBetweenBlits == 0: Blit(0, 0, PanelSize0, PanelSize1, dc, 0, 0) dc.EndDrawing() def SaveAsImage(self, filename, ImageType=wx.BITMAP_TYPE_PNG): """ Saves the current image as an image file. The default is in the PNG format. Other formats can be specified using the wx flags: wx.BITMAP_TYPE_PNG wx.BITMAP_TYPE_JPG wx.BITMAP_TYPE_BMP wx.BITMAP_TYPE_XBM wx.BITMAP_TYPE_XPM etc. (see the wx docs for the complete list) """ self._Buffer.SaveFile(filename, ImageType) def _makeFloatCanvasAddMethods(): ## lrk's code for doing this in module __init__ classnames = ["Circle", "Ellipse", "Rectangle", "ScaledText", "Polygon", "Line", "Text", "PointSet","Point", "Arrow", "ArrowLine", "ScaledTextBox", "SquarePoint","Bitmap", "ScaledBitmap", "Spline", "Group"] for classname in classnames: klass = globals()[classname] def getaddshapemethod(klass=klass): def addshape(self, *args, **kwargs): Object = klass(*args, **kwargs) self.AddObject(Object) return Object return addshape addshapemethod = getaddshapemethod() methodname = "Add" + classname setattr(FloatCanvas, methodname, addshapemethod) docstring = "Creates %s and adds its reference to the canvas.\n" % classname docstring += "Argument protocol same as %s class" % classname if klass.__doc__: docstring += ", whose docstring is:\n%s" % klass.__doc__ FloatCanvas.__dict__[methodname].__doc__ = docstring _makeFloatCanvasAddMethods() tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/ArcObject.py0000644000175000017500000001304410773624641020772 0ustar timtim#!/usr/bin/env python """ A FloatCanvas arc Object, and a test for it """ from FloatCanvas import * import numpy as N # define the new Object: class ArcPoint(XYObjectMixin, LineAndFillMixin, DrawObject): def __init__(self, StartXY, EndXY, CenterXY, LineColor = "Black", LineStyle = "Solid", LineWidth = 1, FillColor = None, FillStyle = "Solid", InForeground = False): """ ArcPoint(self, Point StartXY, Point EndXY, Point CenterXY) Draws an arc of a circle, centered on point CenterXY, from the first point (StartXY) to the second (EndXY). The arc is drawn in an anticlockwise direction from the start point to the end point. """ DrawObject.__init__(self, InForeground) # There is probably a more elegant way to do this next section # The bounding box just gets set to the WH of a circle, with center at CenterXY # This is suitable for a pie chart as it will be a circle anyway radius = N.sqrt( (StartXY[0]-CenterXY[0])**2 + (StartXY[1]-CenterXY[1])**2 ) minX = CenterXY[0]-radius minY = CenterXY[1]-radius maxX = CenterXY[0]+radius maxY = CenterXY[1]+radius XY = [minX,minY] WH = [maxX-minX,maxY-minY] self.XY = N.asarray( XY, N.float).reshape((2,)) self.WH = N.asarray( WH, N.float).reshape((2,)) self.StartXY = N.asarray(StartXY, N.float).reshape((2,)) self.CenterXY = N.asarray(CenterXY, N.float).reshape((2,)) self.EndXY = N.asarray(EndXY, N.float).reshape((2,)) #self.BoundingBox = array((self.XY, (self.XY + self.WH)), Float) self.CalcBoundingBox() #Finish the setup; allocate color,style etc. self.LineColor = LineColor self.LineStyle = LineStyle self.LineWidth = LineWidth self.FillColor = FillColor self.FillStyle = FillStyle self.HitLineWidth = max(LineWidth,self.MinHitLineWidth) self.SetPen(LineColor, LineStyle, LineWidth) self.SetBrush(FillColor, FillStyle) #Why isn't this working ??? def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): self.SetUpDraw(dc , WorldToPixel, ScaleWorldToPixel, HTdc) StartXY = WorldToPixel(self.StartXY) EndXY = WorldToPixel(self.EndXY) CenterXY = WorldToPixel(self.CenterXY) dc.DrawArcPoint(StartXY, EndXY, CenterXY) if HTdc and self.HitAble: HTdc.DrawArcPoint(StartXY, EndXY, CenterXY) def CalcBoundingBox(self): self.BoundingBox = N.array((self.XY, (self.XY + self.WH) ), N.float) #self._Canvas.BoundingBoxDirty = True #um set an error ? if self._Canvas: self._Canvas.BoundingBoxDirty = True class ArcPoint2(XYObjectMixin, LineAndFillMixin, DrawObject): def __init__(self, StartXY, EndXY, CenterXY, LineColor = "Black", LineStyle = "Solid", LineWidth = 1, FillColor = None, FillStyle = "Solid", InForeground = False): """ This is a non-resizing ArcPoint(self, Point StartXY, Point EndXY, Point CenterXY) Draws an arc of a circle, centered on point CenterXY, from the first point (StartXY) to the second (EndXY). The arc is drawn in an anticlockwise direction from the start point to the end point. """ DrawObject.__init__(self, InForeground) # There is probably a more elegant way to do this next section # The bounding box just gets set to the WH of a circle, with center at CenterXY # This is suitable for a pie chart as it will be a circle anyway # FIXME: This doesn't work correctly... radius = N.sqrt( (StartXY[0]-CenterXY[0])**2 + (StartXY[1]-CenterXY[1])**2 ) minX = CenterXY[0]-radius minY = CenterXY[1]-radius maxX = CenterXY[0]+radius maxY = CenterXY[1]+radius XY = [minX,minY] WH = [maxX-minX,maxY-minY] self.XY = N.asarray( XY, N.float).reshape((2,)) self.WH = N.asarray( WH, N.float).reshape((2,)) self.StartXY = N.asarray(StartXY, N.float).reshape((2,)) self.CenterXY = N.asarray(CenterXY, N.float).reshape((2,)) self.EndXY = N.asarray(EndXY, N.float).reshape((2,)) #self.BoundingBox = array((self.XY, (self.XY + self.WH)), Float) self.CalcBoundingBox() #Finish the setup; allocate color,style etc. self.LineColor = LineColor self.LineStyle = LineStyle self.LineWidth = LineWidth self.FillColor = FillColor self.FillStyle = FillStyle self.HitLineWidth = max(LineWidth,self.MinHitLineWidth) self.SetPen(LineColor, LineStyle, LineWidth) self.SetBrush(FillColor, FillStyle) #Why isn't this working ??? def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None): self.SetUpDraw(dc , WorldToPixel, ScaleWorldToPixel, HTdc) CenterXY = WorldToPixel(self.CenterXY) StartXY = self.StartXY+CenterXY EndXY = self.EndXY +CenterXY dc.DrawArcPoint(StartXY, EndXY, CenterXY) if HTdc and self.HitAble: HTdc.DrawArcPoint(StartXY, EndXY, CenterXY) tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/Resources.py0000644000175000017500000003701610773624641021115 0ustar timtim#---------------------------------------------------------------------- # This file was generated by /usr/local/bin/img2py # from wx import ImageFromStream, BitmapFromImage import cStringIO, zlib def getMagPlusData(): return zlib.decompress( 'x\xda\x01*\x01\xd5\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x18\ \x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0w=\xf8\x00\x00\x00\x04sBIT\x08\x08\ \x08\x08|\x08d\x88\x00\x00\x00\xe1IDATx\x9c\xb5U\xd1\x0e\xc4 \x08\xa3n\xff\ \xff\xc5\xdb\xb8\xa7\xee<\x04\x86gFb\xb2\x88\xb6\x14\x90\x01m\x937m\x8f\x1c\ \xd7yh\xe4k\xdb\x8e*\x01<\x05\x04\x07F\x1cU\x9d"\x19\x14\\\xe7\xa1\x1e\xf07"\ \x90H+$?\x04\x16\x9c\xd1z\x04\x00J$m\x06\xdc\xee\x03Hku\x13\xd8C\x16\x84+"O\ \x1b\xa2\x07\xca"\xb7\xc6sY\xbdD\x926\xf5.\xce\x06!\xd2)x\xcb^\'\x08S\xe4\ \xe5x&5\xb4[A\xb5h\xb4j=\x9a\xc8\xf8\xecm\xd4\\\x9e\xdf\xbb?\x10\xf0P\x06\ \x12\xed?=\xb6a\xd8=\xcd\xa2\xc8T\xd5U2t\x11\x95d\xa3"\x9aQ\x9e\x12\xb7M\x19\ I\x9f\xff\x1e\xd8\xa63#q\xff\x07U\x8b\xd2\xd9\xa7k\xe9\xa1U\x94,\xbf\xe4\x88\ \xe4\xf6\xaf\x12x$}\x8a\xc2Q\xf1\'\x89\xf2\x9b\xfbKE\xae\xd8\x07+\xd2\xa7c\ \xdf\x0e\xc3D\x00\x00\x00\x00IEND\xaeB`\x82\xe2ovy' ) def getMagPlusBitmap(): return BitmapFromImage(getMagPlusImage()) def getMagPlusImage(): stream = cStringIO.StringIO(getMagPlusData()) return ImageFromStream(stream) #---------------------------------------------------------------------- def getPointerData(): return zlib.decompress( "x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\x12 \xcc\xc1\ \x06$\x1f\x94\xdb\xfe\x00R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4o\xf5tq\x0c\ \xa9\x98\xb3\xf5\xdaE\xa1V\x05\x0e\x96\x0bw\xbf\xfc\xdf\xbfc\xd1\xf4\xd9\x87\ \xa7\xa84Mw_n\xa3\xeb&\xbcS\xf4N\xa9\xdcn\x86\x03aZ\x1bWl{\xcet\x92m\xed\x8a\ [\xd1*\x9c\x82\x91\x93\x9eMuP\xd6\xbe4\xa3\xa1\xcd\xe8\x84\xc0\t%=\x85\xe6\ \x1d\x8d\x1aF\xac.\x132\x13\xc4^\x9ek\x14\xffx\xc6K\xa3\xd1\xcd-3\xa8\xa1M'\ \x85\xf3Ck\xcb\xb9\x07\xd7\x7f\x85\x7f=\xa7Ts\xe2^\xff\x83\xfb\xf1\x97\x15\ \x15\x94\xd2\xbc/5tl\t\xb3\x11\xcc\xe7\x12\xbe0;\xfa\xef7\x85X\x87\xfc{z:S'\ \x86-}\xb6\xe0\xbb\xc2\xfc\x03\x7f\xa7\\\xf3\xb5jM/fX\xf0/\xf7\xe3\xb5\xca7\ \x8f\xe66s\xf3\x99\xe7\xf8\x9e\xb4(\xfd\t\xf4\x00\x83\xa7\xab\x9f\xcb:\xa7\ \x84&\x00\xc7Jh8" ) def getPointerBitmap(): return BitmapFromImage(getPointerImage()) def getPointerImage(): stream = cStringIO.StringIO(getPointerData()) return ImageFromStream(stream) #---------------------------------------------------------------------- def getMagMinusData(): return zlib.decompress( 'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\x12 \xcc\xc1\ \x06$\x1f\x94\xdb\xfe\x00R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4\xdf\xf6tq\ \x0c\xa9\x98\xb354\x9a\xaf\xc5\x80#e\xd5w\xfb\x8d\xa7\xea.\xa6j\x06\xec\xeaU\ Q[vE\xb2m\xba\x83\xf5\x0b_k\xe5\xe3\xc5\xf12?o\x15.\xf2b\xf0ol`V\xe63\xd6\ \x9f\xc8\xc35\xefw\x12\xff\x0fi\xc1\x96\x0em\x15{\x16\xb1\x98E_9\x18\xa6x\ \xdc\xe2\xdaa\xcb>\xe1\xda*\xe1\x1b\xde\x82\x15O\xfc\xa5\x9d\xdc\x83\x19\xb7\ \xabD\xee\xed\x98dv\xd6n\r\x9b\xe3\x12\x91=\xa9\xeb\x85[4\xa3<\x9d\xd3b\x1d\ \xb7f$]]\x96\xe1\xf2\xf8\xc6y\x8f5\xf6\xd2\xdb\x96\xe9\xdfT\\\xd5p\xbe-7\xa2\ ls\xac\x88\xa4\xf1n\xaf6=!\xd5\x9b\xab:\xca\xa6,?\x92\x1b\xdc\xe9r\xe0\xcb\ \xe2\xe6\x15\x13v\xfco^\xe5\xfa\xf2\xca\xcb[R[\xba&\xbd\xf5\xec\xf3\xd8U?\ \xfd\x80\xf2EM\xae\xf0\xa3\xf3Ut\xde\x17\xed\x0b}\xd2U\xcb0Ugv\x82\xa1Q\xc7S\ \xa07\x19<]\xfd\\\xd69%4\x01\x00+\xecq\xf9' ) def getMagMinusBitmap(): return BitmapFromImage(getMagMinusImage()) def getMagMinusImage(): stream = cStringIO.StringIO(getMagMinusData()) return ImageFromStream(stream) #---------------------------------------------------------------------- def getMoveButtonData(): return zlib.decompress( 'x\xda\x01,\x01\xd3\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x18\ \x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0w=\xf8\x00\x00\x00\x04sBIT\x08\x08\ \x08\x08|\x08d\x88\x00\x00\x00\xe3IDATx\x9c\xb5\x96\xd1\x16\x84 \x08D\x19\ \xf5\xff\xbf\xb8\x9a}Y[\xc2P\xe8\xb4<\xaa\xcc\x15\x1c-\xa0T\x89\xc6\xb1o\x14\ \x11)\xb5!\x9aS2\xe2\x00\x04\xc0\tz\r\xd0\xc5{d K\x80\x15\xcfB\xa6\x00O<\x03\ q\x01+\xf1(\xa4\xb9\xe4\xda@\xf2\x92\xd8\x81fx\xea\xaa\x01p\xec\x1b{\x82N\ \xb4\xbb\xb4\xa2\x9e\x85\x8b]\x94\xb5\xa1\x8e\xbb\xdc\x13\xa0{\x9e\xb9H+\x08\ P\xeap\xa0\xb6\xc7:92\xdf\xd7\x94\xda\x00\x92!\xb7<\t\x92\xf1\xa7\xe2i\xb4n\ \xc7\x7f\xb5\xa8\x89\xfc<\xaf\x17x6\x8c\xccwq\x11\xe5\xa2/\xe4\xbe\xceDh\xf1\ \x0b@C\x9e\xd8\xd4\xcb\xc5\xec\x83c\xdb\xf2\xcaS\xa1\xc5=\xfb\xdaq\x92\xf4 \ \xaeM\xa3g\xb2j\xe9\xf4\x1e\xac \x91\r\xb8-2\x90\xa1]Q3\x84n\xb2\xad$\xe3\ \xb4e\x05\x06\x92\xfem\xf9\x00\x8d\xa7\xbb\x936\xe9\xf2\xae\x00\x00\x00\x00I\ END\xaeB`\x82\xed\x9c\x836' ) def getMoveButtonBitmap(): return BitmapFromImage(getMoveButtonImage()) def getMoveButtonImage(): stream = cStringIO.StringIO(getMoveButtonData()) return ImageFromStream(stream) #---------------------------------------------------------------------- def getMoveCursorData(): return zlib.decompress( "x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\xc2 \xcc\xc1\ \x06$\x8b\x02\xcc\xce\x00)\x96b'\xcf\x10\x0e \xa8\xe1H\xe9\x00\xf2\xd7z\xba8\ \x86T\xccYz\xe5\xa0\xd0a\x05\x0e\x96\x0b\xb1_\xff\xef\xb7\xe0\xb4-)\x98\xb0\ \xe0\xc6\xab\x8b/Ns\xf5\xa5\xac(+y\xdb\xba7\x0e*\x1f\xefL\x97I\xe4b<\ \xc0gqTg\x892\xb3\xb3NS\xd9\x01\xf1eG\xc5\x04;z\xaaK\xd6]9\xc6!c\x10\xfd&\ \xf2\xbbH\x97P\xd0\xfa6\xdbY\xbe)\xfd\xd2g\xb3/\xf5\xad\xcd\xdab,\xb2\xa4C\ \xc6\x91y\xc5Q\xbb\xb6\xacd\xe6}\xae[9\xff\xaf\x8d|\xbf\xcc\x7f\xc7\xabe\xfe\ W\xf6\xffl]]\xcd\xd2\xf3\xfd\xc2\xff\t\x17WO,5o\x8a;Ys(~\x81\xa6\x19s\xf8\ \x05\xa1\xcf\tlKg\xb0\x96\xc7\xdd\xe2_\xd9\xbe,\xc7\xc4,\xf8=\xd0\xe1\x0c\ \x9e\xae~.\xeb\x9c\x12\x9a\x00\x0b\xb6b\x8e" ) def getMoveCursorBitmap(): return BitmapFromImage(getMoveCursorImage()) def getMoveCursorImage(): stream = cStringIO.StringIO(getMoveCursorData()) return ImageFromStream(stream) #---------------------------------------------------------------------- def getMoveRLCursorData(): return zlib.decompress( "x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\xc2 \xcc\xc1\ \x06$\x8b\x02\xcc\xce\x00)\x96b'\xcf\x10\x0e \xa8\xe1H\xe9\x00\xf2{<]\x1cC*\ \xe6\x9c\xbd\xe2\xc8\xd7\xa0\xc0\xc3r \xf6\xc1\x7f}\xb6WG\xa5Z\xa75H=\x96\ \x93\xb6Z\xb8\xa4\x91G0_u\x8fZm\xdb\xd5I\xa9K\xdf%mMQ\xbciZU*~\xb9-\xd0\xe6C\ \xd3Y\x07\xe5\t\xbb\xa4\xc4T.\xf9'\xcf\xe54\xfcx ,/\xc5\xd5\xb1\xeb\x84\xf2\ \x0b\xa6\xb6\x19\x19\xbd\xc5\xcf\xd38\x19\xca>|\x9c\xad\xaa[\xb5@\x8e\xe5W\ \xab\xad\xb3\xc3f)m\xe5\xed\x01\xedg\x9b\xc4X\xe6|[\xe3\xab\x1b\xb9\x86m\xbd\ \xdd\x91wO\xf6\xff\xbf\xc9\xf6\xc6#\xdf|\x8be\x98\x16\xd0]\x0c\x9e\xae~.\xeb\ \x9c\x12\x9a\x00\x11\x04M\x96" ) def getMoveRLCursorBitmap(): return BitmapFromImage(getMoveRLCursorImage()) def getMoveRLCursorImage(): stream = cStringIO.StringIO(getMoveRLCursorData()) return ImageFromStream(stream) #---------------------------------------------------------------------- def getMoveUDCursorData(): return zlib.decompress( 'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\xc2 \xcc\xc1\ \x06$\x8b\x02\xcc\xce\x00)\x96b\'\xcf\x10\x0e \xa8\xe1H\xe9\x00\xf2gx\xba8\ \x86T\xccY{\xc5\x91\xef\x88\x02\x07k@\xc0\xfb\xfaG\xdb\xf6\xcf6\x14t\xb1\x9b\ ,\xb9\xedE\xb7\xc2\xaa[\xbb6T\xbc\xe3^\xcb\x9f\xfa:\x8a5(\xb4\xf2\x1d\xb7}\ \xa2\xb0\x90\xe0\xca\x06\xf7\x9c\xd64\x03\x83#J+\x98\xf2"\xd8\x0c/$\x88j0\ \xb7O\xfc\x1d\xc0\xf0av\xda\x8e)?\n\rg\xc4\x0bL\x9btFz\xee\xe6\xfcG\xebo\x84\ \xa9I\x9f1\x9d\xff\xad\xe7\xee\xb2\xf3\x8c\x06\xf9\xd7\xa6\xfc\xdcy\xf6M\x82\ \xf6\x96\xb99\xaf#Y{\x16\x08$?\xe0\xb4JR7h\x0e:\xd3\xcc\xb3\xe8\x06WX\xdd-\ \xf1\xf5<\x05n\xca[\xef\xfd\x01\xba\x91\xc1\xd3\xd5\xcfe\x9dSB\x13\x00/\x9bT\ s' ) def getMoveUDCursorBitmap(): return BitmapFromImage(getMoveUDCursorImage()) def getMoveUDCursorImage(): stream = cStringIO.StringIO(getMoveUDCursorData()) return ImageFromStream(stream) #---------------------------------------------------------------------- def getGrabHandData(): return zlib.decompress( 'x\xda\x01Z\x01\xa5\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x18\ \x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0w=\xf8\x00\x00\x00\x04sBIT\x08\x08\ \x08\x08|\x08d\x88\x00\x00\x01\x11IDATx\x9c\xb5U\xd1\x12\x830\x08Kh\xff\xff\ \x8b7\xb3\x97\xd1C\xa4Zw\x93;\x1fJ1\t\x98VJ\x92\xb5N<\x14\x04 I\x00\x80H\xb4\ \xbd_\x8a9_{\\\x89\xf2z\x02\x18/J\x82\xb5\xce\xed\xfd\x12\xc9\x91\x03\x00_\ \xc7\xda\x8al\x00{\xfdW\xfex\xf2zeO\x92h\xed\x80\x05@\xa45D\xc5\xb3\x98u\x12\ \xf7\xab.\xa9\xd0k\x1eK\x95\xbb\x1a]&0\x92\xf0\'\xc6]gI\xda\tsr\xab\x8aI\x1e\ \\\xe3\xa4\x0e\xb4*`7"\x07\x8f\xaa"x\x05\xe0\xdfo6B\xf3\x17\xe3\x98r\xf1\xaf\ \x07\xd1Z\'%\x95\x0erW\xac\x8c\xe3\xe0\xfd\xd8AN\xae\xb8\xa3R\x9as>\x11\x8bl\ yD\xab\x1f\xf3\xec\x1cY\x06\x89$\xbf\x80\xfb\x14\\dw\x90x\x12\xa3+\xeeD\x16%\ I\xe3\x1c\xb8\xc7c\'\xd5Y8S\x9f\xc3Zg\xcf\x89\xe8\xaao\'\xbbk{U\xfd\xc0\xacX\ \xab\xbb\xe8\xae\xfa)AEr\x15g\x86(\t\xfe\x19\xa4\xb5\xe9f\xfem\xde\xdd\xbf$\ \xf8G<>\xa2\xc7\t>\tE\xfc\x8a\xf6\x8dqc\x00\x00\x00\x00IEND\xaeB`\x82\xdb\ \xd0\x8f\n' ) def getGrabHandBitmap(): return BitmapFromImage(getGrabHandImage()) def getGrabHandImage(): stream = cStringIO.StringIO(getGrabHandData()) return ImageFromStream(stream) #---------------------------------------------------------------------- def getHandData(): return zlib.decompress( 'x\xda\x01Y\x01\xa6\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x18\ \x00\x00\x00\x18\x08\x06\x00\x00\x00\xe0w=\xf8\x00\x00\x00\x04sBIT\x08\x08\ \x08\x08|\x08d\x88\x00\x00\x01\x10IDATx\x9c\xad\x96\xe1\x02\xc2 \x08\x849\ \xf5\xfd\x9fx\xdb\xf5\'\x8c!\xa8\xab\xee\x975\xe5\x83\x0b\\@\xa9\xb2\xab\xeb\ <\xa8\xebR\x1bv\xce\xb4\'\xc1\x81OL\x92\xdc\x81\x0c\x00\x1b\x88\xa4\x94\xda\ \xe0\x83\x8b\x88\x00\x10\x92\xcb\x8a\xca,K\x1fT\xa1\x1e\x04\xe0f_\n\x88\x02\ \xf1:\xc3\x83>\x81\x0c\x92\x02v\xe5+\xba\xce\x83\xb7f\xb8\xd1\x9c\x8fz8\xb2*\ \x93\xb7l\xa8\xe0\x9b\xa06\xb8]_\xe7\xc1\x01\x10U\xe1m\x98\xc9\xefm"ck\xea\ \x1a\x80\xa0Th\xb9\xfd\x877{V*Qk\xda,\xb4\x8b\xf4;[\xa1\xcf6\xaa4\x9cd\x85X\ \xb0\r\\j\x83\x9dd\x92\xc3 \xf6\xbd\xab\x0c2\x05\xc0p\x9a\xa7]\xf4\x14\x18]3\ 7\x80}h?\xff\xa2\xa2\xe5e\x90\xact\xaf\xe8B\x14y[4\x83|\x13\xdc\x9e\xeb\x16e\ \x90\xa7\xf2I\rw\x91\x87d\xd7p\x96\xbd\xd70\x07\xda\xe3v\x9a\xf5\xc5\xb2\xb2\ +\xb24\xbc\xaew\xedZe\x9f\x02"\xc8J\xdb\x83\xf6oa\xf5\xb7\xa5\xbf8\x12\xffW\ \xcf_\xbd;\xe4\x8c\x03\x10\xdb^\x00\x00\x00\x00IEND\xaeB`\x82\xd1>\x97B' ) def getHandBitmap(): return BitmapFromImage(getHandImage()) def getHandImage(): stream = cStringIO.StringIO(getHandData()) return ImageFromStream(stream) #---------------------------------------------------------------------- def getGrabHand16Data(): return zlib.decompress( 'x\xda\x01\x0f\x01\xf0\xfe\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\ \x10\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\ \x08\x08\x08\x08|\x08d\x88\x00\x00\x00\xc6IDATx\x9c\x9d\x92Qn\x031\x08D\x07\ \xd6\xc7\xc0\xf7?\x98}\x8c$\xaf\x1f[,\xaf\xb5n\x9a !\r\x08\x0f\x0c\xd8\x00\ \xfc(\xa6o-"\x000?\xc4\xaf\xedp\xc6\xe9\x00\xa5\xf7\xaeZ\xab^\xcf\x07\xb5VI\ \xda\xe2\x8c\x13\x9b\x99\x06{N\xf2\x0e\xa7KB\x12\xe5\x13\xb9\xbdw\x0123\xc1\ \x18\xe4dZw1\xeb\x9c1\xe7\xcb\xe1\x0e(".\x9d\xe6\xab\xec0 @%\x17\xd4Z\xd3\'\ \xe74;K\xbd\xb5&I\xe3\x12\x7f=\xca\x8bD\x84\xc6\xe4\xa9-\xb7\xbb\xdez\xd6\ \xbf\xd6\x00xj\xfb\xef$\xb3T?\x8a\xf9\xbc\xa0\x1d\xc9\xfa\x99f\xf3K0\x91\xbc\ \xeb~K\xf0\x8d\x99\xf9qI\xbc\x9e\x0f\xf2\xa7e\xb7\xbb\xdc\x96 \x1f\xac\x85w9\ I\xfa\x01\xd6\xd0\xefe\x16\x16\xb7\x9b\x00\x00\x00\x00IEND\xaeB`\x82\x0bmo\ \xbf' ) def getGrabHand16Bitmap(): return BitmapFromImage(getGrabHand16Image()) def getGrabHand16Image(): stream = cStringIO.StringIO(getGrabHand16Data()) return ImageFromStream(stream) #---------------------------------------------------------------------- def getMondrianData(): return zlib.decompress( 'x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\n \xcc\xc1\x04\ $\xffH\xbc]\x0c\xa4\x98\x8b\x9dI\x90\x1c\xf2\xb6\ \x95\xfex\xea\nH\x92n\x0c\x9c\xf6\xdb2`\xba\x9d\xd0!\t\xd66>\x02\xea\xbb\xfb\ \xe3\xb4\xaf\xb3\xe3\xde\x8b3\x16\x80\xb0\xef;\x00\xa0\xf7^\xd3\xad\xb2\x10\ \xd1\xfc\xee\xcb\xfbNL\x06KZ\x1b\x19p\xcdO\xa6\xe5Ysj\x1e\x98\x18\xdf\x7f\ \x1f\x03!HoAn\xfe<\xeaK\xfd\xd2\x9f\xeao\xac\xa8\xae|\xba%1\xca\xc9U\xf5>\ \x98\xdc\xd9g\xb0\x13Hr\x00\x00\x00\x00IEND\xaeB`\x82\xde\xa5p@' ) def getHand16Bitmap(): return BitmapFromImage(getHand16Image()) def getHand16Image(): stream = cStringIO.StringIO(getHand16Data()) return ImageFromStream(stream) #---------------------------------------------------------------------- def getMagPlus16Data(): return zlib.decompress( "x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\x02 \xcc\xc1\ \x06$\xe5?\xffO\x04R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4o\xf3tq\x0c\xa9\x98\ 358\x9a\xef\xb0\x01\xc7\xe3\x89\xc9S~\xc7oZ\xfb}c\x93\x86\xe2\xc5g\xeb\xb9\ \x12\x93}N\xe9xI~/m\xe2ra\xbf>+9\xc4\xe8\xf3\x1dn\x06\xed\x89\x02\x05F\x06\ \x92\x0b\x96\xdf\xeb\xea\xf1\xfa\xb6\xec\xb7U3\x03\x83\xb7`\x8d;\x13C\xc4\ \x94\x88/\xcf\xa5\xba'\x85x\x9b\x1e\xd1\xbbb\xd6\xbc\xc7\xeb\x9e\xed\xce\x9c\ \x8fE\nV\x12\x0e,/\xef\xef6\xf6\xd3\xbe\xf2Lvf\x87G\x8d\x96\xf1\xf1}q\xa7\ \xc5\r7\xdf\xf3\x9d^t\xb4PFa\xd17.\xc1G\xc6\xa5_\x85\x94\x03\x8c\xab\xf7\n\ \x9e\xcaz\xb7\xe4\xd0\xeb\xb5\x93\x7f\x19\xbf\r8\xcf\x93\xb0\xef\x10\x9f\\\ \xde\x84\xd2\x0f\xf1L\x91G\x8c\x7f0t=<{\xccE9L\x01\xe8\x03\x06OW?\x97uN\tM\ \x00\xe1\xf8b\xe3" ) def getMagPlus16Bitmap(): return BitmapFromImage(getMagPlus16Image()) def getMagPlus16Image(): stream = cStringIO.StringIO(getMagPlus16Data()) return ImageFromStream(stream) #---------------------------------------------------------------------- def getMagMinus16Data(): return zlib.decompress( "x\xda\xeb\x0c\xf0s\xe7\xe5\x92\xe2b``\xe0\xf5\xf4p\t\x02\xd2\x02 \xcc\xc1\ \x06$\xe5?\xffO\x04R,\xc5N\x9e!\x1c@P\xc3\x91\xd2\x01\xe4\xaf\xf4tq\x0c\xa9\ \x98\xb36\xd8Q\xa8\xc5\x80C\xf9\x80\xf1\x9b\xff\xf6+\xd3\xf8\xb5\xb75\x87\ \xdc\x9dy\xd6P5\xd3I4`\xb2\xe0\xefmABWdfrW\x881_\x8f\x9c4g\xe6\x1c6E5}\xc6'\ \x0f\xbc\x85\xcf?\xca\xeaPIW\x93\xe0\xcb\xdf}N\xefc\x96Aq}\xe4#mfSw\xd35\xcf\ VL\x8a\xe5\x99\xf7(\xec\xc2\xe30\xc6\x80o\xe2?\xc3\xb2\xd7^\xedn\x9b\xe5\xa0\ [\xb5\xe9\xd0&\x1d\x91\x89\x9fmL\x02^\x8b.\xfa\x9f\xd2)T\x93\xed\xfb-\xf7\ \xed\xfd\xc3/\xc4<\x8d\x9a\xf4'?\x99\xff\x92\xef\xe7L\xcf\xae}a\xdfg\xc5\xe6\ \xf4\xcd\xe7q\x9b|\xe3 \xfb\xa7#\x1bw\xe4\x1f\xcdj\x01:\x9a\xc1\xd3\xd5\xcfe\ \x9dSB\x13\x00<\xbf^\xf7" ) def getMagMinus16Bitmap(): return BitmapFromImage(getMagMinus16Image()) def getMagMinus16Image(): stream = cStringIO.StringIO(getMagMinus16Data()) return ImageFromStream(stream) tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/CrossLine.py0000644000175000017500000000247110773624641021041 0ustar timtim from FloatCanvas import Line import math try: from numpy import array, empty, dot, sum, asarray, float except ImportError: raise ImportError("I could not import numpy") t = array([[0,-1],[1,0]]) class CrossLine(Line): def __init__(self,start,delta,Number, LineColor = "Black", LineStyle = "Solid", LineWidth = 1, InForeground = False): self.Number = Number Points = empty((Number*4,2), float) Points[0] = start Points[1] = array(start,float)+array(delta,float) Points[2] = Points[3] = Points[1] for i in range(4, len(Points), 4): # i = normal start # i+1 = normal end # i+2 = cross start # i+3 = cross end Points[i] = Points[i-3] Points[i+1] = Points[i-3]+array(delta) Points[i+2] = Points[i+3] = Points[i-3] Line.__init__(self, Points, LineColor, LineStyle, LineWidth, InForeground) def _Draw(self, dc, WorldToPixel, ScaleWorldToPixel, HTdc=None): Points = WorldToPixel(self.Points) pslop = dot(Points[1]-Points[0], t) length = math.sqrt(sum(pslop**2)) pslop = pslop/length for i in range(0, self.Number*4, 4): Points[i+2] = (Points[i+1]+pslop*2.5).astype('i') Points[i+3] = (Points[i+1]-pslop*2.5).astype('i') dc.SetPen(self.Pen) dc.DrawLines(Points) if HTdc and self.HitAble: HTdc.SetPen(self.HitPen) HTdc.DrawLines(Points) tpclient-pywx-0.3.1.1/extra/wxFloatCanvas/ScreenShot.py0000644000175000017500000041152310773624641021217 0ustar timtim#---------------------------------------------------------------------- # This file was generated by /usr/local/bin/img2py # from wx import ImageFromStream, BitmapFromImage import cStringIO, zlib def getScreenShotData(): return zlib.decompress( 'x\xdatzeP\\M\xd0.N\xf0\xe0\x16\xdc\xdd\x12\xdc\xdd\t/\xee\xee\xee\x0e!\x10\ \xdc\xdd\t\xee\xee\x8b\xbbC`\x91`\x8b;\xcb\xe2.\x97|_\xdd\x7f\xf7v\xd5\xd4\ \xa9\x9a\xd3\xa7\xa7g\xba{\xe6y\xa6N\xe4we\x194d"d(((49Y\xc9\xff\xa0\xa0\xa0\ />\x9a\xe8\'\x84\x8f\x1e\tK\xd6\xe4\x8f\x07\x9c\x9b\xb8\x9c\xfa\xa7\x0f\xf1\ \xffd\x1e\x01\x05E\x0e%\')\xa6\xee\x9ds\x96\xeb\x95\xf3\xc5\xe3\xf5=\x9fK\ \xaf\xf6>\xa9\xaac\x8f\xb5\xdb\x80\x11\x89\x9a\x9aZ\x92\x9f\xb2;"\xea\xf7\ \x00\xc6\x85\x02\xf9\xcf\xab[&O\xb1\x84R\xf2\x01|\xf8\xdeBJ\xf2\x08\x1c)qq\ \xf2\x04\x90\x1f\xeb>\xeb\xb2\xdff\xf7\x1a\xe7\xf5\xb3\x99\xe3\xe4\xd9LkgwZ\ \xf6\xe1\xaeK\xfcZn\x8f\x80\xc0u\xd6\xfd\xf35\xeb\x80\x01\x8d\xca\xd8\xd1\ \xffJ\x0c\xe3\xd0\xb60\x14\xc9\xffH\xee\xd8\x1c\xbc\xbe\xcc?\xb1\xc2)Di\x8f\ \xfb\'3\xf4C\xbc\xeb\x88\xbf\x8b\x8av\xb7W\xb0\xef\xd1\xee)bx\xcf\x19}L\xdb1\ \xc4d\xac$\x0b\xf5\xb6\xf8\xf9\xa9\xe0\x0c\xba<\xdc\xdd)\xc5\xda\xfa<\xdc\ \xa5\tN\x97\xeb\xc8\xce%\x080\xabu[l\xffW\xab\xe8\x9f\xd6?)\xfal\xf0\xa1\xf2\ O\xa4)\x00?N\xffw|qw\xe8\xe5\xb9\x7fB\xf8\xeb\x08\xa6\xb6\xe8\x9fp!\xff\xbf\ \xfc\x90\xc4w\xfe_/U#X\xff\xff\x06Q\x191j\x1c\x88\xce%x\xa9\xe6\xec\n\xfe\ \xb7\'\xc2\x19\xee\xa9\xa0E\xe9e\xefr\x8a\x827\xab!\xe4\xe3\xeb\xa2\x9fkl\ \xde\x8c\x85\xfb\xf9\xef\xb3Yb\xfcX\x1fV\x9d\xdcO}\x1f\xfe\xc0\xeb[\raUX#\ \xeaj\xe1\xbb\x91\xe4\xf6\x8b\xe1C\xb6\xa5\xf0\x9ds1\xc3\xd3\x9cg\xfd\n\xf8\ \x0b\x1d\xce\xde4{6\xef\xdc)\x96\xe7"YE|\x04\xd5\xf0/M$\xff)\xfcj\xf3\x96a\\\ \x05y\xd7\x9db]\x7f\x98\x96\xc7w!\xc9\xa5\xdf%Z^\xfa\xe5\x7f\xf41\x19+\xc9-;\ \x0f\x0c\xc9\xae\x80\xcc{\xf1\x16\xf9!\xb1\xb6\x11\x0f\xf7\xc2HV\xd0`H\x9et)\ \xd7\xd9\x83\xee\xc6\x1c\x0eDt\x8dd\xec\x01\xf01\xd7p\xe7a\xbdx\xd1x\xe1\x8f\ )\xa12\xcd\xb9f\x86G\xb3\xee\xf0\xf3\xcfm\x7fL\x02zX\x0f\xff\xb4@\xeccH\x13\ \xb3\xf2a=;#@\xc4\xe9\x91\xa42{\x95\x1e>\xa4@\x82\x0cv\x99\xd03\xec\xbf\xae\ \xee\xfbc\x92\x8a\x8f\xb5\xc4&\xdd\xd6\xdex\xcax\xf8\xf3\xfb#\x04\x83?\'\xaf\ H\xd0/=\xb7W\xdb\x1c\x7f\x9d\x1e\x85\xd2b\xa5\xfb\x94\xdf\xf3\xcf\xfd\x8b[XN\ "}\x86oTf\x9c\xb2\xf1\xd3.\xe7\xb2\x94\xdf\xc5?\xa7\xff\x12(\x9f\xae=\x13\ \xb8k\x01>\xfaoD[\x12\xa3\xcf\xc5\x97\t\xff\x93\xfey\xba\x8e\xbf\x91Z[\xb4\ \x1bOj!|\xf5\xa1IG\xf9\xa5\x11\xadsA`=\xbc\xc0\r\xe1\xa2\xbb\xf7\xec\xcb\xb9\ \xc4\x1f\xa4\x1f\x1fo\xf9\xff\x18\x1c\xf1c^Z\xder}\xbd\xd3t\xd1\x1a\xc7\x0e\ \xe9a\x93KJ\xb0\xd0\xf96m\xcc\x8e\xfa\x14\xe8\x81\x80\xef\xb4\xed\xd9\x1d\ \xb8W\n?\xe8\xc1+1r\x02nk7\xaa\xd3\xbb\xb9\xaa\'\x91\xa1w\xaf\xf2\xbb\xf9\ \x8d\xf2@ #\xbdc\xfcl\x89\xee\xe1X2\xac\x19\x1e\xa3\x98\xc4\x11\xeb\xc2\xb1\ \xab\x93\xf6H\xb3\x83\x1a\xa9\xba\xa6U|\xee\xa6z\xc3\x1b\xd1<$\x98\xd5>2\x10\ \x10\xb2bX\xe5\x9b\xf3\xcb\x06\xff{\x0e{vl\xac\xd3g;Ys\x97\')L\x87\xceq\xcd\ \xc1\xfe\xbb\xd9\x8aV\xd2\xb2\xc19T\xd10\xbexx\x9b*\x06\xe5\x0c\x12\xf7\r\ \x8bIA\x9ei\xa5\xec\x9b\x85\x9c\xb9\xa86\xefNP\xfcWL2\x1b\xcd{P\x19\xe3kij-\ \xc3\x97\xab]\x82\xf1#\x18\xe1\xd2D\x1d\xadw\xad8\x0f\xf0?\x83\xfai\xcfh1?3\ \x19\xed\x08\xdf+\xfd"\xe1m\x0e\x9f\x91\x1e<\xe0\xef\xd1\x80\r\xe8B\x1bq\x9e\ \xba\x0eh8#J\xf0\xe6\xca:\xe8\xae.3\xcbT\xa0\x99\xc48\x07u\x9dI^\x9ekyW3\xba\ y\xf0\xd9V\xf2H\xefu\x1d \xfd\xc1\x14D\xf2\xa1:\xa7?\xab\xd7e\x00\x91\xe9\ \x8c@t\xcd\x0e\x82\xb0\t\x8c\x86\xe2\n\xffG\xa8|\xb9\x84e\x9b{\xf1\x07\xde\ \x1f\xd5\xad\xf1\x19j\x14\xe0\xc9\xc9\xe6A\x83\x02duVaS\xce\xf8%\xf7\x15c71\ \x16u\x82%\x9c>";F\xee+\xf0\xaf\xde/j\x81\xf1\xb8\xe3|\xf8\xef)\xec!\x97\x97\ @(Y\xdc&\xed\xcc\x00\xa1w\xadK\xb58w{\x14\xfa\x8f\xe2\x91\xe8\xff\x0e\x98\ \xf2h\x88c\x05\xfc\x887A\xf7r\x84\x85;(\xad\xbd\xc8\xa4rVz\xeb\xa6\xce\x9e\ \x87\xf6\xee\xd8\x19u\x17X\xd5Px\x88\x0b\xd6\xcb\xc9\xedR\x7f\x93\xb8\x7f\ \xce\x1c\xb7\xe2\xe2z\xb4\xe7\xfe\xfa\x16[\n\xd2\x9d\x9f\xde\xd5\xde\x80\xa1\ 9\xa6\xbd\xe7\xecqt\x11\xfb\xbc\x1e\xf4\xda\xef\xe5WH/\xdd\xc5\x92\xadv\xf0\ \x98\xbc9L\xb1\xb6\x01\xcc\x13\xda\xbe\xe4\x7f\xb9\x1b\xd2=(\xa9\xdd\xcb\x89\ \x99\x1c\x04Y\x8a\xad\x9b\xc7\x08cH6\x98\xc2@y\xea`|rw\xa1\xd5\xdb>\xc5\xeb\ \x16\xdc\x19\xe9C\x04\x9e\xc4\xa5}O\xafeX\x90\x12\xf9\xf4\xcf5"_\xe5dSy:P\ \xc2\x19\x0f\xdb\x86\xe0\xcc\xeb\x13\xd3n/$\xf0U\x0e\xb8\xc9\xb7\xd0\xb0\xe8\ \xe4\x93\xfcy\xf0j\xaa\xea)\xcd\'\x19\xdd\x8f\xeb_\x18\xe4"\xdd>":\x1d\xb7\ \xe4\xa1\xeeQ\xda\x01\xbfN\xd3\xca\xbd&|\xcf=u\xc0\xf7\x8a\xe7T\x06\x8c$\xff\ tN\xde\xc6CD\xbcq];>\x81\xec\'@\x1b\xd2\xc7C\'\x8c:\xd6\xa5\x7fi\xc6:\xfb\ \x8aGx \x08\xaa{\x86\xc5\xc6\xb2d\xa7\xb2\x91\x1b\x1a\xe5\xa50)\xddlv\x9d\ \x14\x83r5\x8b\x86\xadm\xb3Q\x03f\x10\xc3\x8a\x00\xa5\xfc\xcb\x91n\xfe|f\xb9\ \x8c+\xfd~*\x19\xc7\xbaeFP\xd5\x14\xad\x0e\x1cJ\x98$\x84\x9b\x9d\x95\xfc\x94\ \xe0c\x8d5=\xa5\xac\x83\xd0G\xd7\xfb \x9c\xda\xe7!\xf2\xc8\xa5\xc3\x01\x0f\ \x95s\x06\xc2\xf8\x0b\x95`\xb1\xa2\xd2\x05m\xdf\x1a042\x13\xfb\xe0&\x9b\x04\ \xe7\xfd\x13\xd45\xbcv+\xac\x8f\x89\x0f\xa5\xfa\xd9\xa6\x89g\'\x85\xc4|d\x0f\ \x1a\xe6Vh?\'\xd9\x85\xaf\x90\xfdbj\xd2QF ;\x0bD\x0b\xcc\x19=K)\x11K\'A)\xac\ \xe1\xe2\x85C\xce9\x8d\x9f\xd4\xc7?I\x8c\xfc\xe7\x86\xd8\xe7\xdf\xf9xN\xbc\ \xedC\xc4\xc6\x1ewJS\xd3\x8fL\xa2\x7f\xac\xaf\x9ck\xf4\x9c\x12{8\x85\xba7\ \xd3\xfc\xc8m\xfd\x94\x93\x88\x050\xa1\x13\xf1\xf4\x84\xa0l\x0e\xce\xa0\x9d\ \xda\x06AS\x02-l\t\xf6\xf2\x87I9z\x1c\xc8\xbe\xd5\xc1l\x126\xbf\xe2\xbf\xb6\ \xdd\x19\xbb\xceT\xf5\xee\xe4\xb4\xac^\xeb\xef\xd4\xa0\xdc\x1e\x89\xe3_p(vQ\ \xac8\xd9\x0b0\xfa\xdbAs%\xcf\x86U\xdbm$\xcfOw\x14\x0fI\x969&\xd4\xfdz\xd5T@\ \xd1*-\xdbu\xe7\x87\xadu\x1b\xc6\xd5\xba\xb8[s\n_\xbf\xdb\xcdo\xbb\x94\xa9\ \xe3p\xda\xbct\n1\xde\xcb\xc6\x0e*\xb8\x92\x0fU\x90p\xa2\x81,\xbd\xb1I]\x02\ \xf9\xd8NW\x03\x1d$\xe8|c\xc2\x16j\xad]>FE\xe6\x85\x9c\x883\xdd\xa8\xb5\x17\ \xd1,\xcc\x06jE\x0ev\x9c\xa6\x13\x175v7\xfc\x0cD$\x1c\xdc\x1bQ.\xae\xb6\xe31\ \x88\xe3\xc6\x8a\xad\x90\xe8yoo\xf7\xd1\xae\xe9\xd4\x80\xde\x1e\xb2\x97\xa4h\xdeF\x18\xf1Aw\ j\xf7v\x1bv[\xf1\x8e\xc1\xa79\x1c\xa1\xc46\xc2)\xed\x8e\xd2N\x06\xc0t\xa7\ \xa0i\xc9\xd4E|\xf9\xaeQ\xe4\xf8\xf5f\xf2\xdf\xedNF\xc7\x0b8\x97\xd6\xc8\xe7\ \xc6\xd1^\xec\x053\x81\x15\x03\xaf\xe4;L\x7f@;`\xdf\xba\xdb\x1fW\x7fVK\xb9\ \x94\xbb\xa0\x97X_\x83\xe5\x87<\x16>\xe0\x94\xdb\x08\xfb\xfc\x90\x00Q\x8e\ \xdc\x92W\xbb\xe0\xc3\x91\xc3\xf92\x86\xc8\xc5\xb3\x89`\xd2\x1bv-\x8a\xff\ \xeb/\xa3p\x94E\x88V\xc0E\xd2\xe8\xaa\xe0\x17_b\xaa\x9a\xe8\x8c\x99?\x98\xb9\ C\xfa$\xb9\xec.\x1d\xe5\x06\xac\xa7\xd6f-\xe7\x9e\xef\xbf&\x8d\x01\xb3-\xdeW\ \x17\xb6\x8b\xed5l\x0c~w\xed\xef#X\x1f>\x89\xd2\x80\xb60\xaf\xc1LB|oW\xa6*\ \xe0@#\xbbf\x91\xf3k\xeb\xcb3/\xad\xf6\xebLDq\xea\xda\x1dc\x8d\xc5\x01L\xc8\ \xe2\x9a\x93\xcb\xfbq\x8c\xf0\x07\xd8#\xe4.d\xd9\xe9)$\x89\x8b\xc0X\n\tE\xd9\ $\xafP\xc0\xaeZ\xaf\xcb\x17\xecZuzK=>\x0e\xf1\x15\xb4B\xbe\xda\xc1u\xa4\xe8\ \xf5z\xe2\xbf\xdf\x94-uW\xa2\xc8\xb6u\xb2T\x03O\xa7\xd42\xa0*\x94\xc3\n\xfd\ \x16ln\xb5\xe93\x18jF^A\xe5\xe9Y\x0e9\x17\xc6\x88\xfb\x87M\\\xf3\xdeg\x89\ \xbc\xd8\xd7dM\xd8k\x9c\x96\x95\x18\x12\x16\xc1Y\x10\x83[\x87\xaf\xd7S\\\xb3\ \xce\xf7\x1b^2\x01\x9d\xb5\r\xce&\xa7\xd2{\xc3L\xeb\xef\xd0\xa15\x83F\xfdL\ \xdfY\xdd\xd8\x0bz\xbc\x9e\x00\t\xaa7=\xc0\x19\xf7\xf4\x0e\xf9!\x99%\x07\xd3\ \xa1\x02\x94\xf6\x99\xfa-\xac\xcb\x8d\xcd\t2gI_\xeasW\xa7\xb0U\x0faM\x82\x08\ \xef\xb2\xb3\x95\xa2\x89\x10\x8co\x08\xe7X\xe7\xd6\x9f\x1e\xbf\xef\x85\xdaE\ \xfaS\xe7\x85\x14\x9cm\xd4p]\xcd}\xa0\x9e\xc1\x89\xc8|\xc8v\xec\x88t\xef\xd3\ \xc16\x96bW\x88\x86\x0f\xb1\xfdr\x07\x1e\x95M\x97\'ur\xa3\x15\xc6G(\xfc\x94.\ \xefHQ\xee\xa5\xff\x02T-\x12e&d\xdd\xe9\xfc\xb0\xd1\xd2;\xd8z0\x18\xa8\xbe\ \xd1\x19\xd2\xb1\x03\xe0k\xb9\xecs\x1e:\xf8e\x99\x92Z\xf3\xfb?i\xe4-\xeau\ \x15\xd9\x04\x84\xef\xc2\x04i:\t\xe3\xe1\x15\xccO\xe0\xe96/\x13\xdb8\xdeZ\ \xb3g\xb0\xba\x194\xcb\xf0|\xe0\xc6\x18\x86B\x16P\x08\x87c\xb7\xed"\xe3R\x9d\ \x11\xd9-\xf8.\x9cD\xc0\xb3\xdey{`[\x18U\xa4k\xb4\xbf\xe5@\xcc}\xfdd0\xf6\ \x9cs\x19)\xec\x03\x12S!\xa7\xf7\x85\t\xb0\x92:\xcap\x19\xa5?\x8a\x0e\xfb\ \xd5\xc3\xceh\xd6\xe8\xc2\xb3W\x8b\xf7\x98\x8d\xa2\xdf\xbfo\x7f\xbet`\x03\ \xd5\xa5\xfc\xb7H\x9e\x81{>\xa07&\x11\xf9 [\x15-\xbc\x1el\x0b\xcb\xa0R\xc5\ \xe5\xfe\x91o\\\xf6\xd6\x1b_\x15\x9e\xb2<\xa4\xb0\xd6\xb9SX\xaf\x0b\xe2p\xc8\ \x94)\x8c\xda\x9d\x0b\xf4\x86d\x88A%\xaa\x83\x1eU\x18m\xd6\x9d\x04r\xffR6\ \xfaa\xec\x1fx6\x19\xbe/}|\tZj\x8f69{^J=?N\x94\xae\xb4\x83\xaf@\xfb\xe5-\xd2\ 5\xb9T\xe7 \xc2+\xf2\xb0\xf5\xe0\xdc\xb9(\x93\x84{npf\xb1A\xe9 v\xc7\x12\xcb\ \x9f\xe3x\xdb\xad\xa2\xd1XqgI\xee\\\x99\x19\xdd\xef\x9a\xd9Y[!\xfaL\x16\xa7{\ QpW\xd1\x86\x85\x16\xfb?H?X2\x16\xa3\xd5\xf9^\xab\x19\xd6\x81*!\x03#\xed\x1b\ \xa9\xe3\xf3|";\xe9\xb9^\x85\xc3G\x19S6\xe6\x84\xcb\x8f),\xe3H/\xa8\xda\xb7\ \xd7\x9co[\xefq~y\x16\x04\xfe\xe3\x02\xdf\x8fg\xb5\xb3&\xe5\xbdI\xe3/\xa4u\ \x1fJz\x0b\xc1v\xb8p\xd8\x10\xebO^\xf5`\x04\xec+\xeb\xc8\xf6\xff\x01\x8b\xcd\ X\xb5\xd1\xdc\x040\xa5\xf1\xb7\xe9\xb2#\xa3Eb\xec\x93~\xf4C\x02)\xfb\x10%\ \xdea\x0bwi\x84\x7f8\x9eh\xee\x8b\x02q\xa5)\xd3v\xc4\xbd1\x92\xd7\xefWk\xa4G\ \xe7\x8e\x85\xf0Id2T\xcc\xf0m\x15\x01\xe2\n\xd5\x03\x80u<\xfa\x8d8+??\x91\ \xa4Z\x97\x97\xc1]\xf3s\x9d\x08\xdcj\xd9d\x89p\x06j\xdb\xe4:\xfe\xe6\x0e+\ \x19(\xc0\xb6o\xe0\xdc\x00\xae\xb4\xf7\x971\xa5\x05;r\xd3Q\x8c\xd0?\x06ui\ \xd2\xce\x02\x91\xbd\x13\xfa\x8ey\xef\x91\x8e\xe8\x96\xbf\xe9\xd1\xbb\x03OX;\ \xe6\xae\xa5\xe2\xac\x95\xda\x1aN\xf6 $\xb0\xb3\xdc\xf4\xa7\x91\xb1<\xa2\x13\ \xd0+\xe4\xe3\xfdm\xb6\x07\xcf[\xd6\xbc<\xd4\xbf}\xb4\xd3c\xe6\xcb\xbf\xd2\ \xfc*mv\xfc\x9d\xe52\xd0;\x9d\xc5vg\xc3\x88I\xf0\xaf\x8b\xa4\xc4\x10\x95\x83\ \x11\xbf\xee\xfc\xa4\x7f\xb8\x8b}\xd3=<\xae\x0b\x81\xb7\xce\x921j\xf3kY\\\ \xdc\xbf\\Ce,*Y\xa4\x82\xc3\x83\x04s\xbeo\xf8\xa9C\x10)w~\x07(Jl+#\xc6\xe3\n\ \xeb\xb7W;\xb3 P\xfda\xd1]j\xffH5B\xd4\x7f\xce\x12\xc2\xf8K\xbd(\x1a7ko\xc3R\ \x109\xde\xf6j\x8d\xc0\xe7\xf0\xe8\x0e\xad\xf9\x11\x88[\xed\xfd\xfe`|\xe8!V\ \x01\x88\xe2m\x03\xcf\xf1u\xb8\xe7D\x88\x88AL\xeb]A\xca\x7f\xee\xb7\xe7\x8d(\ 0\xa8AE\xe3\x16\xb5\xa9J\x85\\\x9c\xff\x82\xb4p\xfdo\xb7aR\xba\xb5{\x15\xc3\ \x82 z\x9d\x1d\xf6\x93\xefy>\x17[\xb1*o\xb8\xf8\xfe\ \x91\xf64\x19\xdfHk\xe8\xdd6\xae\x16\x91~\x19\x8eIY-`\xcb\xa52\x18!4\xf1\x8d\ \x0f\xa2X\xd9)\xf7\xde\xc9\xe4\xc10w\xb2\xfa\xf1\x9f\x14\n\xabK\x19\x9e\x03\ \x82b\'\x18\xe3\xf1jO\x9c\x9dZ\x9a\x9d-|}\xfb\xf6\x11\xaa\xda\x15\xda\xadS-\ \x84\xb0a\x17o&\xec\xa9\xf07`>\x82iJ\xcf\xbc\xca5\x8e|\xefYR\x97\xbf0\xf3$\ \x07\xfep\xdb\xc9f\xb9MWw@w\xd6\xef\x8b\xff\xda{g\x90\xe8\xe8g\x06\xd66_\xf2\ \xcb\x1e\xc0\x1f\xfe\xe2Q.\x82\x98R\xfb\xa4\x86\xd0\x8fS\x04\x95\x8f\xaa\x04\ r\xf5\xbd\r\xe1\xd6\xf2\xad\xf3\xbe}\xb4\xaf\xa5\xfa"\xe8\xf5R\xca\x17\xd09\ \x08\x02\xe9lz\xc78\xb0\xf9\x862\xad\x9am\xc7\x0b?Y\x8fYx\x9e\xfd\xed\x87\ \xc5\x10\xfc\xec\x9e)\xfa\xdam0z\xca\xf4\x97\xed\xf5\xc9\xe1$ln\x02=\xbd\xff\ 3\xc4\x99\xc5h\x83\x9f\xb4\xf3\x08\xaf}&a\x87\x05\xa4\x0b\tO\xden6G$\xfa\xc3\ \x9d\x83\xea\xa5\x0e\xe0\x91p\x08\xe8\xbc\xf0H|\xf7\x06.\xbe|\xb4W\x10\xe8\ \x83\xc5\xd5\xfb>\xb3t-k|^\xb8\x12R\x1b\x1d\xbf\xd5,\xdc.\xd0\xdb\n\x99j\xe0\ \xc3\x02\x13\xba\x8e\xed\xd3\x92b\x8eW\xe3R\x1a\x8aT(\x19\xaf:\xbe\xf2\xd9\ \x7f\xddq\xf8\xf5\x9c\x94j\xf4cz\x15\xdby\x83\xd4\x8e\x07\xac\x14\x1cR\x02\ \xf5\xef\xaeAt\xf4Pi\xf8\xfa\xbb{g\x88\x15\x99\x1fc\xb9\xb1\xc8\xd3Q\x91\xba\ \xd9Ck#\x89\x83\xdd\xaaG\xf5\x07y\xa8\xf6-On\xe5N\xc6*\xeba\xb5\xe70V\xfa\ \x14\xa0\x84\xf6\rD\xc9Z\x9f\xf8\xb1Ap\x1e\xd6\xf1\xdc+!\x89(K\x9cRx\xf1\ni\ \xf0S\xe1\x1b\xf4y\x8cP\x0f\x1e\x0bc\x84\xb61\x05l\x9fD\xffd\xd5s\xdb\xe1\ \xd5\x13\xf1f;\xe2\x9c\xcdkg\xab\xa4$\x8d\xb1Fh\xf6\x89\xd6H\x0cK\xaeg\xd0:X\ \xf8\x1a\x04\xfd\x0e^\x85W]\t\xfa\xba\xe2\xb5\xcb\x045\xb5}P\x0f\xc8E\x0b\ \x93\x91\xf7j\xc8\xef8*]#O^\xa0MX\xfa\xfd\xf2\x88\xb5\x19\xe9g\xa8\xf8\xa3\ \x80\x13r\xabdHj\xb8\xdc\\\xdc*\xc6\x7f!6\xb0\x9cD\xc0)^\xc0\x97\ \xf6\xbe\xd9\xcc\xff\xb9\x9b\tQ\x0c\xda\xd8\xab\xdd\xcfQ\xe0\xee\xac\xb9\x9f\ \xa3>\x91p\xf8\x15>\xc0\x02\n\xf8\x07{\xd4\xa5\xf4\x99\x1e\xec!V"\xb7\x8a\t.\ |\xc0\xf5v\xfd\xd3\x1eJR\x96\x99#Jf\xa2\xcdCm\xb3=}\x03~\xfe\xa2/Z\x1bn\x9b\ \xc8\xf6@Z\xf7\x0e#2\x06\x95\x05\x1c\x93t\xed\xf7\x8e\x17\xf1\xfbf6\x95\x07\ \xa8\x8bvPwz\xd3\x1e\xd4u\x91\xdb\xfa\xf6\x7f\x97]\x1c\xd5\xb27\x89\xc6\xbf:\ \xab!7\x95.!\x002\'\x17\xff:\xa6\xb1\x9fb\x17\xb55\xa4\xb5zBX3\xf4sK\xaa\x1c\ \xbe\x88\xffy\xb8KC\x7f\xd8\xbc,s\xf2\x97\xb85\x8c~\x84\x80\x8a\xb0\x9c\xfa \ \x01\xf4\x9e\x06w_\x97\x0f\x84FZ|V\x87\xff\x0bKr\x86YE\xd6\xe5\xc6X\xdcFE\ \x9eC\xfd\x14-\xbd6oMA$\xd9\xdb+zS\x96\x98\xe0\xbbf\xb6\x1eJJ\xfeq4\x17a\xd3\ \xc0,\n\xbfOD\xb3\xa1[w\x82\xf0\xfc\xda\xcf\xbd\xd2#x\xb4\x85\x82\x93W\\\x06\ \xb9\x84\t\xc6R\rS\x03[G\xe6a\xe9\xbe\xefu\xf8\xbc\x7fI%\x16ZM;.\x89\xd4\xf8\ \xa8\x8c\xad\xc0^\xc7\xb9\xc9\xcf\x05T\xe2U=O\xdf\x9b\x0e0\xf0U\x05\xd9\xf4\ \xbe\x81\xcf\xf9\xd8\xee\xfd\xfczX_\x8c o\x95\xcf\xaf\x07m\x13\x0f\xd7\x18"\ \xa7\xf7\xad\xa3\xfc\x80\x1f\xf9&pL/;z\xcc#&aa\xfe\x91K\xa8\x99y\xde\tR\xec\ \xab\x14\x05\x12\xe4\x9d\xd2\xe4%\x1d\xef*\xa3\xca\xb0\xcd\x16\x13\xee\xc5\ \x93\xda\xd8\x16\xf6\x1c0\xe8E1\xcc?\xc8C\xfa\xa1\xa5;\x93\x84\xf17Y\x12\xfe\ \xd6\x16O\x11"d\x04S\xa3\xfcId\x05\xe6\xa1o\x8csv7p*S\xc9R~J\xbaz4\xf5\x85\ \xa7=0\x94\xd0\x92\x80\x07k\xc84\xe8\xf0?\xb5\xd4\x19F\xff*\xcd\xb2\xd5%:=\ \xb6\xb7\xe9\x9f\x9fS\xae[\xfc9h)\x91D-\x19\x12\x8c\xb1;]lQ\xfa];G\xe2x\x80\ \xa1\xd8\x92\xfa\xd1\x81.)\xc2+=c9\x87W\xd9,B\xd0\xd9\xa8kx]\x8a^\xb5-\xbb\ \x80F\xaf\x90\x0b\xb7\x1a\xa9\xfe\xb9\xfd\x87Z\x98\x17\xe4\x89%\xb3\x02I\x91\ (\x7f8i\x05[\xa7\xc1\x19\xab\xc1\x12\x9b\xf6\x19\xf3\x1e\x90\x08\x98\xa7\xc1\ \\\xe52_\xe54\x07$\x17\xf0hJs\xfe\xa0\x0f.\x80t\rk\xf7\xdb\x1c\x05a\xe2_\xbf\ \xf1\xe5\xdc\xae\x9b\x89uf\xfa\xec6\xb2J|\x9b\xe2\xe0\x05~.\x81\xeb\xc1\x81E\ \xcfN\xfe\x86\xf2\x0e\xd7\xf7tM:DM\xd4\xa0\x80\xee\xe8\xb77\xfb\x03\xc7]\x80\ \xb5\xeb\x97?9\xe5\xb9\xdf\xdb\xd9\xc7,1%\xcb~t\xe0\xeftR\x94\xc8\x91w\xabf"\ \\\x0c-\x83\xbc\xea\x82\x061f,WZ\xd46 \x93\x96\n\xcd\x16\xbe=\xefM\xad\x0c\ \xd0>kZ\xbew6\t\xc6o\xd2\xfb\xcf\x8b\xf2fz\x1e\xd7dG\xcai+O7\x0e_\x0f&\x02\ \xd1l,\x1d1f9\x04YE2Cw\x08\xee\xf2\xbe\xac\xaa\xf7W_\x8eS[\x8d\xb8\x98._\x94\ \xd1\x9f\xc0\x08K\xdb\xcc$2\xe4SR<\xae\x8f\x9eYJy\xafqZp\x9e\xc2\xd3~\xc1\ \xc3\xa4\xec0B\xfe.`XX*{\xb7\xd2jE\xd5\x08\x85\x8e\xcd\xab8\x11\x12r\x1a,\ \x91@\xd1\xa1a\xec\x9f)ZM3\x10\x8e\x08Mten\x1bE}\xc6\xb1\x1a=F\xf9\xd7\xac\ \x8f\x94*9\xb5+\xa3\xda&\x1a\x9a\xfe\xfdl\xba\xde\xcb\x0c|RXy\xf6i\x91.\x0e\ \xb8\xfa\xf9\x05&-G\x19\xc0_\xe3\xee\xa1[!\xa81\x9a\x16\x7f\xaf\xea{.O;\x95Q\ \xa2;C\x03\x8a\'\xcb\x18Y\xd5!\x85v\x8f\r\x0e_k\xb0\xff8\x15.\xb6\xfc\xdd$Yo\ D\x0b\x1dy$4\x1a$\xdd\xe2\xae\xfe\xec?~\x9f\xe8%\xcd\xce\xad\x0c\xe3\xae$Z}\ \xf0\x96!\xec\xf53\xc3\xbe7\x10\xc9\xd4\xb8v[\x8f\xce:\x93Y\xa7$e\xfc]\xe3\ \x93\xa3h\x11y\xd7\x91,\x99\xf04\xa3\xa7\xe5z1\xcb\x95\xe2\xb3\t\x826U\x96`\ \xd2{7\x1c\\\xd1R>\x08cz\x97\xdd\x97\xdf\xe7\xe9>\x03\x894\xde\x1e\xafi{B\ \xc8L\x00\xef\xdc\xe2^jz\xb3\xa1%\xc0q\xf7=i\xea=\xe8Y#\xb2$\xb1\x8e;\xdf\ \x9d\x02\x1a\x85\xd2F\xb8\xa8\t\xc9\xf9o\'\x1a?\xe8D\xeb\xce\x96DB\x03P\xe7\ \nk\xbf\x17\xba&\xbd+\x1d\xf9-O\xefM\x94\x00\xb5\xfdg!\x1b\xc0\x81ce\xfc\xf2\ \x13\x8b\xf6\x9c\xf7\x96L\xe6N\xcf\x93\x1f]Xs\xff\xae%d\xa7\xe12O"\x0bX\x82K\ ]8G\x0c#\x07\xb0\xb7\x850\'ar\xb2(\xe6rjz\xfe\xa2J\xc3^zR\x1d\x18~\xa6&\xd4\ \xc1\xa9\xcf\xee\xc3;\x0cr;\x1e\x87\xf7\xab\x92\x15o\x82J\x8a\x01\xdabt\x18\ \x85\x13\xc6\xcd\xa6\x1c)\xde\xf6\x8e)q\xafc\xc0v\xbbpr\xa3\x05\xb3g\x98\r>\ \xf9C\x11o\xfa\xa2\xd9Y\x95\x1dt\xb5\x0fI\x9a\xeeb\x7f\x86\x83\xb6\xf3\xc2_b\ \xbd\xf5n\xdbK\xf9\xdbtI\xf5\x1f\'\x97\xdc\xe4\xdd\xa7\xdc\xa3[\xe7\xeb=\xe8\ \xf8\x163\xf9\xbf[\x81\xdd\xefO\x87\xf4\x01`t\xea\x9a\xce\x06\x8c\xbae\xef\ \x93\xe0N\xc6\x06\x1b$\x0frF\xac\xdc\xaf\xd3\xf0\xe3\xc5y\x8e\xcdb\xf2\x8d1b\ \xa1\x7f\xf7\xdc\x19O\xf5\x12\x9f\xd1\xbbk\x80\x03\x12l\xe7\xfb7\xfbx\x8e\ \x1d\xed\xdan\x9dRm\x02\x7f\x03\x15\x9f\x1fTf>\xcdr\xa2IS\xeft\x07\x94p13\t\ \xa6\xec\x83\xc1a\xefW\xf1\xe9a\xdd\xef\xb2\x9f\x95I\xa5\xca\x85\xf0Z\xf5\ \xba\x85$\x0e\x86\xdc\x91\xcaF\x1e\xa3[~\xd03\xc18)]L\xb9el\x0f)F\xe6y\'v\ \xb9\xce\xf21\xb6\xdbV\xda\x12\x03\xebr\x07\x83\x83\xe8\x07?\x1b\x8c\xbf-;\ \x89\x97\xfd\xe0\x18\xa2!\xde\x84/\x9c\x8d*5\x8c\x00\xab\x96F\xc2\xbe3\xc4\ \x10\xbaC\x8b\x0c\x12h\xd1$,\x95\xeb\x7f\xda\x07\xbe\xd4\x85\x8e\x08\xc6{\ \xa3p\x16\x7fC\xa6ne\x9al\xb3\x90u\x7fh6\xaaeK\x19\xafM\x8b\xf1%\x93\xa9\xc2Q\x1a\x8a\x81\x05\x06\x9e\x0e~G`qt\x83\ \xb8j/>/\xcfZ\xe63"7mN"\xd6\xe0\xd5\xbc}\xda\xd4\xd4\x8e\xda\x1a\xa5"\xc7\t"\ \xb4\x82\x0c"b\x9b\xbf\xf4\xe2\xa5\xd9\xb9M#*\xdd\x1d\xd8%]\x1e7q\x9c\xc7\ \xc6\x8bd2\xe8\x9a\xa9\xf2\x1e\xbdzau\xf7\xd9\xa3Z\xb7\xd6\x95E\xb5mO\x14(\ \xa8\xces\xf0\xd7RV\x08\x99\xc3\x01\n&ziL\x14%\xbe\xee\x956\xc8\xdb\x8f\xeb}\ \xd5\xfdO\xf7Y4$E5)}\xac\xa3$\x8fcA\xd6\xe0XZ\xa0\x98;\x92\xba5d\x9c\x95|\ \x8c\xd3\xb3h\xe7\r\x1c\x1b\x02\xe4:\x89\xb4\x9bF\xef.0\x91\xe8{5\xa7\xba{\ \xc57O\x80\xef\t\xda\xed\xf0w\x19\xc7\x81J\x0b:\xb4x;\x8d\x1a\xd6\xef\xb2\ \xc6*$\xbf\xb8;\x94\xf1~"[KxZ\xc2\x85k\xf7]A\xad5\xe2\x8a\xedz1G\x95N\x8c; e\ \xb4\xad\xdd}\xcd\xaf):)/s\xd3\xd3O\xcaT8\xa7\xb7\x98\xf9\x85-;\x19U\xb6|\ \xb0\xa7\x1e@\x1c\xdf\xfdF\xa8\xe1\x97M\xcfkC^\xa1g>\xac\x04\xcc\xf4p\x84~T\ \x03\xca\xca\xc6\x0e;z5^K\xb2\x88\x04\xeec\xebvV\xab\xab\xa4D\x9cb\xc9\xd9\ \xcd\xf7\x80f;\xbd)\xe2\xc2\xd1\xa1\xfe$\xb0\x99\xe9\xe0L\x92\xa4\xb3\x18\ \x1f\xc7\x88\xff\x87eZQ\x036\x1f\x84\xdc5Y8\x11n]\xfe\xf7\xa9\x11s.\xf3g\xf7\ \xda\x90\x88\xd1+\x7f\rZ\xdef\xd7\x1c\x05\xbbY\xdb\x8f\x15\xa2#\xd2\xdd\xdb\ \x00\x98\xa0\xa0#]dN\xa1\xda\x8c\x1a\x95\xcd\x83\xc0\xd7\xb5\xa0\xf3\xad\xf8\ \xd3;\xc0\xa6U\xc9\x88\xdbh\t\x8a6\xbf\x1a_O\xe5\x882\xe8\x1d(\x8c\xfer\xc9\ \x0b\x95\x1e\xe4G\x8a\x1f\xd8\xb4\xd0\xfd\xb2JS\xf7\xc7\xce\x85\xddC\x8eu3P\ \x0c\x89r\xe3\xda\x04\x9e\xadv\xa3/\x1e\xd4\x195%>\x1b\x98\xbf\xe2\x15\xfd|+\ \x92\x0f\x1a\x0f\n\xec\x15\xe9\xbb\xc4 \xfdwl\x157{\xb3\xfe\xbc\xb29\xf1\xd9\ \x90\xe3\x8c\xf5\x99\xf8\x95\xf0\x87\xe2\xbb\xbf,\xf5RU\xe8i;#\xec"\xb6\x85-\ \xadw\xa8\x11\xdeo\x1abW\x95p\x90W@\x81n\xd7\xb5\n\x83\xcau\xd8\xaf\x10|\x1b\ _\xd7\xb03:P\x07\xeeG\xda\xb4t#p\x08%\xb8\xe9\xfef.\xca\xfc\xbb\x10\x1c\xd9\ \x17\xef\x98;\xd85>\x81=\x9b\x06\xfb\xa6\xe9\xef\xef\xca\x89\xd2\xeb\x8c)\ \x84\x87\xa2\xf4M\xe3\xfcx\xba\xa5\xe5u\xd5HE\x83)\xe64\xff\x87\xdd6\xd3\xc9\ \x92$\xaf\xd0r\x05\x16\xa4\x18YV \xf4\x80]\xde\xd2\x16\x06\xc3\xdf\xe1[\xa4\ \x8b\xa5\xe1\xbbs\x9b\xdf\x13v\x90\xc0\xd4Nf\xe6\'\x17\xae\x97\xa5\x0e\xcb\ \xa8)b\xe8j\xe7\x1f1\xfc\xc1\x85\xbb\x94\x08\xa9\xb8t\xe5oN\xafW\x08Q\xcbFu\ \xbau"\xb5\xd7\xce5\x17\xb2\xe3\x158c\x15\xea\xad\xa7\x95C\x96o\xa6,\xbbA\ \x86}F\xdcgtL4yMe\xf8\x17Mu5C\xfe\xf3#\xf9\xe7\xef\xa14Z\x8a;a\x8bMG\xde\x9d\ \xc1\x01\xc4)\xd1\x0e3\x95\x97\xfe\xa7\xabM\x8f\xcffk+W\xf1\x9c9\xe8\x91\xeb\ I8\x8e\x01g\x82\xc8l"\xe1\x13\x0b\xca\xa15\xc4\x1c\xc3D\xda\xd7\xe1\xd1\xb2\ \x93*{\xe1A+cw\xbb\xdfp\xcci\xaf\xd7:\xd9\xb6+\xf7\x87\xf5/6\x1e\xabs/19\xe4\ \xa4k{\x820\x83\x9e\x1f\xf1\x0c\x1f\xb7i\xabI\xb8\xf1\xf4\x05\x13\x89\xc9\ \xf8\xc3\xab\xd2\x94v\xef\xdf5g\xb6\x8f\x198\x19X\xc4e\x15\xbc\xffs\x12\xbc\ \xdfp#\\\x04\x1b\xac_\xde\xf8}\xf5\xd4n\xb7\\A=\x7f\x19\xff\x8f\x19\xdc}>{\t\ \xbcn\xbb\xe8^f-k\x99\x19\xe8\xcd\xdf\x14\xf7\xcbN\x9d\x91jx\xb9\x88\xd3 \ \x97\xb8\x14k\xf1\xf6\xf3\xa2\xbc~\x15\x86\x0e\xf4z\xd8$\x88\xa1\xc4\x07\x89\ \xe4\xbbi\xe2^\x97\x90\xf5\x1e\xe4\xf1<\xc2"F\x03R,\x92\xb9v\xbd\xb7\xea\xd2\ \x81\xfa\x1b\xe3\\Fo<`4\xbc\xb4M\xf6X\x81%\xd6\xdd_@\xee;\x07\xde\xe9\xe7Y\ \xb0\x05\xe4I\xfe<\xe0\xd1t\xc2s\xc1\xe4T\x95\xd4V\xe5\xcc\xf6\xb7i\x10v~O`\ \n\x18\x92\x0b\xb7U\xa1\x97\xfaj\xf8\x06~d\xee*\xce 3|\t\xf3\xebM\xbb\xdbf0\ \xabFiG\x18)&\x98\x9f!R\x99\x98r\x19\xc2-\xc1J\xce\xfc\xc1\xc1\x81\xd0ON\xb9\ \x92\xcb\xdb\t\xfe\x9b\x05\xa8W\xf72\xe6\x9b\x93|\x0e\xf6\x05L\xea\x89\x12\ \xf9\x90$u\xd9\x8ci\xc5\xb1}P\x8c+C\xcc\x90\x11\xf8,-\xd6?)\xd1\x13\x8b\xeb\ \x89\xac\xf7\xa9\xeeh1\xc0\xadM\n\xc6N\xc6\xbe\x01\xd5B\x16\xec\xde\x1f\xdd\ \xcd#};`%\x95\xd1>8\xfd\xcf\xc6\xb6&\x11\xd0:\xa2\x9f\xe1\x90iUT\x91\xbc\xe3\ i^\x847%\xc6+*\x94\xcd\xeb\xeaX\x1b$\x8cW\x19\x12\x11\xf8\xda\x9f_\x97\xd8r\ \xa7\x11\xb3\xe3\xff\xcc\x95\x08\xa2q\xb7\xde^\xcc\t\xc3V\xe1\xfb\xa5!\x8d"\ \xab8`exS{O\r7\xd5m\xc8\x1c\xcc\xfd\xa2\x10QhGM\x8b@\xdcQ7 \x8e\x05\xe3A\xd9\ \xea\x01\x1en\x10\xd7\xa0\xcb\x05\x17\xa6\xd6\x17\xa5\x14\xb3D\xe2\x02Nq\xb7\ \x89E\xa8$\xf8F\xbcT\x8c\xc1\xeap\x85;\xa2\\\x88"5\xa5^A$\x03K\xae{\xc3L\xda\ ]\x94\x91/\x15\xc7\x82oW\xb4\xc2|\xe5\xd5z\x9a\x1b\xe2\x12z\xf8\xf8,3\x88b+\ \xf9\x83\x07{d*\xe7\xc6@;\x99u\x04\xf0\xa1S\x9a\xcb\xae\xc4aB\xee\x9e\x0fr\ \xeb\xf0X\xb3\xe5\xa4\xf9\x02\x92z\xb7O\n\x92\xa1\x98=H\xca\x92\xb5\xa7;%\ \xa6\xd9\xfb\xfceX@\x9d7e\xf3\xe6=\xa09\x9d-\x97+\xd5\xc2(\xf7\x00\xef\x02\ \xa5\x97/\xfc/\x1c\xd7\xec\xc6#\xb7\x03\x1a\x9e\xb2r\xba\xb50\xf3\xb5\x04y\ \x81\x9a\x83\xfbC\xe1\xa2|s\x8d\xe1\xa3\xa0ft7\xc4\xef\x06\xd5\x06\xd7\xddgf\ \x7f\xb8-=)\tw\xb4\xce1p\xb9{&<\xe8\xef\xec\xbc]i\xfd\x0e\xed\xfe\xc3Gb\x03\ \x11\xb3\x1f\xd6f[\x9d\xafU\xd2]\xfbk\x9a\x1e\xb7\x86\x03\xf4]f\xfd\x191x\ \x9a\xf6\xc9,\x02\x9f\xc1\xc7\x9awk\xfa\x1b\xb3C\xef\xf4\x85(\xed\xf8\x1fQFv\ \xcaQ\xb8;a\x88\xb0\x04G\xeb~%\xfc\xac\x86\x96\xf1\x9f\x99\\F\n\x12S\xca\xa5\ \xb0\x9f\x1e\xc6t\xf6\xa4\xcd\xc3\x11\xef\xc6hH\x9b\xcf\x17\xe5)!\xf6\xe3\ \x1f\xad\xde!\xa66%\xdc\x91_\xf7\xfc\xf0\x8ebQ\xba\r\xc2\xc7\x83\xb2\xecr\ \xaaN\x16\x85\xd4\xbb\x01tGO\xa9\xc9\xe6\xb5\xcf\x8b\xcb\x12\x90\xb1\xe8U\ \xf1\x96\xfaO\x9c8\xa4\x18\xb3\xab\x90\xe3O\x01q\xcd\xc8M8\x8aYQ5\xa3\x13\ \x8d\xe2(\x97\r\x13\xfb\xd7\x0f\xc16Y\xa7\x9d\xec\xcf\xedK4e\x87\xed4p\x8c\ \xe0\xc8\xacS\xdc\xac\x17\xa7\xcf\xdb\x08\xcdR\xf22YX\x8f`\xa5~$hs\x96\xfbN~\ \r\xf2%\xfb\x9du\x9f\xe1\xae\xfb\x8a\xd1\xd4\x1e\x93gUM6\xcd\xf8|\x80\xa4\ \xfe$2>\r\x81\x11\xad$\x1e;\xdf\x84\xcfA.\xb8=\xa7\x8dD)\x8a7cW\xb0m\xcfl\ \xed\xa4\xfdH\xaf\xc4\xff0U\xe1\xef\xcd\x13G\x9cCU\xd1\x895J\xdd\xab)\xf7#\ \xbc\xc8\xff\xfd\x17 \xda\x8f\xd0\xe4T\xba\xd4\xd0\x8f4a\x1c\xb0\x8b[\t\xf6R\ \x88%\xf7U\xae\xec^\x1e\x07\xa4\xa3\'d\x10)\xbc-\xb8\'q\x9a\xb2g\xa5\xbc>r\ \xab\xd9\x8e\'\x8d\x95_\xe7x\xd5\x9c8\xbbi\xc6\x96\x95V\xa7\xde\xcc:,\xb0|\ \xddbg\xa4\xab\x03t$W\x00\xb9\x9c3R]\xee\t\x15\xae+\x84\x97\xc4\xf5B~=\xc1d\ \x1e|\x99\x95\x8b\x83\x90\nBrN\x1f\xf8\xb3|\xd5;\xce\x944rq\x94\'\xbf\xb3t\ \xee\x839i\xa7\xc6\xf7\x1a\x9df\xe98X\xc2v:v\xbd\xafN\xdf\x89\x9a\xcd\xa2\ \xf1\x00?\xee1\xb52&n\xc8\x02\x833\xa6B\xff\xa0\xd8\x19\xcb\xc7\xd2\x1c\xee\ \xd8\x0c\x99\xd3\xb8\xeeYQ\xb5]\xa9\x8eSH\x8c\x91\'\xf3\x92\xc1\xceY\xa2\x07\ h-\xfa\x92\x97\xb3%\x8c\xd5|b\x83b-\xe1\xab\x1e\x16\x1c\xc5\x815\xa88\xb1\ \xa9P\x12\xd76\xbb\x85\xea&9!\x11\xe6\xdd\xfc\xa2\xc9S\xa7c\xc5\x14,\x8f\xb7\ u\tk\x02F\x16\x8b8W\xb2]\xb6PI\xbe\xbe)\t\x04\x92\xe58\x9d\xdfs\x13\xbb-\x1e\ \xfe]/\xf2\xb6\x1d\xb0\xb8z\xb0\xef\xa3\xdaz\x9e\xb0M\xb0\x18V+\x90\x92Gm\ \xbe\xf7\x05\xd1\xb5\x95\xcf\x1a8\x1c\xd3\xf6\x86}\rY\xac7\'\xd7l\xf7\xca\ \xca\xa4\xf6\x19\xa9\xdd\x90\xd8\x12\x9b\xe9\x9e>\xdf[\x81\xd4\xba\xd6A&\x1b\ \x1cZ^\x9eZ1\xb4o[2\xf5}\x0f\x05{\xdc\xf3\xa1\xed\xd2c\x85\xc8\xf2\x0e6\xac<\ \xe7@\xe5\x11\x81\xfaI\xae\xa0\xb5N\xa1\xdeM\x97c\x17\xc5\xfc\x84O?\xf7\xd0\ \x9b\xa3#y\\\xafU\xd28\xbc<0S\xc3\xb3m\xca\x8f~/W\n\xc6<\x82\xb0\xfd\xebXjf_\ \xb3\xab\xbd\xffk\xdcy\xdc8\xa8{\x9aN\xa7\xce\xdc\xe5\xa2)=\xc7\x94\x9b\x8e+\ \xbb\x93$\xce\xad\xe0LMN!\x96\xcaq=\xfa\x92\x95<\xd9\xb4i\x80\xc9\xa9]/Bm\ \xc58z\x98\xebu.,\\\xf6.\x04&S9\xdb\xaa\x9e\xa4m\xb8b\xe2\xf2\xd9\xa9\x82\ \xec\xd6\xff"{\xe0\xd3?\x82\x89\xa3\xec\xe1\n\xf4\x87>p\xbf}(l\xa9\xcc\x05`\ \xc4\xcd{\x94C\xebU\xc1\xaf00\xa5\xdd\x0f\xb9\xff\x87\x8f\x93\xd0\xe3\xed/\ \xaa\x10@\x9ddP\xb3\xa7\x17>\xb0\xe5\xc61ib]?\x87\xd0\xa0yt\xd9\xb8T\x15eqf\ \x19\xb9\xee\n\x9d,\xd4N@\xdd&M\xeb\xaa\x8byX\x81\xb9Wcd\xdb\x95\x15\x04Q\ \xbf2\x108U\xb6a\xc5.g\x9f\xb4\xa6X7\xdc\xaa]\xf7q\x12\xcf\x8d\xfff\xc7\xfa\ \xb3\'\xc7\xa9\xd3\x86\xc8f\xfc\x04q\x93U\x81\x8d\x05\xbcAMSQW\xe1\xb4\xe1\ \x85\xa1"\xf2\xd4,\xdf\x05\x8d\xda\xd2\xc8X>S\xbfo\x7f\xf1\xc4\x12;\xe4h\xd6\ \xa3-\x80\x03\x1d\xab\xf4\xb5\xd3\x00\x84\x14F\xe0\x9bS\xc0\xc5\xd0\xe5"\xd4\ E0\x8d\xa0|f\xb3\xf5\xf7N7\xc6\x12\x16\xfb\xd0\x9c\xc3o\xdf{\xe6\xc32\xa4\x8b\xe2\xdc\x92i\xad\xda\xe9\xc1|\x8d\xce\ t\x85i\xcds?]\t\xfc\xee\x86`\'8\xafWW*\x8bH\x05\x9d\x97\xe1q\x1c\xc5Ic\xb0\ \xdeu\x82\x85\xf7\xd1\xbd\xdfJ\xfd\xe4\xb5_\x1d[B\x05\xbd\x13\x8d\x97/\x91\ \xf8O\xe83\xe5(\x8c(}\x8f\xe8\xa4TN3#\x16\xaf\xd7\xc6\xa0\xd4\xbf{\xc2\xf129\ +\xa1%\xcb\xef\x146\xef\xa3e\x1b\xa3Z\x1e\xd4\xed\xd1N\x97\xfb\xc9\x19]\xf4\ \xe1\xa3\x8e\xfe\xe9r\xd1\xae\xed\xbb<\x87n\x8b^xWO\x83z\xb0\xe7<\xb43\x92\ \xf14\x8d\xe1M\xd6\\\x07\xf0\xeb9\xa42\x07QX\x8b\xcd\xe7\xc9\xd39/`Ks\x06o\ \x82\xd2\xa2\xa6\xf4\x89\xdes\x8a\xebuS\xd3kq\xc4\xaf\xb9\xc7\xe6\x8b\xc87\ \xd4\x9f\x16\x1e%\x8b\x14`\x9a-\'\x9a\xef4\x9c9W\xc8+4\xc8;j\xde\x7f\xd6Z\ \x90d\x0c\xba\xe7#R\xea\xf3\xf0\xff\x00\x1e\x17\x17\x14\xfe\x04\x00\xcb\xac+\ \xea\x8a:kp\xcb\xdc\x9c\xe1\xe9Z\xc9\x1d\xbe\xb7\xaeU]\x1ah*\'U\xe4\x14\xbf\ \xfa\xa4m<\x8ai\xaf\xb5h\xb7\xf4N\xce\x97L>\xbe\xdc\xaah\x00\x15\xd3\xfa\xd6\ |^s\x9fag\xbf\x88\x9d\xbd\xb7\'\xddI3iU\xeb\xc8J\xf8 \xa2w&\x13G\xa7_y\xde\ \xce\x04:\xb9\x9d\x9fP\xda\xaa4\xbb\xd8:\xc1\xa6\xa1\x13w\xd00\xe4d\x93L\nh\ \xe4\x89\x9dv\xb4Y:/\x1cjZ(rs\xec^\xd1V\xea\xf1?\xd2\x1b\xf2\xc5\x97\xa09\ \xe3\xd5\xefi]\xeb\xf4\xb6\xe5\xec\xe4\xa8\xf7\xdc\xc1[\xe0\x80\xbe\xe3(\xa8\ z"\xe3\xa2\x81\t$\x87\xf7i\x87\x08\xd6\xc3"\xef\t\x1a\x99\xe5\xc68\xbb\xaeO7\ \x14\x85\x98\xe2!\xdd\x81\x0c\xca\x15\xb0:\xf5\xd7\x7f\xb4\xf08\xbb\x7f#`\ \xc2\xce\xbe\xa8!\xfdy>\xad\x1d|1^\xedx\xd9I\xd383\xd4\xea\xe7\xc3?\xd8=j\ \xb2\xe7BI\xa6\xcf\xca\x95\x1b~\x1b\xdb\r#\xb2M\xa5\xbb\xab\xab\xce\x1bl-ZTd\ \x9b\xa2\xe6\xd1;H\xeee\xc8\xa3X\xbe\x0cx\x0eb\xdb\ny\xdf\x18=\x0eQ\x8a(\x94\ \x05-|\xfd\xafi\xe7q4Y\xe03\x1a\x8cO\xf2|\xfbI\xb0\x94`\xc0i\xefq\xc3_\xbe\ \xfa\x86$\x8c\xf7\xfa|\xb6u\xfel5?\xe2\x95\xdb~\x86\xd4\xc9\xee\n\xf9\x15\ \xc8\x89\x9e\x95\x8b\xb9\x1b\xda\xae\x95\xe5\xce\x91\x07\xe0^ %\xc6\x07Z%7\ \x1fb%\xb4\xfcv\xfd]\xf6\xf2\xae\xb4\xadB\x01\xffB\x189>\x9a\xda\x93\xbe\xb6\ \x19\x04u\xabzfiMH\x07\xe4T\xee\xa07\xadI\xc0\xfb\r\xa3N\xee\xcf4\x16\xbc\ \x93\x15\x1d\xda)\x9f\xb7\xb5\x82\x9d\xd8ai\xa1s\xb0\xf7\xd6\xfde\xa3#\xd7\ \xd0\xee\xf3"!\xf5A\xaf\x9f\x8a\xf6\xed\x9fA\x8f|X\xd9\x10w\xfcz\xbe/Y\xe0\ \xa4,\x81\x97\xde6\x17Z\xd8\xc2\xd9F\t\x9b\xe0\x90V\xdc\xdaoxd\x11\x86\xd1!\ \x9b\xa0G\x8a\xe5\xf7{\xac\xc0\x8bY\xa6\x06\xf7\x9b+\xdbk\xe6\x8c#\xefm\xce\xe3-g\x89:k\xb2\x19\xef\ \x1e\xea[;\x85o\x1a\xa0)\x0b\xa9y\xf7\x8d\x07\x00\xf7\x03\xaf\xb1\xd4\xd4\ \xc6\xc7\xa6\xe9\x18\xbe\xc5\xfe\r\x95\x9c\xe2\xb0DE\xa0\xfa)V\xdc\x00\x88\ \x1a\\k}pr\x0e%\xb7V\xf7\x8a>\xd5\xb4\xb5@4]\xe5\x8cG\xd1\xc2j.:RK\xde\xa9\ \x00:\x0f\xaf}]\xcf\xd5\xe5\x1b]qA\x98\xfd{?#\xcc\xe4\xd9\xff\xb3\x0f\x11\ \x976\x9a\x9b`\x80\xb1\x03)\x94\x05\xc4Z\x19\xdfZn\x1b\t;\xa6\xc2\xd0\x0b\ \xbe\xaa\xe3\xb9\xbe\xee\r\x9c\x98}?\xb9\x14f\x16\xf71~\x98+y\xdb\xf7g\xba\ \xe3\xb9\x1cE\x14\xb9\xcd>\x8fV-\xd2\xfb{\t\x9c\x16|\xcd\xf9\x0f\x8ea8\xa0EV\ \xf0zB,\xcfg\x9f\xbc\xb9\r\x90\xde}Y\xdb\x0b0*#w~\xc7H%z~,\x83\xc3\xe2\xff)\ \xa2\xed\xd5\xaa\xedB\xb4\xda\xf7\xe7 Os\xcd\xd2dc&\xf9&\xe0\xab9\xa1\xe1\ \xcb=+\xc8\xdb\x82\'\x19\xdd{\x1e\x0eQ7ja\xdea\xb77\xef\xb9\xcdv\xb50\xf7\ \x04\xb1~\x06\x8f\xa9N\xa4K\x03\x88\x8b~1\xe3\xe4y\xfd\xd1\x9e\x95z\x9d.\x99\ \xa0\xef\xed\xc0\xcd\x97g\xe0\xf7\xe3QL\x99|\x0e\xb6\xad\x03\xf5\xf7\x01\x82\ ;\xcd\xaa\x91\xa4\xe0\x86o\xe1\xe9\xcbv\xf5!{\xfb\xb5\xee\xd2\x0f\xe0\xce4|i\ \xb1\n1\x1a\x12%99\x89\x1f\xe7\x92\x99q_3g\xbe\x1e)^\xd6$\x93\xf2\xf5\x04{B)\ sE\x88I\xcaD\xcbV_\xbc\xe6\x07\x9c\xd0\x812}\x1e\xa7\x0c\x019\x0b\xd5}|\xfb\ \xddic\x81*\x05\x19\xef\xe7B\xf6O\xd2\xc6L\x82X\xa7\xc4}\xd6\xd7A\xde\x13\ \xd5\xd8cHI\xcfF\xed\x92\r\x19?o\xe1\x11y]\xc9\xbb\xf4u\xb4\x92\xb3\x9d\xbdi\ \xc16y[\xd7\x17xK\xbf\xfbO\x8a\xcbU\xcc\x98XUg\x89O\xba.\xac/v\xb4\xbc\\\xde\ \x98J*m\xa4\x05\x14W\xaany\xab$\x1b&\xa2S\xcf\xa9\x82\'\x1a\x97\xd2\x1c)\x0b\ \xa8\xba\xc2\xf1!Y\x17K\x86tF\xef3\xb49D\xe3\x82\x0e\x99\x9c-R\x8d\x95\xeaU3\ }\x04\xd70\xac\x19_\x03\xf70\xdfz|\xb3\x07\x9b\xfa\x94\xb8\xa1;\xb5\xe4\xd3\ \x84\xa4\xe3\xac\xad<\x93\xa1\xc6(\xa8\x002_\x1a\xb1D\xd3\xff0$\xf8\xe9v\xe8\ x\xd11\x90\x0c\xea\x8e\xc8\xdd\xdc\x14\xb5g8\x81\x18\x7f|3\x1cY\x10\xb8\x80H\ O"\xb7\xb9{\xb8\x9e\xfc\x06\xa8\x9bZ\x8aQ(\xb0=c\x15\xd6A\xbc>\xd1\x07^\xccG\ t&\xc2S.1\xb63\x06\x00\x1a\xa8C\xef\xd7\xfc\xef\x1a\xca\xc4\xa3\xda\xd9.]\ \xde\xa0\x9d:\xda\xf8\xcb\xfdT\x03\x04\\u6\x9d\x94\xec\x83#\'\x9a\x99Z\xb0\ \x11\x9e\x94\xe6\x9e\xdf\x80\xadF\x9c\x00IA\xcd"\xb8\n\x9c\x1d:\xc2J\x07\x9b\ \xe2\x88\x9ak\x16\x88is\xb9\xe3\ \x93#\xa8*\xa6\xa6\x86\x82\xc8\x134\xd2\xc8f\xf8\xab\x7f\xef\xfd\xc6\x04|Rx~\ $\xf6\xaf<"\xba\xc6F\xea\xbc\x00\x8b\xc5\xf5\xeb#\ \xe2J\x1f\xc2\n$\x7f\xd776k\xa1Ml\x1dK\x90\x96\xbc\xfc\xa2\xb9\xa6cO|\xd6\ \x81\xf2\x7f;f\xed\xae+\x8a\x86o\xb3\xac\xf7\x9c\xbb(\xd7/Ck\xf4}\xeb8t<<\ \xfa\xc7^]$\x88\'G\xbc\xdfe^{\xe3\xd9we\xf0?\'\x83\t_\xee\x85{Y\xd77K\xf6B\ \x1d\xa5\xd4O\xb9\xf3\x0f\xfe(\x08d\xb8\xacQ.\xb6Z\xad7&\x8c\xe4.\x9es\xdc"T\ %\xaf\xaf\xa5\xda-\x10\xa2h\xc8\x1f\xbb1\xa7\x91\xd2\xaa\xe4\x1d\xe19U,\xf7\ \xcf\xc9,\x01\xd5\x96?\xb8\xff \x1cK\x07\x16z\xb2\xa8aG\xdf[\x0b\xe4)\x00\ \x0f\xdf\xea}\x17o\xf19,\x8c\xd6\xf0\xf5t\xed\x07\x16\x1b\xd6\xd9KG\x02\xfc\ \x91|\xa2\xcdD\xaa\xd8\x8fHC\xc7[Qu\xe5\xb4u%\xe7\x1d\x01\x17\xbdU\xdd\xc7k\ \xec8$m\xac\xfe\xa4\xbd\xcc\xbb=\xbb\xf0L\xf5\xad\xcc\xad\ry\xf5*\xecL\x1e\ \xdd~?4\x1f,\x86\xe9\xd5\xde\x80p$\xddF\xa1\xcd\xc3\xcc\xbe\x0c|\xe7\x1fya\ \xac\xe8\xaf\xb3\xbd\x99w\tA\\\xd8b8\xe3\x1d\xdeD+\x87*\xa5\xe7\xdd\x83\x0b]\ \x1eP~2\x19\x13\xc5b\xbe\xdd\xa2f\xb5\xa2V\x95\x8as\xa10\x96\xb3w\x10s\x8f\ \x93G\x96\x85\xd7\xd3O\xad\x04\xfb06\xe3\'L\xde\xa6\x97\xc5wc\x9c7\xea-b8p]o\ \x83\x9cm\xde\x88\x92I\x15\xde6\x88:\x87\xa9\xe5\xd5\x7f\xff\xfe\xc4y\x97B\ \xab\x87\xd8\xd3]\xe6\xca\x13\xe9\xb8\x12\x0fy}zCS\x81\xa3A\xff\xdd(yg\'E\ \xc4\xba\xcb\x98zy}\xe0\x92wk!\xd60tzm\xd1\xd8\xb9\x9b\x11\xb4\x89\x9c\xea\ \xad\x904\x84\x18\xf4\xf8\x03\xbb\xe1v\x0cH\xd1\xa1\xd1\xad\xa4e\xabc0\x8c\ \x14\xd8}\x87\x17x\xb5\x1c/\x18\xce\xfc\x89\xd9\x903\xfe\x1e\xf4\x1a\x91\xf6\ \xc4\xbf\xd4\xfd\x84,\xc5e\x99\x94\x94\x17i\xfd\xf5\x0fpQJb\xd1&\x8b\x91\xa9\ \xfd\xb2\x94\xe9U\xbfQ\xaf\xed\xccr\xad\xd5 \xc7\xed1\xf5\x1cl\xb1_\xe5\xa4\ \xde\xc8l\x1c\xff\x15\x97\x129\x02K\x11D\xe7\xea^\xab\xb6h\xd6\xcd\xa4s\xb0E\ \x999\x84\x1e\xbc\x87\x17\xd1\xf4\x89\xe0\xec\xbb\x13f=\x9f\xc5\xdb\xd5\x9bg\ \x9c\xe6B\xd3\xb3\xf5\xb7\xdc\x8d\x89\x96\x06\xff\xb7b(?\xd5\x0c.\xbe|\\\x14\ \xda\x06\x97C\x97\xfb\xe6\x83VG\xcb\xb7W\xd2\x83\xc0;\xc1\xa5f\x04\xc9\xf0D>\ 4\x8c\xcfkyrh\xb9\x19\xa8\x94\xefn@\x9f\x85V\xdf\x97&\x0e\x0e\x0e}\xe79\xf9T\ o\x14\x18fy\x8f\x04K\xe4\xb7\xec\x93\x8a\xe3\xad\xbff\xc4\x19\xaf\x7f\xf7\rO\ }g\xd8\xe0\x94\x99&\xe3\xb8\xfe\\\x9e\x8b\xe9Z\xc5RMO\xfaY*\xb2\xbb,I\x1c6]\ \xe6\x05U\xc2\xfc\x81B\x152n\xfeAE:\x0f\xfcO\xfb\xf5\xd7\xfe\xb9\x8f\xdf[sdX\ \xadf\xb1}\xfd\x88\x84U\xa5\xa4U\xe5\x95\xdeLyH\x84\x9aY\xd7\'\xf77\xa8\x1c\ \xda\xa3\xd8\xe0s\xf3\xcc\x19u\x159\x03-\x13\x1a\x93S\xe9%\x96\xd5r>\x04P\nS\ \xa7\x1e\x0e1\x98\xfd\xf1\xf7Q\x9c\xc8\\\x94)\xfe\xd3\xc8\xc8d\xaf\xf1\xefn\ \x05B\x84\x06\x01\xea\x9e\xf7\x01\xd2+\xa5D\xab\xe5\x0c\xdfT{\x1c\x08Eg\xab"\ }6\x98\xba[u\xc8Z-\nG\xea\xf9\xf9\x8b\xdc\x11\x0c(|\xdf\x9d\xf8\x19\xe2\x17\ \xbe#0C\xfb\x9aC\xd9\xfbX\xb8"\nJ\x95\xbfP\x03\x0b\x84\x97\xfb<\x93\xc7\xcd|\ J\x8eS\x1dq\x90G\x8f\xfa\x92\x0b1_\xe1\x0c\xb2;\xb9i\x00\xdaW\x0bE\x04`jw\ \x17\xfeT\xe2\xce\xe82j\xa07\xd0>}\x89\x0eZ\xc6\x95\xaf\x94\xf5r"\xba\xa2\ \xe6\xff\x0f\xbe\xd1\x95Z\xdf\xb3\xc0\xdc\xcbT\xa8\x06\xc7\xc4\x9a\x94\x0e\ \x98\xc7j\xb7$*\xccg\x00S\xad\xe8pD\xce7\n\xac\x1c\xc31g^I\x82K\xa3\x8e\xcc\ \xea\xb9?0\xa4IUN0\xcfA\x08\x06\xb5_\\\xf7w;\x91\xa7\xd3jv\x188\xfeD\x1d\x0e\ \x97\x8a\xe1\x8e\xf4\xcd\xc7\xaaE\xc7\xc61\xe2\xce\xce\xa0n\xb1\xb28\x8c\x0b\ \xf8\x02\xa9\xc5 \x82\xde\xc1\xbaLF\xf4lr\x02\xcaL\xe9x\xf6\xf8\x19\xba\xb8`\ \xba\xb8\xb8h\xd7h2\xe7\x92|\x01\x01V\x9c^\xe1Q\x0e\x13R\x8a\x03\t\x04\r5gZ\ \x1d:\x13,\x1e\xce\xf2\x9d\xa0\x8d\xd9\t\x1ev\xc0^\xcf5\xbdf\x1b\xbd\x0c]\ \xda\x01\xd8_\xe9\x8a\xd9o\x0b\x9d\xa0\x8c\xa3T\xae\xf4\xca\xfa\'\t\xec\xfb"\ W~\xf7\xc8)\xf1R"\xb0\xcc\xc0L@\xecW\x1da\xe9\xca\x14\x02\xbb\x97:\x93,\x00I\ \xfd\xb8\xab\xfe\xd5\xc8\xa2\xc6\xa7z\xaf\x93\xe3\x86\xcf\xa9\xd7|:\x8b\x92\ \x16\x01\xd9\xb6\xbe\xa6\x1bpX\xa7\xb4\xe5\xf1\x93\xe4W\xaf\xd93fwC.\x8c\xd0\ F\xcd\xe5)\x0f\xde\xb7\x8f,\x91na8N\x10VS\x87\xceJ\xb9\xdc|H\xdea@`\x08\xc5\ \xa4\xf3\xcb\xb1\xd2T\xe0\x0b\xa7\xa9\x9b\xd0\xa0\x8e\x1c\xf6\xbcv\xe3\x9d~\ \x9c\xc8#\xd2-^\x0b\xb1\xe0#\x8e\xfb\xcc7\xd7\xf1\x92*\x8e\xdb\x96\xab\xf5\ \xeeS\xf2l\x80\xca\x0f\xfeT?Q\xeb\x8e\xf4\x80Y#\xeav\xc9N\xdf\x15o@z\x99\xa8\ \x1f\x13\x89\xe1\xb1I!\xf6D\xd9\x18u\xcb\xc4^\xdeRO\xbd\xed\xa8\x82{ip\x8b\ \xea\x7f\xdf*m\xecO\x0b\xdczD\x15\xe3c\xcc\xdc\xf8\xc3\xf8\xc0\x9f\x90\xb6\ \xd1\xc8\xf6\xd4\xa3\xd4\x1f\xcc\xeb\x9b-\xc4\xf5\x0e\xe8\xe9\xd30\xe1G\xfc?\ g\xf3\xdc\xc5\x91\xc6\t\x03\x82\x8bD\xde#\xf2\xb2\xd0\xa7-\x86\x08\xa8\x1e\ \x97\xa7L\xdeP\x96\xbf;\x1b0\x84\xfd\x1d\xcb\x0fV\xe4\xd6^OV\x91\x0e\x0br8\ \x8d\xe7q*\xa1Rb\x01\xc99\xc0pyF\x06~\x1b\xf4\xb3}\x8do\xa0B\xcbr[\x10\xf22p\ \xa7c\xba>A\xcdMy7\x11\xd8\x0f\xfa;3~\xc8\xdd\xb9\x11\x90Fm!T\xa3\xf9\xb3\ \xd6a\xd5<_@"\xdf\xc2\xee<8\t\x96\xd2&\xf6$\x1c\xd5\xc9\x9eC\xfe\xcdK+\x8aSs\ \x9f\x05\xd4\x1f\x16\x10\x10b\t:et\xc6\x8f\x83\x12\r\xbb\x1c\x95*=WE\x9c\xcd\ \x98\xa2\xb5\x9c\xcd\xac\xd5]\xdevo\xf4k+\xc3(\xef\x87f`YM\x0ff\xa2\xb1\xbb\ \xa7;\xa9T\xf8I\xcenb\xba\xd5\xe0$\xf69\x83\xc7)\xcd6\x8by\xd2\xffn\xa5\xb5\ \xbe\x13\xff\x9b\xe63\xa2V\x944\x17\x03\xbc\x9a\x1cC\x86\xbc?\xa0\xf7p8\xab\ \xe4\xcdN%]#h\x1b\x0f\x9ds\xd5dB8q\'\xa4\xb0\x13l\xd6\x9e\xa1$\xcd\xca\xeb\ \xc7\xdf\xe6\xef"7f\x91\x8ce\xeas\xf5f\x97!\xc4\xd0\x8e\xcf@\xc7\x928\xda\ \xe3\x83\xa9PZ\xd1\xebVs\xcd$\x87\x85Mus\xd0|\xfe=h\xb9\xe7\x90G{\x91;|xdN\ \x86\x9b\xfc\xb62}\\\xdfp\xaa]\xa14\x99\xc4\xea\xf7\xdd#\xd1\xbd\x91\\r0\xca\ \xacp\xfa\r\xea>eUE\xc5n\xd3l\xab\x8d\xa3^\x02E\x91\xf2\xa7N\x9a:\x1e\x0e\ \xcd\'\x8f78\xb9\x15\xab@(\xfc\xa6\x92\xee\x1cO\t\x14\xf0qc\xa5B\x01\x8b\xe6\ c\xb7N\x88\xbbY+-\xfd\xe4\xdf\xaf\xa6\xe6\xbe;\xa9\x9b\xe5\x0b\x9fQ\xe2.D\ \x9c4cEKG2:\xf1`\x1f\x85e\x18\x01\xf0\xb5b\x93w\xf2\xba^\x1a\xc9-\x95\xa1/v\ \n\x91\xd3w<6h.\xb4\xc8NY2\x1f|\x84\xefuB\x99h\x89\x0c\x91\xe1\x85X\xe6N\x07\ \xfb\xa5tQ}yni)\x98\\L1~\xfe\x89\xab\xc8\xf0\xc6\xed\x12p4W\xdf7\xd8?\xbf!\ \x01\x06\x84\x14\xe0\xc7@\x89\x85\xddH\x07\xdfHC\xeb\x84\xce\x0c\xbb\x1dq6\ \x9b9\x08H\xa9\xe4\xcc\xab\xe9s\xde\xa6&\xa5\xe2n\x7f\xbdG\x1e\xf2b\xc2\xa0\ \xaf\x88\x155\xbf\x15}\x91u\xc4\xcd\xe8\x18\x14\xf5j\x9c\xe7\xa5\xf1\xd3I\\\ \x9bpQ\xf5h$23`\xdb\x05\xc0%\xe9\xa5\xf6\xfe\xae`f;+\xe6\x1f\x16\xa9\x16\x96\ k\x9eWU\x93\xf6\xf7%-\xe5\xdd\xbf\xc7\xccN\x10\xb5\xf7\xfb\x92|%\x1f\x11\xaf\ U\xa7\xa6f\xa0\xe2\xd7\xf9\xfe\x98D\xc2\x99\xda{5\xf4\x19\'\xd0\x8a\x1bc\x86\ \x87\xeb~\xe4=r+\x19\x03\x9d\x10\r\x86\x10\r\x01\x90d\xb1\xdah\x0eHN!\xae\ \xd9(.>\x8d\x80\xc9@\xfb\xfe_\xca\xe4\xde\x00\xb3|\x19^\xbd\xb7&\xa6K\xc3\ \xf6=\xcd\xac\xac\xdcV\x05b\xad\xc9\xc0i\xf4\xb8 !\xf4I<\xa6\x957\xe7\x80\ \x14\xc0e\xfb\x00\xf9\xc5\xe3\xb2\xfdS.#&\xaf\xac\xfb/\xdc~\x7f\x8b\xf7\x8ew\ \xef\xf5\x1ah!\x94\x81\xce\x1d\x88\x0fa5^\x9a\xe0\xee}\xec\xe0[\xf9"\xac~\ \x10HV-\x9e]R\x98\x9a\xdc\xfb\x1a#w\xcf\xaa\xa5\x94\xef\xbcF\tP\xe1\x86\xcds\ \xd9\xc8\x89.\xe5r1\xe4\x80\x12\xca\xd5\\\xean!=\xc3"\xc0aZ2\x86WC4\xf7\x8a(\ \xfe\x86$v\xca\x10J\xb9\xf0\x88m\xbeo\xc2R*C\xde\xa3f\xc3\x9e\xb2\x8a\xf5\ \xbaP\xdb/\x99`\xb2\x83\x99x#\x9d9\xa2\x9fyNmA \xca\xf9C\x0c\xa6\tw\xe7\xa9\ \xf6680\x9f\n\xd3\xa0\x0f\x96\\\x80\x86H\x98\xb9\xc8eP\xaeQ\x13O\xcd\x19\xfc\ \xc5\xb4\xf1u#\xadtA[\xfe\xdcP\xfe\xeed\xfc\xcb\xfbm\xe9\x8f\xb4N\xb6\xf1&\ \xd7\x97\xd2\x95e\r)u\xe8\xca\xb6\x82\xec\xac6!qf\x01\x8b\xd2\xb3\xd3w\xa0\ \xc5\xb6K\xe2\xc0n\x7fzd7\xf3\x8d\'\x1cR\x12\x0f\x84\x8a\xb0.)6\x1f>\xce\xd2\ \xa3\x83+\x1dQ\x1f\xe6\xed&\xd6\xe9"\x15\xdf\x08\xb5\xdb-\xa595\x14=X.\xfdI\ \xcfs\xa0\xccCq\x93D\xe7\x87V\x99\xb4\xca\xd6\xc2\x02u\\\xd7\xfb\xcf\xcd\x9b\ p\xaf\x15Y\x8e\xbfP\x1e\x95j\xa6 \xef\xda..\xe7\xc58\xc4C\xa6B/:\x81\x8ekZ\ \xf0\xb9F\x83\xab \nK\xd5O\xd2\xaaz\x8f"#\xec\x847\xb8f\x9f"\x9c\x8d\xcb6W\ \xfd_\xfa\xe7\x80w\x00\xb4\x83\x11\x0e\\\x16\x1d\xb8\xc0\'\t@!\xa9\x10\xec\ \xa9\xf2S!m\xcfm<\xc9\xbfu\xb9\xc4e\x82N\xcc\xdcF\x0eA^\xe3\xe5b.\xcaFNa\xd9\ Y\x02\xbe\xc0eW\xae\xf4\xdd\x98\xcf\xb3.CH\x0c\'\xd3\xf5]\xde\xd3\x93\xac\ \xff\xe4\xccR_Q\x18\xfb\xe9\'\xc8\\n\xe7a\x90\x8c\xeb1!vq\xcd\xc9\xad\xee:]\ \xa7\x17\x91\x9c\x89\xd5\xd7\xac9x\xc6(\xe8\xe3\xa0\n\x08B\xa2\xfboC\xea\xd2\ $qg\xb0?\xfd\x12\xdd4\x1aN\xabs\xa7!\x8cu\x8b"\x81DYjl9\x9f\xdc\xce\xa2\xc14\ 1\xfe\x1a\xff\xaa\xd8fe\xcag\'\xfaK\xd0\x0e\xb6n+<\xdb\t%\x01\xda\x90\x1d\\\ \x90G\xaa\xd4R\xa2\x8c\'\xef\x07>\xf2;\x82\x7f\x8e\xb4\xe6$\x1f!\xc2\x8c),\ \xab\xf9\xcd\xc1\xc9\xf1I\xa3\x91\xe3\xcb\x12\x8bof\x9d\xfd}D\xdb=\x817{3\ \xd1\xa26\xa5"R\xd7i:q$\x93l\xb0\xd5\xc2\xdc\x94\xcd\xcaj\x85\xc9G"_oE;q\x00\ \xe9|\xef\x83 =IB\xf9\x81\x04\xaeA\xbd\xaf\xd1e:\xa3|\x18O\xea\xb0\xcd\xba\ \x12\x81AW;\xb8\xe6\xd0\xb1duZJ(\xe9\xc1\x9a\xbb\'\x18H\x9d\x03m\x7f\xbbm\ \xc0\x97Fl\xfd[\x97?K\xb4b\xaf\xb3\x83\x0ew\x05\xa0o\xadnj\x07\x0e@\xca\x85A\ \x99C\xdf=\xe6\xa7\xc7\xb7\x9a\x83\xf7n\xcf,\x95\xe3w\x7f\x86V=\xd6o+\xb1\ \x8e\xf5 \x14\xd4]\xca>*\x08\x1c\t\xaaCx\x04\xdd\x81\xc1k\xeb\x94\xa4\xacUm\ \x9b\xe2^\x1eG\xfb\x08\xb0Z\xa0\x07\xe7\x17Gwwh\x0c\xe2\x15\x86\xb9\xfas\xde\ Xb\xe5\xa4\x807jd\xa7\xea\xdf\xea\\\xe3\xf9\xb3:\xca\x1a\xa2A\xd5\xd2\xbd\x0eC_-\x1f\x95\x80\ \xe21\xa72\x1e\x19\xec\x91\xd1JKg\xe6\x96\xec\x04r\xe37l\xd8\xab\x8b\xa4\xe4\ \t\x14P\xfd\xb6Ykj\xfc\t\xe2\xa1\xc9eP\xb9\x01\xfbc\xc5qpD\x80\xdd\x01\xacKY\ \xc7\x01\\\xbdT\xdf\xa3Y\xe1;\x1c\xbb%\xfd\xe2,\xabF2$\x85\xa1g\xbb\x00\xaf\ \x96\xb8A\xd2J\xb3Q(v\x82\x16\xa7\xd8\xfe\xea\x0b\x8fhC\xcb\xdb;\xbd\x08\xb9\ \x10R2\xab,\x85.\x96\xb25\xde\xcb)+\x13D\xae8\xfa\xbd\xd3\xd7!;\xb5EZ4\x8aC\xe6a\t\xc6`\ \x89\xb8\xdd4M5\x06\x0e\xae1q\xed|\xf9@\xe2\x1d\x89\xf5\x1d\'\xca\xd8}\xba\ \xad\xf4J\x02\xa6\xbe\xc2\xed\x16\xfc\xaf%\xe9\x93\rA\xadD\xef\x18\x80\x85Ar\ \xa8\xe5\xc5\xda\xd3c\xca\xb63\xf9\xfe\xf3\x026\x16\x8a\x1f\x9fJ\xc9\x9dgs\ \xfc\xa9O\x07\xecF\xf7\r\x80\x1b)\x04\x8bw\xd1\x89.cL\xc0eli\xadX\xf3kq\xc6\ \x07\xbe:eA\x02\x93\x84\xc3\xe4\x80x\x0b\xb6>\xe3Z\x90E\x8c\xedI\x98[\xd31\ \xb7\xa4!\xf4\xf5\xb2\xec\xd8W\xeb\xb7\x8d`c\xca\x92\xc5\x86\xbd\xa3\xc7/\ \x08.~B\xfa\xa0\x0bx\xcee\xfe\xfd\x8c\x9b?/\xa7\xe2\xa5\xedC2.\' \x90\xbem\ \x91\xe6<_7\xe0\x89\x8f\xd6qd\xeb[\xfd\xdeWwE+\xf1\x13\xd3U\xd3\x12\x8a\xd3i\ \xfc\xf8D\xbf\xb7\xe9\x8d\xaa\x98L\xdf\xfb\xfbf\xaeG\x96\xf1+\xa1jL\x8c\xc1\ \xd6\x12aU\x8d\x00$\x1e\x0f\\\xa6\xb4\xe5,\xff\xac\x84D\x93Hx\xc9\x8d\xa3\ \x8b$\xa3L\x87C\xfdEw\xd8!_\xdb\t\x12\x16\xbe\x82\x13\xac\x88\x8b\xaf\x15.\ \x18D\xa6<}\x9d\xdb\x0bc\xebrr\xfc\xbdF\xa6]=\x0e\xd1\xe89\xce\xcc\x15%t\xf4\ \xa4R\xb7K\xe3\xacxe\x0f\x8cvt\x97\xfa\xe03f\x04\\\x16\x9dt\x97\x9c\xc2\x96\ \x16Y0\x91j\x1b\x82\x84=\xb5\x1d{j;\x8e\x94v\x12\x8e+\x8d\x08\x1c]\xfe\x16]0\ W\xb8,+)ci\x0b\xd4\xd6I\xda\xbc<\x9a7\x05\xeeI\x1c\rR\xe7\xfa\xa7?\xd5\xbe}p\ \xc8\x82jB\xf5\x15V\x113\x80;1\xd0q\xb0\x8e\xac\xf3JT\xd3R\xe6\xe6\x03\x83\ \x97z\'K\x12\xf6V\x0b\xe6tu\x1aR\xcc\xb8\xc4\x88\x04\xdc\xa4Q<&Z\x0c\xa7+]\ \x96\xa3c}\x03\xa4\x9be\xaa}R\xb8\x1bm"\xd3C\xe4\x81G",\x8b6\x18\x02\x8a\xb8\ \xaf+\xbd\xe8k\x0bH*P~\xb3\xb2$q\xecg\x1f\xd0y\xa4\x81S\x8d\x93)\xb9{\xa9j\ \xdd\x89\xab\xd3\xe8\xfeh3]\xc7\x02\x0f\xe7D\x96\x11\xa0\xc6\xb7\xeb\xdep\ \xa1\x8b\xf8\xe02&\x04\\\x16$:\xa7\x96\xe1H\xf2O\xd3\x12E#\x99\xc5\xd3\x883f\ \xd0\xf4A9\xc8\xe04\xd9q\xc6[p$u"\x1bC\xbb=Mi\xfeB\xd3S\x1f<%\xacmg\xb5\x9f\ \x80\xa7\x9f3\x01\xe3\xef\xb7\x07\x8c^\x1f(\x86X\xa3\xa60t\x97k\xa4\xdb\x0c\ \x02Z}\x85\x83\x8axo\xff\x9b\xc6\x00\xb4n\xadD\xfe\x7f\x92\xeaf\x16?>\x95\ \x84I\x99t\x1f\xf7\xbfqjuP\xea\x0f\x96\x8a6?\x01O,\xc9\xa4\xf3p\x83\xe6\xf2\ \xbe\x0f5\x82\x00%w\x9f3\xe0\xe3\xf0&;\xce\xa0*\xf02\x18"\xee\xebFW\xa2\xd0\ \xd5\xdd\xc8\x02\x85\x01\xf4\'pm\x9cY\xe6\x80\xa0n\xcb\xde\xe5\x14h\xb3\x0b\ \xa4\x86\xa8\x85\x1em2\x96N \xf7\x8b\x1e\xefV\xf9K;\xe8<\xa2\x9c\xef\x86ue\ \xd8oI`Z\xe2\\\xf7|\xc1 2\xf5\xfe\x95\xec[\xfbN\xc0\xe6H\xa1D\xcf\xb7\xc9\ \x887bRR\xbf\x1e\x00\x06Chu\x11\x1f<\xc6\x84\x80[\xf3k4\xc5;\xa61\x8b9\xd7}\ \x99\xec\xb3\'\xd3\xdb\xd0I\xe7\xff\xfd]5_\x16d\xec\xa9m\xf4\xe6\xd4c\xd7X\ \xdfE\xf2L\xff\xaaj\xae\x8b7\x10\xcd\x9f\x953\xe1\xb6E*W\xbb!\xceD\xde\xd5\ \xb38\xfd\xa7]A\xd6\xec?\xa29\xc0\xe9\x0e\xb7p\x95(`\x88\xa0L\xe6P\xe0-J\xce\ %\x9bU\x02l\xef\xe8\xa1yS\x85_4\xf0\xf8\x9b\xe7s\xe4\xc7\xff\xf1\xf3:D*\xde\ \xf7N_\xe77\x06\x0e\xd0y\xb8\xde\xaf\xcdk\xea\xc2\x02j5r\x7f\xb5\x1ej\x0e?\ \xba\x9b\xb4E\xc1[)\x02~)l\x007\x9eu\xa3\xdf\xb4MM\xff\xe0\xe8\t%e\xef\xda\ \xbc\xc7\xdc\xd3\xbd\x8f\xddl\xd6\xee/\x1e\x8aGyT\xf5\xde7uL\xf0\x11\xd8\xea\ \xde\x81E\x98\xffg\x9d\xba\n@C\x8fH\xec\xc4\xd9$ey\xbe\xefc\xdd\x06\xceJ\xd5\ \x0e\x14\xed\x0f\xa1\xac\xf0\xe5e\xe9\x94|\xdb\xf3\xdbi\xfe\xbc\xdc/\xcf{S\ \xf3\xbf\xc84\xe7\x90i\xf6\xdc+\xccY\tL\xbaw9G~\xfa!r?\x03\x1c]\x0f\xc0K\xde\ \xfc\x9aj\xdc\xddhr\xf4K0\xfbk\xf5\xf7\xa0\xd4s\x17*=\xf5\x0eLm\xa9\x18,\x8a\ \xc1\xe0-\xe2\xde\x8dd\xbc\x89\xa4\x95\xa8\x8e\xc2\x19/\xe0\x92\xc9No\xae\ \xffM#\xb6n\x1c\xf1\xa7\xc7c2)?0SZ\xbc\xdf\xcdF\x90\x05\xcc\xadi\x98[\xd3\ \xb0\xe6\xd6b-\xf4/\xce"\x08\x90s\x99\xba\xa1\x82\xecp\xd2\xba=xI@{\xbb\x95\ \x86\x8f\x8e3\xee\x02u\xa4l\xde\x95\xb3i\xdf_G\xfb\x9e\x9a\x00k\xf6\x1f-W?@L\ N\x92f=ho\x04Q\xa0\xf8\xce\xa5\xc4\xe5\'\x07]n\xa8\xf9s\xf9\x85\xee\xd7_\x9e\ \xa0t\xe1\xf2\xb6,\xab^\xdbC\xe6\x8a\x89\xaa\x06L\xa9s\xf3\xc8\xbf\xb6\x94\ \xaa\xd7\xf6\x0ex\xffZ\x15\xe1Z\xb7\x9d\xa6\xf0\xa6y\xaai)\xa5y\xc4\x17\xa5a\ \xa9\x08>\x84c\xb7\xc0\xf8/\xcf\x0b\xba\x0ch\x8bw$\xb8\xbe\xb7\xf7\xba\x14/\ \xd0[--\\\x99\x9e\x1el\x95~a\x14\x05\xec^\x81}\xc9d\x91@*\xddx~o\x91X\xdfo\ \xbf\xeb\xdf\x13{\xee\xe5)*\x01o\xb2\t\x1c\xb7\x0c\xcd\x10\x81\xc9dd\xea\xf7\ V\xb9\x9b\x1aY\xab;8\xf1\x1b\xff\xaf\xaf\xb5\xaa\x9d\xa2\x9bJ\xb0\xf88a\x04A\xe9Ko\x8a\x89Q\x04\xdf\xd6\ \xbf\xca}\xaf\xd7\xdc\xcf\x9f\xb90\xf4\x82Q 5V\xa4\xa3G\xfd\x00}\xbd\xe1\x87\ \x9c\x94vS\xc7\t\x95\xf5m\x93\x05\x1a{\x05jzD\x1am\x02\x93\x13\x9ca\x8de\x8f\ \x8b\x910\xc4\xc84\xf6\xaa\x05\xffb\xf1N\xe6\x99.\xe4=\xe97l\x97\xde\xa5K\ \xd6~@\t\xe7\xfc\x82\xbf+}N\xe9L\xa6L)v\xbf?\xf9\xdb\xcf\xb0\x9c\x0e\xee\xc9\ *\xb7\x1c\xa3\xfa\x8d}\xe4_\xe3\x19\xb2\x10\x04\x98|\xefr\xf6\xad}\x07*\xfa\ \x97\x85\xd2}\xa2\x89\xf8\xf1\xea\x06,\xe3\xbf\xba\x80\xae\xe3M~\xf7\x04cR\ \x0ci\x0b\n\xc8\\^L\xca\xbc|\xaa\xfe\xb6G\xf3\xf3\xea\x8c|\xcex\x01w\xc6\xf9\ \xe7\\\x9b\xba\xfdkd\xbbH[P@\xda\x82\x02l-\x16Z\xb6\x9c\xa6\xfd@-\xd6\xd3m\ \xd8\xbb\xd4\x96S\xea\x82\x02?\xf1\x96z\x1d\x1c}x}X\xd6\xb7\x8b\x96-\x15\x9c\ \xfc\xddf\x8a\xef8\xdbo^\xfa\xa2B\xd2\x17\x15\xe2\xb4\xda\xb1T\xb6\xe1h\xb3*\ \xad8\x93b\x88\xcdI\xf2\x0b\x94\n\x87\xda\xb7\x0f\x92s\xf14U\x9dsA\x80\xa2\ \xaf/\xa2\xe0\xbaR\xbaN6\xe3\xb4\xda1%\xc7\x92P\x9c\xa1Z\xce\xdenE\xfe\xff\ \xec\x9dw\x9c\x14\xf5\xfd\xff_\xb3\xbd^\xefw\x94\xe3\x8er(E\x11PQ\x11Ab\xc3\ \x825\xe6\x1bC\x14%\x881\xf6$_\x13cb\xf2%Jl\xf9I\x8c\n\xc6\x125\xb1a#\x82\ \x1d;\x10T@\xfa\x1dw\x1c\xc7\xf5\xdbk\xdb\xcb\xcc\xef\x8f\xb9\xd9\x9d\x9d\ \xb2;\xb3;\xbb\xb7\xb77\xcf\xc7c\x1f\xb73;m\xef\xe6\xe6\xf5y\x97\xcf\xfb\x1d\ \xa4`(\x8c>\xef\xe4\xbb"\x03\x90\x96\xd7w\xf3\x12\xc44\x06-\x08\xbd|\x97\xa6\ PE3\x00aW\xa1?\xa4\x01AP\xe1y\xbfBtzBxq\xdaz\xfcp\xf7u\xf09\xf8"n\xaa\xc8\ \xc1\x84\x1bOE\xf5\xcaS\xe1k\x1b\x80\xaf\xd3\x89\x907\x00BC@g7\xc1Tf\x8f;x\ \x11K\xce\xeb\xfe\xb4\x91\x17\x7f7U\xe4`\xe2m\xd1}\xd7|\xacg~\xa0\xdf\x83\ \xc2Y\xb9\xbcih\xcc\xbes_\xfe1\xe6\xe2\xc7hk\xaa\xc7\x9dK\xe8J#;Y\x96\xf3\ \x9fW\xad\xe2\xedw\xe7\x9f\xfe\x84\xd9gEw1\xfb\xd1\xf8\xf5\xb8\xfa\xfb\xebx\ \xdb\xee\x94i\x85o\x8e\xd3!\xae2W\x87\xe6\xbe\xe8xt!Q\x89\x07\x0c_\xa3\x89\ \xda\x85\x1d\xfdZ\x90 \xe0\x0e\x11p%\x11\xb6>1\'\x88o\x06t<\x11/#jp\x9d\xf6\ \x11\\\xab}\x18\x1d8\x0c\xf3\xbd\xe6\xc8\xdf\xb7\xa2\x04\xa6\x9f])yp\xaa1ha4\ \xd2\xf7qqI\x11N?#R\xe9e\xff\xfez\x0c\xfc\xb7\x05Z\x93.\xaa\xd2\x1a\x17\x83\ \xc6\x88\xd67\xf7 gZ9\xec\x93#\x96\xaf\xcen\xc4\xe4\xbb\xceD\xc7\xffn\x06\ \x15\xa4\x07<\x04\x15\x92<;\xa4\xe7\xcb#(^\x10\xed!3\x16Y1\xf3\xb1K\xe0jp\ \xc0\xdf\xeb\x82F\xa7\x85\xb1\xd4\x9eqa0\x95\xc4\xc9z\x01\xa7\xf4|w\x16\x11\ \x8c|m\xe7\xc1.\xe4\xce(\x87\x86#0\x86\x02\x0b\xca\xce\x9b\x82\xb2\xf3"I9\ \x9b\x1f\xfc\x16A\x1f= `b^\x0c\xben\x17\x0e\xde\xff\x11\x9c\x87zd_c\xc7\xa6\ \x03\xf0;<\xa8\xfd\xf9<\xe8\xecF\xde\xe7Z\xb3^17\x97\xdf\xe1F\xc3c\x9fc\xe2m\ |\xf7\xa1\xd6j@\xee4\xe1.[\x83{;p\xf0\xc1-\x18\xb7l6\x8aN\x8f\x16%\xb6\xbb\ \xbf\xf3\xe3zp\x8b\x86V,\x9d\xc6\x1b\xecH\xc1P,\x1c\xb6\x98\xf3\xc2\xd5\x00\ \x807\xea\x01\xbb!\x88s\xab\xdb\x01\x00\xb7,\x0b\x84\xe3\xdf\xdc\x96\x9a/M[\ \x0f\x8dV\x83\x13~r\x02*/\x9f\xce\x9bfC\x10\xb4@\xc6\x0bC0\x08u\xb0\xe2r\xf8\ o_\xc0Tf\x87m\x92\xb4\xcau~\x87\x1b{\xef\xd9\x8cy\x1b.\x89\xbfq\x92\xfc\xe6\ \xfb\xeb\xf0\xc7\xe3\xa3E|B\x8c\xed\xc5\xf8\xc1\xf2\xe5\xd8\xbcn\x1d\xd6\xae\ y\x04\xab\xee\xe47t/\xb5\xe9Ph\xd1\xa2\xc7\x1d\xfd\xf7\xd0@\x8b\t\xc4\t\xe8\ \x881\xd6\x15\x1b\xc0\t\xa1%\x80\x93r\x82\xa8wkP\xef\xd6\xf2\x84\x8f\x00\x81\ 2\xd4\x00\x12oC\xa1\xbf\xef\x98\x1f\x9d\x88\xb9\x17\xf1\xeb(\x00\xc0\x94)\ \xb5\xc0\x0b\xb5\xe8\xfdo\x0b\xf6\xffQ\xbc\xdd\xce\xd2\xf2\xeb\x90\xf7<\xbfK\ \x1e\x00Xk\x8bp\xee\xcb?\n/o\xbb\xea\x9f1\x07\x03l\xfav\xb4`p_\'\xecu\xd1u\ \xf8\t\r\x01\xdb\xc4B\x00\xc2\xe7\x040\xec\x15\x02U\x12\'\xfb\x05\x9c\x10\ \xb89Y\xcf\x85\x96\x97w\xa2\xfd\xdd\xfd(:\xad\x1aE\xa7W\xc3>\xa5D\xb4>\xb89\ \'\x1f\x83]\xd1\x16=\xe9\x0b\xa2\xfd?\xfb\xd1\xf2\xcaN\xc1\xd2\xa3R\xe9\xdd\ \xd6\x8c\xefVu\xa2\xf2\x8a\xe9(={24F\xe9\x16+\xe9\x0f\xc1\xf1U\x13\x06\x0fHs\ \x83u\x7f\xda\x88\x90/\x84\xda\x9b\x84\x07\x0cl\x02\x03^\xb4\xbc\xf4\x1d:6\ \x1f\x00ER\xf0\xb6eVI\x90\xceF7n=\x8f~`\x12\x88$\xc9\x94\x08\xf4\xc5&C$v<\ \xbd\x03\xdd\x9f5\xa2\xea\x8a\x19(\x8c\xa5v\xe8s\xcd\xd0\x18u\x98x\xfa\xf9\xf08z\x10r\xfaA\ \xb8\x0c8\xf4\xf0g\xe8\xdd\xd6\x9c|\xfdr\r\x05\xbf\xbd\x1f\x9e\x1c\'\x1c\x9f\ \xef\xc4\xce\xff\xfaA\x19\x83 \xa9\x10\x1d\xf7\xd4\xe9a\xb0\xd8`\xb2\xe7\xc1\ \x9aW\x0ckn9l\xc6RP\xdd:\x0c\xec\xed@\xffw\xad\xb2\x07\x0f\xbd[\x9b\xf1\xcd\ \xae6\x94,\x9c\x88\xbc\x13+@\xe6\x04\xe0\x1c8\x86\xc1\xaeV8;\xdb\xe1rt\xc3\ \xefv\x82$\x03\xf4 h\x16\xfd\xbbt\x1e\xde\x8f\xb6\x97\xbfD\xc1\xd8ZT\xd4\xcd\ \x829W\xf9\xcc\xe5d`\x97q,\x1eZ\xe6\n\xf9\x91C\x0e\x1c\xf9\xd3\xc7\xa8,\xb5"\ \x7f\xce\x18\xe4\x1cW\n\xcb\xf8\x02\x18\x8b\xac\xd0Z\xf5 4t\xd9Sg[\x07\xda\ \xbe\xff\x16\x8e\xe6z\xb8z;\x11\x089AjB@.@\x9c\xa8\x81\xc6o\x84\xd6m\xc6\xc6\ s\xff\x82\xc5\xaf\xaf\x82\xdeL\xbbb\xd9q\xfe\x907\x88C\x0f\x7f\x86\xb6\x8d\ \xfbP\xf6\x83\xc9\xb0\x1f_\x06c\x91\x15\x14I\xc1\xefpc`O;\xba>\xa8\xc7\xc0\ \xdeH,\x98\xdd\xe0\xc2\xe7\x1aD\xfb\x81\xef\xe0h>\x84\xc1\xae6x\x07z\x11\xf4\ \xfb\x00P\xb8\xf4\xd2K\xe1\xf1x\xf0\xf2\xda\xb5\xc8/)AQ\x19\x7f:\xa3\x1c\xfe\ x\xfcz\xc5E\x9c)\xdaro\xe0\x078Ys\t\xe6h\x96`<1\x03%\x9a*\x84(:\x8b\xd6\xa4\ \xa5`\xd3\x01\xf9:\x12\xa5&\n\xb6\xa1\x9e\xder\xc4;\xea\x9c:`fN\x08\x17\rN\ \xc5,\xe2\\L\xd1\x9c\x8a1\xc4q(D\x15\xacTn\xf8\xef\x1b\x18\xf0\xc2\xe7\xd1\ \xc2\xb5\xf30\xaa\xaf\x99\n\x8dI\x0b\xfb\xf8j\x1czHZ\x82\x95w\xb0\x0f\x1d\ \x87v\xa3\xf7h\x03\x06\xbb\xe9\xbfM\xc0\xeb\x015\x9b\x02\x11\x8a\xdc\x1f\xfa\ \x81\x1ch\x02\x14H\x81\x84>1Zv\x7f\x8d\xae\xe9_I\xde\xde\xd8U\x044VcU\x97\ \x13\'\x93\x14\xaerx`\x9dP\x08]\x8e\t\x1a\xa3\x16\xa4?\x84\xe6\xed\x9fa\xcf\ \x96W\xf8;\x9f\x14\xbdhj-\x83\xa5E\x9d\xc65\x12 V\xd5<\x94\xd5\xfe\x93\xfei{\ \x102Ggh\xea\xdcV\xe4\xec\xa9\x03\xa8\xd4t\xaa\x92\n\xa9\x0f\xc0[\xd1\x0e_Q\ \x17(\xad\xfc:\xd9\x9a\x80\x01\xc6\x8eb\x98[+\xe2o\xcc\x81\xd2\x90\x08\xe4\ \xf6#P\xd0K\xb7\xa7\xd4%0\x08\xa1\x08\x98:J`n\x1e\x03BF\xd7/n\xf68 <\x1d\xcb\ _\xdc\x03g5\xbf\x8f\xb6X)V\xc1Kd5V\xe0\n9\x03\xb7\xa0I\xc0>\x08_E;\xfc\xb9\ \xb1\x13\x92\xd8\x10\xa4\x16\xc6\xf6\x12\x98[+\x04\x13$\xe3\xc1\x9dON\x1a}\ \xf0T\x1d\x83\xaf\xc0\x01\x08y\x91d\xb0\xf0\xd2Ky1p6\xc9Z\xe1L\x1c\\\xc8\x85\ .\xb7\xea\xda?_z\t_m\xdd*\xfb\x1a\xe4\x90\xbf\xed\xa4\xf0\xfdJ\xcd\x9d\x8f\ \xb3\x1f\xe3w\r\x8b\x95l\x19\xb0\x0f\xa2cZ\x1b,A\xe9\tg\x94\x8e\xc0\xe0$\x0b\ \x06\x8e\xb7a\xfa\x1dcE\xb7c\xeeQM\x99\x03\x9a\xc9M\x92\x8fo\xec*\x82\xb5\ \xb1Zt\x8e5 \xfe\xff\xc4EH\xc0]\xd5\x8d\xf0\x15\xa7\xa6\t\x10\xc3\xd1\xabJ\ \xc3\xdeOu\x1e\xb84\xb2\xde\x02\xd7\r\xd8x\x02\x1e\xb4\xb8\xe0\x1e{\x14\x96\ \xe6\xb1Q\xf3\x83\xd3\x06\x01\xf8J:\xe1\x1e\xd3\x02J\x93x\x83\x0bR\xef\x87?\ \xbfW\xb6\x80{\xc6\xb6\xc0[\xdc\x99\xd0\xa0!\n\x82\x82\xb7\xac\x03\x946\x04k\ \xa3@\xdf\xcf\x14\x11\xeb!\xc5\x85m\x91\x97\x0c\xbd\xe7\n9\xb3\\l\x07\xdc\ \xe3\x8e\xc0W(?\x8f\x81\xd2\x84\xe0\xadhC\xa0\xa0\x17\xf6C\x13\xa1\xf1H/\x03\ \xcb\x16o\x8a\xa2\xb0dm!\x9e\xfb\xc7{<\xcfQ:P\xd2\nW\xaadj\xa6@\xe9B\xe1\xfb\ \xc3"3\xe1\x8e\x08R\xc8\xd9\xeb\x82\xa5\xc5\x07\xd2\\"z\x7fp+\xe6\xc9E\x9d\ \x9e5\xba\xc8z\x017v\x15\xc3W\xca\xaf\x8a\xe6-\xed@\xc8\xe8\x83\xb5q<4\x01\ \x91\xb9\xb9)\x80"H\xb8&4\xc1/"\x12DP\x07}_.t^\x0b\x10\xd4\x00Z\x12!\x93\x17\ \x81\x9c\x01\x90\xc6\xc4\xa6\rq\xf1\xe5\xf7\x88\x8a7\x11\xd4A\xef\xb2A\xe31B\ \x13\xa4\x7f/\xa4.\x80\xa0\xc5\x8d\xa0\xdd)h\r\xfa\x8a\xbba\xec*\x86\xce)\ \x9e\xdd?\xdc\xb0\xe7\xfd\n\xc5\xc7\t\xb3\x0f\x8e\xbaz\x10f\xfe\xef\x98\x08j\ a\x18\xc8\x85\xc6c\x86&\xa0\x03E\x90\x08\x99}\x08\xe4\xf6\xf3\xfe&!\x93\x17\ \x03S\xf6#g\xefTh|\xf2\xaa\xd6Q\x14\x85\x7f\xfd\xeb#l\xda\xb4-\xad\x15\x1a\ \xb8\xb1\xf0T\xb8\xd2\x192M\xbc\xe9\x01^\xfc\xc1g\xc8\xe4\xc5\xe0\xe4\x83\ \x82\xff\x83V\xab\t\xc7\x1f?\x01\x15\x15\x85xjc\x13\x00\x12\x95-\x01\xc1\xfb\ C7\x10\x94t\x7f\x90\x83fP\r\x95\xb0\xe9\t\x10\x04\x01oY;H\x81\x84\\Co>\xb4\ \x83V\xe8<\xf1g\xa4h\x9df\x98\x9b\xe9\xb9\xff\xbe\x92.\x90\xa6\xc8\xb5\x99Z\ \xcb\xc2\xc9\xbd\xb1f\xe9\xa8d\x16Y/\xe0:\xb7\x05\xc6\x8eb\xf8J\xf9I)\x81\ \xbc>\xf4O\xdf\rsK\x05\x8c\x9d\xa5 R\xedR\'\x00wM#\xfc\x05\xfc\xa9:\x04\xa9\ \x81\xf9h\x15L]%\x00)t\x1dt\x0bTO\xd51\x04\xf2\xa4\xbbv\xa5\xa0\xf5\x98`p\ \x14B\xdf\x9bG?\x08D\xbc\x12\xa4\xd1\x0f\xd7\x84\xc3\x82ee}\xc5\xdd\x92\x05\ \\\xac\x04\xa9T\x12\xb52\xb8\xf1\xf1G\x9e\xa1\x07(\xdd\xdd\xfd\xb8\xed\xe7O\ \x810p\x1e\x90!\r,-U0v\x16\xd3-fy\x07\x04|\x05=p\x8do\x02\xb4\x11k\x99\xd4\ \x07\xe0\xacm@\xce\xde)\xb2\xc24\xef\xbc\xf35-\xde\x02\xe8\x07r\xa0w\xe4C\ \xe7\xb6\xe2\xf9C\xabA\x92$\xf4z=L&\x13\x1e\xfd\xe7?\xd1\xdf\xdd\x8d\x9e\x8e\ \x0e\xec\xd9\x9eX\xa3\x16\xae\x88\'K\xa2\xbd\xbe\xcb\xcb\xca0e\x12\xbf\x8f7\ \xc3\xfe\x83\x07y\xeb\xcaJK\x91\x97\x9b\xcb[\xbf\xc5\xf7\x19o]\xd5\xee\x89\ \xf4\x14=\xd6=\xfe\xfeM\x8dQnt\xae\xfb\x9c4\xfa00e?(\x81\xfb\xe3G\xd7\x9c\ \x85\x05\x0bN\x80^O?J/\xbe\xf84\x9cv\xe3f\xf4W\x03\xb3?\x19\x97\xf8\xfd\xe12\ \x83r\x99a\x1e\n\xef\xe8\x06m\x18\xa8\xdb\xcf\x1b@\x07\xedNX\x8e\x8c\x85\xc6\ \x1f\xff\xf7\xad\xf5X`\xf6X\xe0+pp\xc4\xbb\x1c\x96\x16\xe1\xb6\xaf\x91}\xe9X\ \xbe\x18\x81\x1c~r\xab\xd6k\x86\xc6/\xc38\x921\xeb@\x85&\xeb\x05\x1c\x00,\ \xcdcA\x9a}\x827\x19\xa5\r\xc1=\xee(\xbce\x9d\xb4\x90;\nS\x16\x1b\xf7\x96v\ \xd01M\x0e\x9a\x80\x1e\xf6\xfd\x93\xa0\x8d9\x8a&\xe8\xc1Hw\x91\xe2\x02\x9e\ \xb3wj\xb85j,4>\x03l\x07\'\xa2\x7f\xfan\x9e5\x10\xb4:E\xf6\x12F\xaeh+\t\xb1u\ Kx\x00\x11\x08\x04\xf1\xe8\xa3\xaf\xf1\xc5\xdb\xafGhW-Ld\x8cA\t\x05\x18{\n\ \xa1\xf5\x19y\x0f\xd7\xa0\xd5\t_\x11\xed\x99\x88\xc7\xadu\x1f`\xe5\x9bS\xf0\ \xdak\xfc\x81\x89&\xa0\x87\xad\xbe\x06\xba\xc1H99\xb7\x9b\x0e\ty\xbd^\x0c\ \x0e\x0e\xe2\xea\x1fD\x8a\xb2\xfc\xf0\x87\xfcZ\xe8k\xee\xbe\x1b\x07\x0e\x1c\ \x88{\x1d\xec:\xe9\x7f<~}T\xd5\xb6X<\xf0\xc0\x03\xf17\x824\xeb{\xe1\x82\x05X\ \xb8`\x81\xe8\xe7\xabn\xe1\xc7\xd9\xcf^\xb8\x10\'\xcf\x99\xc3[\xff\xbb\x96\ \xdf\xf3\xf7\x7f\xe5\x02\xc1\xe3\x8a\xc5\xbc)\x82\x84sb=O\xbc5\x01=\xec\x07&\ a\xf1\xe2\x18\xf9\x18\xac\xfb\xa3\xff\xf8}`\x17\x84\x94s\x7f\x00\x80\xcei\ \x83\xb5y\x1c\\\xe3\x9a\xa2\xd6\x93\xba\x00\x9c\xb5\xf5\xb0\xef\x9b"<\xc8\ \xe4\x102{\xe1\x9e\x10\xe9x\xa8\xef\xcf\x81\xe5\x98\x84\x8am\xede0\xb5\x8b\'\ I\n\xb5\xb15\xb7\x95\xc3\xd0\x15c\xfa\x1a\x17"v\xf9i\x15>Y_J\x15\xa0\xfbx\ \xdb\x0fN\x82\xa1[\xfcf"\x8d>\xb8j\x1a\xd1\x7f\xfc\xf7C\x89C\xca^\x03i\xf0\ \xc3]%p\x83R\x04l\x07\'\xc6\x11\xef\x08\x1ao\xeci_r\xd1zM\x92\xc4\x9b\x81\ \x08ia\xec\xe6OS!\x8d\xa9\xe9\xa0\x96j\xde~\xfbK47s\x84\x85\x02B{\xabA\xb9\ \xcc\xe8\xf4\x84\xe2\xc6$uN\x1bL\x1d\xa5\xbc\xf5\x9e\xf26i\xf7\x11A\xe1\xcfw\ \xbf\n\x8a3y\x99\x08\xea`\xdf[\x17%\xde\xa9\x84+\xd8lA\xe7\xf1\xe4\x0e\xfa%@\ \xa2\xd6w&\xe2\xa9hC\xd0\xc2)SJ\x01\xd6\xfa\x1ah\xdd\xb1\xffg\x99\xaam:\xa7\ \r\xce\xc9\xfc\x9a\x06\x92\xef\x8f!\x8c\x1dE\x82\xff{A\x9b\x0b\xee\xf1\xcdq\ \xf7\xa7\xb4!\x0c\xd6\x1e\n\xe7Vh|\x06\xd8\x1aj\x86=\x997\x1e3\xeam\xe1\x97J\ 4\xa3B\xc0\x01\x00$\x01\xdb\xe1j\xd8\x0eO\x00\x11\x14\x17\xac\x90\xd9\x0bWm\ \x03\xfa\x8f\xff\x1e\xfe\x82^\xc5\x84\xdcS\xde\n\x08T\x0c3\xb5\x96\x8b\xd6Y\ \x17B\xab\xb4\x80\xcb87\x83\xd0 \x82\xd2\xa6?\xe1J\x88\x87\xf7-\n\xbf\xe2\ \xd1\xd7\xe7\xc4\x7f\xfe\xc3\xcfx&\xdb\x8a@\xf5G?,\xe2\t\xb9\x90\x80\x93&\ \x9f$\xcf\x84?\xaf\x17!\x0b\x7f\xfe\xb7\xe5\xc8Xh}\xca\xfe\xbd\xe3!\xd5\xea\ \x96K\xa6\xc5\xbe\xd9\x88\xd5E\'\xf5\x01x\xcb\xdbx\xeb\x8d]\xc5\xd0\x0f\r\ \xaa\xb8\x9e\xa4\xd3n\xdc\x1c\xb5\xcc\x88\xf8\x98\x7f\xf1\xfb\x08H\xbd?XW\nK\ \xd38\xe8\x04\x06\x0e\xbe\xe2\xae\xa8,\xf1\xfbJ\xc9\xf0\x8b\x86\x82\xb3\xba\ \x11\xa4\x99.EHP\x1a\xd8\x0e\xd5F\x15\xb5J\x07\x8b\xb6/\x0b\xbf\xe2!$\xda\ \xaa\x88G3z\x04\x1c\x00@\xc0\xd0]\x88\xdc]\xd3`\xec,\x8e9\xf2\x0c\x99=p\xd6\ \xd6\xa3\xff\xb8=C\xd3\x89\x12OW\xa74$\xfc\xc5\xfc\xa45\x82\xd4\xc2\x1c\xc3-\ %\x04Aj\x93N\xba\xb37\xd4\xc2\xbeo2\xec\xfb&\xc3\xd2\x12\xdf}\xc6\xbb\x06\ \xc1\xdbf\xf8g#rE;\x96\x88\xdfZ\xf7\x01>\xf9\xe4;\x04\x02\xfct\xe2\xbc\xca\ \x8bE{e\x8b\x89\xb8\xc6g\x80\xd6\xcb/\xc9\x19\xc8\x8f\x1f\xee\x10\xca\xcf\ \xd0zMt8G\x80U5\x0f\xc5=\xa6R\x88Z\xe17\xcc\xa2_\x1cRa}/_\xb9R\xf1cJ\xc1W\ \xd2%<\xe8n\x8b\xaeVxk\xdd\x078\xed\xc6\xcd<\xf1f\xa3\xf1\x19\x10\xcc\xe5\ \x8b\xa5\x94\xfb\x83\rAj\xe0\xd6\xf5\xc1\xaf\xe7g\xb1\xbb\xc77!hu\xb2D;\x82\ \xb7\xbc\x03\x81\x82H\'\x80@\x0e?)\xd0\xd0S\x18sL$&\xe2\x0e\xf0c\x91\xa7\x15]\ \x8cEA\xbe\x87 \x16\xec\xef|y\xc5\x1a\xd1\x01\r\r=\x08J\xd5\xb4\xb1u\x8f?\ \x9e\xd4\xfe\x89A\xc1W\xc8\x9f\xf7\xacuY\x04\xbd"\xf1z\x86\xcf\xfeX\x0b\x7f\ \xae\x0e\xba\xfe\xe8\x01c\xbc\xfbC\x88\xb2\xef\xe6\xe1\xf5\xeb\xc7\xe1\xcc]\ \xafE\xf5?\xa6\x08\n\xabm\xfc\xe7\xd3\r\xafO\xc4\x9fWG\xee\x0bSg\x89\xbc\xd8\ t\x9a\xb8\x86\xd3\x96Y%>\xa3R\xc0\x194\x1e\x13l\x87\' \xd4V\x01oE+|\x05\xe2B\ \x1e\xc8\x19@\xff\xf1{aj+\x85\xf9X\xa5\xa4\x84\x91\xf0\xbe\x02Y\xdb\x00`\xe8\ \xcb\x13\\\x1f\x0fcw\x11\xb4\x1e\xfa\xdf^\xebO\xaf\x8bu\xa4\xc2\xed\x16F\x9a\ \xfcQ\x99\xb8\x0c\x86\x01:\x9bYJE7\xae\x90k\xb8\x1d\xeb \xdcL\x87M0w\x00BJ\ \xad\xef\x1f\xde\x86\x13r\xe6#\x1fyB\x87q+\x92\xe8D\x92\x010nt\xe6\xef\x1e\ \xef\xfeH\x04\xd2\xcc\x7ff\xc4\xbb?\xc4X\xfa\xd4\x11x**\xe1\xa9j\t\xaf[{\x84\ \xef\x11\x01\x80\xbf\xfd\xed\x8d\xf0sM\xe7\xb2\xc1|$\xb3\x8a\xa4\xcc\xa8\xb7\ a\x06T\xf1N\x84Q\xe6B\x17F\xeb1\xc1\xda0\x01\xb9\xbb\xa7\xd1\x89nb\xaeu\x82\ \x82\xb7\xa2\x1d\x83\xc7\xed\x93\x95\xb4\x15\xe2&\xc1\x0c\xa1Kp\xbe\xa5\xb1\ \xab\x18\xd6\xa6\xf1\xb06\x8d\x87\xa9U\xb8\xf9\xc8h\x84\x1b\x8fd\x96\x85\\w\ \x01\x91\xd8#30b`z\x18Ss\xe7\xa3\xc4\xac\x15\xb4D\x99\xf8\xb8P\x056J\x17\x8c\ Y\xac\'h\xe5\xb6~\x01\x00\x02Z\xb72\xed[\x95"\x9e\x98\xdf\xb5\xf0.\xc1\xf5\ \x99\x1c\xfb\x8e\x85\xd4\xfb\x83\x8dP\xcfp\x86\xed\x0bB\xa0\xb4\xfc\xe7J\xbc\ \xfb#\x16\xe6\xb6r\xe8{i#@L\xbc\x01``\x80~\xfe\x10\x01\x1dl\x87jd\x19\x1fJ\ \xc2\xcd\xf4\xff`\xf63\xb2]\xe5;k\xe5\xcdv\xc9vF\xb5\x05\xceE\xeb\xa5-r\xb2\ \xb5\x12\x9e\xcaVA\x17\x1a\x00\x04-n\x0cL\xdd\x0b\xfb\xde:IIF!\x81\xe2\x0f\ \x04\xa9\x917G2\xc5P\x9a\x10B67\x82f7H\xb3\x0f\xa4\xde\x0fR\x1f\x00\xa5\r\ \xd1\x0f\x18\r\xc0X\x8a\xc3Q!L*R\xa7\xa7\x91&\xaf\xe0\xfa\x90\xd9\x03_\xb1@#\ \x8b\xc3\xaf\x82\x9a;\x19\x00\x90{\xf8\x00\x06\x03\xfc\xdf\x81\xdb\xe8\x12t\ \xe0P\xfa \x08\x9f\xf0\xc3](yM\x13\xd0\x81 \x87?\xc8\xc1\xb5\xc2;=\xa18\xae\ \xf4\xcc\xa1\xa0\x85\x1f2Xu\x85\xf4\xdc\x01\xd9\xf7\xc7\x109A\xf1\xff\r}\x9f\ \xb0\x97"\xd6\xfd\x11\x13\nxd\xa0\x06\x90\xd0_H\xa3!`\xad\xaf\x914_<\x950"\ \xaef\x95+\x83*\xe0\x02h\xbcFX\x1b\xaaal/\x86kB#Bf\xfe?3\xa9\x0f\xc05\xb1\ \x1e9{\xa6\xc6\x9d\x86!Tg\x9c\x08\xe8\xa1\xf8\\5\x99P\x9a\x10\xfcE\x0e\xf8\n\ {\x10\xb2;Ae@"Z\xba\x10\xcb!\xf0\x08d\x1d\x87\xa1\x9a\xe8\x9f\xd5\xf2\\WT\ \x8c~\xe5\xa4\x81?\xb8\x13r\xc5\x0f\x17R\\\xe9k_\xbeMp}\xa6Y\xdf\xe3V\x04q\ \xe4\ti\x8f\xbc\x84\xee\x0f\x00\xc5\xb1\x8a%\xb6\n\xaff\xdf\x1fk\x1bn\x8bJ\ \x1c\\\xdb \xfc\xbbe\xb8\xaf\xf4/1?_5\x8e\x9e\xeagj\x1a\x03\xfd`j\xc22m3>\ \x87\x11\xd2ByRE{g\xadS\x15x\t\xa8.\xf4\x18\xe8\\6\xe4\xec\x99\n\xbdH\xac:hq\ \xc3_\xc8/\xcc\xc2C\xa8\x88\x97`\xb5\xb5tA\xc1W\xdc\x85\xbe\x99\xbb\xe0\x1a\ \xdf\x84\xa0}0\xab\xc5[\xc8u\x07m\x1a\xbf/!n\x95\x85\x84\x06w\t$6\xa6\x0b\ \xa9q\xf1T\x88\xb7-?\xb5\x03\x82\xa8\xe9d\xc3p\x7f\xc4\x13\xebD18\n`j/\x89\ \xbfa\x82\x94\xef<-\xee6r,n\xd5M.\x1d\xd5\x02\x8f\x03Aja;T\x8b\xc1)\x07\x10\ \x14HF\xf3\x17:b\x16\x88\x01\xe8\x02]<#}\xb8\xf4\x9b\xa0\xe7\x83\xfa\x8b\xc4\ \x1bv\x10\x01\x1dt.\x1b\xb4>\x134>=4!=\x10\xd2\xd0\xa5f):\xa1\xcf[\x96Y\xd6U\ \ \x03\x0c}\xf9\xbc\xf5\x94>\xbe\x10\x0b%\x8eP\xba`\xf2\xed$\x13\x81\x08\xf1\x7f]\x1a\t\tG:\xa7\xb0\xcb-\x90\xd7\x9f\ \xf45\xc9!\x98\xcb\x8f\xe1\xd3\xcdI2\xaf*S\xaa\xd1:\xad\x82\xedc\x85:\xd6%\ \x82\xd4\xf9\xe3!\x0f\xffaJ\x1a\xfd\x82}\xd7\xe3\xc1kw\x99B^y[\xd9\x9a\xe9R\ \xca\xa5:{\x85]\xc0\xdc&0\xb1`\xac\xf0x\xa4\xfa\xfeP\x82\xba\xba:\xbcE^\x1c\ \xb5\xcer\xac\x12\xfa\xfe\\\x98[*x\xdb\x9b}N\xb8j\x0f+\x9e\xb0*\x16\xe7\xa6H\ \xfa\x00\xef\x98c\x82\xc7\x94\xd3\x08\ \x08\x88\x9fYN\n\xd4JPQ\x96Q#\xe0JX\xe0\x01\x81\x18\x92V\xc4\xbaf\xa3\xf1\ \x1a\x05\xb7\xa3\x0c\x01\xc1F\x16\xa9B0\xb6\x9a@\xb6m\xb6L93v\n\xe7\x86{\xab\ \x8eA\xc9\xf42\xb65\xce\x089\x03\xd5/|\xff\xf8s\xe45\xb9\xf0\x94\xb7\x0f5\ \xdd\x19}\xb8\xdc|A5\xec\x9e\x1e~q\x91j\x85\xa7\xeb\xfe\x90\x8b{\xa0\x0f\xf3\ \xe6\xcd\xc3\xdf\x9aO\x8aZ\xaf\t\xb2\xbc9\x14`k\xac\x11,4\xe5)o\x83?\xbf7j\ \x9d\x9cF@R\xa7\x84\x1d\xbd\xcf\x95P\x8c[M`\x93\xce\xa8\x11p\xca\xe0G2\xfft\ \xa4\xc1\x8f@.\xdf\xe5-\x94\xd8&\x84I\xa4\xeb\x98\xa7\xaa%\xe1z\xc8r\x11,\ \xf5)\xd3\xed\x1a2y\xe1\xa9\x14\x1e\xc1\x8f4\xf4\xfdy\x82\xad\x19\xfdy}\xf0\ \x95\x08W\xe1K\x06\xc1D\xb7\xde\\\x08%&\xf8\x8b\xbb%\xbb\xd1\xfd\x85\x0exD\ \xac*\xa5\x19\xee\xa2-z\x1d?n\xdd\xd3#>%R\x8cX\tm\xcc\xdfH\xa9\xfb#\x9e\x15\ \xfe\xf0\xbeE\xf0\xfbw\xc1\xef\xdf%\xba\x1dC(\x18\xc0\xe7/<\x05\xa31Z\x98\ \x7f\xdb\xc1\xff\xdf&\x82\xf4\x14X\xa1\xff{\xd7\x84F\x84D\xaa\xcd\x89\x11K\ \xb85z\xfe9\xc8\xa1\n\x94b%\x8eU\x92g\xf4\x088A%1u\x8b\x82{\xdcQ\xde\x03U\ \xeb5A?`\x97t\x04co\x81`\xdfoJCbp\xcaA^\x17+9\xd7&\xf5A/\x94Y\x1b2y%\xbbk\ \x83v\'\x06\xa6\xeeS\xc4\x9b\x91\x11P\x80\xa5i\x1c\x84\x04\xd45\xae\x89n\'\ \x99\xcc\xe15\xa4\xe0\xef*J\xc8\xb5F\x18\x04]\xb5^t\x17\xb4\xc7=\x87\xaf\xb8\ \x0b\xce\t\x87\x01P\xd0x\xf8-&\xb3\r\xbb\x9d\xff\xffv\xb8\xa9IV\x1c<\x14\x8a\ v]\x8b\xba\xd2\x15\xbc?\x84D\\\x03\x12o\xfd\xf1\x94\xa8u\xf1D\xfc\x9b\x8d\ \xaf\xa1\xe7hS\xcc\xda\xe7l\xb4n\x0b,\x8d\xe3y\xeb)m\x08\xce\x89\r\x92\xca"K\ \xb1\xb8\r\xb9\xfcg\x0b\x9d\xf5N\xff]n\xad\xfb \xfc\xe2\xc2L!#H`\xc6-\xea\ \x1cp9\x8c\x1a\x01\x07\x00\xe7\xe4C\xb4\xebHV\x82\x10\x05w\xd51^\xf69\x00XZ\ \xaa\xa4\xc7\x8f)\xc0z\xb8Z\xd0eM\xea\xfd\xe8?n/\xbc%\x1d\xa0$^\x1b\xa5\x0b\ \xc2W\xda\x89\xfei{$7V\x11\xcb4w\x8do\x8c\xd9P\x81\xd2\x84\xe0\xae<\x86\x81)\ \xfb32C:\x19tN\x1b\xcc\xc7\xf8\t? \x00\xd7\xf8&\xb8j\x1b\xc2\x96\x84$\x08\ \xfa\xc1\xe5\x1a\x7f\x04}\'|\x07\x7f\x9e\xb8[\x9b\x11qC\xee\xd9\x82\x9fk&\ \x1cCW^;:\xbd\xfc\xbfM\xc8\xe0\x83\xb3\xe60\x1d\xf7&(\x10\x14\x01{C\x8d\xf4\ \xebL\x80\xe1\xb6\xbe\x01:\xf6\xcb\xa5\xa3\xa3\x03\xbb\xf7\xec\x89\xb9\x9f6\ \xa0\xc5\xd6/\xbe\xc2\x03\x7f\xf8?l\xffj+\x00i\xaet\xa5\xef\x0f\x02\x80)\xe4\ D\x91\xff(\xc6\xb9w\xe3\xbb\xef\xea%\xef\xdb\xf8\xedV\xd4o\xfd\x8c\xb7\x9e)\ \xe6"\x86\xb1\xa7\x10\xc6\x0e~%\xb6\x90\xd9\rwu\x13\x00J\xd0J\x96S=-t\x98\ \xef\xaa\x0f\x99\xbd\xf0\xc7I\xd4\xa54!X\x9b\xbc(\xf9\xc0\x01\xf3\x11a#f\xd3\ \xa5\x9b$]\xc3h$\xeb\xa7\x91\xb1\tZ]pN\xac\x87\xc6g\x84\xa9\xab\x18\x86\x9e\ \x82\x98Ih!\x8b\x07\xee\xb1G\x11\xc8\x11p\x9dw\x15B\xef\x90\xd7\x0eT\xeb1\ \xc3\xd60\x01\xce\x89\xb4\xc5\x14\xfd!\t\xf7\xf8fx+\xdb`p\x14B?`\x87\xc6c\ \x84\x86\xd4\x81\xa2\x00J\x17\x02i\xf4!du!\x903\x88\x80mPv\xa6\xb2\xa1\xab\ \x08\xdeR\xfe\xc36hw\xa2\x7f\xda\x1e\x98\xdaK\xa1\x1b\xb4C\x1b\xd4\x83"(\x84\ \x8c^\x04s\x07\xe0+\xee\x16\xac\xe7\xce%J\xdc)"\xa3K\x82\xb21\x1f+\x07i\xf0\ \xc1W\xccw\x8b\xfa\n\x1c\xf0\xe5\xf7B?\x90\x03}\x7f.\xb4.34~c\xd8-IiC \r~\ \x84\xcc\x1e\x84l.\x04r\x06d\xf5j\'\xb6n\x81\x01\x14\xf4s& \x80\xc3\x9c\x0f)\ h\'\x1d\x05U\xd5\x85\x9e\xde\x1cX(\x03\xa0\r!hu!`\x1f\x882\x0c\xad\x8d\xd5\ \xd0\n\xb8{\x81\xa1\xcc\xe9!KK\x130(\xda\x0b:\xddE[&\xd5\xd6b\xdf\xfe\xfd\ \xbc\xf5\xcf<\xff<~\xb0h\x11\x8e\x9b:\x159v;\xcc\x83fX\x07\xad\xc8\xef\xccG\ \xe9\x91RT4U\xe0\xa9\xc0\xdf\x01\x00g\x9cufx\xbfUw\xde\x82\xb5k\x1e\x89Y\xa1\ M\xa9\xfbcj\xb3\x0b\xee\xa2\x01h)\xf9\xb3\x05z[\x8fb\xfb\x86\x17\x01\xc4\xee\ <&\x86\xa5y,BV7o.\xb8\xaf\xb0\x07\xdaA+L\x9d\xa5a\x11O\xa4\xec\xa9\xbe\xc2.\ \xf8\x9ct\xd5\x1eF\xe8X9\xfd\xbb\t\xeaAQ\x14H\xa3\x1f!\x8b\x1b\xfe\x9c\x01\ \x04\xf3\x06P\xf0%=@u\xd6\x98\x05\xcf{\xcek\xe7\xa81p\x11F\x95\x803\x90F\x1f\ \xdcU-pW\xb5@\xeb1A\xe7\xb4A\xeb3\x83\x08jA\x11$H\x93\x1fA\xdb\xa0H\xabG@\ \xdf\x97\x07k\xd3x$R\xf0\xc4\xd0[\x00k=\xe0\xae9,hm\x93\xfa\x00\xbc\xa5\xed\ \xf0\x96\xc6w\x9f\xcaE\xe7\xb6\xc0\xd8U,\xd8M\x894\xfa\xe0\x1e\xd7\x1c\xf7\ \x18\x1a\x9f\x01\x86\xee"x+\xf9\x9d\x19zO\xfc6\xfc^\xdf\x97\x07\xfb\xc1\x89\ \xfc\x03\x10\x80\xafH\x9a\xeb1`\x13\xee\xa3\x1e\xab\x1b\x14\x1b\x83\xa3@\xe2\ \x82\x80\xb5\xa9\x1aD@\x07o\x85\xc0\xef\x9d\xa0\x10\xc8\xed\x17\xcc\x81P\ \x06\x02\xd6os0p\xbc^P\xfc\t\x8b\x17\xb0x!\x16d1\xb7T\xc5,\xe7\x1b\xc8\xebC`\ \xc8\x13\xa0uY\x12\x12\xf0L)\xda2\xe7\xa4\x93\xf0\xce\xbb\xef\xf2\xdc\xe0>\ \x9f\x0fom\xdc\x88\xb76n\x04\x00\\\x8c\x8b\x85v\x8f\t[\xc4\xa3\xfb\x83+w\x7f\ pK\xac\xff\xe5\xa5\xbd8\xeb\xac\x13\xc3\xcb\x06\xc3P\xd2\x9d\xd9\x0bM\x1e-Z\ \xf5\xdb\xbf\xc0\xdeO6#\x14\xe4{\xbffw\xc4\xcf\xde\x0f\xe4\x0e\x804\xf8\xa0\ \xef\xcf\x11,\xe6\xc2\x84\x07\xc7\xfe\x91\x0e\xf1\r4\x90\xc8\xa9\x89]\x17\ \x82+\xa8\x86\xeeB\xb8+\x8f\xf1\x8c\nJ\x13\x82gL\x0b\x1bL\xfc\ \xa9\xe4\x8a\xb2\xf6\xe5\xdb"\x02\x9e\x01,^\xb8\x10\xc1@\x00\xef\xbe\xf7\x9e\ \xe4\xe45\xb7\xdd\x8d\xab\x16\xff\x08g.Z\x80\x9c\x18\xb5\xc3\xe35;Q\xe2\xfe\ \xf0\x13F8\xf5\x85\x18\xd0\x15!D$\xfe\x08^5nG\xdaf\xb3I\xb1\x82M\xade\xa0\ \x08\x12\x9e\x8aV\xc9\xceI\x8d\xdf\x80\xbeY\x068\'Z\x102E\xa7d\x15\xf7^\x06\ \x00X\xb4]\xa0\x19\x91\n\x80Q \xe0\x00\x00\x8a\xa0cT\x039\xb0\x12\xe3\x114\ \xbb\x11\xb2;\x11\xb4\xb8\x102{A\x1a\xfctmr\rE\xdfwA\r4~#\xb4n3\xf4N;\xf4\ \xbdy))?H\x80\x80\xb1\xab\x18\xc6\xae"\x84\xac\x1e\xf8s\xfb\x10\xb4:\x112\ \xf9h\x8f\x81\x86\xce0\'H-4A\x1d\x08\x9f\x1eZ\x8f\x19:\xa7\r\xfa\xfe\xdc\x84\ \xaf\x89\xa0\x08XZ\xaa`\xea(\x81\xbf\xd8\x81\x80\xbd\x1fA\xb3\x070\x04AQtu6\ \x8d\xd7\x08\xfd\xa0\x1d\x06G>\xaf>:Aj\xa1\xf1\x1b\xb2\'\x1b\x9d\x0bI\xc0\ \xd4Y\nSg\tB\x16\x0f\x02\xb9\x03C\x7f\x97\xa1{EK\x86\x13\xc7\x88\xa0\x8e\xbe\ W\xbc&\xe8\x9cV\xe8\xfa\xed\xd0zMH\xb4\x9e\xbc\xc6gD\xce\xbe\xc9\x08\xe4\x0e\ \xc2_\xd4\x8d\x80m\x10\xa4\x91v\x17k\xfd:\x04\xfb\xcd \xbb\xf2Au\xe7\x85\x13\ (\xd9\xa5YS\xc6\xach\xcbo8\x1b\x96\x10\x04\x81\xf3\xcf=\x17\xb3g\xcd\xc2W\ \xdb\xb6\xe1\xe0\xa1C\xe8\xea\xea\x82\xc7\xeb\x05I\x92\xd0\xeb\xf5\xe8\xb5\ \xf4b\xb0`\x10=e=h\xafnGwy7^\x9c\xf5\x8a\xe81%Y\xe1\x0cI\xdc\x1f\xf57\xba\ \x10\xcc\xd1\xc1\xff\x96\xb0\xd7d\xce\xf25\xd8\xb6N\xb8PN"\xb1\xefd\x91\xe7\ \xbe&`>V\tCO!|E\xddt>\x88\xc9G\xf7| (\x10\xa4\x06D@\x07\xad\xd7\x0c\x9d\xd3\ \n\xfd@.tN\x1b\x8e,;\xca;\x12#\xde\x0c\x8b\xb6/SE\\\x00bU\xcdC\xd9Q\x95CE%\ \xcb\x89\xd7\xf1\x0cP^\xc43!\xf3<\x11\nZ\xf8\xd9\xea\xae\x13\xe3\x0f8\x19\ \x11g\xacpj\xee|\x9c\xfdXu\xf8\xf3dE\x84\x992\xe5\x7fS \xb3}\x88m\xeb\xee\ \xc4[\x8d\x0e\x9a\x90ZfU\t\x12\xedF\xf6\xf9\x0b\ \xd7F\xaf\xb8a\x96\xa8\xf5=R\x85\xbb+\xff\xd5\xa8e\xd5\xfa\x16ft\xc4\xc0UT\ \xd2\x04\xdbBK\xf5C\x87\x11q\x00(\x19jc\xca\xaea\xfd\xa3\xf1\x9b\x13\x8e\x8f\ \x8ff\xeb\x9bAJ\xdf\xf0T\xf1\xc7?\xad\xc7\xb8\xa1\xf7O\x8c\x97\x9fO\x91\x89\ \xaer\xb9t\xe5\xbf\x9a\xb1\xd7\x96)\xa8\x16\xb8\x8a\x8aBp\xdd\xabJ\xb9[c\xc1\ \xb6\xc6\xb9\r(^h\xfaA\xf8\xbdj\x8dK\x87m\x85s\x07aJ\x0f\xca\xe4Z\xe1<\xeb\ \x9b\xc3H\xb5\xb8U\x12C\xb5\xc0UT\xb2\x00\xba\xe0H\xec6\x90R\xadq\xd5\xfa\ \x8e\xae\xd0\xf6\xfeM\x8dC\xbf\xdf\xf4#\xc7\xfa\x96[=-\x93`\'\xb0\xa9HG\x15p\ \x15\x95,\xa6\xc4\xac\xe5Y\xdf\x89\xb8\xd5G\x93xs\x19?\xf3C\x1c\xd9*\xfc\xa8\ T"d2\xfbc\xad\xa4\xde\xe0b\xd6\xf7\x93\xd4\x93\x92\xce#E\xb8\xd7\xfe\x92\x0e\ \xc9H\xc9hO5\x998\xd0\xc84T\x01WQ\x11\xe1\xda\x17\xf9S\x91\x18\x9e\xbe\x9a/h\ \x1f\xcc~&\xad1p\x06\xb1\xde\xcd\xb7,\x0b\x00s\xe7\x87\xe3\xe3R\x84\x9a\xado\x86H]\xf4\xd4\xb0m\xdd\x9d\ \x82\xd3\xc7\x18\xd8\xd6w\xfb\xf8Wc\x8a\xf7\xa6K7\xe1\x9c\xd7\xce\x01 _\xbc\ \xe3Y\xdem3>G\xf9\xce\xd3\x04?\xe3\xde\x8b\x0f\xef[\x14W\xc4\x999\xe0*\x89\ \xa1\n\xb8J\xc6\x90\x0e\xf7\xdd\xb5\r\xf3\xe3o4W`\xddV~\x07,\x80\x16r!k<\x93\ `\x84\x87\x9a;\x1f\xc5\x10.\x04\xd3\xe9\t\xe1\x95\xb7\x85+\x80\xa9\xc4v\xa3\ \xb3aD,\x11\xeb\x93-\xe2\x9b\xf6\xf2\xad\xef\xf6\xf1\xaf\xf2\xd6\t\x91\xca\ \xee]b\xe2\xad2<\xa8\x02\xae\x92\xf5H\x12\xedx\xcc\x9d\x12y\xcf\x11s1k\\\x08\ \xed\xf9M\x92N\x17\xda8^\xea\x95I\x86-\xe4bnu.#\xd1\xfaN\xb4\n\x9b\x10\xb1\ \xdc\xe8\xdc\x90\xc9\xf9\xb6H#\x0f)\xd6\xa7TV4Q8[\xa2x\x8f\xc4\xb8\xb1\x9a\ \xc0\x968\xaa\x80\xabd\x0cJZ\xdeb\xa2\xfd\xeb?\xb4%t\xbc\xd5\xf7\x94G\x16b\ \x889\x17\xae`\xff\xf5\xca\x9fH:\xdf\xcdx6jYL\xd0o\xad\xfb@v\xdcQh\xfe\xb8\ \x1a\xfbN\x0c&d"\x96\x87 \x97m\xeb\xee\x84\xe3\xd4\xbf\xc8\xdeo\xd6;t+\xd3Y\ \x9c\xb1\xc6\x9f\xfe\xf1\x15\xee\xfe\xe9)x\xfa\x96\xd4w\xfaJ\xe4^\x14c$\x0eD\ \x86\x03U\xc0U\xb2\n!\xe1NT\xb4\xc5\x8e!(\xe6[\xf7G\xb9\xd3\x19\xe1\x96*\xd8\ \\\xb8\xfb1\x82.$\xe4\x89<(\xd9\xd6\xf8\xdfn\x17n\x921\x12\xad\xefT\x92\xea8\ \xb8\x10+\x9ab\xb7\xaa`\x84[\x8c\xbb\x7fz\n\x00\xe0\xdaG"\x9e\x96T\x8a\xb9\ \x9a\xb8\x96^\xd4f&*Y\x03W\xbc\xa5\n\xf7{e\xb4 /n\x97\'\xf4QB\x0e\x00[\xf7\ \xe3\xd9\x17\xb6\x02H\\\xb8\xe3q\xf3\xbf\xc5\x85\x1cH,\x0b8\xdb\xe6}\xc7r\ \xa1\xff\xf8\xd2\xab\xf0\xfck\xff\x92}Ln\x93\x13!\xa4\xfe\xee\xd9\x89[3n\x19\ C\x1f\xbf\x81\xfe\x1bp\xado\xb6\x80\x9f},\xd2\x06\xb5\x7f\xc9?\xa4\\v\x98\ \xb3V,\x15\\\x9f\x0e\xcb<\x16;\x1f9*\xe8BW-pi\xa8\x16\xb8JV\xc0\x16o%,n)0\ \xe7Y}O9\x9e\xbd\xf9Y\xe0\x85\xd4\t7\x03s|!\x8b\x9c- W]u/\xfe\xb5\xef\xde\ \xb8"\x9em\xe2\xcdeC\xb5\x03\x00\xf0^\xaf\x13\x8b\xf3m\t\x89\xb7T\x92\xb1>\ \x9f\xa4\x9e\xc4\xa6K7\x01\xed\x91u\xaf~\x91\x03TF[\xd8\xeb\xae\xef\xc7\xe5\ \xed\xaf\xcb>\xfeGOD\xf6a\x8b9c\x99\x0f\xb7\x90\xab$\x86*\xe0*#\x9aD\xadn6r-\ o.\xcf\xde\xfcl\xca\x85\x9b\x0b[\xc8\x85\xac\xf1\x7f\xfd\xeb\xde\xb4^O&\xc2\ \x887\x03#\xe2\x99\x04\xbbz\xda\xba\xf6Scn\xbb\xeezZ\xcc_)[\x9a\x90\x8830b\ \xce\x15\xf2\xe1\x10q5\x81-9\xd4Z\xe8*#\x16\xae\xd5\x9d.\xcb\x9baJ\xf7{\x98\ \xd2\xfd^\xda\xc5\x9b\xcd_\xaf\xfc\t\xb4\xe77I\xceng\x93\xad\xd6\xf7\x86j\ \x07O\xbc\x93\x85\xa9\x8f\xaeT\x83\x93k.\xa8\x8b\x12\xafe\x81\x93\xa3>\xb7}\ \xb2X\x91\xf3\xc4\xe2\xa3\'^\x8f\xb2\xcc\xd9q\xf2\xe1Du\x9fKG\x15p\x95\x11\ \xc9p\xb8\xcc\xd90\xc2=\x9c\xe2\xcd\xc0\\\xc7\x1dw\xac\x8bZ\x9f\x88Kw\xa4\ \x8b\xf7\x16\xbd~\xb8/!&3\xeam\x82V\xa7\xf3\xcc\xf7x\xebb\xc5\xb9_)\x13\x8ei\ \'\x02W\xc43E\xc8U\xe2\xa3\xba\xd0UF\x1c\x99"\xde\xa2\xec\x19\xfay\\\x12\'I\ \xe0\x18\x7f\xbd\xf2\'\xc0\x1d\xeb$\xcd!\x1f\x8d\xd3\xc6\x86\xd3}.\xa7\xbdg:\ \xaco.\\\xb7\xfap\xb9\xd4U\xe4\xa1Z\xe0*#\x96\x8c\x14\xefa\x86q\xa9\'\xc2H\ \xb7\xbe\xc5\xb8\xa4\xb1@\x11\xf1N\xc4\x8d.\xa5\xbd\xe7e\xf3\x06x\xeb\x1e]\ \xba"\xee\xb1\x95\xb4\xc2\x192\xd1\xa5\xae"\x8ej\x81\xabd\x169F\xa0:O\xf8\ \xb3\x9d\x1da\xeb;\x15\xe2m6\x1b\xa0\xd7E[\x1dN\xa7\x17$EO\xe5\x91,\xde\xc9X\ \xde\n\x1c\xe3\xafW\xfeD4\xb9\r\xc8n\xeb{~ \x10\xe5F\xbf\xa4\xb1@p;\xebS\xbb\ \x01\x00\xae\xeb\xa7%t\x9eX5\xc1\x01y\x167\x9b\xf5\x05\xaf\x01K_\x93\xbc=\ \x93\xd0V\xfb\xdc\xc6\xf0\xba\xfak\xceO\xe8\xdc\x0c\x1f=\xf1:\xceZ\xb1\x14\ \xcd\xf3\xae\xc3\xa2\xed\xf4\xbaT\xd4\xf8O\xf4w\xa4\x12A\xb5\xc0U2\x8br\x1b\ \x88\xcb\xa6\x08\xbe\x14)\x89\x1a\x83\x82<+\xcaJ\xf3\xa2^\xda!A\xcft\xcb\x9b\ \x8b\\K<\x95\xd6\xf7\xf2\x95+Svl!\xd8\xa2\xadt2\x1b\x83\x12\xe2\xfd\xdc;\xfb\ \x04\xado\xb9\xb0\xc5[h9\x11\x9a\xe7]\x17\xb5\xcc\xed\xbc\x96*\xd4\x046y\xa8\ \x16\xf8h\xa6\xdc\x06b\xde\x18\xa0:\x17\xb0\x19\x01P\xc0\x80\x1fh\x1d\x04u\ \xc0\x01|\xd7\x0e\x90i\xae\xf3s\xa0\x07\xd4oY\xd5\xaer\x8c \xee\x8c\xce\xd0M\ \x95\xeb\xfcX[o\xf8\xfd\xa4\xda\xf2\x18[\x8e\\\x86\xc3\xfa^\xf7\xf8\xe3i=\ \x1fW\xb4\x85DnE\x90W\xd4E\x8ep\x0b\xb1\xbe@\xba\xe5\xad\ \xa2\x02\xa8\x02>z\x19\x97\x0b\xe2\xa7\xd3\x01\x82\x00\xf5\xdf6\x10\xad\x83\ \x80A\x0bL\xc8\x03\xea\nAL-\x02\xb5\xbf\x1bp\x07\x86\xfbJ\xa3\x18\xc9q\xef\ \xd9C59v\xda\x01\x7f\x1a|_\\W:[\xbc\xd9\xa26?\x10\xc0\x96\xa6A\x00\xc0\xc9UV\ \x18u\xaacN\x0eR\x85\x9b){\xfa\xdc\xd0\xf2[\xab+StE*\xa3\x05\xf5?u\x94B,\x9e\ \x00h5\xa0\xde>\x04\xbc}\x08\xd4\x8evP_\x1d\x03\xf5\xc2\x1eP\x1f7\x0f\xf7\ \xe5e%s\xfb\xe8\x97\x81T\xf6\xb8\xfe\xd9\xfa\xf0K\n\\\x8bt\x8b^\x8f\x0f\x1b\ \xfa\xf1aC?|\xc1\xec\xac\xac\xac\x0f\xec\x0f\xbf\x94BJ\x82\x1aC\xbc\x9a\xe5R\ \xaco\xb1\xe2-\xab\xefZ\x1f\xb5\x9cl\x0c\x1c\x00.y\xb5\x11\x97\xbc\xda\x18^\ \x1e\xfb\xc5\xfa\xb4\'\xb5\xad\xfd\xe5\xfcp\x8ba\x15aT\x01\x1f\xadT\xd2\x0f\ \x1e\xe2@\x0f\xef#\xa2\xd7\x9b\xee\xab\x91\xc4pX\xdf\x13\x1c\x9fet\xec\x9b+\ \xda\xdce&\x16\x9eM\x89k\x05o\xb6\xa0\xe0\xcd\x16\xd1\xcf\xb9\x89k\xec6\x9f\ \x1b\x9dUx\xaf\xd7\x89\xf7z\x13\x8f\xb52\xd9\xe8}k\xfa\xe2n\xbb\xb3\xd6\x19\ \x15\xd7e\xb2\xbc\x95\xb6\xbeW\xdf\xb5\x1e\xf5\xd7\x9c\xaf\x88x\xb3\x91r\xcc\ \xb6\x19\x9f\xcb>\xae\x9a\xc0\xa6\x0c\xaa\x0b}\xb42dhQ\x06\xfe\\O\xaa\xb9\ \x1f\xc4\x87M@P`\xc4M\x00\x98Z\x0c\x9cT\x0e\xa2\xc2\x0e\x98u\xf4v=^P\x8d}\ \xc0{\x87\x81 \xcb\xc4\xd4i\x80\xc9\x85 &\x17\x02U6 \xcf\x04\xe8\xb5\x80/\ \x04\xea\xe8\x00\xf0n\x03\xd0\xe9R\xe4+i4\x1a\xe4\xe5Z`\xb7\x99`0\xd0B\x16\ \x08\x04\xd1?\xe0A_\x9f\x13B\xb6\xa5\xd1\xa8GA\xbe\x15\x16\xb3\x11Z\xad\x06$\ I!\x10P\xa6\xda\x16@\xbb\xcd\t\xce\x89g\x0eD\xbb\xd0{\xf5\xc0!+\x7f_=\x05L\ \x1f\x04&\xf6\x00\xf9\x1a@C\x92\xe85j\xb0\xdf\n|\x97\x03\x90\x04\xbd\xdd\x8e\ f\x12/l\x8b\xfc\xadn\x02\xb0\xb9\x88uL\x83\x157\x1d\xd8\x11\xfe\xfc\xbf\xed\ \xad8\xe9\x94\n4\xd6\xf7\x82\x02\x11u\xce/\x9a\x07ab\xb9\xd0\x8b\xaczL+5\'\ \xf2\xd5c\xb2|\xe5\xca\x94\xc6\xc6\xd9"\xee\x9f\xb6\x0b\x00-\xdelRYZ\x95-\ \xda\xf1,W9\xb1\xef\xcb\xdb_\x17\x9d>\x96l\x89U6k\xde\xbaIp\xbd\xd0\xfc\xf0X\ \t}r\xe0&\xb0)\xd9^8[Q-\xf0\xd1J#m=\x10\x97L\xa6\xa7n\xb1qx@}r\x04\xf0s|\xbd\ \x1a\x00\x97\xd5\x81\xb8j*\x88J;\xb0\xfd\x18\xf0\xe6\x01\xe0\xebV\xc0f\x00qJ\ %-\xd8lN,\x03q\xd5T`\\\x0eP\xdf\x07\xbc{\x18\xd4\xbb\x87\x81\x01/\x88\xda|\ \x10W\xc5\xae\x85|\xe5\x91\x93c~\xce\xa0\xd3i1\xb6\xaa\x10E\x85v\x04\x83!tv\ \x0f\xa0\xab{\x00$E\xa1\xb8\xc8\x8e\xf2\xf2|\xde>v\x9b\x19c\xc7\x14\xc1n3#\ \x10\x0ca`\xd0\x03\xb7\xdb\x07\xb6\xd2?w~rsm\xe7\xf4\x01s\xfa\xe9\x17\xc3\ \xcc\xc1\xc8\xba9\xfd\xc0$7\x7f?[\x08\xb8\xb2\x158\xa5\x17\x18\xa4\x80\xcf|\ \xc0gE\x1a\x044\xc0\xa9}\xc09\xdd\x91m\xc7\x17\x12\xb8\xea$-\xf2\xcc\xb4\x18\ w\x18\x80\x0e\xd6\x9f\xf4\xf1+\x1f\xc1\x7f\x0bi7\xeb\xce\xfc\x17\xf1\x82\xfd\ gx~\xf9r46\xf4\xa3\xb1\xbe\x17\x8d\xf5\x91\xe4\xbd\xaf\x8e:\xf1q\xe3@\xf8\ \xf5}\x872\x83+.\xc9\x88\xb7\xe3\xa2*8.\xa2\xc58\xdd\x19\xee\xf1\xe0Z\xdcl\ \x12\xb1\xbe\xe7\x9c\x18\x11\xe4m\xdf\xd0\xf7\xa2R"-\x07\xf6\xfc\xf0T\xa3\ \xba\xce\xa5\xa3Z\xe0\xa3\x95\xb7\x0f\x01?\x9dA\'\xb3\xfdb\x0e\xa8\xaf\x8f\ \x01_\x1c\x8d\x99\xb4F\x9c:\x06\x98^\x02\xb8\x02\xa0\xfe\xfe\r\xd0\x17q\xb5\ \x13\x14\x05\x9c1Vt_\xea\x89o\x00w\xc4\xb2\xa5\xf6v\x81\xb8}.Pl\x05,\xba\xa8\ \xcf\xe4C\xa0\xa2,\x1f\x06\x83\x0e=\x8eA\xf48"\x0f\xd0\xfe\x017\xc6\x8d)\x82\ \xcdj\x82\xd5b\x84\xcb\xed\x03@\x0b~YI.\x08\x00\xad\xed\xbdp:\xa3\xc3\x06Je\ \xa1\xaf\x1d\x17y\x7f\xd3\x11\xfa\xe73\x95\x803\xc6\x7f\x1eA\x01\xe7v\x02yA`\ [\x1e\xb0-\xd2E\x12{\xec\xc0U\xad\xc0\x0470\xce\x03\x18\xb6\x07\xe0\x9f\xadG\ \xa1\x95@Y\x0e\x81\x87>\x0e\xa2\xd4\x0f\xe4\x05\x80\x81\xa1sP\x04\x89j\xe7\ \x19\xa8\xb7\x7f\x80\xcfJ\x1e\x02@\xe1\x9b\xc7\xa3\xa7\x8d\xdd\xf3!\xedf\xbe\ c^9rL#\xa7\x02\x97\x94\x81\x80a\xf7\xf4\xb0\x15\xae\x14L6z\xdf\x9a>\xe4\xdd\ \x99\x97\xf0\xf4\'\xa53\xcf\x95\xb4\xc2U2\x1f\xd5\x02\x1f\xa5P\xbd^P\x7f\xdb\ \x01|\xd9\x02h\x01\xe2\x8c1 \xee\x98\x0bbq5-\xa8\\4\x00\xe6\xd1\xbd\x8b\xa9O\ \x9b\xa3\xc4\x1b\x00\xa8\x1e\x91\xb8\xf9A\x07\xa8\xe7v\xf3\x05\xba\x9f\xb5\ \xbd.9\xc1\xb0X\x0c0\x99\xf4\x08\x91$\x1c\xbd\xd1\x16#EQ\x18\x1c\x12g\x9b\ \xcd\x04\x8a\x0c\x81"C\xc8\xcb5\x83\xd0\x10p\xb9\xbc<\xf1\x1en\xc6x\x81R?\ \xe0\xd5\x02;r\xa3?\x0b\x018d\xa1\xdf\xd7\x0eY\xee\x86\xed\x01\x18\xb6\x07P\ \xdb\x10\xc4gC\x8e\x86\xc5\xdd\x80=\x04\xc04\x0bgt\xfc\x12\x1a\xca\x80\x8f\ \xca~\x0f\x08\x06\x12\xb2\x9f\x80~\n\xcf]\xae\x94\xfb<\x96x3\xees\xc6\x82\ \xbd\xceq\xa9"\xe7\x8c%\xd2\xa9\xa8\xd0\x06D\xbe\x83R\xc9l7<5\x0b7<5\x8b\xb7\ ~\xd5\xfd[T\xf7\xb9DT\x0b|4\xe3\r\x82z\xb7\x01\xf8\xa2\x05\xc4\xbc*\xe0\xa4\ \n\xe0\xf4\xb1 fW\x80\xda\xd4\x00|\xd3\x1ey\xde\x17Z\x01\xdbP\x82\x94@\xe2\ \x1b\xf6w\x83z\xda\r\xf89\xff\xdc}\xde\x88\xd8\x13\x00,zz\xba\x9a\x84\xa9J\ \xd76\xcc\x87K\xb8\x90V\x146\x0b\xed/\xf6z\xfc\xa0(\xbe@\x05\x87b\xf9\xbe\ \xaeF\xbc\x7f\xef5\x00\x80\xabV\xbf\x08\xe4O\x86\xd3\xed\x8f\x7f\x82d\x08\ \xb1\x7f\x1f\xd2\x06*\xe3\x86~]mFZ\xb0\xb9\xb8\x86\x0eS(p\xe9\xbb\xed@\xb9\ \x0f\x98\xe4\x02\xce\xe9\x02\xf6\x05.\xc5\xa4\x81\x1f\xe0\xe5q\xd7\xc0\xaf\ \xa1\x15?[K\xa6J!\x93\xda\x89^\xf8\xebc\xb8\xe8\x89\xe1\xbe\x8a\xf4\xa3&\xb0\ )\x87*\xe0*\xc0\x80\x8f\x16\xf2O\x8f\xd2\x16\xf8\x89e .\x9e\x0c\x98t\xa0\xbe\ \x18\xca\xe0\xcd5D\xb6\xef\xf3\xf1\x8f\xe1\x0e\x80j\xec\xc5\x9e\xfe\xaf\xb0w\ p+\x1c\xfevP\xa0`\xd7\x17`\xe6i\x97a\xea\x82K\xa0\x1d\x9b\x0f\xe8\x95w\xfa\ \xe8\x86,x\xab\xd5\x14\xd3\xf5\x9d7v2\x16\xff\xe1\x1d|r\xff\x8f\x90[F\xbb\ \xfb\x83A\xe5\x12\xd6\x04\xb9\xe9z`\xd7N\xfa\xfd\x8b;bo;\x84m\xe8\x92\xaa\ \xdd\x11\xb7\xbb\x10\x06\x11c\xfa\xe3B\xa0\xc8\x0f\x94\xfa\x80\xd2\x8e\xff\ \xc5\xfb\xe5\xbf\x81\xc3\xd8 \xe3\xa2U\xa4\x10\xab\xa8\x8b\x10B\xd6\xf7\x9b+\ N\xc6EO|-\xf9\x9c$k\x80\x9a\xae\x84\xb6T\xf1\xe4\xf5\x91\xff\x07\xb5\x02[b\ \xa8\x02\xae\x12\xc1\xe5\x07\xb5\xe1\x00\xe0\x0b\xd1\ti\xf3\xc6\x00C\x02N\ \x84XjA\x08\xedL\xe1\x83\x8e\x97p\xd0\xb9\x03s\x0b\xce\xc1\x05\xe5\xcb\xa1#\ \x0c\xf0..A\xee\xfc\x13@y\xfc\xc0\xa7G\x80#\x03\xa0\x9c~ @\x81\xb8}\x8e"\x97\ \xcdX\xdd\x9dM\x07\xb0k\xf3K\x00\x05\xe8-vX\xf2\xcbQ>\xe3L\xe8\x8c\xb4\xcf\ \x99dU\x95\xd3\x1b\xcdC\xfb*r\t\xe2<\xfet\xe4}\x0c1f\xc3\xa4\x0e\xb6\x19\x81\ \xef\xed\xe2\xdb\x05\x04\xff\x0e|(V\x1a\xfch\xb6\xbeS\x89\x90\x88s\xdd\xe7l.\ \xfc\xf5\xb1\x84\xce\xf3\xcb\x8d\x11\xb1_s\xc1)\t\x1d#\x19\x98:\xe9j\xb7\xb2\ \xcc@\x8d\x81\x8fR\x88kg\x8a\xff\xf5\xb7\xb7\xd2?m\xac9\xc5\xec\x98w\x89\x85\ \xb7\xcba\xd7\xf78\xe8\xdc\x81\x13\xf2\x16\xe0\xa4\xfc\xc5\xb0hs`\xc8\xb1#\ \xf7\x8c\x13\x00\x00\x83\xcf~\x06\xea\x93fz\xaaY\x97\x1b\xe8\xf3(\xf3E(\n-\ \xbb\xe9y\xa8Fk\x1eJ\xe7\\\x8e\x8a\xd3\x7f\x0cm\xfe\x04l}\xe9At\xb64c`\xd0\ \x83\x81A\x0f\x9c.\xfa;\x94L=\x15~/\xedN\xd6h\xf8*8\xa5G~\x1fmY\xc4\x11\xde\ \xc5\x15t {\xb2\xc9\x88\x03V\x88\xbe\x0e\xf3\xff\x0c\x00\x803{\x00\x0b\xd9\ \x8f/\x8b\x1f\x05\x00,h\xff\r\xf2\xfd\xd5\x92.\x8d\x928(P\xe1\x13\xabK\x99R\ \xb1\xef5\x17\x9c\x82\x93\xc7\x95\x86\x97\xd3\x19\x0b\x7f\xe4\xb3]\xf8\xbe\ \x9d.\x02\xb4\xfao\xafc\xabc\x93b\xc7\xfe~\xe0K\xc5\x8e5\x9aP\x05|\xb4\x12\ \xae\x7f.\x80i\xc8\x92`%\x9aQ}^Zx\x01`\x16\xdfM\xbdop\x1b\x00\x023\xf3"\xd3?\ \x88\x02KX\xac\xccCc\x82g\x8e\xfc\x1ek\x1bn\xc3\xdf\x9b\x7f%zi\xee\xd0 \xd66\ \xdc\x86Y\x98\x85\xf3p^x\xfdW\x8f\xff\x02\xef\xdf{!\xbe\\{\x13\x9c\x9dt\xb5\ \xb8\xce\xfd_c\xe7\xdb\xff\x00\x00\xe4\x16\x97b\xcf\xbf\xef\xc3\x965\xd7\xa0\ \xf1\xd3\x7fC\xa33\x08\x1e\x1f\x00z\x9a\x0f\xd1_\xd5\xc8\xaf^F\x8d\x99)\xba\ \x9f\x12\xe8bTb\xdbPW\x8d\xe2\xa1\x01\xd2@\xbf\x0f\xcfW\xc9+\xf8q\xbc\x13\ \x98\xec\xa2\xf0^\xf9\xdd\xf8\xa6\xe09\xec\xce{\x05z\xd2\x8cs[\xefGGy{\xdc\ \xfd\x83\xa1\xd1\x99\xe4\x96(LQ\x17\x06)\xadFGb\xcd\xf3~\xaf\x1f\x9dN\x0f&\ \x15\xe7\x81\xa2(|\xbam/\xc6[\xa7Fm\xa3N\xffJ?\xaa\x80\x8ff\xaas\xf9\xd6\xa0\ \x86\x00\xe6\x0f\xcd}\xda\xd9\x19YO\x01\xd4\x16Z4\x89\xd9\x15\xc0\x9c\x8a\ \xa8};\xbd\xcd\x183f:,\xb6H\xd6\x19\xc5\x9a\x92\xa6\x1fW\x04\x00\xf8\xf1\xd8\ \xbb\xf1\xb3i\x8f\xe0g\xbf\xfb\x8f\xe8e\xe9\t#\xce(Z\x8a\xbbpW\xd4\xfa\xc2\ \x9a\x99\xa89\xf3j\xb8{Z\xe1\xe9\xa5\xc5\xe8\xd8\x8e\xf7\xd0}\xe4\x00\x0e}\ \xfd>\x00`\xe9\x1f\xfe\x89\xf9\xbfX\x0b\xb7\xa3\x1d\xb5\x0b\x7f\x0cK>=\xd8\ \xf8\xe6\x1f\xbf\xc2\xee\x17~\x83\xf7\xee\xb9\x00-\xdb\xdfE\xc3\xb6\x0f\x01\ \x00y\xb9\x16\x18\xf4\xb4+\xd0\xef\xeeG\xff\xee\x8dp\x80\xe5\xb7n<\x0c\xfc\ \xf4j\xe0\xf4\xd9\xc05W\x02\x8d\xacX\xb2s\x10\xf8\xeb\x83\xc0\xd2\xf3\xe9\ \xcf\x17\x9e\x06,\xbf\x06\xd8\xb7G\xf0{\xf9\x02C\x1e\x00V\xf2\x99\x06@\x19\ \x93R\xd0E\xff\xbe\xed9\x06\x94\x96\xd3UXv}\xdb\x89B\x81\x99}9A:Y\x8dM\x89\ \x1f8\xdd\x01l+z\x12\xcd\xd6\xaf\x00\x00\x9f\x97<\x84N\xd3\x1e\x14\xf8j\xf0\ \xf6\xfe^\xd1\x1ct\xd3PnB\xeb`\xe4d$E\xa1\xa5?\xc5I~\t\x10\xaf\x12\xdbp\xc3\ \x15q\xa5\xaco1\xe4X\xe1\xbfx\xfd\x89\xf0K\x0e\xfb:{Q[\x94\x0b\x83V\x83\x03\ \x87[\x11\x0c\x86Pb\x1c#\xfbZ\x85\x12\xd8\xc4\x9a\xbb\xa8\xc4G\x8d\x81\x8fV(\ \x80\xb8\xac\x0e8m,\xa8\xfd\xdd \x1c^PV\x1d\x88\xe9\xa5@\xb9\rh\x1e\xa0\xa7\ \x8b\xb1\xd9\xd5\x01\x94\xd9\x80\xd3\xaa@,\x99\x08\xcc\xab\x02\x8e\xd1M0.\ \xca[\x8f\xc215\xa0\xd6\xee\x00\xda\xde\x88\xda1u8\xd3A\xcf\xe3\xd6\x02(\xf7\x02N-\xf0/c\x0fp\xc32`?\xfd0\ \xab;\xbe\x18\xc1\x00\x89\x9en\x0f~\xe8\x06\xda\x8d@\xbf\x8e\xde\xa7\xc0\x0f\ \x14\x04\x80os\xe889#\xe6\'\xf7\x01~\xad\x03\xad\xe6\xef\xc2\xe7$\x11\xc4a\ \xdb\x16\x94x\x8f\xc3w\xedn\xe4\x98t\x18\x97g\xc0\xc4BS\xd4\xb5M\xc87bo\xa7\ \x07o\xee\xef\xc5\xbe.\x0fB$\x89\xe6>?\xecF-n\x9c[\n\x15\xe9\x0c\x0e\x0ebm\ \xc3}X\xbb\x84^v\x9c\xfa\x97\xf0gE_\xdd\x89R\x9b\x195+"\x05\x8a<\x81 \xde?\ \xd8\x82\xdd\xed\x0e\xf4{}\xd0k4(\xb5[p\xc9\xf1\xd5\x18\x93\'-c;VB\xdb\x03\ \x1f\x7f\x8b\x05\xb5\x95\xf8\xe7\xf6\rQ\xeb\x7f\xf1\xfa\x13xt\xe9\n\xd1c\x06\ I\x12\xf7l\xde\x8e%\x17]\x8c\xd7w\xd1\x03\xc2;\xdf\xf9\nx\x87~\xff\xb7\xfe\ \xdbqB\xde\x02\x9cZH\x7fQu\xeaW\xfaQ\x05|\xb4\xf2\xf0VP\xd3J@\xd4\x16\x80\ \x98[\t\x98t \x82$\xd0\xe9\xa23\xd2\xb7\xb6\x02!\x8e\xaf\x97\x02\xa8\xcd\r \ \x1a\x1c\xc0\xc9\x95\xc0\xd8\\`Z\t\xe0\'A\xb5\xf5b\xff\xc6\r\x98\xdc[\x1c\ \xbd\xfd\xbf\xbe\x07\x16\xd7\x80\x98Z\x04\xa2\xae\x10T\x8f\x17\xc4\xc7G@}u\ \x0c\x9e\x1b\'\xc3RR\x02\xe2\xb8b`\xc0\x0fjgg\xb8\x07\xf1S\xc5\x00\x00 \x00I\ DAT\x1f8\x00|\n\xe0t\xdc\x19>\\Yi\x1e\xfd\xf3\xea\x9f\x03\x14p\xb0\xa1\rA\ \x1f\xed\xd6/\xac\x99\x85c\xad\xbd\xc8\xb1\x9b\x90c\xb7 \xbf\xb2\x1aZ\xad\ \x0e$E\xc1\xef\x0f\xa2\xc7\xe1D\xff\x80w\xc8\xadN \xe8\xf3\xe2hk\x0fJ\x8ar`\ \xb5\x9a`\xd0k\xe1\xf2\xf8\xf0\xce\xff\xad\xc2\xd5K\x16\x86\x13\xc9\n\xca\ \xc6\xc1R7\x0e\xc8\x01\xf0\xe9G\x91\xef\xf6\xee\xdb@\xfdA\xe0\x97\xbf\x01N\ \x1br\x1b\xd6N\x02\xc6\x89\xc7\x9a?\xfd\xf6=h;;1~\xe6\xa9\xa8%\xf5pj\x81F\ \x0b=\xf5\x0b\x7f}\x12\xe8\xee\xc2%[\xbe\xc6\x86\xf9\'C\xab%0sV\x19~\xf9\xe3\ \x9bPw\xfa\xf9(\xa9\x9e\x822\x1f\x9d\xb8\xd6\xab\xa7\x8b\xbb\xec\x19r\x14\ \x94\xfb\x80\xb3\xc3\x95\xd9\n0\xd3\xf1#\xb4X\xb6\x01\x00\x08\x82\xc0\xc9\ \xdd7F\xae\xa1i\x00U9|\x01\xbf`r\x1eH\x92BC\xaf\x0f{:\xdc\xc81j1\xa9\xd8\x8c\ 9\x95\x025^\x87\x19\xa6\n[\xa6b4\x1aq\xf1\xc5\x17cR)\xf0\xab\xdd\xd1eF\xcf\ \x9eT\x85\x0f\x0f\x1dC\rk\xdd\xdf\xbf\xda\x8b^\x8f\x0fW\xce\xac\xc5\xc4\xa2\ \\t\xbb\xcb\xef\xb1\xf9\x1c\ \xbeH9\x1d\xa2\xc3:}\x00\\\r\x05\x8f<\x8b\x8b\xb4B/\x10\x0f\to\x91\xablIc\ \xec\'\xff!\x068\xf4\xfb\x8d\xf71iL\x08\xe3\xabgVcw\x11\x84\x00\xe8\x90}cI\ \x00@%\x9dT1:\x99\xe2\x1a\xa1vrI\xafY#\x00\xca\xd9\xd2|c\x90\x1b+ \xe0\xe2a$\ \xb2\xbb\x13\x83\x8e\x88\xe8\xdb\xe1\x92\xd2\x8b`<\xce\xc5\xc3\x9a\x7f\x90"\ \xaf\xc7\xea\x91\x87\xe9\x9f\xd0V\x18\xe3\xf7\n\xb4\x0f\xf6(lExtL}\xd4\xeb\ \x8b\xd2\x0b^\x0b\x7f6\xfe\xa5\xf7t\x90\xc5\x06`\xd0T\xa0\xd1\x04\xa8\xa2b\ \x93?\x9a\x9a\xfa\xf56\x126\x81|\xa5TW\x8ffd)\xaefP\xf4n\xa1\xb0\x8b\xd1\x15\ hpl\xb3\xa3\x04\xa8\x08pJBW\x1aL\xd5\x94Ak\xc9G\x0b\xf8\xe0\x08Ix\xcdM\t\xb6\ \x88\x05\x18|\x96\\a\x98\xe1\xf4\x99\xd1X \x9fV\xda\xd2\xc0\xc1\xa4\xf6x\x0e\ \xe2\x87\xcd\x8e\ts\xddM\xb7\x8c\xba\xe4\x8bt\xc0\x14\x16G\xc8\xc7\xa9\xeds\ \n\x89\x14\xba\xc9\xfa @\xb0\xe1C\xe2\x06\xbe\x88\x10Y!\xf8\x87\xc2\xbb\xeb\ \x0bj\x0c\xf3\x803\xcb\x98\x0fvME\xc8\xa0\x18\x8a\xb4\xdcJ\x97\x91;\xe6\xbc^\ \xe1%w\x9f/\x02uZ\xd6\x9f\xe96B[\xbb\x89w\x1e\xff\x1av\xfar\x8em\xb1\xbb\xa6\ <\xd2\xfc<,\x13\xe5w\x0f2P\xaah:\x7f\xd7\xa1p\xe5\x0e\xb7f\xd8C\x08\xab~\xf0\ )Z\x84N\xfa\xbc\xa9^\x83[@\x16q\xbe*\xbcf\xb6\xcaj\xc1\x8c\xd1zmnf/FRD\xd0\ \x94b\xdcw\xf3\x8b^\x8d@\x97\xcc\x9e\xefy5m\xf1\xe4\x95\xa27_\xc6C\x9eb\xaa9\ \xe0\x0f\xca\xe1\x14\xe6;\xfe\x08\x84\xe1?Ur\x00@U\xb7a\x82q\xe1O\xa5\x19\ \x17\xf0w\xe2 \xbd\x01I\xd9\xb7/z\xc3*\xf8h\xff$]\xe8\xdb\xbb\xd9\x0f\xe9Rk\ \xbb\n\x97~V\xa3\xfa\x14v~!ud9\xbf\'\xd0N\x16_\xd8\x19S\x81\x1f\xa3\xb3\xcfA\ W \xa8\xbd\x1c\x01\x1f~9\t\xb9\x1e\x90\xccUTBWQC\x10\xbc03{@\xd1Yg\xc8\x86\ \x13\xb8\x00\x8fC\n_\xac\xb9$DbP\x98(8%\xb6~\xfa\xaf\xe5g1\x9b9\x90\xbd\xa4\ \xce\xa7H\x12\x03\xa0\xbf\xbf\xbe\xd3Go\x8d\xc8\xd4\x06\x83\x08\x01\xce\x93S\ \xe7\xff\x9c\xb6\rWV\xfb\xa9\xc1\x1e\n\xb0+\x19\xb5\xda\xf5\xa5\x07\x9a\x06Z\ w(i9Cg-\xeaXR\x13b\xaf\x10\x19.$\x14&\x85H\x1e\x10Z\xb7\xfa!\x99S\x9bvR\xc6\ \xdfP\xd0j\ru\x9a\x9e~\xe8<\xae\x1f\xfc\xb4y\xe0H\xc2%\x0cP\x15\x87\xb8_\xf3\ \x13\xe9\x9d\x8a+\x90\xab\xa6\xa0.\xb2\xfd\x18\xd9\x03\xf9M\xe8\xbe\xc0\x01l\ \xeeN:\x96\x1e\xae\xf5.\xe7\x02Q\xa4\xff\xb0|\n\xb8f\xe0\xbf\xf6Cg\x90\xb0~\ \'}\x9d\x88K\x1b\xaf\xc7\xa31m\xb9Ul\xf7\xdd\x7fS}gZ\xc48\x90:x=\x03p\x01\ \xf9f\xfe\x0f\x11c`]\x8b"\xdb\xd6\xdfi\xfa\xa0\xbf\xce>X \xdf\xfe\x8e\xf8\ \x9c\xb4\xc6\x9f\xd4\x85\xa7[E\x9a\x83\xa5y\xd2A\xe2\xc8\x8d\xf8\xac\xbd\x9f\ \xfc\xb6\xed\x83\xd6\xabm\x8cF\xabq\xad\xdd+\x89\xc1\xc1\xc1\xa7\x8c\xe9\xe3\ \xe3\x028\xf2\x8c\x81\t~\xa19l\xf4\x88\xf3\xb0\xda\xaaq\xb3\xb1,R\xc9\xf5\ \xd8\x1d\x0f"\xc3\x11\xe6/\x18\x80S[e\xed9\xee\xd8\x97\xaf\xcc,\xf4t\x80\x82\ U\x18\x13\x18\xe7~&\xc1\x80[t@\x90af\xa2\xdd\xd0\x13\xdeq\x12\xce\x8b\xcd=\t\ \x01\xa2\xedX\xc2\x84\xcdo\xd1\xc4gFe\x83\xb8?,]|~\xe0W^B\xc0\xf9 \xf8a\xed\ \x99\xac\xe9\xe8\xf1\xdd\xf0s\x07\x12Q\ri\x19\x18\xdb\xc6\x1dA\'v\xb8G\x8b\ \x03}\xa5\xf0\x19\xc8\x7f\xf0\xa2xr\xd9Ml\xca\xa60\xfcpc\x84+\x0c\xf9}\xd3\ \x85\x04KDP\xdd\xf6QH<\xf4]J\xdc\x1c\x07m\x94\x8d\xf6u\xdf`\x8f>q\x10~!\xe2\ \xaa\xa3\xc9\xb3n\x90\x12\xe2\xe1\x13iy9,DO\xc2i\xb86\x1c\x82*\xbct\xf0\x89\ \xe8~\x89Qk\xda\xe5J_\x0bv\xd1\x00E![\xce\xc980\xca\xb3f\x9d\xe0\x0e"(\x95t5\ \x01\xe4\'\xb7\nw\xc6jV$\ \x1b\x18\xa4f\xab\xbbgk{\xd7\x88\xca\xa8\xddd\xe0\xa7\xdc\xf2\xc9kp7\x1eB(\ \xbaZ\xeeET\xfd\xfe\x8cb\x8f\xf2\xbe(\n\xd7\xdf\xe0\x92@\x1e[\xab\x0e\x8d\ \xa8W\xd3+J35\xd4\x86\x8a\x8f\xc6\xbc\x0f\x84\xb3\x9e\x14V\x1d\xb2\x1d\xbe\ \xc7x\x0bB\xef\x80\xdd\xdaw\xf0\x81x\x93=\x853O\xa4\xcf\xbe\xdb\xca)\xfc\xd6\ z\x98\xf5]\x9c\x9a=\xe1\xab;rz\x1b\x15\x10\xb1Va\xc9\x1f\xe9\x1d\xb5\x854\ \xb7w\xcb\\\x89\x12H\xb7\xe7\r\xacg\xf7\x07X\xb1^\x90%l\x03\xe1N\x04\xa7\x86\ \x9d\xe0\xc2\x9bV\xd63S\x7f\x94.\xa1\x85\xf8\xd7\xe2\xc2\x1f\x8f\x90\xce\xa7\ \x95\xa7\xcd\x837\x0f\xcf\x07(6\xdc\xadk\x92*\xd3\x82\xedA\x80i\xbd\x13\xcb\ \xff\xb4\x12\xc7{<\x01|\xf6dv\xaf\xa7`\ )d\xf5\xe1\x05\x83]\xfb\x8c\xbf\x91\xcf\x8d\xd4jh\xa0\x18P\x97\xfa\xb1=\x10\ \x8a\x9a\xee\xf4\x01\xef%W2\xa3\x1d\x89c\xd3y\xf2\x89\x02^n\xcdu\x8d\x8c\xf9\ \xfa\x07W2\xc8\xda\xd0\xadY\x99\xab/\xe0\x82\xe9\xb0&\xb9o\xf8\x16\xef\xbb\ \x1e~\xfc\xd8\xc0\xed\xbe\xdd\xb8\xb8hy\xe9\xdd\xcd|\xc4X\x00{\xe0@\xb2\xc7\ \xc9,\x90{\x1d\xcd\xfa@="\x16\x1e\xf388\':f\x13\xe1\x8cPe\x83\'\xb8\xf1r\xba\ \x818\xe4.\xe9\xcf\xc8\xf5\x0c?\x91|65\xbe\xbf\xdd\x1a\xfd\x92\x95\x88\xc2\t\ f\x86\x8esPn\xe1?\xb6\xf1\xfdBN\xb4\xf4\xaf\xa2\xc2\xd0\x07g[\xb6D%j\x0c09\ \x91/\x18*\x98\x91\xbf\xcfk6\xab0\x91\xe6\xe0\xab^\x9f\xf4\xfcza\xb8a?\x9dA9\ g\x10\x16\x96;\xa1\xcbh\xa3\x1c\xb4\x1c\xcd\xc4\xa9\x02o@]\xe2\xd3n\x85R\xeb\ \x90\x958\x7f\x93\x16\xdb>\xbd\xceXr\x90_\x17\xe7\xc6\xc4W\xdc\xd9m\xc3\xee\ \xf8|\xd3\x98} \xa5\xbdt\xcf\xb2\x01j!\xa1\xd4\xb1\x08\x9fB\xbc\x8e\\G\xbcTW\ sE_\x07w\xff\x82\xee6\x9d\x07\x9e\xdf\x07\x8f\xc92\xc9KU\xff\x1e\xc0qL\x1f\ \x97\x00:\xa77\xf5\xba3`Wf3\xcd\xcf\xd7\x16\xa3\x9a\x85L\x18\x16\xa2\xfd\x1c\ \xcc\xd5UJ\x8f\xe2\xac\xee\xe0\x95\x1ak#\x7f\xe6\x0c,\xffU\x18\x86`$\x87\xc4\ \x85_\xeb\x9c\xab\xa0\x08\xd8Z\x94\xd5\x1eE}M\xed\xa3\x04[\xd1-I@\x88\xcez\ \xec\xca\xca\xe9\xad\xb9C\xccP\x0f\xe7\x02\xb2v\xcf\xfd\x8e\xde\x92\xfd\xa6V\ \xdf\xbd\xe7u\x06\xf2POdh\xfe\x10k\xcd\xe1\x94!\x8dh.|\xf63\xab\x8d\x98[]\xc6\ \x0c3\xad\x15]@\x90\xa6J\xad\xcb\xe8r\xc4\x8a\xc5I\xc9\xd0\xc4\x97\xd7\xa5d\ \x89\xa3=\x19\xcdV\xf7\xd4F\xee\x07\xb8\xb0\xb0=\xf2Y\x8d\xdb\xb0\xeb\xea\ \xf43\xb1Q\xf2\x18\x97\xa3\xe7\xb8\x953\xd0\xe6\xa7\t\x97\x89\xf35C(j\xa9\ \xda\x15y6\xac\xb1[\xe43U\xdc\xb0\xdc2\xc7\x1c\xd8\x19\x80\xba\xcc\x12\x85\ \x1f\xfe\xe18\x8b\x1f.#\xd8O\x93M\x98\xd5\xben\x94\x9eM\xee\x19\xdf/\xaf\x02\ \xbc\xc0~^\xe7\x9a\xd3\xc1\xa3QE\xd6X\xe9!\xddMd|\x87\xcd\x18/\x06\xf3\xf5\n\ \xbc\x13f_\x7f\x9d\x9f\xac_\x980\xd7\x12\x0e\x84\x95\xe7\xce\xd1\xd1f\x9e\ \xd6Bw\x05\t\xbdV6\xb1\xed\xb8\r6\x8d\xdcW\x92L\xdcb:\xde\xf7R\xd5\x1d\xd1\ \xbd\xc8\xa8\xc1\x12\xeb\x9b\x14J<\xae+s\xc4Y\xb1k\xbf\xee\x1f3\x15#\xd4\x9e\ QPK\x8c\x18\xbf%VH_v\xe0\xde\x8a\xe9\xc8^V\xeb\x0f\x84u]\xe5\x08\x13\xe8\xd2\ \xc6\xe2&U^\xfam\xc5]\\*\x8a\x8bXus\xe7to\x06\xa8\xaa\x05RA\x15,\xf0\x1e\xf3\ \x88l\xdc\r\x82\x8b\xb2\xf3\x19\x0e\xe5{\xb1\xc1r\xd5\xec\xd1\x94Bu5\xd8\x97\ Ka\xd7\x02\x89-\xb4&\x95\xe6\xdb\x1e|\x05\x81\xbe\xd7\x7f\xfc\x15\xdf\xc5+\ \xe2\xc9\xc3\xc4g\xe6\x10x*q\xd9\xf5\xc2\tmW\x08f\\\r\x02ysRk\x85K\xe4\xd6w\ \x99\'\xcb| \x06|\x80\xbf\x19{U\x0cgc\xa0\x958<\xf2W\x90\x96\x12\xe4\x96z\ \x84\xb9\xf6-`\x98\xbb\x05/\x1a\x14\x8f\xca\x14(\xa8xB\x07\xea:\xc8Ozg\xfdb\ \x08\r/\xc5\xac\xe7\xbd\xd9\x0e\xb2\x99tv\xccw\xff\xa8\x07\x1e\xac>\x91\x18\ \x14P]*&S\x1e_\xe4^\xcd\x98\xa7xu\xea\xaf(I\x99\x01\x87u!\xb4\xddq;\xa0\x08\ \xbey8+\xe8\x06z\xda.\x7f\xcd\xc5\x10@\xaa\x9a\xd2\xd4\xf5\xa7m\x90\xf5\x1a\ \x17N/\x87\xad\xe50\xe3{\xf8\xa3\xef\xd2t\'\xf1\xc1!AG\':\x8a\x97x\xc5K96`\ \x88\x19\xfb\xe2\xac\xf3fk\'P$w\xee\x0e[4\xc6[\x006\x18\x8b\x12\x8a\n\x81\ \xce\x9c\xcaK\xe6\xf5\xaetGc\x9f\xd0\xd6>\x8b\xca\xd9f\xca;\xe8\xa4\xc8\xf6M\ P\xa7\xd6)"\xcd\x11\xbcZ\xb6}\x98\xe8\x14\xafG\xca\xc9\xbdL\x91\xbc\xa5\xa5\ \\&N\xc8\xa9\xe3}\xbd\x83\xab\xc8.\xdfs\xaf\x14>?\xa1\xa12\x966S^\x8f\x19\ \x13\xac\xee4\x8f\xde\x9fN\xa7\xcc\xb0\xba]o\xb6\xd9(\x92\xe0\xe4?\x8c-St{c\ \x19\xde\t:\xfd}}\xea\xca`\xb6!\xf6\xbem\xae\xb17\xfd-v~\xa9V"\x13\xe3\xd7\ \x06\xc1\xf9a!\xa6\xc8\xbb\xe2\x88\x8d\xfc\n\xbc\xb6Z\xc6\xd6\xd6\x18\x81\ \x7fg\xa0\x00\xde\xc6\xb3\xa2\xf7Ne\xa1\xfd\x07*g\x80d\xf4\x8b\x17\x87\x86\ \xdb\xe3:\xd7:\x1b\xf3l#\x8d\xf3\xb1\xb7]\x7f\xb7\x1f\x90\xc8c\xdep\x1d$\x1e\ a\x82AlP\x1f\x98\xa7\xe2NOKE>\xc3\x0bu\xf9\xd1\x18\x9e\xc7\x0c\x8a\x8ei\xcb\ \xb2+\xe0[\xd7%p\xfd\xf3\xb2\x8d\x0f\xc0\xc5t%\x9c\x1d\x92R\xab\xd6G\xd6\xbf\ \xf45)\x87\x19\xbdk\xc9\xc0Je\xf3\xda?\xde\xf7vXf\x91L\xa4\xa7\x82\xca\xf5RU\ v\x9e[Y\xac\xd5\x91\x81X\x1e\x03\xae\x0c\x0f|\xb4x\xfbe\xdc\x15\x87\xe5\x1c\ \x89+\xde\xee\xe0\xd3\x7f\xfe\xd923\xab\x1d\xa8o\xcb\xf3\x18.\xb9$.\r\xcb\ \x0bO\xba\xca/\xf7\xb6\xae\xdc\x9e`\x8e\xceI\xd8\xa1\x94+\xfa\xee\x8d\xd26\ \xd6\xea\x8f\xd3M\x91\x83\x0b"\xdcI4~W\xed\xc7\xa9\x07\x86\xf1\xf5y}c\xbd\ \xc3Z~L\x1e\x0f\x0e\xe1\xbe\xee\xfe\xdbE\xbc\x90\x99Y\xc1\x1e\xfb\xf7\x1e\ \xa0+\x82l\x08K\xef=\xa4Eo\xa7_r\xe38\x8aQ\xef\x85\xd6\xf2\x1d\x07\xe1k\xdd\ \xb2Aqp)l6\xa3o\xa9\x01\x18\xb5e:\xee\xf2\xed2\xfb\xb0\xb8\xd7\x7f1\xdd\x94h\ \x86\'\x1f\x1dN1\xf3Gi\x9b\xe4\x0c\xb6o\xec\xd3\x84\xd1&\xd4\x1c\x01nY \xa1\ \xf0\xc1IO\x85\xdfV\x05\r5\xd6\x9c\xd8\xbbe\xbf\x06\x8aS\x84F\xdb\xe4\xef\ \xad\t&\x8c\xcc(\xb7\xf0\x87\x04q\xbe\xcb\\d\x13\xc9\x03"\xe8\xb5\xda\xbf\ \xd4X\xf24C\x96\x1d\x06\xc4 \xbe\xb1E:\xb3pc\xad\xa5\xdcKv\xb5^\x99\x96\xb7\ \x97\xaa\xcaR\x1a\x88\x06\x06\x8a\xba\xf3\x945\xb3\x0e\x17\x94\xf0/\x0f|\xed\ \xea\xf1\x02\xcai\xe0P\xce\xe2,\x85\x11%\x84\r~\x8d\xa2e 83\x08\x1d;y\xb2\ \xb1)\x05_\xc8dc\xb7\xdc\xd7^\x81\tx3%\xcc\xd7sY\xd6\xc2\xc6\xd8x\x8a\xfc\ \xd3ir\xab\x9d\xdf:\x032by\xa61\x86y \xa3y\xe8\xaaA\xb7\x1e\xd1\xd1\xad%\x95\ \x94\x8c\x86;\xf6\xe4V^\xa8\xe6Q\xf3\xb3\x02\xc4\x98\xcd\xed\xd4\x98X\x1e\ \xecF\xe8\xdd\xb3\xc6\xe4\xcc\x91&\xd7\xc3z\xa2\xd3\x08)\xad}\x93>G\x1fL\x08\ 8\xa7\x1a\x81o)\x8d\xe9\x84\xd5[\xc7\x99A\xb7\x81\x8e\xfc1\x8dy\x8b\x85*\xaf\ \xef\xecs\xed\x15\xb3T\x99\xfe\x9a+\xd3\x96;\xa6\x10A\x16e{\xfe\xb3\xb2|$5\ \x02\x04x|\xd1\xf2\x88\x0e`k\xa6h\xfbS0v\x0f=\xe1\xc6\x0b\xc2:\xeb\x19\xd3L\ \x91\x14\x9c\xf7\x83^\x8b\x00\x82\xd025\xcd\xe5\x85\xd8\xba\xaf+L\xbb\x8a\ \x93\xe3\x196\x18tc5`2(Z\\M\xc8\x12u\xad\xc82\xdbjoN\x12\xd3B\x80\x1e\xf9\ \xda\x02)xN-_\xf5F\xa8\'\xd8\xf2\xc4\xc6\x8fV\xf2\x93\xae:\xcd\x11\x9f\x1a\ \xf9\x1b\xfe\xc5\x1b\xdb\xf7\x0f&\x0e\xe1\x9d\xb9\x93[\xb8\x9c8\xa4\x0b\x03&\ \x02\x1f\x94.Y\x8a\xfelv\xca/||9\x8a\x92\xf4c\x19\x0euql\xa6\x94\x1b(\xe5x0g\ n\x89\xa5j\x9a\xd0\xedB\xf0\xce\x8f\xfb\x8a\xca\x87d\xaf\xff\xafn7\xfa\xf6\ \x9c\xb3\xd5l\x8d6{\xd3q\xd2\xfd\xb5\xa4\x11\xce\xbf\x8fv\x90\x02\xadF\x92\ \x8eDGy1-^\xe2u\n\x9b\x1b\xcef\xfb\x1a\x8e\xf6\x01\x8f\xbb_\x9eN\xca\x8d\xbd\ \xb5s \x01\xf0A\x99\x96\xba\x9bf\x14\xcf\x07\x88\xb5\xfd\x19\x88{7\xae\xcc\ \xd64\xc1\x0e\xfd\x96\xf3.-a\x0c\xd0\xff\xf7\x15em\xea\xae\xcf\xa3\x9b\xc8\ \x8c7\xa8\xcf\xa4\x05\x0b\xb0v\x01JC\xea/7\xc3\x18\xa1z\x1dH\x00\x95\x87M8\ \xd9\xe8\xdb\xf9uc\xc4 %\xde\xaf\xda[=\xb4\x84\xda\xfc^\t\xa0\xa4\xed\xea\ \x94\x8070\xd3\xdf\x19\xd0!IQ_\xf3\x9dw\xa4\x8fhmu\x91}xt\xb7j>e\x82\xf9\xe7\ :\x0c|\x93ytou\xc3\x15P;~\xd0\xfa}\xa8\xf0\x87\x84o\xb4o\x99\xb7M\xaaGg93\ \xc20C\xb1\x08\xbc\xf8D\x10 \x9f\xf57]\xa3\xb6\xe52\xe5\\N,\xab\xa9\xf5\x0e\ \xc9\x1e\xb7\x84W\x85OZ7\x9b\xff}\xfc\xc8\xf7\x9f\xc9\xce\x83\x19\xcc3b\xc7\ \x1e\xa3\x8eP\x96l\xfc>A? \xae\x93\x9e\x8a\xfe\xcf\xe9\xec\xfbJ\xbb\x00% \ \xc7K\x93\xa1 \x96\xb2T\xd6v\xcf3\xb1\xaa\xcc\xc9\xa7\x06\rd/A3\xfd\xads\xc3\ \xfdQLf\xe84\xdeC\xa8\xf1*\xe2\xe7W\xd5\x06\xfbvd\x04G\xf56\xe3l\x8cW%%j\xd6\ M\xe4S\x05\xb8\xe1\xb5x\xf4U\xfaKe\xac\xa9\x1d}c\xa9\xb3$%\xb2Y!\xfb\xd8\x87\ \n\x1f\xb16k\x9fNa\x0ekb\xe7vh#Q\x8d\xe2\x9bX\n\xe8#\x1d\xc2Q&\xb0\nY\x7f*\ \x97i\x99\x8ci\xbdQ\x9a\xf7j\xf3\xf5\n\x0c\x06gJ\xc4\xf4\xee\xd9\xb4p\xfa~m\ \x92Z\xdc\x1a\x02fV\x8d\x89\xdc\x7fcn*\x05\x9cz_\t\xed\xe9B\x1d\xf1\xf9\xf5\ \xfaO\xca\xeb;#\xc1\x00\xff4bC[TA\xdd\x81\x9d\xa8*T\xb2\x9c\xcd.\x00\x10\xf8\ \xf1.\xc1RmWc,\xf8\x80E\xfb\x93|\xfb2\x966\x98GC\xa0\x8f\x95\xdaY\xc3C&`4\\\ \xff\xd8\x9d\xca\x1dC>\xe3\xbf\xf4\xedT\xb3\x96\x966\x06>V\xdb_\xe9\xf2~\xf4\ \x05\xaf\xe8|T\x07\xd7\x01>\xd36\xd6\xfb\xb4m\x8b~\xf0\x8bu\xd8\ \xbcQ\xa0\xe9H\xe9c\xde\x91R\xe6Q<\xee,\xe7P\x0e32\xff\x9cY\x07O\x05\x14\x8b\ vQ\x98\xe3^YX\x93\xc5w\xc1\xda\xc8+%\xb2\xf7F\xe3]d\x03\xde\xe8B\x86\xf1\xf7\ A{T#4\x07\xc4\xafkYf\x99\xc6\xf24\xe6\xc5E\xd1\x9a\x87w\xab*\x84\xaf3\xb2\ \xec\x88\xe3q]\xed}\xc0\xc4Gv\xc2\x06zi]\x1f\xcar\x12I\xe4\xbeQ\xees1\xc3\ \xcb\x12\x8e\xfc\xdf\xdb\xa8\xb5\x90\xbd\xed@Vx+\x168\x9a\xd8Ue\xb3\xb0G\x18\ A\xff\xdb\xcc\xf7j\xc9\xdd\xfb\xcb\x112\xcc!\xdd\\\xab\to7,s}\xd4\x00\x1b\ \x14\x8f\xa3\xf6\x15\t\xc9U\x85=\x97\n\xd3\x9d(\x05\x13\xe2\xd1\x05\x9eWi(\ \x97\xd1\xa3\x14\xa2\xde\x97^[\x9e\xd5X\xedH\xbf\x85\x16\xa7T\xe5E\x95\x84\ \xbc\x99\xb1%\xe5u\x03pb\x82\x83\x98[\x96+wa.\x9d\x7f\xed\xc9\x82\x8b\x13Q\ \xbf\xbfk\xf2%\xa9\xad3B\x0b\xea\xe3\x94\x0eH\xa4\xde\xe6\xf96\xa5\x12\xfc\ \xd2$\x12\x7f\xb6P\x91e+B\xf8\x8e\xfc\xa9@\xc4\xba\x02!7B\xae\xba\xe1G\xa2\ \xc7vw\x8e\xea\xf1\x85}c\x17\x0cW\xb4"\xb5\xfc\x06M/}\xf6\xdc\xb5\x14;\xf0*E\ \xf1C\xe6k\x05\xf4\x0b\xf8\x88\x19P\x81\xca:JS\x8eT\xff\x0f\xa2O\xe5\xf40\ \x91\x1a\x94\xab\xaeo\xb2\xa3\x0c\xf8J\xfdsw\x9dCY\x01s\n\x93\x08\xf5\x1d\ \xc9{UQ\\B\xc6\xcf\x98\xef\xf8\xc1\x8a\xe5l\xf3\x9f\xc5m>\x7f\xd4\xeb\xd1\ \x9e\x17\xc4\xe5)\x8a\x17\xb8\xc9\xed`\x92\xea-\xc4/\xda\x98\x8c\xb5\x08@\ \xf2y\x1f}#\xd3\xda\x05\xf3\x1aI\x11\x84\xb5\x1d\x06\xa3\x04\xde\x0c\x1c\xb3\ 0T\xb4;\xb0\xb8MiV\x06\xd2u\xd3\xbf6\x8e\xd6OW\xb7c/\x1c\xfa\xdd\xb9\xb0rZ\ \x00\xf0y9\x9f:\xf1kE\x95\xa8\xa7:E\xea\xcd[|0JV5\xd0`\x89.\xef\xbf\xbc\xf8u\ \x15I\xb8?X\xc0;\x81\xf4\xa2\xad\xaa\xbc\xe1*Q\x0c\xa9\xe1d,\xb7\x88(\xb7*\ \x18Z\x7fE\x81\xb0\xd9\xdd^\xf5O\x19\x05]6\x80G\x94y\xad\xd8\x7f\xb3\xcb\xf5\ \x91rh\xf7\xd8q\x196\x10\xdek\xeb\xe2\x96\xab\xce\xc6\x85\xd1\x07\xbfy \xc6\xa6\x96\x1f\xe6\x95Pi;4\xbc\ \x16\xc6\x0b\xae\xae\x15,\xccPs\xb1\x89}|\xe3K\x19\xb8\xa8\x90\x151\xe4<{\ \xfc\x14s\x03g\xfc\xacQ{\xe8\xaf\x96ORp\xd47\xf1\r\x02\xa7=*C\nm\xa5{\xfcE\ \xc5\xcd_\xf5sZ\x17\xc8\x02\xc3h\xc1\xdc\x18\x9e\xc2\x08\x1e?\x87\xe8\xfd\ \xf8\xe6\xdd\xd8\xd6|\x1czj\xf7\xba\x86\xa4\xee~t\xcf8\x0fY\xfc\x05D]5J\x12\ \xb5\xc5\x1b\x85\x19\xa5\x17\xd7\xa3\xe2\xe948\xcd@\xbd2\xeb\xa9\xdeYn\xad\ \xfd\xe0\x01X\xe8H\x13\xae\xc9\x85\x11O\xf4\xea\x1f\x14\x03\xea\xc1U\xbd\x9b\ \xe0C\x02\xef2\xdd\xa5q\xaf\xa5\xbd8\xc7~\x90\xcd\x03G\xb5\x03\xae\xa7W#|\n\ \xf3VU\xad\xf7{\x01\xac\x97`\x16\x04\xed\x81t\xd7V\x8cV\x0f\xa3S\x1a\x07 ?Ke\ Lc\xa9 \xc7\xbcfA\x00\xca\x93%@e\xf5>a\xb82\'\xb2\xefb\\\xc48%\xa7O\xaeD\xf6\ g\xdb\x7f\' \ro]\x02\x01^./u\xc5[\x92eTo\xea,\xa1\xedz{\xa5x9\xe9\xd7\x97\ \xf0\x1c\xfa\xec\xa3\x12r#V\x8b\xa2\x1fZ\x03\xc6J\x9b\xf5\xe6\x8d\xfe\xa2\ \xef\xabz\xda\xa5\x89\xb1\xc9\x9c\x1b\x08\'\x8a\'\xa4\xde\xda\x06ei\x86\xc0\ \x84a\xab\xb3\xcf_:\x82\xfc/\x1f4\x0c;\xf2H\xb7\xcedZ=H[\xc0\xacDw[\x9d\xbc\ \xeb\x19I\xe1\x13\x16%\x8b\x01\xb7\x80\x7f\xf8\xd0\xd2[\x8f\xd2\x95{<1\xa0\ \x91\xa5\xaa\xf9\x06\x03!\xa2\xf6\x06\x87du\x1b\xb5q\xf8\x80\xaa\xcc!\xc8\ \xad}\x96p\x91\x8c\xb9\xde\xad\xe8\xc05\x7f\x8f,\x82\xb1H7\xcf\t\xa5;"s\xae\ \x1db=7\xfc\x12\xa0\xc69\xaf\xf9\xb7D\xefu\xa6lY\x14w&\x1d\x16\xfe\xa9\x82Ue\ \x8f\xa5\xdd\xa1\x1fUJy8K\xe1\xa6K~]GW\xa0\x0eD\x80H\x95\xd9\x19\x98\x8eZ\ \xe60\xb4\x9b\xd2\x9a>\xfb;\xbe~\\:\xd4\xa3 :JwO\xada\xfab=\xa1\xe9\xea\xd0\ \x90"c\x9f\x04\xebD\xc19\x7f\xb8\xb1\x0f\xdf\xc1\x18/\xa0BF\xfa\xad\xfb\x19\ \xfbs\x02|\xae\xc2\x0cI\xeb\xa4\x8f \xf6\xfea\x86\xed\x81`*\xce,\x87G\x97\ \xa7\xab\xc4\xc0CW\xcd\xfa&\x06\x1d\xd1\x90]\xf4O\x7fQ\x19\xe7eB\xed\xa6\xd7\ \xc9\x193\xe8\xe1\xbf\xc3^\xd3\x10\x03}\x18\xd6\xb0\x02\x1a\xd2\xfb"oM\x10*3\ U\xea\xb3\xfd\xa9\x06\xce\x11G\xb7\xd3\x81W\xbf;\t\xc3\xbe\x18\xd0\x19\x08\ \x04\xaa\xce-\xf9\xdc\xcb2\x11\x0b-\xffSB4C\xb2\xaf\x97\xab\x8e\xd1\xddd\x88\ .\x1az\x05`A\xa19\xa0\xc6~\xf2\x15D([\xefF\xef\xdf\xd2\x18z\x19\xdbJpV\x89\ \x82LN\xeb%NM\xf4Z\xe2\t]\x9a&n\r<\xedu$}\xa4B^\x91MPn\x0e\xb0\xb1\xec\x8f!(\ #\xd4+\x9cS\xaa\xca\xf73\xaf\x1a\xfc\xd5\xdb\xac\xb4\xa1\xfd\xaf\x055\xc1=\ \xc6\xabx\xd4\xfa\xb7\x8d\xff0e:\xc9|Jp\xfd@\x9bX-\xc6\xe1\xf0\x9dx\x0e\xc9\ \x94\xf2\xe61w\xb5\xc4\xea\x9eb\xb91\xaf\xf0NK6\r\x94a_\xfc\r\'\x16v\xcd(\ \x8b&x\xf1\xd9U\xb8\xd3\x1f\x9bY\x853]\xe1\'$QPT\x04:T\xf3~f\xb1\xa7a\xe8*\ \xf8Iu\xe5\x1f\xdc\x03\xa7\xd2\x00a\xd8\xbb{\x9a\xbf\xf2\xcb7\x18\x18\xe8\ \xc6\x08\xed\xd8\xf5\xa7\xf6\xcfd\xaa\xb0\\\x08\xb5\xc5\x14\xa1\x16a6\x9f8\ \xf3\xea\xdd\xa4F\x82\xa7q\xf1\x95\x99\xc5\x90\xec\xc5\xce\x9c\xb8L\x99\x9b\ \xffkQ\x0f\x19\xc1*\x9f\xb6\xd5\xa4\xfb\x92O\x16\xd8\x87\x04\x08B\xd6\xf8vu\ \xa45}\x94 X\x14\xdb0\xe0\xd4\xb6\x9d\x176\x99\xcdB\xc0\xe3\xfb|^\xd5w\xe0\ \xbb\xf8dGP\'\xa3\xfb]g\xb3\xe4*P\x82\xa1\x12\xbe6\xc5\x93\xa3y\x91\'S\xa1f\ \xb4\xc0\x81\xca6_\x9b\xa9"\xa9\xf9)\x99\xd6\xdd\xd4\xee1Y\x9a[\xd2?\xa3\xe2\ \xd8\xed\xf8s(\xf3\xce\x19\x81\xd2\r_\xae\x0eE\xcd\x82\xac2\xfa\xab\'e\x19\ \xb3\x17\x0e\x04H\x0f\xedb\xad\xe9\x13\x86\x06\xb8J\x93m\xf3\xc7\x80N\xdcq\\\ \x90(\x90NF{\x8c\\\xd9\xdb\x99c` DY\xe4\xaf\xd3Q\xeb\xc59Yh\xd57o\x9f\x0c\ \x1f\xb9\x06y\x97\xe9\xac\xa3V\x02\x0b\x88\xdex\xad\xaaE\xe5\x83as\xd7\x97\ \xbf\x9f\x8c\x93c\x93\xe6\x99\xb5A\xbf\x9d%\x05q\xc2\xf3\\\x8e\x8c=\xe6;\x01\ \xdf\x07{\xd4\xc9\xa1\x87V\x94j\xd8Kj>d\xe5\x12o\x7f&%\x81v#Y\x1e\xc7\x82\ \x9d\xaf\xcfL\xb5\xbc\xef\xde=\xecZT\x05KJ\xec\xd9\x8f\xdc&)\xc0\xed\xfdL\ \x01z\xc6\xbe \xd9\xbcQ\r\xcc%\x11\x00\x8c\xc8\x07\x99a\xaf\x06\x8d\xbbUp\ \xc2\xc5\x16.\xdd\x17/\xac_\x0e\x8fh4\x0c\x07\xcc\xa2|\xf4\xd8\x9a(\xfd\xef\ \x97\x03\x15\xc0%3\xdd\x15\xdb\xa1v\xbfW\xf9/\xb7<\xfa7\xab\x95@m@`:X\xb6%\ \xb5\xd2Q\xdd\xde4\xb1\x05\x929%\xa2\x03K\x86\xe1\x98\xe1[\x16\xcd\x0b\x10<\ \x18\xff\x13\xcd\x9b\xab\xe0\x96[\xf5\x9dt>\xbc\xb6\xb8\x18 6\xea\xc3\xd0?\ \x860il\xd6\x05\xb2\xb050\xf8eb\xf6=\xaa\x95\x08E\x1b\xef\xed\xf8\xb1S\xcdj\ \x0bh\x96\xd7^\xcc\xb9E\xdf\xa1\xab\xf2\xf8r\xbc\'\xbdxi\xf5\xdaQu\xc5\xbd!y\ \xd1\xf0\x9a<>\x84@;R<=>\x06SQ\x92\xff\xa423\x8db\xa7\xd0\xd9\xf9\x84ao\xde\ \x83I\xcb\x01\x93\xfa\x8dJ*\x81\x1d\x1d\x89\x95\xc6\xf3Q\xc1>\xd4>\xce\xd8\ \xe2\xa3V\\|\xea\xedF\x14kTR\xef\x08\xf2Gw\x93\xd1\x94\x9e\xbd\xae\xe6\xaaN/\ \xcf\xda\xda_dB\xda\x93\x97\xe3F\x9c\x1d\x8d\x1dW>\xca\xca\x9c\xb3k\xf3k\\\ \x8dO5\xeb\xaa\xdd\xe7SGjMC8\x8f\x1b=\xc0\xd1\xc5\xc1\xfb\xaf:\xdd\xf6\xf9c\ \xb1)\xfb\xc2d\x0cw\x0cM_""\x12\x82\xed\x86\xd2X\x03\xee\xf2\xfe\x1e<\x9c\ \xacpEh\xa7\xe4\x1a\x1c_\xb8\x9f\x91\x1e\xdc>\xca\xc8\n~\x13y\xfc\xf3\xf4y\ \x13\xc5&\x8e\n\xa1\xa0G\xdeY$oX\xd1\x08uz\xf2/\x864\x06\xee\xd3\x87\x8d\xeb\ \xf7T\xab{Fn}\xb1O\xb9\xc4\xf6\xf0-\xc1S\xf5\xa7}\xdf\x98\x9d\'\xb2\x92XVq\ \x82\xd5.\xd1\xbd\xb1\x1e\xfcZ\xaa\x9a\xf7\xb7\xb2\xc1.\x1c\xaaN\x1d-t\xbb$q\ 6Uzp\x0fuD\x82\xad\xba\xc6_.\x9a\x06\n\x8f_\xf4\x94\xb0&i\x8f\xa3\xcd\xa5\ \x7f=\x12\xba\x9d;\xb2\xa6\xf5\xd0V6P\xdf\xee\xd6\xf1\x9c\x9d\x1e\xc1\x7f\ \xf1U\x98\xb2\x8b\xc0G`\xde\xc8Q\xb5,~\xdf\x9ay\x00\xd6\x90\x14 \xf1\xe8\x12\ 9h\\0\xd1?\xbf\x9a\xe5a\x821y"H\xfb\x89\xbb\xddwq?CX\x19\x851\xa7%,\xa7\xb9\ \x11ItB\x8a\x01\'?q:\x05[K\x08Z\x96\xb4G3\xf5/e\xbe\x90Q\xfc\xb0\x1e/\xdd \\\xf5\xf2[M\t^\x7fx\ \xc3\x96\x83\xd7\xb2\xa3v\xf29\x92~dp[\xb7\x03\xc8Hs\xecQ\xe0\xce\xf1#\x07\ \x8d\n\x12j\xca\x0b+\xf2\x00!@\\\xd4[\xe5\xdf\xf5\x99$\xf0\xf6\x05m\xe50\xdc\ \xdc\x18\xca\xa5c4\x03\x85]\x9b\x82\xecb~\xa9\x84\t\x04\xf3b\xf7/ME\x1alE"\ \xec&.\xbd\x8e\xf6\xdc_\xeac\xfd\xb1\xe2\xd0\xfc\xcb\xbd\x1eT\x15\xcb\x1a\'{\ m6Y\x84!\x95\xc4d\xae\x83\xbd\xc3\x0c.5:\x19\x1a\x07c\x91&\xba\x92\xe7\xfe\ \xe4e\xde\xc0\\\xb3(\x10\xb8\x01\x99k\x181\xe8\xce\x89Dw\x85\xf3\x15\xc0\x90\ /i\xc5\x08\x86\xfbc\xcd\xd9\x84:c^wj\x987\xd9\xa1\xb0\x82\x17(\x92\xa4\xe6\ \xf4\x8e\xd3N\xca\x1dm\x1f\xccW\xb7\x08D$Sz\xd4W\xe7u\xc7\xce-\xa3C\x95\x06q\ \xca\xb6\xf6\x80\x99\x86\xdf\xd5\x7f%R\x1dcp=V\x8fzWY_\x96%\xeb\x1a\xfd\x1c\ \xfa\xf8$\xb8\x8cz\xfd\xc0\x8a\x1bz\x14)\x86\xe7O\x1f\x06<\x19t`}\xfe\xb8\ \xbf,s\x12\n\x00`\xffx\xeb\x05\xd0\xbc[\xf09\x0e\xd7\x93\x1b\x84U\xfe\x86\ \xb3\x1c\x91\xd8\xd2\xc3\x05o\xf9q\xd3\xa8\xde\x87\x9aQ\xd8\x1b\x86\x8d\xdfL\ \xaf\x9a\x82\xa2\xb4\xa7\xe4\x86\x05Q\xcakt\xb0\x9e\x08U\xc8\xf7\xe43c\x98\x18\x1b\x86\xe78\x88\xbe\x1b\xa8e\xdb\xb9\ \xe9\xc0\x94>\x1f\x9e\x9c\xefxZ\xcaD0\xe9\xc2\x987\tQ\xfe\xacA\xce\xef0\xc0N\ \\O\x1b\xe7\xddI\xe6\xe2\x1d\xe4iu\xaf\xc2\x08;"\xb9=e_\xf4\x0b>\x0c\x98\xd7\ \xc2~-\x85\xa9/F\x90\x1bRk\x8e=;\xe7\xf8|\x0b\xe7wv\xf6\xd5\xfbo\xd1\xba\xdb\ \xee#\x87MK\xd4\xb3I\x84\x1b3y4\xaf\x999x.\xb2\xbe\x0b\xdf\xe2\xba-\x92\x11\ \xda\x96\x842\x96\x9c\xa9\xd9\xd7\xe7\xaaQr\xc1\x8b\xe5\xc0>p"F r \xf9!q[\ \xc8\x88+{\xa4\xaaJ%\xf6\xa9\xdc\nE\x01F\x88\xbbx^JQV\x08\x14k\xea?fW\x99\ \xac\x8d\xa8\xb6\xa8\x96\xcbo|8\xbds\x08\x970\xfc\xb3\xeb\xafR\xd2x\xd3\x90\ \x88\xfb\xb0+w\xb3\xd7\xcf\xd6\xbaBH\xd6\x1f\xa2Z\xd6\xaa\r\xc3yu\x90\xfb\ \xb2_Y\x1a\xa2\xc10\xd9\xd1\xc9\x96]G`\xbeG\xa5n\xba\x87\x9fUoi\xedd\xc1\xd2\ \x03\x83@\x87R\x0f\xe2\x0e\xefQ\x00 c\xfd\xe5f\xa0%\xd2\xa6\xbd\x08\xe2\xc1\ \xfa\x83_Y4{\xe4++\x1c;\x96\x982\x0e\xc9k\x88\x99&\xcb\x83\xe4\x9b\tbC\xb7\ \xc2i\x0b\xc4k\xe5\xc6\x9co\x04\xd4\xab\xccN\x18\xfa\xbd&ey\x8f\xb0\x12qL\ \xea\xaa\xc5\x8d\x80\xcaP$\xfa\x81.\xbaK\xf9rL\xb6\xfeH\x03\xfb\xde-\xd7[\ \x19\xae.\xfdD\xdfB(\xc0\xc7\r\xed\xda\x83\xeb#`\x9fj+\xfa\x9b\xc4\xc4i\xaf;\ \n\xdfZ\x88\xe4\xb6.,zB\x94\xb2\xee\x85jW\xfd\t\xa6\x811\x9a\x1a9\xfa0[\xc2\ \x90J3\x82m\x0b\x06\xd7dO\x816b@\xf0\x99\xc1\xe4H\x07\x13bK\xca\xa1\xfdJ\xf8\ S\x0f\xeen\xa8\x12q=\xe3\xdf\xa8\xa1U\x8e\xbf\x88UI\x99\x08ld\xb6\xc3K3\'\ \xbf#\xc0 \xec\x07\xd6\x83T\xb1\xd4\xef\x0b\xee\xd1_\xeaU\xd2a\xb9\x06\x1f\ \xb0\xf6\xae|\xae.\xf5\xc4,&\x9dyA\x0b[q\x1dTW\x8b\x85c9\xfe\x880\xe5g\xba\ \xe3(\xb7\xd1t"\x91\xa1\xf9\xf6\xb6\x02=;\xd7\xfd\x8fw\xd9c:\x1a\xb9\xd8s\ \xae\xfdf\xa2\x13\x9f\xf8)D\x95"\xf2N\x18M\xd29i\x93\x84\xc8\x02\xac,I\x1c\ \x92?\xd2\xdew\xd4\x8b\xb1\x8bu\x98M1Gz\xb0R\xa4\x89\\})\x87f$\x83\xb6\xc6\ \x16\xf8\xe0\xa0#r\x85\xbb\x9e\x0e\xe1\xbbR( \x9aX\x83\xf9i)[\x07\xeb\x0c\ \x0b\xa6\x9dr\xe8\xad\xa2\xc8\xd05f\xbdf|y\xb8%@\xf0ecv\x84\xd8niM\xab\xbf\ \xa0\x85H\xf8\xfaD?\x99\xacN\x94\xe5J<=\x18\xdcBdnxm\x86ek\xea\xa3\x06\x8e\ \xc7\x7f`[\xf4\xe0\xc7s;\xb7\xf88\xc9\xa2\x1c\xad\x8b~\x98\xab>\x0b\x1d(`\ \xdb\xa1$\x89Z\x00QS}\xeej\x85}\xe0\x8c\xf7YQ\xf1\x80\x9c\xc3\xef\xf0l\xf5e]\ \x7f\xd4\xb2\xce4}\x99\xc5M\xa3>\rl\x08\x97?~\xb1\x11}\xe0\xbdz\xa2o\xc9\xbf\ \xcf\xe7\x0c\\E\xb8\xa8G\x8f\xcb\xbcO\xc1\xeb\xae\xe4\xa9\x17Y\x8c\xca\xd1\ \x8fx\xda\xf7\x8dS\x96\xfe\xd6/\xc4\x96\x12;V\xffR\xd6K8\x92\x17c\xfa\xfc\ \x93\xd8\\\x9b\x00\x98\x16\xc5\x00\xc75\xd8\xd7U\xc3\x92\r4B\x1d\'\xf30\x7f.\ \x17\xb8\x832F3\xdbQ\xd7N\xe0[\xdeT\xc0<\xd8\xfe(\xe6\xef`\x0f\xdf(\xdb\x9f0\ \x98S\t\xfd\x8cy\xc5\xfc\x8d\x91h+\xba\xb3\xce\x95wi4\x15\x11\xba\xd1\xe5\ \xa6\xa5\xf2\xc7m\xa7\x83\'\x1d\x11\xe4\x06\x95\x0c;\xa4\xc38\xf2\x89^p&{\ \xf2\x0c+\xbd\xe2l\xa8\xbd\x99\xf9r\xb1\xb4\xe0\x92\x86\xdc\x18\xf7E?\xd1\ \xecJ\xfa7x\x92\xf01\xef\xd9\x08Q\xddmU\xbe\x96\xaae>\xd0\xab\xe1#\xfb\xa9X\ \xc7V\xa7\xd9\x86\xde@\xe74l\xad\xcb&\xf5L\xb8{jb\x0e#\x0b\x15\xf9;\x8ab\x19\ \x99\xc0\xe5c\xc8\xd9\x84\xe7_/\xbd\x1e\xda\xa4\ \xd8\xa7\x82\xaa\x87r\xea\x8a\xb6\x91\x9dTC\xc73\x84$\x93Ct\xca\x0e\xaaJ\x8e\ \xfe\x1c\x85&\xf6\x95H0\x8b\xb0\xf5SZ\xfc\xd5\xf6,\x84\x8b\xc6\x0bP\xcf)X\ \xae\x8fS\xc3\x1e\xb7n\xa5\xbf\xb7U\xf3>^3\xbe)|\x19i\xe8CU\xeb\x94\xcb\xbf\ \xab\xb1\x05rV\x14\xde\x0cN\x13\xc1\xf9\xe8\xfa\xa2I\x7f\x12\x12\xee\x85\xd6\ \x95\xe8\x80N\xc2G\x84\xebt\xcd,\x91C\xb9#\x93\x10p\t\xe9\xbb(\xc7\xe8\xab\ \xc4\x1a\xccB\n:@\x1f\xf7VS\xfc^J\\$=\xc7\xf9\x0c\xc0\xb6\x82rdQ\xc9n+\x91xu\ \xfe\xd0\xd6?\xc01\xdb_\x18\xe3\x18\xfay)\xe1L\xee \xa06\xbbk\xaa9q\xfd\xd2e\ e\x15E\xb7q\xd7\xb2\x8fc\xc8\xeb\xc6i\xa7\x11\x85E\x11\xb9\x13\xf6\xf9a\xc3S\ )\xdc\x17d\x0e\x95\xb4\xf7\xde<\n1\xf8Jo\xf1\x9d\xb6\x8f\xb2\x8a\xec\x12"\ \x13\xf8\x142\x06\xd0\xb9>\x98\x911c\xa2\xbe\xb4\xb5\xc8\xa1\x12\xc7:y-\xe8\ \x9a[\xc7\xe7\xf6q\x8a\xa2\xe3\xc6\x97\r\xffz3S1\xd0\xa6i\xb1\x1eH\xf0\x0br\ \xfe\t\xf5iw\xa5\xd1\xb1>\xac\x1f\x08-J#`\xea\xdf\xb3C\xa3\xbd\x1dS\xc9P\x07\ \xe6\x91\xc6\xad\xbf\xaen\xe5\xf3vi\x8b\xd5Io\xf0\xa3\x1d4\xd2\x92\xf4\x8e\ \x05\x9b\xf2\xde|K\xa3\xf4\'{>{\xb6h\xf1\x15\xc5\xfcX\x17\x8f!!\x86|q\'|\xf2\ \x84>\x8c\xe9\x00\xe9\xe7ml\xcf\xe1\xef\x86\xe5\x9a\xaf\'\x893\xbe\xa6\x19\ \xfcj\x902M6F\xac^{\xc2e\x170Xbl(\xbeQO2\xfe\xf4,\xfao\xecC\xac\xb7\xf6\xa2\ \xcbdY\xce\xd3\xfc\xea\xa7\xaf\xf4\x00\xa1i\xcc\x83k\'\x9a\xb2\xbc\xf5~\xc6\ \x1f\xd7\r\xcd\x7f\xdek71\x99\x98N4Q@\x93\xc4w\xbe9=5x\x08\xbe\x96\x90\xbe\ \xe7\x0c\xc1\xa9\xaat44\x87`\xbb\xa0\xdeL^\x12\xa7\xe2\xfc\x84\xcc\xaf\x1f\ \x82\n@6\xf7\xe0\x1a\xeb?5\xef\xcf\x89v\xafv\xfe\xacdi{\xd1\x9c\x04^\xe1\x19\ \xb5\x9d\xd2/\x06\x18\r\x8a`\x97K\xd2c\x8d\x01q\x10~\x92:F\n\x16\xf4\x85\xd1\ %\x00+G\xc5&\xa2bO\xf4\xb1\xa2\xfe\xd6\'\x0b\xd8\xdbp\xa862\rkDy5*\\\xd8D\ \xf1\xb8\xddH\xd2\xb3\xa9,\xd16\x8a\x08\xdfX\xb3\xd2\xb4Nt\xcd\xaei\xd5\xd4\ \x85$\xc8\x88\xd0\x8a\t\xc9\x94\xb2I\\\x9f8|yBE\x87\x17\xf0\xde\xff+px"4\xe1\ &\xed\xd9\xd0\x14\x800I\xba6Z\xbcl\xc5\xe2\xc4G,3/e\xec\xd9jvAt\xb2^\x83/^\ \x0fB\xd3\xb5\xd8\x9f\xbfb\ \x10; \xcd\x94\x7f}O\xe8I\xd1h\xce\x8b\x91\xe7~o\x97\xe3\xa1h\xda}n\x0bf\xdb\ \xd0p\xaa\x1a\xab\xd3:=<\xca\x98\xa3\x14\x9fh\x12\xc4\x97\x96\xe5\x10\xea\ \xaa#WI\x8f\xf8c\n\x98\xab\xd60\xd0\xcf\xa3\xf3\xafb\xa8K\xda\xdeO\xec<{\xd1\ \x9e\x84"\xf5l\xd6\xba\xfeD\xfd\xae\xf6\x1a\xa6\xe9Z\xd9\xd6\xa9\x8bJ\xc6\ \x03\x9b&\xb4_\xbf.{\x97z\x90\xd5\xb5\x92\x95uU\x87\xe8\xef\xe6%\x9a\x9c\x9a\ \xe5\x7fS\t\xc99i\xd5\x90\x99^\xa0\xd6BL\xc4;\x95U\xa2geIq\x86\x83Kx\xe0\xcb\ \x84\x10\x89\x07\x96\xa3E\xb8\x9fi\xf44\xf5\xe0^{\x91\x14s\xe2\xb6\xfe\xb5\ \xd6\x1d\xd1\xc53\xc0\xea\xc9\xf8\xd8\x12\xce\xf6R\x85\xe2\xd2cN\x94\r\xec\ \x1e\xfa\xf9\xcb\x9f\xcc\x07\xf2\xf2\xf7\xa8\xf5\xe2G.\xd9nx\xe0\x13\xfd9%\ \x97,\xa3\xa1\xbb\xbcu\xa5\x96\xd7;,8\xbc\xb4\xa2\x7f\xf9\xf1\x83#<*_\x08\ \xffTN\x87\r\xf5\n)\x84\xa7{\x1a(.\xb3\xf7>\x92\x87\xaaY\xb3=m\x02-~j\x1e?p\ \x87mD\xe8\xc6\xfa8g\x9aOD\x1e\xd1\xf1\xe4\xd7\x87!\xcf\xea\x9f\xd2R\xf8\xbe\ \x96\xa0"x?l\xf5_[h \x8e\xea\xb3\xe8\xbcc\xbdM\x9cr\x98\xea\xbd\xa2\x14\xc2]\ \xbc\xcfn\xdb\x1a9\x8c?\xb0\xeb)\xc1M\xf7_\xe6\xda\xb6\xcb\xdd\x9e\xca\xf1\ \x86%\xab\x9fG\x94\xed\xa3\xc9\x0ez\xb9\x07<[\xa9\x99C\xb0\x81l\xdf\xd4@\xab\ \xa3\xa1\xdb8\x89"\x90\xa2c\xca\x91D>\x8f\x9a\xc1\xe0\xf7;^\xfcX_)kaD\x0f\ \x0b\xa4\xb4\r/\xc4(\xef\xd504\xff\xa4\x7f\xdc\xa1<\x12w\x12\xffn\xec\xda\ \x95\xac\xbb\xcf\x99\xf6,\xc3\xda\xab\x97o=\xcfU\x81+\xc2\xf7(\xf0\xc3\xff\ \x1d\xf2 k\xc2\xd1k\xe5\xd1`\x18O\xbb\xa1\xd8\x94\xba\xd1\x9b\x92\xe0\xe4{\ \xa5A\xa3\xa3:\x1d\x13\x83\xfb:\xff\xa6\xa1\x16}\xec\'[8\x95\xd3\x9f\xdd\x81\ \x93)\xb1\xa3\x04j\xb2\x01n\xd3\xea\xb25\xec\x80\xe7\xbaB`\xae6v\x1c\xc2\xef\ E\x8f\xa4~!\xe9\xdew\x0f8\xcd:\x84\xb0\x90i\x02p\x15\xaa%\xd2\x1c\xa1\xb0\ \x13\xa3?\x00\xdd\x93\xcc\xd3H\xe6g\x97+\xd1\xf2p\x8f\x18\xdf\x07\xb7\xfb\ \xcfAy\xfa\x19\xac\x06\x85\xb9\xa4H\xccg\x8b\\R\x10*nM0\xa1E\x0f\xa0\xd4\x06\ Q`\x84H,\x10\xb5\xe5\xdd\xc1d\xc2\xd1V~\x81\x16K6\x7ffD\x83\\\x01_Ch\x8b3\ \x992\xc9R\x9f\x83\x1b\xab;\xdf\xf4I\xd7\x83\xdcb}\x81:(\x82\xdd\xe4\x03\x1a\ B%ry\xcdi\xf0\xb4\xee^\x0eU\xf4\xf8\xb9\xda(\x9b\xb2E$\xdc\x08\xfc\xef19\xd8\ \xf2\xa0`\xdb3Q,-r\xf9S\xada##\xc1Kb\x8d\xfc\x87\xb3\xbc\x9f3\x8c\xfe\xe9L\ \xb6z2\x0em\xe6$U\x84\xbf\x7f\x99\xdb\xcb#\xb5\x83\x99\x92\x9a\xd7b\x15\xf0\ \xbd\x9d\x96\\\x86bf\xeb\xf3\xb6\x8e\x92\xf15U$\xea\x06n\xfd\xfd\xdaW\xdcQ\ \xb8\x02\xf7\x1c\r]\xe8\x8e\xbe\xe6\x1f\xf8\x83\r\xfeI\xe7\xffy\xcaOD`\x90\ \x163\xa7\x11?J\x0c\xb5\xab\xb1 \xd4\x92A\xf2\t\xe1\x11H<;H\r4Q\xfa\x16lg\ \xcd\xb4\x95R\xe1\x96\xea\xd6\xe7\xe5\x99o\xd2\x1f\xdd\xabH\xb6""\x02\x8c%;\ \xec\x8c\xe3\x0e\xafE\xe6%\x9c\xc6\xbb\xa5*\xc3\x95\xe0\'\x1bj\xc1\xe4(S\xc9\ \xf8lD\xea\x0cD\x91\xfd\x065FB pB\x15\xc9\xf5yy\xa4\xd9\xb1\x90`\xe0lL\x84\ \xb1\xe1v\xa3\xf9\x86\xd4\x83\xeb\x12|\xb3$]}"i`\x1c\xcf\x80?2V\xc5\xd6\x12\ \x8e\xb9"\xa6\xfb@M\x0c\xa7BH\xf1\xdcI\xb8\x81\xaf\x94\xde q7\xff\xe9/<\xb0\ \x9c\x1aZ\xfb[\x0co\x8a=`&^p\x91^\x0fG\x7f>\xe8$x\x01\x1c\xed\x93\xd6\xd6Off\ \xf7^\x8b7\x94\xc0\xc3\x12h\x7f\xe4\xe53=\x1f\xe2z8\x8f\x06a\xcf\xd6\\F\x96\ \xc9\xd8\xce\x17F\xeb\x1e\x0cQ`\x95E\x97\xf7\xe4}J\xfe\x12_\xd7\xbe\xeb\xa8\ \x14\xe1{\xbb\x19\\Sn\x92\x95\xbek\x18D\xfd\xe1\xe1_\xd9oy\xbe\x85\xf5\x89Q\ \x15\x0c\x11\x91\x96\\N\xd8\xab\xf1:\x88\xf1\':\x9aY\xfbF\xf2U\xf9\x8a"\x9c\ \x85ss\xa3)\xe7A\xfc\xa1{\x8aOD\xca\x14\xc8\x9a\xe6\xfcZ\x8a\x9dH\xf34f\xd2\ \x04\xc9\xe5\xb7\x1e\x9e\x84\xd7\x86hS\xcc\xec\x8b\x9e\x1f\x05\x0b\xb2\xff\ \xa5\x04\xa9\x9b\x13\x1bh\xb6\xce|\xe9n\x89\xe6\x0f\xfcdW\xe8\x9f\xe8`\xbdn\ \xbe\xb2\xcfp">\xc1\xe8\x96\x92vO]l(\xa6\xe0\xb2\xf0#\x83w\x17\xa0t\x99o\x11\ \xb8H\xfe#\xde\xf8\x92"\xe0\x84\xe5\xd7\x96E\xa1\xfc\x0f\xfe\x0c\xc0]\x97\\9\ 7f\'7\xc5;\x9d3\xa2}|\x01\xae\xd5\xc1\xb2\x00\x89O\x94\xdc\x82\xdd\xa8\\k\ \xbbs(N.\xab\xa7\x14e*\x9ccI<\x8b\x1f\x9dj<\xa8/\xb3\'/\x83\xe8u\xce\x96\xe5\ \xb49\xad\xfdm\x91\x1eHW\n\xfcX\xd7\xb5\x91\\\xeaDk\x85]\xd7\xe4\xab\xe2O\ \xf9\xc4\xe4\x9b\x83\xc1\xdf\xb1\x8b\xde\xbd\x03R\x14\xf7p\xa8\xcc*\xccq\x88\ \\\xc77\x8f\xdch\x99\xd8\xcb\xa1\xfd\x1c@"\xbe\x82"\xff\xb0\xb0m\x84od\x92\ \xe8\x0e\xb1B\xf1\xf1\x00^\x1b\xcf\x99\x82\xb1"\x1c\x89\xcb\x06\x7f\xd8\x1c\ \xbd\x0f]\x1f\x11J\xfd\x06(\'\x14\x9eks\xa9\xea\x86J\x1cF\x7fL\xc39\x7fe\xfe\ K^\x0b\x02\x17\x0b(sd\x86\xfa\xa8\xff\xa0\x7fV\'\xed\xea:\x87\xec\xe2\xb1|\ \x8bM\x8f\xf9w\xb1\xcb\xb4\xbf\xc7\xf4\xea\xf4m\x1c\xfe\xab\x00C\x03\xa2\xb2\ R\x0e\x8f\x85\x07\xef\xd0\x1aOs\xf1f\xec\xfb\xd2*\xcek\x91n|\xc4u-tn\x8a\t\ \x8d\xf7\xaez\xb8J\x15\xdbz\xba\xea\x90\xda\xd8\x9e\xd9\xfe5`!\x96\xa8X~\x83\ 0\x88_\xca\x8e\x07~\x11\xb7\xc0UQ=\xb9\xa6d\xad\x92`>\x17\x98\xadvFn\x8b\xe2\ \x11# \xfe\xa39\xee\x07\xfbUS\xe8\x95\x16r\xb8\xad,\xe1J|\x882\x13L\xad\xa4t\ \\Oa\x08F\xe6\xe5\x1aO\x94\xc6"I\xb9\xb7d\xbe\x94\xbc\x7f\xff;\xc1\x84\xb8\ \x0e\x81\xbd\xebwp\x94\xcf\x8b\xee\xe8\x18\xecR\xeb<\x9a\x8d\xae^\xa1`\xc4\ \x9e[lz\xce>\xe5u)\xbd\xca>\xc9\x1d\x077B/\xf6\x08\xcal\xcaR\xc2 \xe8\x9f\ \x7f\x05\xef>1-\xc9\xa6\xe3J\x96\xde\x89\xde\xc4\x95(\xf8\x1a\xb4\x94s\x04\ \xfc\xb9\x90\xe7I\x8b\x1b\xa2N\xf6,\xae9\x92k\xe7\x06)T>\xbe\xb7\x15Y\x10\ \xff\xb1v\xc31,}\x88\x02\xbd\xa1h\x89\xfc\xd9\xe5I\xf4PP\xf6\xd7w\x03`\xe6&\ \xb2\xa0\xadl}dL\xa7\x91\x1a\xfd\xe4\xdc\xd8\x08\x8aC\xa4\xa8\xfe)\x9c\\\x02\ yr~0\xaf\x94\xfc\r\xd7,\xf1\x84\x97\x1c\x84\xc1I\xa3;\xc5\x9b\xbf\xb2k\xb4\ \xc7\xbf#\x1d\xd9\xd2\xd8\xf1@E\x82e\xfdqN\x83\xd4\xa4\xb2;\xa7\xea\x07\xeb\ \xdfl\'\x7f\xfc\x9e\xed\x1c\xb2\xe9N\xd4P5\xdd\x0c\xf7\x86"fg\xc5/\xe6\xa1KK\ \':F\\\x08\x9f\xf4\xa6\x0e\xc5e\xd8\xb8\xaf\xcd\x85g\x12xS\xf2W\xcb\xf02)\ \xeb\xaa`\x02\x97?\x15\xea\n\x0f\x9ce\x99O\xc0\xa4!\x1dv;\x84!\xf77c\xa8\xaa\ Q`\x10\x08\xf4\x13\xe4\x8aGy\x12\x17\xff\xca\xc6^\xb0(\xd6c\xba\x7f\x08]\xa2\ \xed#X\x11\xcfR\xf64\x15\\I\xbd\xc4\xf4&\xbf\x96f7B\x17\xc3\x1d.\xae\xfe\x94\ wM\x81\xecB\x11QO\x1dvV\xb8F@\xca\x98\x13\xed\x18}f\xdb\xcd\xe9]\x11;\xf9t\ \x9c\x1a\xc5\xf3:\xcf\xdd\xecY\x99\xb5\x92z"\xe6\xdd^\xf2\xb8\x88\xb9\xd1\ \xf9Qn\x8d\x00\x92Th\x82>\xd7\xd9d\xe1\xa6\xe3\xc4\xad\xb5\xe0b\xee\x11\x1a \ \xae\x952\x8b\x15\x91d\xd1-\xdb\xf9\x9e\xbd^L\xbf*\xbe^(\xec\xec\x0fi\xdc\ \x8f\xc6\x07\tw\xb9\xb8\xc5\xfb"H\x18\x02\x0eS0/\xf6\xe0\xe3\x17\x8c\x9d@w\ \xb1\xf1#!\x18\xcca3\x16\xf9\x80\xf2\x0f\xc6\xe0\xe4\x7f\xa9\xd6\x7fWYB\x90\ \xeb)\x0f\xc7\x7f\xd7y\xd4F\x7f\x1b\xf0\xa6\r\xf1.\xc28X!\xf9m\xe9.\xbdDf\ \x1b#{\xdb\xce\x7f\xd8\xe0\r/$>\x85w\xbc\x1d\x83\xe7\xf5tn\x9dx\xfc\xd7\x9d\ \xf7*\x17uYU\xaf\xbf\x93\xa9\xb6\x10\xa2\x19x\x0e\xc3\xed\xe4\x9b\xde~#\xd3\ \xdeB\x00\xdf\x96Y\x94\xa4\x8b\xf2\xf4\xab[8v\x97lM;\xa9\x85\xebn\x1a\x0f$\ \xc5\x89D \x8b*\xe8\xd4\xd2\x82@\xd0\x05\x9f\x93\x1d\x9d/ *