rebulk-0.9.0/0000775000175000017500000000000013113544041013574 5ustar toilaltoilal00000000000000rebulk-0.9.0/requirements.txt0000664000175000017500000000007113113544037017063 0ustar toilaltoilal00000000000000# see https://caremad.io/blog/setup-vs-requirement/ -e . rebulk-0.9.0/.coveragerc0000664000175000017500000000024213113544037015720 0ustar toilaltoilal00000000000000# .coveragerc to control coverage.py [run] include = rebulk/* omit = rebulk/__version__.py rebulk/test/* [report] exclude_lines = pragma: no coverrebulk-0.9.0/PKG-INFO0000664000175000017500000005711613113544041014703 0ustar toilaltoilal00000000000000Metadata-Version: 1.1 Name: rebulk Version: 0.9.0 Summary: Rebulk - Define simple search patterns in bulk to perform advanced matching on any string. Home-page: https://github.com/Toilal/rebulk/ Author: Rémi Alvergnat Author-email: toilal.dev@gmail.com License: MIT Download-URL: https://pypi.python.org/packages/source/r/rebulk/rebulk-0.9.0.tar.gz Description: ReBulk ======= .. image:: http://img.shields.io/pypi/v/rebulk.svg :target: https://pypi.python.org/pypi/rebulk :alt: Latest Version .. image:: http://img.shields.io/badge/license-MIT-blue.svg :target: https://pypi.python.org/pypi/rebulk :alt: MIT License .. image:: http://img.shields.io/travis/Toilal/rebulk.svg :target: http://travis-ci.org/Toilal/rebulk?branch=master :alt: Build Status .. image:: http://img.shields.io/coveralls/Toilal/rebulk.svg :target: https://coveralls.io/r/Toilal/rebulk?branch=master :alt: Coveralls ReBulk is a python library that performs advanced searches in strings that would be hard to implement using `re module`_ or `String methods`_ only. It includes some features like ``Patterns``, ``Match``, ``Rule`` that allows developers to build a custom and complex string matcher using a readable and extendable API. This project is hosted on GitHub: ``_ Install ------- .. code-block:: sh $ pip install rebulk Usage ------ Regular expression, string and function based patterns are declared in a ``Rebulk`` object. It use a fluent API to chain ``string``, ``regex``, and ``functional`` methods to define various patterns types. .. code-block:: python >>> from rebulk import Rebulk >>> bulk = Rebulk().string('brown').regex(r'qu\w+').functional(lambda s: (20, 25)) When ``Rebulk`` object is fully configured, you can call ``matches`` method with an input string to retrieve all ``Match`` objects found by registered pattern. .. code-block:: python >>> bulk.matches("The quick brown fox jumps over the lazy dog") [, , ] If multiple ``Match`` objects are found at the same position, only the longer one is kept. .. code-block:: python >>> bulk = Rebulk().string('lakers').string('la') >>> bulk.matches("the lakers are from la") [, ] String Patterns --------------- String patterns are based on `str.find`_ method to find matches, but returns all matches in the string. ``ignore_case`` can be enabled to ignore case. .. code-block:: python >>> Rebulk().string('la').matches("lalalilala") [, , , ] >>> Rebulk().string('la').matches("LalAlilAla") [] >>> Rebulk().string('la', ignore_case=True).matches("LalAlilAla") [, , , ] You can define several patterns with a single ``string`` method call. .. code-block:: python >>> Rebulk().string('Winter', 'coming').matches("Winter is coming...") [, ] Regular Expression Patterns --------------------------- Regular Expression patterns are based on a compiled regular expression. `re.finditer`_ method is used to find matches. If `regex module`_ is available, it will be used by rebulk instead of default `re module`_. .. code-block:: python >>> Rebulk().regex(r'l\w').matches("lolita") [, ] You can define several patterns with a single ``regex`` method call. .. code-block:: python >>> Rebulk().regex(r'Wint\wr', 'com\w{3}').matches("Winter is coming...") [, ] All keyword arguments from `re.compile`_ are supported. .. code-block:: python >>> import re # import required for flags constant >>> Rebulk().regex('L[A-Z]KERS', flags=re.IGNORECASE) \ ... .matches("The LaKeRs are from La") [] >>> Rebulk().regex('L[A-Z]', 'L[A-Z]KERS', flags=re.IGNORECASE) \ ... .matches("The LaKeRs are from La") [, ] >>> Rebulk().regex(('L[A-Z]', re.IGNORECASE), ('L[a-z]KeRs')) \ ... .matches("The LaKeRs are from La") [, ] If `regex module`_ is available, it automatically supports repeated captures. .. code-block:: python >>> # If regex module is available, repeated_captures is True by default. >>> matches = Rebulk().regex(r'(\d+)(?:-(\d+))+').matches("01-02-03-04") >>> matches[0].children # doctest:+SKIP [<01:(0, 2)>, <02:(3, 5)>, <03:(6, 8)>, <04:(9, 11)>] >>> # If regex module is not available, or if repeated_captures is forced to False. >>> matches = Rebulk().regex(r'(\d+)(?:-(\d+))+', repeated_captures=False) \ ... .matches("01-02-03-04") >>> matches[0].children [<01:(0, 2)+initiator=01-02-03-04>, <04:(9, 11)+initiator=01-02-03-04>] - ``abbreviations`` Defined as a list of 2-tuple, each tuple is an abbreviation. It simply replace ``tuple[0]`` with ``tuple[1]`` in the expression. >>> Rebulk().regex(r'Custom-separators', abbreviations=[("-", "[\W_]+")])\ ... .matches("Custom_separators using-abbreviations") [] Functional Patterns ------------------- Functional Patterns are based on the evaluation of a function. The function should have the same parameters as ``Rebulk.matches`` method, that is the input string, and must return at least start index and end index of the ``Match`` object. .. code-block:: python >>> def func(string): ... index = string.find('?') ... if index > -1: ... return 0, index - 11 >>> Rebulk().functional(func).matches("Why do simple ? Forget about it ...") [] You can also return a dict of keywords arguments for ``Match`` object. You can define several patterns with a single ``functional`` method call, and function used can return multiple matches. Chain Patterns -------------- Chain Patterns are ordered composition of string, functional and regex patterns. Repeater can be set to define repetition on chain part. .. code-block:: python >>> r = Rebulk().chain(children=True, formatter={'episode': int, 'version': int}, flags=re.IGNORECASE)\ ... .regex(r'e(?P\d{1,4})').repeater(1)\ ... .regex(r'v(?P\d+)').repeater('?')\ ... .regex(r'[ex-](?P\d{1,4})').repeater('*')\ ... .close() # .repeater(1) could be omitted as it's the default behavior >>> r.matches("This is E14v2-15-16-17").to_dict() # converts matches to dict MatchesDict([('episode', [14, 15, 16, 17]), ('version', 2)]) Patterns parameters ------------------- All patterns have options that can be given as keyword arguments. - ``validator`` Function to validate ``Match`` value given by the pattern. Can also be a ``dict``, to use ``validator`` with pattern named with key. .. code-block:: python >>> def check_leap_year(match): ... return int(match.value) in [1980, 1984, 1988] >>> matches = Rebulk().regex(r'\d{4}', validator=check_leap_year) \ ... .matches("In year 1982 ...") >>> len(matches) 0 >>> matches = Rebulk().regex(r'\d{4}', validator=check_leap_year) \ ... .matches("In year 1984 ...") >>> len(matches) 1 Some base validator functions are available in ``rebulk.validators`` module. Most of those functions have to be configured using ``functools.partial`` to map them to function accepting a single ``match`` argument. - ``formatter`` Function to convert ``Match`` value given by the pattern. Can also be a ``dict``, to use ``formatter`` with matches named with key. .. code-block:: python >>> def year_formatter(value): ... return int(value) >>> matches = Rebulk().regex(r'\d{4}', formatter=year_formatter) \ ... .matches("In year 1982 ...") >>> isinstance(matches[0].value, int) True - ``post_processor`` Function to change the default output of the pattern. Function parameters are Matches list and Pattern object. - ``name`` The name of the pattern. It is automatically passed to ``Match`` objects generated by this pattern. - ``tags`` A list of string that qualifies this pattern. - ``value`` Override value property for generated ``Match`` objects. Can also be a ``dict``, to use ``value`` with pattern named with key. - ``validate_all`` By default, validator is called for returned ``Match`` objects only. Enable this option to validate them all, parent and children included. - ``format_all`` By default, formatter is called for returned ``Match`` values only. Enable this option to format them all, parent and children included. - ``disabled`` A ``function(context)`` to disable the pattern if returning ``True``. - ``children`` If ``True``, all children ``Match`` objects will be retrieved instead of a single parent ``Match`` object. - ``private`` If ``True``, ``Match`` objects generated from this pattern are available internally only. They will be removed at the end of ``Rebulk.matches`` method call. - ``private_parent`` Force parent matches to be returned and flag them as private. - ``private_children`` Force children matches to be returned and flag them as private. - ``private_names`` Matches names that will be declared as private - ``ignore_names`` Matches names that will be ignored from the pattern output, after validation. - ``marker`` If ``true``, ``Match`` objects generated from this pattern will be markers matches instead of standard matches. They won't be included in ``Matches`` sequence, but will be available in ``Matches.markers`` sequence (see ``Markers`` section). Match ----- A ``Match`` object is the result created by a registered pattern. It has a ``value`` property defined, and position indices are available through ``start``, ``end`` and ``span`` properties. In some case, it contains children ``Match`` objects in ``children`` property, and each child ``Match`` object reference its parent in ``parent`` property. Also, a ``name`` property can be defined for the match. If groups are defined in a Regular Expression pattern, each group match will be converted to a single ``Match`` object. If a group has a name defined (``(?Pgroup)``), it is set as ``name`` property in a child ``Match`` object. The whole regexp match (``re.group(0)``) will be converted to the main ``Match`` object, and all subgroups (1, 2, ... n) will be converted to ``children`` matches of the main ``Match`` object. .. code-block:: python >>> matches = Rebulk() \ ... .regex(r"One, (?P\w+), Two, (?P\w+), Three, (?P\w+)") \ ... .matches("Zero, 0, One, 1, Two, 2, Three, 3, Four, 4") >>> matches [] >>> for child in matches[0].children: ... '%s = %s' % (child.name, child.value) 'one = 1' 'two = 2' 'three = 3' It's possible to retrieve only children by using ``children`` parameters. You can also customize the way structure is generated with ``every``, ``private_parent`` and ``private_children`` parameters. .. code-block:: python >>> matches = Rebulk() \ ... .regex(r"One, (?P\w+), Two, (?P\w+), Three, (?P\w+)", children=True) \ ... .matches("Zero, 0, One, 1, Two, 2, Three, 3, Four, 4") >>> matches [<1:(14, 15)+name=one+initiator=One, 1, Two, 2, Three, 3>, <2:(22, 23)+name=two+initiator=One, 1, Two, 2, Three, 3>, <3:(32, 33)+name=three+initiator=One, 1, Two, 2, Three, 3>] Match object has the following properties that can be given to Pattern objects - ``formatter`` Function to convert ``Match`` value given by the pattern. Can also be a ``dict``, to use ``formatter`` with matches named with key. .. code-block:: python >>> def year_formatter(value): ... return int(value) >>> matches = Rebulk().regex(r'\d{4}', formatter=year_formatter) \ ... .matches("In year 1982 ...") >>> isinstance(matches[0].value, int) True - ``format_all`` By default, formatter is called for returned ``Match`` values only. Enable this option to format them all, parent and children included. - ``conflict_solver`` A ``function(match, conflicting_match)`` used to solve conflict. Returned object will be removed from matches by ``ConflictSolver`` default rule. If ``__default__`` string is returned, it will fallback to default behavior keeping longer match. Matches ------- A ``Matches`` object holds the result of ``Rebulk.matches`` method call. It's a sequence of ``Match`` objects and it behaves like a list. All methods accepts a ``predicate`` function to filter ``Match`` objects using a callable, and an ``index`` int to retrieve a single element from default returned matches. It has the following additional methods and properties on it. - ``starting(index, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that starts at given index. - ``ending(index, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that ends at given index. - ``previous(match, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that are previous and nearest to match. - ``next(match, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that are next and nearest to match. - ``tagged(tag, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that have the given tag defined. - ``named(name, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that have the given name. - ``range(start=0, end=None, predicate=None, index=None)`` Retrieves a list of ``Match`` objects for given range, sorted from start to end. - ``holes(start=0, end=None, formatter=None, ignore=None, predicate=None, index=None)`` Retrieves a list of *hole* ``Match`` objects for given range. A hole match is created for each range where no match is available. - ``conflicting(match, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that conflicts with given match. - ``chain_before(self, position, seps, start=0, predicate=None, index=None)``: Retrieves a list of chained matches, before position, matching predicate and separated by characters from seps only. - ``chain_after(self, position, seps, end=None, predicate=None, index=None)``: Retrieves a list of chained matches, after position, matching predicate and separated by characters from seps only. - ``at_match(match, predicate=None, index=None)`` Retrieves a list of ``Match`` objects at the same position as match. - ``at_span(span, predicate=None, index=None)`` Retrieves a list of ``Match`` objects from given (start, end) tuple. - ``at_index(pos, predicate=None, index=None)`` Retrieves a list of ``Match`` objects from given position. - ``names`` Retrieves a sequence of all ``Match.name`` properties. - ``tags`` Retrieves a sequence of all ``Match.tags`` properties. - ``to_dict(details=False, first_value=False, enforce_list=False)`` Convert to an ordered dict, with ``Match.name`` as key and ``Match.value`` as value. It's a subclass of `OrderedDict`_, that contains a ``matches`` property which is a dict with ``Match.name`` as key and list of ``Match`` objects as value. If ``first_value`` is ``True`` and distinct values are found for the same name, value will be wrapped to a list. If ``False``, first value only will be kept and values lists can be retrieved with ``values_list`` which is a dict with ``Match.name`` as key and list of ``Match.value`` as value. if ``enforce_list`` is ``True``, all values will be wrapped to a list, even if a single value is found. If ``details`` is True, ``Match.value`` objects are replaced with complete ``Match`` object. - ``markers`` A custom ``Matches`` sequences specialized for ``markers`` matches (see below) Markers ------- If you have defined some patterns with ``markers`` property, then ``Matches.markers`` points to a special ``Matches`` sequence that contains only ``markers`` matches. This sequence supports all methods from ``Matches``. Markers matches are not intended to be used in final result, but can be used to implement a ``Rule``. Rules ----- Rules are a convenient and readable way to implement advanced conditional logic involving several ``Match`` objects. When a rule is triggered, it can perform an action on ``Matches`` object, like filtering out, adding additional tags or renaming. Rules are implemented by extending the abstract ``Rule`` class. They are registered using ``Rebulk.rule`` method by giving either a ``Rule`` instance, a ``Rule`` class or a module containing ``Rule classes`` only. For a rule to be triggered, ``Rule.when`` method must return ``True``, or a non empty list of ``Match`` objects, or any other truthy object. When triggered, ``Rule.then`` method is called to perform the action with ``when_response`` parameter defined as the response of ``Rule.when`` call. Instead of implementing ``Rule.then`` method, you can define ``consequence`` class property with a Consequence classe or instance, like ``RemoveMatch``, ``RenameMatch`` or ``AppendMatch``. You can also use a list of consequence when required : ``when_response`` must then be iterable, and elements of this iterable will be given to each consequence in the same order. When many rules are registered, it can be useful to set ``priority`` class variable to define a priority integer between all rule executions (higher priorities will be executed first). You can also define ``dependency`` to declare another Rule class as dependency for the current rule, meaning that it will be executed before. For all rules with the same ``priority`` value, ``when`` is called before, and ``then`` is called after all. .. code-block:: python >>> from rebulk import Rule, RemoveMatch >>> class FirstOnlyRule(Rule): ... consequence = RemoveMatch ... ... def when(self, matches, context): ... grabbed = matches.named("grabbed", 0) ... if grabbed and matches.previous(grabbed): ... return grabbed >>> rebulk = Rebulk() >>> rebulk.regex("This match(.*?)grabbed", name="grabbed") <...Rebulk object ...> >>> rebulk.regex("if it's(.*?)first match", private=True) <...Rebulk object at ...> >>> rebulk.rules(FirstOnlyRule) <...Rebulk object at ...> >>> rebulk.matches("This match is grabbed only if it's the first match") [] >>> rebulk.matches("if it's NOT the first match, This match is NOT grabbed") [] .. _re module: https://docs.python.org/3/library/re.html .. _regex module: https://pypi.python.org/pypi/regex .. _String methods: https://docs.python.org/3/library/stdtypes.html#str .. _str.find: https://docs.python.org/3/library/stdtypes.html#str.find .. _re.finditer: https://docs.python.org/3/library/re.html#re.finditer .. _re.compile: https://docs.python.org/3/library/re.html#re.compile .. _OrderedDict: https://docs.python.org/2/library/collections.html#collections.OrderedDict Keywords: re regexp regular expression search pattern string match Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Topic :: Software Development :: Libraries :: Python Modules rebulk-0.9.0/runtests.py0000664000175000017500000100531113113544037016043 0ustar toilaltoilal00000000000000#! /usr/bin/env python # Hi There! # You may be wondering what this giant blob of binary data here is, you might # even be worried that we're up to something nefarious (good for you for being # paranoid!). This is a base64 encoding of a zip file, this zip file contains # a fully functional basic pytest script. # # Pytest is a thing that tests packages, pytest itself is a package that some- # one might want to install, especially if they're looking to run tests inside # some package they want to install. Pytest has a lot of code to collect and # execute tests, and other such sort of "tribal knowledge" that has been en- # coded in its code base. Because of this we basically include a basic copy # of pytest inside this blob. We do this because it let's you as a maintainer # or application developer who wants people who don't deal with python much to # easily run tests without installing the complete pytest package. # # If you're wondering how this is created: you can create it yourself if you # have a complete pytest installation by using this command on the command- # line: ``py.test --genscript=runtests.py``. sources = """ eNrUvduWG9mVIFYeXxvu6RnbMy/2g0PgsBFgRQYvJfUlWyiJYmVJXGKRXCSrxZ6sbDAABDJDCUSA EQFmQt1ay5/ktfwlfvCLX/wr3rdzjRMAslTlbmt1FxPAOfvc9tln3/f/9m/++PGz+P1ffPbZZ5td Ot1k7VW6qubZ6uN/8f7ij599NhwOB/Q5wp+iYr1Z5eu8bLO2qMp0gD8v62odTafLbbut8+kU21R1 G90U7dW0gYbUfsDN5lXZ5rftqpipZvLNOiuzy7weyLfNrkmiCv6/zpMIQNwWbRIVlfp5s2NwasoG 2Hpdle5vKX+pmhTNTVF+8YTb4PTUD2+nz9++ePnbhP746vkb/uPN2a9l6lWT2kNlswY/JlFZ1Wv+ q2jgyySCyTZtgx8XRY3/LItVjv+uivI6ieDLMlvng0GxxGWmn/K6gb2cFuWyir6M4i+SR+PTQQT/ W+TLaJ1tplkzXQHIeLkt5wCnzWtpgP+rc9j2MqIG0NhuNB7kqybnphacaIKfBoP5Kmua6C1sQVzN fp/PW2vY6fQyhx/aejqNm3y1hGXCnLvDSitqk06rBje0zpvtCo5r2LTTYfQ59xxYoIuyaDVc3jq7 pzUKgaVdn1BD9wdnPGhhf+Txfrmpq01etzs9enVT5jxdaxg4CUEL8x0tMiuaPHpZtc8V2ueLs7qu 6nj4/v37iHoMxwaMIOfNQn8FXeodTn6X5tgxnV/l8+t8MYUbtYqhZQo7uLnZFouE1wR/jf1NJiDn jy761nRZV9uNvya4mfqQ8Hc6hqhaRoiNKf78Iy3/st4cuXxoicu/rC/18i8PLh8XTDfLX7C0ltsb wMgU8HFdLWxc5Lu5BxJc/2Mh4e32IdFl00icrhBEPA4NBJRn/0B8W19XTXH7GmDFTNVS/PtXWZNb d3d+BUgut2vb5ECCCAGQls4njzwUmV9l5WXO16K5KjZRW0XtVR5dFp/ykrpHWblgCKmDHe5vQFJ2 0SyPmk0+L5ZFvohmuyiLyu16Bs2q2unKPwE+poR8MC/Yv+hdvc0783ERMp9vgVh+yle71F6F/htu D2w44BROrljE+I/Z7kv1K80YfqZ/x/Y9gBHcO7Cs6ug2Kko+xU9FU7Qx7uMqW88WWXR7Gt0yUsd4 /rC9Y7e/wPUaddvg/8K3BN4dOlG4IUBob8dJRNTCuSnH9CTUtDtrhKnzbBHCXouEfMpWW6IeGbxZ 61m1KuYRdnEJiTTunY0aSC47zAqvhTWT9TX+3FaCvdVq4T07OKUN3gFY0m6VR1dZvaCJIN5mZQWo Wwtm2RPrnZHMBrZHjWVtljMxWLYzN9qRBNmAarVt88lj/2LBYtvc3y/iiqwLxvsab6qibIvy0l/F uEOo1XguBvWuT2bNi6LBxv7ma1qteQV9TYGuKPrF5EZAOK3u8Zr4VAyr2ESjhyO81tnqJtvBP8Kc EVTvVq+aalvP9VjTKRE7YBF4OMCbFew7dhz7PRe5obF9zUpoIE1hHduyZUrb5Bu3XZvVQBwUNPg5 /T2cSxyP0nSUROMHJTAzsZ4tfDO+4yHwAB3spzfcpVl8EB5DAccPuAF7WpTwRJTzPGbyDrhjIR/R 5UmkeQvAI4Z5/uRiYN1S/E6P7VJEZ3T1nndHl2fFHZ5fg0mkH3ccn8F6E6AvB4Ov3/6K8YyhE1dB 74p+6+D5iLznTr2HLxDf6D1kMDIRvIDM00LfghgXnGZeLzNAM7hkipnHcfi6MeYiOwBMOcgsFlFb Zdwf3oK1yD32w8MzeU679U3RQJP5FbNJ/B397ZNVZK1gaCSWvM/xGHcYp5LTrYnWAgqpLkhXMLHp dNTgoAPmgDfE8iKeWtN4RrhXN4o/UJ+t8YkJJ07Eo/d0B+pd93GSA+PLiT3nGeC40yy/neebNnoK wkAxA/pEi+5CCoI3DL2G7bBNHtfkDamv3dmLV69e3x36qgd8z6KdbQywob2sKA+TWnyjghLiQXv5 0H4wLHfuAWQDcLuGXv8j+NcQD9umHmcckPcmL6syR0F5A/cP6dDk62zV+O/8c+hWZKviDzldUxko k5tKhEGRotQsh76fZyUyo3R14Z1VTC1wjzUQAzw2IA1VbXGRz5ei4GginBwI0Dj5DHjwxu99U9XX +FaHoZhFKZ4W6H4Bj88J/YKiPv4AEhySk3xhOoOgBTO9ylp3bfoFnWc1CFOwMsUD0Iy9/rCPFQPZ ADnAaRZmz2iFQhdvitUqalCfs5Ot1YBwsfltBo0alBmtXmn0LZDqMr8BagW7gq9lhh+BPG96WPLC 3VgPv6yHsFdMBBoHA81vFjavQjKrfolYiRAWifrGYspSO2qFMFyY1mxbrIBBS6fIXUAv2FgPfGEf fZcKyajy7qSmaexyYYGZiqYpPsSusbj+98gyiZSO16Aq4YARFyK+dB5uDYP0Uv9vCE9vWZUn+XrT 7iJeOF0I/fAOnat+lTVXctW7AjX+GPdw/tNp/lHTCHqRbTH6sWbKvANrnrBER0oo6kZ6J2o0VIAO KjoY/uN0Vd3AgYwPP4g0bPMk2OHIl1D2hAifv1E4H4Rvb0+Z926P9EL+iVpgZ1m5BWDVHgLg4N3P D2+rrS28G/Av7wAcaZB+IbvgLSGVFAhwxiNqM4Kvl8BNEZojSSNihpCiDIQThDYKkyxmCO+GV8y8 wlWN/QnaENVV7vZ3zi34euPqDqvsLKwCyUyzk2Wl9/E4ab2Dr4pyKTCuFNM9tjpfV5/UoaHG5DFI CpdlVedTGq4JvvncCx4VOicgPvqRjWL4lFmf2zrPRWUDwnfqbI09jnmG5fPNFcKmkexnvAA0wUdR AwIGggEtel82Fo1JswNgcIlBBU9IscSiM/AA81ytumJVDFFsEkRQPoBDXlQ3TUipFMQA5xGZXwEz Fv/0p38jRzCGIat5i7zAo79+9GhwnAYKvm3aRdpcbYGRSes17rx3/MEpuMftfPJIZuct2ytP12sy rByrxti3U+4u7duePUotPLxelRYwJRt4BfTbl9Az2O42+WS4XvwMiMn8alteN8DmTn725KdP/uZv wsTtKr9dFJeo7QA0QRCsOkL9ZHsFKN5V63deruBTJlI+QkSrHJBG2IzQg2YJs0EVp1oWUrFhc5U9 HoYR07SjZl0GBMaH30BsoAHhXVE9XKTBby0iDb3M1o6tN1mmH7sPchKFhfMwI/VVVY7a6LqsbqIr +H/gf+RYo/s1DTqM7utpJpZeaKkYl2qTl/Gono3G/efDhOlxd9tmW4SzJP1prNFlHDoFfIegeXjr LT4s1fgUEH2pwXazyNo8BmDWcooSsN6bNlygVdXksYX0KCEwsj94cH3TpxmFI2NTgZhAEbMJl125 Rokky2oF/BaS7Ot8B0LYIsrqyy2apRoGtYs+ZXVRbRkA/Kdum9PTgbe87PRhU63zh9jmYVs9zB7S 1clvW6/h7e0exnhRg1zZ6eD9z+kgZt/owP+svihrHN1HkaltnR/dT3WmW9KGeaHZ71FsYekPudAb YfSMlrbDB13feNzP7PeWOBPk4y3shNYDZ5e1yTzRO5I460xg8lp3DPRgtkMrlMfCDBmWAqX7+oCG znJG6qcRytH+wrCB3V8aId8yAlDBPmECU5RAzouFMp/NSc0IxAXoCkDY97ptZrD065u0yVtRWMTu nNy9OkK44d28vjmnNVyE3oLf5ruehwAlzSPedpKWW9LrIMbA36jlg/uKtoR4lI56TGQ8N/g9+jzy byzOWK/6AkX8mbSyTzQeCQqow1JzwO7qpwtveOc3gOze/u4SvfNQXTUmm1PwWjb5ZpREXfOEe4WU y4mL4sP7sQLf3I+xO/yjz73xUcm6bkaQM7eHyTf+6ZHvJicNEHEeN6hoGmGjkejcfINgA9M9NzhE NNkjAmmzWRW2TUa3BvqOjYE+tyBms/4CB5Meo2Q0jsyCsg28sQuy9TQpfxjYZlxygEBtGEDt3GP6 ETiXER3tqIt9DDCmBZw/uvAZWAeEHHcvENe+xCBPTx5fjI9hi9WJkg4Le0LHICegpqPvRPhKyZzC BKJ/GjQKzEH1S2tgDhZ0dcNtl9h8Ep08Pu19lxxaLHfdfB6NwiShd3qHQJ6fFhfmTTkvTi/6Zq73 0qGs/aMqZOklvGHEQXp7ECg0Gn+Pjeh/cxCLgg+PO22hF3C5DL0ATCc6JLwe3ixm+fCvsByDnJwR 4omg4S0ALpDMyFm5E9M42+cUh5d2ZG+m2d3LrDStx7EsqodFXeX6xmH5UtnhO+NaYxNAutu0JUGD icP+KB3ZdgN0TqtW+SEYp2qX/f0150Bj3eEQWGlPs0VfHEIsZKyBuY9G2G2EgqAzRRR4gADzUbAj wuQx6la2aMgErMDnOyJPybpCZdgSz9I8YGTbZIqO5s1eK4Z9ymzjVNTS8qqq5WU4V9IffHYUdPB5 TEQf/lA0/8IGsI8Zhanz5qHdIR7BRH12BHZPzeCi4y4kQ9Y5ijU5UHuebtgxiHWGON0eNY4xA9SX fS1kLjKrYKsZCF3XnV+kR1qUTV638SPeuEFgNTKKO0n8jSaGW1hs4o5HxT7Vyz3ENhCmt6X25mG/ kRxvv9F8pd1X1Bt29DDw5phGdb5ZZfMcm+GN8qZo4YL89Tnh3efOht9JDOph1jqkJMSBkZ6AbzLa USejGiadlw28JKwwxU/zCm8rWVF77ndJgOBikh7VczpCwJbFFI2WNIDRlIqIDi+DbS5FDSkS3jxf 7NGJMqyA7U2RsXHKTVhlOnb78tKCSu2wBq6oSLfiq6NxjdZWqT/GR/qq9UC0bR7LrGktuus5qs2v itXieJSh5j1CMiEkk0DxpvYXQb0P+aJKW+vHkLaSdNlB1U2PcK+cdI3zQffNhK4rQGsAh2zO4w7z PQRMGPYKy8a6BWIYNb2I/tHyAe59o4eI/MfCpbYMWFub0r4r2/NQ8+7RvvGWYgACiC7l/CqrWexp 4+GDX5yjW7w2qCiKxI4YTavWleDlFVeJpqrb0H0nf37DTlEwRYnBB5uqaYoZGxJgBvjMGwIA30UY J+ASc5CddC8cb88dRwDKUwL7NRxZEbDwI7o2+0z7suI+db616XYoBN8jdQX59jWeoVdb8WG2xxvx ER8Yun12KXmPNbDNwB4jwMBzra68OzdqHNZ/0I1xbv54r972nNpe9GGyz4rAGU2UT8TXL79BXzJA Wmc6f+rpdOR7W84m4O6CeraoKx95OAZQ4SPv1Th0lZXAL028OBFET0IbaMh3ab9Yg9r1Pc7Q+LNi aLflIq9XO2Se2WTJ3jUBr2jZQfLeQgiWc3FbrPeNB49FK8pykc+wg5oBEZFDA9IQtlFqsxMao3xS idsImWSxLYsK6AdFrdN+MyhuguMLLU2ko2UrDZyjdsCV1vp5TcNSNDyiec3X9ScT7uOiG0ydzCX5 wlltB9dw8YELDd3xl56+XXmb7d7zeDPufW42biDAUbEGtaODs/xShVm4Fc9nwqAQj3/rbal0Dbc9 yKf1hTU87qFeBNR2oL/VgQDxOKzKwHesKLf5IKgvud2Ha6Gzv01oEuP94PqwUq/h4HaE0chBJT0V y1FCaxs0jvlkgEiqNo1ZF9E1+Krro6RidbctwdhH4sMhG6w5c3lhBcUogrbrjXLQmf0+iWZF2YmI 2BTza0Mh4UGteDXom4hUzV6KZze92Ws33eu1wKOmOEGZ25Kmd3ej5vracGYPAroVEZr+MqzpcpRc KHO7ASpqvSGtUe/h0IwSfdwb56Q34+4pm8Xc1EWbT2Efslq9BIuszVxZ01sg9Ym4D7U2h5iG5EjZ EQ1jXbBHales/OGFSdpnD4NQp7X0j5kWFeNqxv7uYFyytzcsRR6xS9jX26NoS6snVzQdJadApv3i uEKsf9HtG4WE6TtuqLOXrN24GR2xl//KUY3MxGRN7NJ/EShs4aNoZrs2b3iHjrENGy/euprnTRNR /+EBl6fusITOPaPefZ50sngwpDiT8z7eJCFd7QHbSs8wocj4S20YVRgX97rWsHam94lw0fKulH/K Bw/n3gmvEASbeKjiur9zE27TG5nR7WLxJb5HoTSwJzbe45j46JgoH+rDj1zQo9kE2py9f/72XUij W2N4FTBviwIf9FMSiR4CQLmeHBQs8Y3tFXKBDwWp0wA0NDmsMrhXKM637Mbasg9oCIEPrNm5YCFZ yZy33PNjDCpChijiImM7w4k89UTzWcqPYli44DIQTVeIoV0ap7iEXbWVtwEjpH03J7IsT5DcjXzn qFKLgrhN5FW6QDZxljs+s/2mlr0MiGcQAXhAth+Fg4w2PUgZ8FyxKGu4j02ZDvH8G/1SjfUFDk3P kvJVCFxCOIEvG+6td8BvjEa9EWk6arebQA4FAYIXHeGEY7nMmP3hotDGU7jsoWxdwGqePRCMC8+s yurFc1Rs1dtNG/CB9Puc0T94s0NTQE2N2d1VKMKws6Gr/h29w46tgltmDjpvjYolYXVLSJkK7QJq FvawzS2rNBtARwRnpHRUGlJMfD/f9bG5m4i4o4YHxz44GPqRSlAZfm3ZZEwsGPatczKV4pRwNtbI QB9bjCODAVH9hW9CH3+jR+4qaQ8JgVvs2rGH4JeHEfNuQOOTxwpyB2PN+/P85d8/ffFDjEYfM8KN sRnXsoYEAjytrBlWMELFERxWoGK1WnQDDvc7aFeWclTHwO/Zh5evzl6+C4FwEHJPcoi9ql21ioHk nfEyNalNyprp/GaxR30p/SLpiG7O8yvZwsa+A8goLLa1CEmGl6d+i2iIQslQgUujVyVGjSH5wqRT rQzHsT64DQCuJ77HbDOf8B4s3hU5tMZd2Ms0QgMNy86rsdLuMQcdMWRbYHXA8nDEjp05okn7VLwG VZRJyRk4RBGzYzTO2ZykjTvrmjNX1zyd1vmm7g0KHFFoany/Ho+i+64/hgWiaQMQbJU8WXMiHClv VHoyNevXB2btjcbhIMYGvzdxziavSdasysZNnUNGdhRU8Q92eXH5GkBcvA2Fog4g4JGYI9FqVXOi fLIIhMche2lzJJz4cIacbhYHXqKbxMEIou92GyWH0kLu19F6C8iBjGWpFoHOYgxn/P2y6YQ13HsI F0V7qHw4rux3TC/JheOZ9De7zfXlgQtL+LRrrzBzQza/zi5z7Ua1qiqKC1cMA16igeX+Ly/AdgOs 9KKR+960GIetb31W6nj51I6ofmNYLPKsimSm5HVLMR/Ic7SIjGWf3VZ18Z4HnK6IqOpgyK80Fgcm nyl2RVQ2w+/RKHAzkipG1tKASxcDaI+YFnZYMuhL0TvZbIVB2jSENhHdBZ7ZE4bS0Zjy7x1VQLNr LMdH/o4vkmfG1Yqlrm6oEdVJ0HfBdKJ4KrZuDoPbzGIxnt2O6X+PJ5n8qiylR8XgEfifTHTn80cX B6AbV7LGuVqS5USTVTwqlQfC3tKQDGa5TKLKMVPJHFHI5rsIALcrz6lJBlEsb0IXVN9OuXKsJKSL PLA9IeBnOJvtnKX6+RzkcGzK43CGKd3+HYCTHyirAtzFzbZ9iMPBDLcbdTbcpkm7yCFr1+RcSw3k Sol8EU6bFw3TcDI1kNk5bjOiPdYNkxBS0pviArZA4TsBrvBcktxAygJ1hlrfgkFvHEKcrVBZswto qdWxTRSOuvNWG8I/5gvHRUONIdDVmVCyHYNRe7eLI52BWXIEt4pSa1KbKxq52fsaWpqj4CPocdxi aD1EWIsOCnr6D92Nia5+fTrEQLUUDVgXlICjXZ+o5gFtpO/3QQNjsB4w1JPhUGXaElDjTmRGj2s8 xSAQnVL41xP7SY3TTbUJzEntFUBJh6n2CzkuVFivvUcN2x2E99yOlutq/j1i73xK1KDuIFbYqozl /s7BrRY1OJdmF4OQOtMEe1ibC6gy7HUwwAHuRTfADlDMKmE1emK3V+Tg3eBP6+Lyqu2LFKDOlDSG tn+DKl3F6qRpCoSiior5Ncm8BN1fHxGkCf6VqrxVAX8L/OH85KenFzhWPII1zUdJhP9WoeAvBy71 PfXjXsiYL7+mQGwkluw/we0lAelYsH97EX1OExn1TNsAt3z4oI9zQGGWyD3Unxw81N6lP7k4IrS7 aSxc13k0BMoBHX9At+DAdBOXOLwZtugzbNFUQrnS5BokapHiUzkIo/getfLeDGaH7t3B+Ea6HVcZ 5aiYgyBUrSM980WFjHmTbxfVCVOBnth2cU3AYPEm/Ybmg3JWmGJIN32XhGsMO/uEFsiIc3wqNssm l9/mc/aGdYQmmMuimLd+HI3ZwB6bX746fAJhBXQAA4x6d9fgPC1zzSc012zQHjCtNm3TpzJYVNuW DfUUtoJAtpSFE5N2Yg5A8VcUE1XiBevnZPfJJZWMxJxjIk/SBDA0FFBcwR2ZRWXIhfdcy/5F+YnY RRWO2l7V1fbyysylucpXqzAbw7nMtzMNl3M6vGY39tfPX5/ZIZWfOAG48aVta4r7+GTJ0Hrvzke8 TxxQ634NlIK+dgbAOeB3ZI0513hzwQEV/slYITk4CkrnCBbHAjiUdXRbIleXu2mTVYObrGg9a2vA hM3AO7nt6PyDNmg9m4NWaNJytEjJH3VF5PBUYH2Bx8EsPDgd+O2Y6Tg8qzKtztcLxMaUCW2NHmH0 H3Opj8sUEDqppOsbT78715MiQ+erhv20E2Yb8lrEP4r62RfM4uStW4Igs7DVLWIj4VvimlYt59zX T9/9xg1yJOUcSYI8G5u7dk+y1VKMuqRwv8Wvnl4wFiJhFSkJRpn4SLm+qFkpehpaQSK6nEZWmbsE Gu0/p0ArCiIScJCzDN3yEYJKP4gaKLKOc8bU0Ppn25bycmMXbD/fXULjXlGIY9ECOpQNo6UpDhH2 2D5oo9U22L2eKxwFFhSZDsWUqRjMxjyywKLl5aeirsrzESqCRxcqevzv+iOVRyOlU2FoSJQx6YD9 5Z6YY0IFUbP0BkT3vr/yjsNpikxjL+HtP7x9d/bNm1ev3o0uejIkHOBgejM1HBlQLdt7XucpPDnx 6P5bmusbmOv9UWLNXHRhh2kLayApLSGDv7iDI9G+44Y7b477dNTJfZEtFt0Qzn34JX0+d88Exzl7 /04PJVJBN7809VaIMRyOB2HleA96UTTmYoH8CjRiYD170rmvt2MjUVPSclaz4aNMEO+Oocfcd6+9 ENrTgxghkoS0D7rT38lrfC8N2isFPX327OztkXfIdoOQO4wPHwbhoPi5ztsrtCvxt2M36cZVtUbn F3wkrcV2DuDWowa/efXNmUUH9t794Gl6AIcI8Ks3z//+bHjBIWrOUHyh7iYw+btihy2umlic8q09 8PbL+kX27J56tu7Re56tJPW1Vtlikj+8LH5Kb75YLgzJfz6FnzdItLwT8Cw/DGcEDH6OLDb5QSvD jrPyWMQDaMZq2Aw+bZstWo61M5zthB4uo2DdYCUzCkTkA/Fvsr4wGHsZ3ibaP7ke7fgts2b4G/qX 7WPEXluMmFOzAESQvLkiY/YRW4OGr5tc70O1rTl+MsyYsDCjFu5w3jzlHqcW+RF3gthmc8bjECaG 7YZ6v2WvKIXPBDlngT+W3ZffvY2Xb+09z67zKZdFgTHkzieoiF8WtxOQJcmYfDJyDySJrvN8M/li H6cOeHI9Rds7izWP//rJ3zx6ND4lpUV7U0WLbNeEjhUErI9b25mFYxRU7ZZLOiU0mmSlnQfbVftl t8V6uwYmE2u6oIwrvdHw3TTbtVgYKEmElnmzJQLmpXfM27hg7N7W1uQ4Sac9vRX5KODcYpgEfHmC Hd2HV7HvnKqxP6z1++OTk019kwE+4xnHgZhOioTBBrSXqj7OtuXiKsQGxWwbIdFCvAF4j8bOhInD L1W6kWDSNwA0K+3MWgLnDon5Vdh42caz8hzDuBWMi96U/MZ7vY9naxqzZfd0MkVcqcIk2RlBNlKQ YKoRncvA6s4T0l+g3R2g+OYYzq7Y9cxkrIkwM9GgjyuVs1fhsCGbNcPwjj5oMIGGew05zqTgD8Hr BHt6LOM9IieMSUB6wwQ3eLRbRmW1MHb75o3EfAOYUJNG/fzx+IdyBg87futXQMKlAoAKpjvrPCvJ TRIIDMW6b/n9yS5BCg7ttEaEiezn6R00jQaLuO/gKG6TvQxs3Nyixzq+4ddsqZXFOMfFnp4elYqy 1sFx3i2shOjkVbCIvrs8/EXsBnjY4oJBM/EkofVuQ5WxONE+loHpiPZXWUMhZgpoEo2siM6QZUW1 dCI/Ca9wtKMynWkQEj3U0xlJLuD4lPdtqnqFLuk9NmzB1b6Ox1FTtFtSBSUcX6OcdvRmN1fVdrUI oTYnbMYOtKGS/vqmELLOiC5ggITX29KhWRakorkmc3Wei98j3EuHhYL/b1BkzGpA/K8pH/9N2Czh z0rhmnj30BrjIoULdJPLqxwApL2OSfldU7qIsgDmbpbDvuUWxHEaunUWFqFalE5s39Ny/FOk8UFy ix9REubAG+TEYVCVUYB9iaFSdRxAqbFzs+FQtaOpYk4GHgNz+i/xpLANAb77+UQxRdEJTadHkMbU 81bSsiCROEop0GIhhdVSufVL2oHe1lhFQR/qcX1ENeDwuqgXmTVx++SkfTyOfr6HJvbRcDrQ5rrY OIwm++YhtHxxnLrgsMaNRuK7xzcNGT142Bp973TC/tFqObr7EYgDMF0Qzvl+QE24Lwrk8DNp2fyI dsDUybuAnIucfUmi33FCL/qErgT71SoDj8mhcoNWp84uYDUVce6wFRffvj17M7qwSRxA2t4mERav Wf0JupM94718inoZHCuUvv+gzsSCPBIGeGT2o6nnkRiBt6QVMQ8h12uq5+en8B+VkfNkRNY3+Bf+ q0DvCUJo0m1JyRkQXif64NXbwKQdYhqCKCxADNNKoiDcWAAnkZ+oPVCAdhwY3pfpt4qZ7Ejcvozu /y4l+Uz6Dz1pHtath2CaoTmtnksFSWpvQdJ5SDxgOp07zIrz/wPCX2UYSwKE4RJ5A7IcUuMlnj2d sJ9Q3tn0pWACVTw8JoPCoczzhE1/YvL5sAMuTVUYvCNSzXMNRyu8r9OM5qojeDkdmuUsbFm3VOZV fC3p+/NHFynwWqvNVQa8i2Qygi8pN+vUZnLlcnLeW0kvOJwOMUftOFSWh2svS2VSHAKf8/Hg4795 /+8/++yz6QYPuE2vquoaVZof/8v3/8vnVHo9wq9csyWrNrlHtFltL4sSa42LYZI8AdYgD6EDKC5M TMmqpaRRlZrtMu4Uf7zcKU3bb2Qa32T1NZaIVNOCBbs/xUMGgIaMe9HJD/U/gKVLv7E7J80gQn0c LhGWj57pO1nTDzr04JdqtTE8ZcgHzNlSMmAvZlzuNFssqFXME5C4JlN6UiaaqfOJmKesraBC1JlS 9kuAhXw/ioO8yk9Fhq5FmIm1rZjc2KOk0GGq5tjE7EozrWqOAVJ6xDEFCx23Gu3lF5sVCOqikw8S IGxy8qXofTmqeJ0t8uhyVc1Io519yooV3q9IJHESEhhHNXxSDAJ/QDhd6PMMbxNDKZSbNS3nmNUw qKni4oHg8jdJ1DkmFXxlX6Xosmoj05mjho7GioqCY2Pi2Gt7NxkeOsDQbyec7pSbs3UZRCz5FnjS ZXHJlYEb8WhPQWTLanRWt+tZ0G5iHj/CKxWWU5i3kqXdU0CJ0w+yvp/zv1W9yOsvPzgu7+ZIqnKe K7+KGUy+JDd5UlDSXoHkY7vaqwFZgFUnTCTmwwdcDlGZze7DB+WT3kQPHsBJV+XlavfggRUk08yr bU3RfrN8nqG+LwwBzSmr7A/FCv1AsgX7TVkRg5xEmrLWYpTWA3i1QGwuZcsfqFJQHDUr3hROvh4N 68MHeO5xeBgbvTEsQit7cIqpZvnMT6N3FV5pSruHewpMjz7nhLZXAz7d7E7x8OBoqG9qEAjYXJBj FHlmhEhfe62+/GBFIPCoiESk8mHkYSoSGgca0iAaQP9g0BRHopavBGEx6GhFRgH07KcwQVLgscea UnTgwESVTj8ITvujPKN/vvwgJiV0S8JL1lL8miD6ibUA6XaZt7JR9Jr3gDXNYAAhpfQog2wnWhKr qnngwNJ9E8AdPDQ6bR3SSzXoQGV84IGRo+JrQqF0igCQNMxjv7vS9EClzWqI20WEr8kTCm8+Jk2n BJXAC0lDfkhwkR8+yMw+8HXPFHtNZZVVoVSe4AIdxLkTL0r1hEndtpjoAmVtOXCChqMArwvPDjrp Lca6px70jgScu2H6Df7LotfqwSCrUeiGsWPuLKc4/VpNEVvhRRAWSJHblizHQluErFBXJijpQJNY 78HyGRBrgT8sF/SrqmqRgm02SKE6TJBaj3muojyrKYwU7+Hp4J5BClzzFzXn+t+ZncBoANiZzPih QieiwrA+es8t4quKyAon+WPxXcuihkXnzXbVBrBjjXkD8ykdr8t/kQ9r0+FhCl1FeOFepYRwpJuR yyRnCw4M7D6NzbD8QZ2rIEWpHEw1JatEncqoq+aS+hflqN1Ahr/3uhCqcHiwWiy296Y1Z5fIdyZ3 haoBz287865kouAnUAXR8WUV7KT0B9uSJoeDrKpq091LvGBTOZepQjBKgg9vJKHwVO2uz0qZCTGd QlDCm/Rc6ewKqCx1r5YhouHt/A98hecVnMHcCDH/MpdGTyIW9wJrQ1XkOB+nnu2mrtoKPnvpT6R/ 4H7orlNG+wK9UdV4SaQOlL7up+lmtzKhxrpQdkJsnbjdwqTq/IS4WC1vEGhAgxOSx9M9M2SDRmAz jp8NoboqYHe3WyuFMAW8rl3t3V67pi1mvsNo7LIlJ6cCVq15bbIn4CGZ6YaeLuiGLuNMDvA1lNtR OuYLGKbA865oJ1Sk6RrplE5GQIsMPurHIOFUc9iquDabkjpnoKxNdUbVASkqwxhM3QXzYnqRkgJn +obTSUo0sJcYdA3wyZQSyv7zFNgtlBxLaEhwsCICBX0Q/+E+Jx8+8JDAQ2HosgqIF3ZhVV1emsfd XVVgJeTJEcuHyqaL+jv2sWk0HE3ZbAyEmyK/g4CMnyxIN3n0exQldQMl9WG73j2GZxHDu/mf4Lz4 0tEr3D+zRd7k1rSa8HOmp4MSnOqAMQGSMe1u95H0vwpVZB2hLVaUEiVS+TVVl3iMx2ty/2TRM/7h DYFLfwzuULJQ8FOnlAB1viJnin+5x2azU1uJ+8r6qQN3L4s4Bs5Clj3XzyNuymvCZs6z+ZUJzKAN kvB8G0AeohIMU9/nWc7ljSQ1302GmbpYlJSkrBZ0vr9MV8mYt6hI+Usz4ctvtb47BXV3FtHfoKmK rAHWNkDbOE4Rezy07iPV05b8CTopM5dl3aKHh5xBetdZIjKqFMz4t0dfSClhReY4CNylCJd5CaII ZeNFJnGdtxk2tgCqFlG8hhkVwB+OEdVgP0CoJbYfRmzYTdUd7Ee4lTQZeCWFC/5XcCFlJsiK93M8 fUKCWgb2pj5xhzdSdH0cfmf4ycK/EnowrbEtYSkh3z53xiAnXFLv8d3ouequWFg1eH7beqjoCROq YwPXZvMQd+ZhC+LIAhWHNj+sOU6mSvo1QjPMfLUlgWSebVpOZZarpInMbdmMFT82+v239YkI79SA lmqb6DhtzdTMChlBxZraYNSiT5krmcM5wd1enLTVySw/wV+tMWJFdQuuwxwy4xW8VVhocw1sGDCN JZ48E2SdqNRoqfCFqkKALLWke2xqy5XS8VSo2KyqVnlWnjJLTNZGuMk1eVoxm+vIqsp7ywrbs0hu AF0UtsWIpcUi0XnpLYRpgHcHEZP2klyZQaaE/qUEDcM/q3wfs+RgWBwgjIbx/eDvC1e7wi4fPvRD Nq06gHVQMrOoNM0PH7DtPoDqOPpvkSM0Baf94cP3x0mFkOa0Q9hkOmBqTQWyi5ii76RHPYyXisvL bzM0dsnq0cSKjnNye5lDZj0bm6DhoamDF6apmBlQq2Y3PM1h0GtI6HCinqXvIVwZnct1LhwsHxeC DzFclm5eqa8Rj/M6fQd/M9eq1PID5bpmSJ7VXXo/RzTSRph+8M9gQs/LZfXh4GXskyiUc6Y85iFi zX347eUIFU2yjYUh2oBUT9p/O/Cf5vpjsOsyWXp/f0yuwNpMGY2pWvfpF0KjVDqkRBwbPXeXJEhL V3uSkEsy+u5tbWnt5qpSpBCdX4VJCMjogPQHNf5KF5BbvrkF+0LjPH8UzZ0lkRP7XGhVsVQdYu+h H+/0eBjKnYnxEVltdM7VBl6nfIkGM/S16+i889vNKisznTCY+xcNvorA1C2zYsXJgGgh0LoWTBEy bWcbpIpelZIhLMi2z7OmK+jNqpStnJOzkXgg+aTlNUmSPiNVCupjGwpXz0rzBQF6UJQP8G3lBJ+q d94Ag0VnbzIlIyVFEJwUrUauFdW8OuUZMQILNow3q+KyvVrtEtYcUtU83C1Onu6DUInUm+16ndW7 H83gY3CuKJerbQ6yEyc1FS4xdtx8hLJOOetjthr/aKjIM5iiJj2vNRYSXUF3ucD7IsfFG7coGsCa HVsXGQgusBJdDs/eLDO908vHUyPhkGhQ98EwFd4AwgmKG5dVDScP/GHdrjCMsibO/FNezyqMMMKc +0vSMDszskZVk54KRsTqC+7iepksFuTlg/iV4VvPYhP65qulCxRrwOgOjifwVopzCEjHTZNdYoYN ykWpONllE+BlzTsqvS2lJZZpiDSwjMDJmXIEYiawaeMM+CieVRghuhRZBTX2gAA6DqvgjBtqQPFZ bwvmTkk52harrCboD/WkfwxBfVHN6T35lxPMZQZiUkQVJJGhWP7tYrCKJ1moOp+iw2GeTMD9CFtF zjLRFRw1PxtkPxfD8iKfbS0V9o9GgtSANJcYZGp8GJH3mCMlCSs09CTZ26fLe1yL9ztDR/f3eC9A 1T7S7bswtbjPQEGIIIGSWfEk6lAnGBFEjoLk1hUVh0PS8CT96ViNfHOVl+LIYJQJcIcadslfqMzh 8POmooeMfPJmcuVkFuRTw4eoVQSOiYjkEhmSircHBxNGOjPlWEprn3WHVXGdR0OMqEh10YhhmOXn DO6bxSzubvp2g6bIxSxtMNy2JidF7P/xv3o/+Oyzzza7dHq7Xl3m5cf/+v3//b+Sy+xAVL14XqIZ VEgL3A55AuBn6EbfXbXwB6cNwNyOA6B8XKarIXWCqx9F/iiej2HLVpi6+7rOr3M4M/mYIU9YU3BB lG/T6MmjR387wBmJX22zwyj7fDAoKClSSnYtwhN4Cr+cRPEXiUoyjtuzjZtutvTG/FwWcykoyOjt B+5bUXvQZjSdSo/pdBSu3HKbWm3iQF4nzLY9MKF6vZNUU5P0XvIR4xD5L3jXOGPDS+Ua+k3eZvRV jDnxrE2YTqW4nWR/79TZFifu89PHyk07lMDVDSnwshdJWkbsricUAmLX5NINJfcE6hhm6Kszb63C XG12KY7TkqhfvrASYlJpVG7VieBCp3HJOCRt7rw2mh3uH8zhn/7YqRCFifUxlyd2mk69Wr2q6/kI Lgu2oGRvTvDIfIWpd/DMJLNMbBYqRQmScWJA2YV5uWahOVRs1oQyMyhseZddxihfqMAJ+hJXH/Pt tLCCUYcTa1rVzL36TSbPq6QzTLebBaaak5Z2AQIXVm9JKC4MDjNVJcF1T7eikhQeoXOhv2kdGqA9 srmS4QIK1F1dORZwVGFZqZsAY1hgBh0SwouSrk+sEVZudqS3RBK/5V5/j8n7Ad9Wks9IARhLWn83 P6WiDJj1iIMMV+PDJSLsVL26ygX8xejqAx/+/H6NF0UZs+4vvqTCBIxchZQogWHN5Z2ESNBIfzcC hFbOYoDG/0QjjqxrPDrl1OLWDzJL+AWxQP1gXzP4iZKnJoM/jhVu/waeIcRv+H/7CbjjASGUvnMR eSdfb9qd1Fq8w0ndQ8lfMq5T0jl6N7Vrv6wCv4z17sk87V3BEBJeqcZPsy8R180ynXiPMY4Jbmd8 Ds/Y47HJkhXrKY+yJJvN6iSb11W5WycgbaFCI4ENAPEuAd46S2bJbFElM5BbZxiIlpjIytEMIzw/ boF1SmbVYpcAJCCnbVUmaMRBTceceJQELZkJSVbzamVDgI+XdbXdJOhfhnu9WCQL4AwWyzLBEjuL 4lOygI9tkq/h/2b5wu69xBIzQA+TJXD1CSqfkyVaL/Grq8fJ1ZPk6ovk6qfJ1c+Sq79KUH5OcKNt EEVSUJekWF8mRbnZtgmGBV3PFskqm8FMVvkl4sKqSGj1SEZRlrNArLNNAkLox22eJ7CGbYKW1oQs qrjasoJtKSuefFnxBO3+ZdXM62LTJnJhoE+1aXlb2NMu2SQg6iQfkyaRplZ39uJImjVyyYA+ZYLi 5nWecJhAQq7RSbOdwf9vEorlsru3dHLtIsF8mXTg7RJT0LVX8H+4Y20Bon7S1knbJttku0pu1xsH CTK4kPgfPgTazKs6Qa3fIr9NyJ6cNBl0+pTV3E+lRx8lozEVw74QksaX4S3O+OinaRwolJJElPXk +iZlZ7pxOH/XrQ5BA+4nwTjPQF5g57lFyGPNhdXZjTtN4FnJvpFFs+qWmX0ULiQ7P3ytODql5bGy V4jMgWbQfGFnt+W8CNsWcNPOveVtBUA2Lgz6oeRvmYGEP9TEg++RvxJTEif6xE1Q1cCFZWUdpjZQ YEbUUhPfRwlmpDEfLJrq1a2gifMwEwbi/jTP5le5y5WZojj5gn6J7hEiYGGXuaprIMupSrcbTwl6 8R/eWGrKGPmq/nabsG9O474nnDdcLxGfYvMBI+bxU8QfkV5TiGNl5X41D4xj/FdHg4pBSnJUo50Y G4wavj0P8So2HC/pJD1ijhObGo6gP66VxmdFva74hft+DmCOTJuHBwBkR9h8Ykhh5HVd+fxyd7xL 59IpIJp/4RSwwUBaG87BXEHdwNpwOpXAZkynlomvi560TdDW6jkIQCMFh0rOF1nlD6MlUPNZNr8W vQNl1lpj7Cgm1S4+qYrN90j796kqFnT6VyrJF5mpgaHj8FkzU76m/IWpOm8h1z1z+5AgjAO3MmYT Qqx4LGxml0hDqhgC7UIW0mT145TagY5ibQE+FL/XNXusOx8kBOfSAc/hsVO0CV7MNYKAXwMyDV89 bGNNDllMnlurGU13bvj93rl17hj0SN0qyEJLzu0CDXLHnuNrGkqwYANx0nb5e4ETdPcCvhFBQV24 FuUvLbXSYgPyQ6BgsqaTKgs73xLkAtAQFMtQIRmSUWL4XTnELAvxKAKm4IEHduyJ/QEwZgqfT2zK 3jcgjPTz+8395ksY7n6kJpgYAZNUAw1tm5c3yT4rlZQWm4WT0nam62Ha7R7g3YIv3goeqgWoDd63 MSfhjekSPYQkMrbA/Ty0LcHCK1MuIA/yQ1X2HHvwJB7KQaixk6MyXXXAfGm2xIDSu+NUctRrCV3s e1rpmVtNzb2Hr5BgkYxF9yZ11TSqQdqgL8a4T/BcSm4DciCVLr6OUdcbIllfT0YPKqq9bpXDZv8T qATduLZrBa1SEASozBkOCYSBBAi+BkdqJbx58vbi56ZfC/nkAnNejaa+GpIDPg2FssF0iqgg02Pq 10xD2dWsBBTdQjiUwVrXd6ShscT1TagkDVVrwyceW8lrdkxdONXPe0UJzDhYtWUU3W8mw/vNcGQp ZQiMtef6oELIbFuYdRAroW+zLUgkZG4NAOjggt5ni4ahBAdEHVL6rDWB/rvlKlmD6nPrOnT3jKDL TTu//Xx0GmEynp3IeSQf6Qkpae8iOAo+LdSU9xIpBHz1d/DcMAbrkaC/YZZsaqa31kNiylxRRjG+ fSjNjdF0i4GgdbEASktzFB42b3qrqWoBwRld3s8fa2guRmTp0pQ0GBIRxxJZLu6alnopsvRLHZSP R7Oa9CukXmCFAGpGrmpWlZBihdQI4axdI9bLkGphZOsOJI8qb9EdppNFqPWKROsVzSKlvohmiyqa FZcgGUSos2Lz/WJZRuRIDA0CMxwVESwuoklG17NFRIqj6GPURKj2iFhBE5GCJkIFTcQKmiAsVtrg maFGPFJKmahto22EChS1fEDb8cWfRHPJ6sOs3Z9Ac7ltb80JL1OhQnhS9lvoppT+3iqcge92J1Xu cWFxFVPOHe9yw3oAcS+tCpoyOT8NK0N8KYgbo6bCzcMWj5AuneIff4l61b8bjRP88HP97Up/96X+ 7pK+8yH9pf4dkFA6DUdD/eWmajrdPI3K/Apwbzmtc1SW1TkWFdpgQCAA+mf17lvrSa/zHVBfm8ma ioJNifIU0dNjiWEg59QkJfVn/MghxeQRbRRerEPzXjkQXU5kd43Trat1O/C8CVxjdI3VSP7TJsTx qxz/G3jeeiGBiLVtlyd/M9IW6JHsUzcJlncQVDmE+Wy1tWYrBgONWIKPmCrrv3n/51aqLHRW/fjf vv+/lpwma47uoV6sOhb/zknNrRxnTilGPIm056od3cL7KaZ6stLzn5ud+QsbJ8rvTn1dNQmb9uHz QJ8DeeiZKBldk+sbrgn2jSR1yJpI/vymuAUqr8RkamwdBoH7Fpilr5BjEVj4N3XrgHHze7Hrteql gsiA0E0pgnVAjhWopplvJcO5W3pA5wmTCnRjq8AmWYaKluuWm9q6Jsx+cPb++bvpq98C1Ef897uz t+/efv30+Yuzr0iOpy+fv3x39ubNt6/f0ZdPrC9fPn0Bv7x6A19/wV9/+/bpr8/Udz/l716+IrDP Xr14cfaMgfxsMCBBv87dez/8x/Ps5A9PT/7z9OK7mwf/aTgeHJHGyc2dM8QIbtTDYlmKZphEQxOa DBuD7jCN0WmxL6GobYeGVqHdfDJEg+8wUSqzyfkofYBa/Gd//xb/mS6yet7gX/8Ef1z9Ef96kOaX lyNhG7yJ4RqozIU9KYzsxuz7OYLQEbQNeRZRYAXFLKKm2eqAKZaY8Ijy3j7V9OAyZHr3vPkx5tAG CYh7RPT0rrETIkUGAm1vCuTqlSNgoy41z9gGwJPAqSHva09k+ODBQzrZB2l729p9NMU1LTY73Df4 /GAqWU+GzIbfkxobSNBVUt4a5Uom8UN2NVphbx0QRC5HKkxOUtQMLTiphWyjk1uy3ZzgbSK3QfjI WTkmQ/T8zKdYCMFamNiQPU4FEyROhhrIsNPgKl9tuEHEIiKaZyiMD92d2dUPo0OzgmKGcBOG8r4G Jn2yzm6xKUwWmWBg7SbDcrvuDussBVZB51WgWZpnLHCs9T3aN3UONuI5Y3pj7Iv+Wzh18fbr3+kT fGjmfRscHhWDGCRTXMGs75wieUGIFW9WzBABVyQ/NP7wZD60dgsxWe0HVWLk/YDLgr8gAeubEuY+ 0RlYxNmfcq5hxw90uphgqqLs6OKNTTcpxzId9P0Vv5oFSAk+JMqooEpU9aK9PCaI9uaxc1bubLyK Pi5XO8Z2+eJEvtl7HrxqdlPkbkzGEil1bAW3rT2cdSax2SGtOm60tqY6x+ThuKlzDjIwOXzg3RUH QamQ7B27feonnPdjaMaVgukWMiDl7syB+3GijwXHlFrhtxz0fELZJDHiTca/x8QdWK7yUucKgZXg lpfLE9ioE/RMkFPH7E7PVKanhjKXoRepQOJgte3msuZkO5I2qv+QyyVzEiOFzeYr64IbzxlKMqL2 gBqFDl3ju1DmUSMRXp8oQsN4r2Na9X4cLCsF4xAK8NxN+37iy7P8itCQpolhLHbqrCOvE3lT85FY 8xg6sWPG45rCie1b279oVA2gWkafiPrCP4++c3AWip1DdZ6EAURMU2kiccl7s42qqyx6D4wjnDyn 2MVnKlXB5JlJc/A11pr7mipQvOUNmci/44ElbxAsAT2Rf8eDI/LMOcnr0FzOf3CNGtjkGabT3alg Brk9ki9Qv7pGgHIbyCNHXC/N5abONiqsTsfVLKrC8l94e52TisDNXQUSDdzGtRIBFW5M1KaoRdm/ piZQDxoKWy6qJ/4hJya9I092hEtZ1XRRWdvo6VQskI9DndHtPN0TqDhp7GMNgX3iGYkCi8StNPFK AhB5hEeDTg5/OvdvMeIlpON1kt8flzxfQglYnCI/E+0KjxGw3oYFtqU/PGGiwhQOb4EvXXmL+AGm XFYtMOwm8EFNMnGx/05zVUKfr6cT0FhXwDJxcAXSs9uiDZnodk3KtYqVjVZlpjuN5tkWaxW83cCz WsEUDKCffFcqat1JMW52iXy1gTic3TIThWEX6I0BZGiZ1zmm0Z3v5nYJcLVuFTyXzq+o+odTh1cj +ZeA5adH3h4Jyw3YFp37lASKpqgjmHRPZeyTsmleNnDdnbhdh/R2YQyOy1ko/YM0kZoLAbe7mltt HL6U84lPME0+u8JJL24UQjwNEd9YROakTjosTxHcwDF0s+y5JCzQJZCaxfQZaHM07yfNh8WyjubR 16sM2Arl9zYpvSZOvXIbiq9IGRyVSdA7e0mioHPcjQfHZaSxJuy+nJbg0Jk2OQ3bFkSVaiEuHEt4 K9W0M5MuS6tomIt/YrXGcjkUBwTkAy48R+kAzyR8teSBAMqs0grZpYEYGsFoXAhUUobCi2vSwzcU yN3/1HobS6bB8+Lz4z1r7PqrOpNDkUiyjDLKQXym9EmxM4btha8yV0y8zTU0C5Od9OO3m4ln4iYS meiMIq47jpBJyuEC3PkmFPqiWukHGOtrdHo61ImR5U7ZGDeqOJLRetIsuaOqP63II2yRYvzpN/IH U8LxVMuA+NNkE4TkfITDEsMynDM61cKFMKOZTNgiJYoEwC+lNLdMZhZk5R9x7heKNi4/BsSFs4eq hJUNTlmQvn6LNSJe19Xt7rTPpXbZSD64dSI1yzBnaOObl7gZlR/BPzx/VSqNtXa/tICRyld/Ghwf UHarvdjWaKXAwENEabLa5LX4LQhoSYU88Qf3/A2VU8E5dkbftVufhN2qOjEoY8BtAfrZ7uxaJfjr Embu2+HuRSaHVnRiJdFKnTgtGUZZQpUlw7JImhBjHhsH09EpmBHzt5xasYltQ8O494w9b1/ah5Kj AHXaTM9PTPn18idvC8lrtMZj/SdqhFPnVFB/9A4XaYmeBrDQ++pp29YpNcQ59DnSN1g5i8n8+83H ndJZ9sCSEVRyV8r41pqa7poSNlj7G+wsQTn12KAWwBP0b083zHGeleh4tUARNMfWFI8gEyUhe+hG yWEob8BYnJd0q9rYmWbXAdNsZNjfCyGpIL3Q3nXsjjihGHs501zlZW84HVa4lVsrq7EtwWQb7umo HH+PCGzTEWv2zZJUK3BH7jccuaZvTRKZcI2X4q3sRjmQSoYbIBitMSEGFvUpJueXpTxs61xkE9PB ONpwOltVBjIhMGwX0pkrcHINp2foIwREMPmcRMXEj5d8UHyvF71875TjTLAyNXksoDOcGKKAj91o /bWgTJeoWC5yAxus1ckkwySa0kOUhB51YOxkN62c8p7jgadEouqPhK/8RQekUuMQp0qYQIn0KM+c F5ShFT7qLwNcvnGgk/6RhFt+vaU8vR4HA/yNdEBmhFhypblBCu7LrB8UGjmJRvzLSIU22FNQd/Sh IuXeeORXhCfbuINpcjNx3yHrqimEsSsqUV6vts4MuQJOHd9HvB4qOaznz4Ltp9J+qspvM+FySn9S +jh2NaxIH49pS5bFHNPPS6EMuAl8E1k5aiUkNeWNDN1GJH2yafLtojL9OTjIi2mgOeIFUzP6pXqy 9QUskF/xKQ7SCDm2BiT4grTmlPphg7yayojH+egEtSmjR6+jn/DZlxgCUl0TlNjCDhUPgjMyk7Zm dU+mNeRjcmVyMfC9lDtgFXFIrYJDEpZAkGa7qEHrmyFfkpsDf5T8whOfwxryD8I1PyPy2W1E30ub 56JzCjRTP0nLr5WQ2W2pflIti+Dc8Gs1KotfnRHha+cBRuGDEnVxJHOQweUIqstO/L3zGmOjn0zC DKNXe3EHkgPIPdmmQENoPHySPkJz4JZz6xFhvU9yt53tddjhkYZWAthApmMqiYT4yWmXJR1ZAIz1 utHjhA+puzw7s8DRDzUs4X6Nr3LcE42e7Cs06+72SMJSiEZax0f7x004f5NkYPKusc53bDI36Wgp dtggNzEqUMAAtF3GldgdDzIVAmS0qjyHxg4HsDI9+Sg0VL8M/bg2QCerX5BJ3geXyUkHatfH2gEy vN+c3qfDN1+je/7AC5u01RUmkVZKPnoq5Zbkg5iQUcnTxi7yiXNWE5U1y41EoWRZE83PuUm5JlZ+ Lh1GJ+kF6eiozgWVCUSM7iH7DDdE97Po9PSkwSRTJCaKP98iR8U96rCsagHCE0YSQn/AydARn3j8 uzjO2/1QKtZRiXTr/Sr0RlTWl1ba7cmLISyRjPF5NDw9xfgszSDaFOAqa656KQD+GFvnZ11bTubr dTMlaak8vUqiu7fVdJ2vK3zjKImv8X1mFlopLce2IUL9jBg/zW+nuDj1nbm17BzTuVqme+jKSqde WQwIvxQXRSdOkh1j6XT+6CJRAM4fW38/uRiH8hO5Sw1nJ3KnrtvuQ05859SuxeOuxc/MH1jj/Paw xc+jN3pbbQ1vJ9Ctb8el+3jPqE1wzVQmr/OcYfIqJwh1fpUVZYgcWPIq1b5Dhs+Th9Dbgz0GYWAv kCXjXJTEs2MRe66r5IqUbsg2TsSNFxN1MoIfuDWIVQ7nMM4RKBXv5SqNLbD0uHlaJO6JRXTqJu8m t6Kfrai6xUKUFNrjGz/44euYuKSYcwVUzPIozSJTKRXfZJYtrYKS3OrDB5WNWqfL1IV9U2ySPojU W5za45p7bTv5Yg/tZAx/oz830PuqHoTDwngSiXMNKOje90fngpq0rokLWWDYb7IUgQ6M4/QcH8qv pZLL9e4MVyAejsOy4jmPmiqF61pKGVtGIvd8u/FI2KZzorTjRmo2+fINGZIDjxZV3qA7EOlQNBxh 1LI2kNrgU7ZSL6BaB0pXcQ+Bxua9F2Uvajwn43wYSYLxg0kUO60TDWY87guWwfm5BInkvGtHfHd3 /I3OHptryuTJ8BK3wjUdy12kIoztfXTEeCO/76M9ZBMTgxgdgCGgY99DwgaudJFEcYLqgw6lcQG4 O0TOUT0MyPkta7S0dcaf54VDvnRSemVzKcrOM6CqEjv2UFNKhwydjipKAV2kXhFiySqB9Ixc9fYB 4VyU5jjkwOHBoYUknNvgNqP0i+LvKBoH5LPGYVro6CS4vgK5UKTOXiyLUmK0HFrAWKREr1UToAR0 r7E0gaVvxHzMqt5HhcEAdh4tTsqJ6y01GVc6S5HSSK1gP5Tb2kqj4D2M6keVmcAW1Pgnf+ouSPnL fxd1iaDaKDmJF93U2zLXkSGaf7GzowY4WJKihbMB8uN2SyRw1VP1LtV1NOcnSjCp7Dk46AC0XKdf c5cXIM9tN/SKhPlIBYADntFLIaMk6xaFaGdSZdBKSOakiXBcE5bb1Yr2KRDxi07a5eVwX2AwCTze Zge9u6xZkfcpORo4/SLMP50tdvT2AD3r2KqovPAERIVs21bDgKsUN4i8Wd+L3r9/r8qpqP2DS4Hb hoEtmC8baTWQwozws62UgSAem4T97S8GnckEtQHhfW5nZv4UZbxvAdzgmMwL7pIHPdgiq42RUpIu ABFjr8qHgF9VN2RWFxOxuyDz62FAhEycA00jwkT9oU245u5h7Jx3F5X9SFt64pduOSZjAlL3qtHq NrEB6RrfxrHHriDfXm0bMrllkm4YOUuqH6jtTFol60yGuT7ta+jrL0qJS+l4vycqKRl69YhOUBQw lvaXTes84V55qJHqBSTOqOVyEUJxtFayUTdBCr1vnuIx/Ewxp/uyai0dtrC8Vv5YNxxajrCXBPMa sIYDvQ9ObS7u6vKZvVSUcNQ+kQ7vg6lsHQIaVAe1lKA7xXty/ugiHAvaeSm8N0Ju8NjTjuw5Rp2F Gn3UgUwKT0I2jTlXftmuWgohU95bGovdDXK9AmydzGiqjVajJFpl69kiOzWWX1MO0okePvIp7ShE lDXNOwZD781h6O9ctaPdVP+dzrfs5zRxzDV+FhKrr9U5kIrEHqR0RxEPIhrMizIdhxyP0x5YTOfi sfEyMlTsmVeqc5/D0V2t0NrQ6TpJyZbBw3h7e8scrwqqnDKaoUlks/uFn8mWO6YoZzsaOtjvQ64P db4yAOBDW4nVte8AoU1v3hj4bdCTTkYnk6wa4Mc2STR8aEvZlPLA2v5OnmPb3m/KPnec+YMeXoc1 uyvpYHWXzbAfWFRLOSgG28HLQaMWLKiztQJW/tq/B1rhtuJJC0piaLG1Mf2+Gab+rfgYs/mbbPTy anFjNO/5j3SG0Iq5FDwrP2mzChl0TDEcrgwhKU6UfKeqYAF/sMbCQSinqZqZQYhWKTLPE9T4k/5w Ph+MXBz88ydglaoJ06jQe1I9Oro9t4XK9HmFTi7kXeWW4DDBPvhliH/3RlQayjgA0n3dya98We0z YSjixVuneJqu/UeZkHxY+602qtdd7DaWmU0l9FLrcKnQPUAwrH/C14tcrz9uMSFNg44aDlZqgVXS otrXWadnB7FenPvj4dQCTZ2GSfRPf/REJn/pDk3nFJfaOPjo4sJ/kvo9/xxAjuyqSLyZXWwN0c32 2Z1F1+PV2/RYoYTuhTYWZLv0F08uQsn+phaQzsHbrmzqN+1y9g1qszoMOnGeXIME7oeuuCxegxJr nJkfSL/lkjjLc7sTTtUpvNnoaiPcxYQZahI1nXL9D8obPhLNdjOSTLqb3Rc6ebBEmHRJtjUngGF9 6qV3jrs4eXQYoGmwrXqiXCq5XwwUEuoRv4mrduJzXjZPtFNOIMewFUqiI/7cH61IEf9341ivNBFe /zoT9xhaKH2k5ZIyuxsmbluCJamGTgZhO7oH8m54AFRMVYdfG4f88lL23hYdU6rUodYTBkII77Er huwzOhvyzKp3PAWMsI+BFFFoqJSBUtDcuBoVAOlAVtqQQ6EQ0MSNg3D6jL/XvLrlOHl3nCpGmt+k UveCVkpNqSQa/hVkmpus4YwRoSSqNmJ+7geOmuhZ+xQBM0gSjXUKiQ4nrDpKQg53mC8n6veetJwO vmOguGTuIQe1+wudeoI8doM32B9zbEUaq6OXkqWT3p03GIgSe0FJXuQ0iP3voKKK0pB0puxBJ7Ea lu7bdd5TstLR/INNac6575HO8/ciePhA0IMDusnZTKayzGC0s9RmlWg8rycXSiRjGioeO5H23peu 38LawyCHDrgYt5sqKPyqNBR04gT5yA9xSApz41GwowkN4tCRdFEsJVI07o4WkOk0wC623uO0HnW0 xnQRChQ7bEtGZ/Sxy1rWVwV4DNoeeTOsQJ64L2DnCP3qPfYvwNXyTNj8Y9RmB6ZhHxSe+iDA1YRw EPcbP4cwl38wtM4LVhRvC9TyMs99mZckDPkp/sl9NjDF3pvD2kTl5eSPy0WF1GDu5oYDTfEUMFcS 5Qu1+YEuJyHMgzVXDgFsJt5onWjnPcO7lYBDnEiHmcDwCm9EE6qxtk1J/cdibZLzAuFvYYsC/eKe FH4VYFzioTfukGVRHnkc6MG8jUna/bjD1bTLalsuAqUVHKrcMVR7TepgdQaFUupfLykz1ltHCyvM 3fPeEniCipiIBBohDobkBnsSSrilD3sbY5QhSNvc0tMEb4i3czPRxQEEKgKo51QGn8A/B4/lxD4W neJbnYyn5ab0Te5WWttJmlvzroZhkMDG2VyHcVmxfu1+TUdR7vBdu1+PiWFQELvacnc+ateHSMl5 xOh+813JPq4MBkccdwHce//+/SmLSo4PsGEeO8kv4gc8qqNBw5HVxQtyBHASKas/9xg8mVNM0W6c B3ZNx0AVNrzTfr6K1VRusm+eI5elCDqRerSmx6qw5JiatgmwUfBth8TgaZ+eDjmj6DrbxJTPi+9J 4KIoesP2UQ4j4cRSQ6I2fV36CU6/zsNxGrFfnHF4a3dYk8qKU7W4OVEGhJ564OPwiQe+pliw4H+d i26MH8umCvdScYaqXBBih7Y1Ileok4uEeXR9DbXmjS6E65d5/vhiPB4cs6lELsxL1HmBvBJ1h+io qIlY+4G1EB6NXc0/CKrEC8ewAZPH3pGIYz7uD0FIomFRgsiDxZcB5+7XGJSAy+3aJZUIQCNwmQZg jydst4puT6NbGReZZhj4oB2ar9B8orSeJIon0WzJ9vAIqwT4XNJ+HMSRY0/i2IeIXYIi+2Ptoqxm 0D86aaTImT7umQ1rAJrArNSMOvhBnYMSWWFzio7M5coMQmSZrhkpL7A9hYR5pf1ZDCZ2KgOb8et3 2ev6xYae36nepYljVvNjXwU9vs+WmFQLbmKcH2jJXjpvuSr2o+4pojqbb2NbSdiEY/fvrKsnOxof Qruvs631HsHe/ChTeCBgUz7BnaFEiKoknDX3NRWIcqrwCAk7rxrWq2UzErPiUToaX2BAxY5/CFYE uVXZ3lNf6XNPckggV9ReqVpyI+X8yzYOhoNWK68v0gIK+uOuVHNapXfkenToC4Ku7DCy1xdu15yS X6YgxCxEacydQELdkk83gS6Qvt9U9bU4ifoGji3gDc642W42lQRRzkj8xkewRlWYH33rgZC1cgLJ UDEQuElMsTgjxKE09d6zHWYIFgkeM+cdRVW5txPa4OarNPoSVB+cRk8dkSVM5XCJs+Uina8qctz3 N4gWcM51V3ARr3/76+lXz9+cPXv36s0/dKH5iAy3CZcaw7K9ghvhCav+0P7Cv2jwnS2/Kl4gxDZY cRhau8IPTtRu0RrL6kWiMHwtcsIiTNYFErUXukesJ9p/HLYj7EbH1yPEuzLt88mDx8mI1ChjycVG rnccsNIrwU/b04cPgbVlo3qHPbLnaszQSO6YoRawCRbatrTV1rtpEeXxMR6Foa0g+tcQK0/7TU8D 3czIkryO8Sy0ofR27ZO/sPPnUXfvYTMlG1FX3Qs/G/TzOJxEG+G6jI0tjJhuw26XOyk/CIgV0aen 0wsV8zizgogajg9MMGLtE+a9+TKC2UJ3YI157ndWCNDYTk4021uPrZ/exLHkfOet5QBN21h09DEI EmtjKdfS5GZBcbuTxMDy4kFE8UN7HY8jdOVQsgt3eHxqEzSUutUR+oW+RDxX45/uCR7h5CWC3+jZ MQ6+AT0LDUxHCXhccjKg5WyL0nNL7EY2O7My5l9vk4Mqqu64BxQaV1kjsSCLjr20I5wc0nhgleFU Vb2hFEiDfjHN7JmtHbEw8vz2IjGIENAchdfg+MS7PuLZnLmDrxr2QuLE3GTbGcbjIbs/SSVVcTHu Qwd7TMrimOMToLZnjBvwmH4wG4JDhDdELzLlimPxo1AdoB9q68j9946KSxPFqYa2rXSlUvH3pdYS 6qhaDqXV4Pvdyu4CEKpW43Mav+5NYMnYycTTK67/C91GqeZ7rIbR1RqYc2AI4/7bF9Kf3QUtPv53 7/+jVe6GnIRAGvqEIsXHP3v/cEh1bwbrvL5E55tu5Ru0pJIrleo1GFAIE14V/gFT/uBFm8OMmpxi vzi1K1nrLncRBokAynOA64AFtUa0ceJqzdM7IYADcuvpqZqjPv2+qUouTiMMuIpLRN9MmNCU3C2z Vas+8586+dUzHMnNfnWMP04oHZNnZ6E1sPOI66LD3OeQzyDIWexxdvH6mJThxm2B2sxXICoMgy4R fLOpATtX8TyHPXVL1e9hRri7XslbGKrPatqsrzlJscVeXuMP/dGzqk5j5BTGuVKBtF7CEg6GjZ4T 4pr8+7orBTQhsu7ylkUgtF6qmvMSpYKpgf6h2lIUIhq6LVkdcJvt+1LqBlUFTQRDXqaUwyl/WGNu phzeKQxiQoddM4vtetNQlb1G8tqrdOVWFOQp5XfiJzlab5vWieuma8aBKqTmjz58ePjhQyQpOao6 dc/oG9jciG6iubIqzGVXbWs2p1PKL+CGVkXAkS8qkM3Fcgg1Jb7aYOQ7Rvjb5bUrdAUWagAbVjfh mBVALbyWSAa5EHetrqUtuNNbrL8vA9xJN8q7lBS4pAHhAhYUr8GLjSRblWxSM+yJJNFYKpmpES+H WFbDL7in7pzlOuMlQAyCpfs/+jRKogfQXOmyHo7GbhCpnZ1RvFTDd4IBS8lBVTKL7wHCp2tQVpEb X4PUGpFfOksvhiHWkxnGuGSo08FUcqoahlXNgtNiF41MxAnjFQSGCdj46+CpmnMafduwgoy1EnXj KsUidawae+FB8vCWPlrIm/oTkdmaycg7tkDcUs5BGW/HybpoMFOudwPESML4TTO3b6yN4bYGwsUS xI8eW00nKiegZqNrRn0qkFriIVBtfNWWfWIO4Qe+kSlWEYmXQd2buUE9tF09GbQ32lbURmIrJi1K twqy7LiT12ZfxlFyy0XOvg+R//UiF41kpoKYRPVa1rOi1CwUxVn4GyzVflDpiBX/dPh3Ce8CEq/d pivRkF6a3xqMFKMINHRoh3EyrLSW/ik42UE713xi08ROBpx4s0vJzp+enb1//vYdJQORL54+e3b2 NsSPCP9CucoC8vcin4ye/+3I5MMazSlsmJ5ACSZlvhTXd78ZGYx0oI33GWw6i16qFN10zUY3o1C2 H1nZy1fvvnr+5gdZGS3ErI/KSwQWti9pGVGI5TEXmaHfb07Z5BvF5lYmAdmdqAjyLqoA+BLxFbmC yRM21GISCqVJVfz1i69f0zUynvf8WaUzUIIG37+Tk9UyirE0GnRuT9C7FXPHSK07jc5/MofOPoM0 X/TqXy2xeBj70nKpPBeMuBhO8FbHPr+Nt4eIlWQztmB3Vef8YwBXcL3agV6GoGOy+P6HppEXm9KT BsAB+k9WXmvlE8xRRlfwyIufesBNPDRl265sBgmorDlBNxW7Q7dNdF3i+P7c+DmPj1J+K0i5wg7b Vfr+HmdpnX/ZTLTHL2HIz8PQ1+4b0cpCEXh4yVw4HAYdgnDJJxqJYY6n8lquqULqD+oWP2Q3deWT Kw1URpi9eHEujTkH3YWvjNP5l5xBQ/5X+CulZkG1GQr4wx4SZMYmzxVnfCfLbzeaYf/WsIaGYi4J ZLVtqXoi7Eg84h/xljfXxWYDf3pcWFe7Y9Ylyf50ipw9CH9wieODXSQDUBBDOS+Q2izXZuWrmVT6 IRle1JzHk4we1Og5m67zMB6SLozseAj3EhkTUNG3xyh2YmGl1W6qCZvnVmk10SgR8LxU2xPwPlT6 TbPXR519cH79ueX6aV1wFXuS1ImxsrM1uJsdOCE3O11gNuICFSpXlhT1RY6iQ7UjuF/okBCKGlhK 8vFWlddtVD4gYMO5qqYfgqFT/7jbcxwlDhwflbU5Za99f18+7+7KMZ4Fe0D2eMc7tWsWOdfuFXV3 M+lMokv43Epczp0a+zUBXYv3YQ0hZosZUu06FVKlLumwWYEYVpSbbWdvPb7ZYVSaHkbFf3wHx5TH PlgXOVyZUs9shKykqcc5MvU4dcXK1bJTFpS5C8q/oKobiOFJUMfLDz3MOJEX8SPYNUYVGtwcupNl Lt3GR8x2eWC2NsJ3pi3sFc8XPYjwGz0xfWWpdxp1VsEp17IdHO8JpQa2apVRCp4V1v1tq05HeCJI UaqS1HPetYcqO+0Ry2ZRBHFx//INyvqLxy8jJTlRSLwu4CuRF3YCG1Wq/OipkZ78iLmxwr2LUKgL 55gyZ4qoPqHoTF2BPFTctL+2XadWqN6g0750nvjYsW3Erojna22C1fI0cJzf4FDM5+GiqDbdgEvO Rhi7wuj+iFolVKoumCx8yW1pB9UEBSu5FBKNUecft/CLCQSnf3WeSJ6QyraK9x51/4BGDSZy4hKK s7y9wfozOAKnEnSU90ZocxS31m+N+o0VYNzttyiKHlBlJbrKhiiyuJQH3N2tUXENtE6rq8eyVFim Ut0hDT4BJBVho/PLYsgJb9IV0AgkjDOmmKgkgH0CrJ1F7PjnJvzQVmk6htTGAxfzXdF0P+p/yutZ ZT/ZlsOYG7btZFFwHi+tne+oMYfqFyXB6TwtBq/wavQUkKRLuNnUBebiEQsmfeLcKTc8yaJK30mG u9/VBacm4t9TJACxNQlKN65f6870db02sREF2nT1ze4wiFH5etPuugYSDt1fbNdrjKVkHJCpoo3L MXd6o1KjT9xC2ool9NNQLxYwPh6eUPV3S8suvyPb/ilbqSAEhCVBCHYAQtGQO7mdSBY1MxPVVdL7 YO+x9iNUv3WT83AS3Y5Ghi837kMohy794Knz1Rbfb4zxbVuigSWbrfTDEKpkAddHGSbZaL5ANHS0 tl2WNTTeaacf5wKESawtPLxtn7/yzLeMspy6l9tP+J9uUASFqRWlNDNcp/h24s9NyIqsJxwRilPs mTDEIaRZmMqE+DscO6mkiWehL1A1Tl85aO4jmDIJF46THznw4yI6YwrC+W7nqEPYE3Jzj0U63EI4 j4d4DBvBQxlh3JHpNhqTu3vFCO2D6N/S+6pOKXmgLlEndolK5UW/2kyGSWCUpvhDThnoHELwcfD+ 33722WeANNMp1njHmKiP//37v4bvjM/GZhdKn0F9cC7T6dgqgvnxz9//O8tHZVHN8d+P//b95/fJ OwUOq5kDO8U1yJDFlSYUT6cC6olpRYaKLPOUyJkZoelyi9zAdKrocDZrqtW2zaf8WbmUmNR3jscJ GjMGDkslthtpJfli3/DTxi1xoVT1mgqoSENF6N/kmzqJ8L+Y6uuFTpFzWDgSoYgKUxXxSHZhyk2X q+yyQU2XKM3pM1eOkt0aGS4V7UuTIXotDzWvMjkfnr148fz12+dvhxfj/dKYimkOc9PDkxMZ80RO x2KQhaEeGobamgK5NYbEHPvEkavGDA1d2MyXS1v188E5Xq6qWd8ErbkNsfGDtL3FsErE/E9ZPRkC Dne4fz1ZunfaEVeCgBJjk7YghtdAUzu4AH4dThjPTjji9k/acQmmEfh2kEbvbqswKp7EVCYxDlV9 NnFfKt7IEQ90pTxbpaFM5pg5G1XNcP7D04CyQ1hDFwWCXs9fcRMu3OXOxlS9jvWgpE7Go8IrlqKt iN8ct1ZeJ9qOFC3fOcZYL9yro6Vxjr7rVCLzxue6u4/K/EbUBcR/aRzbtKff3Q1TqaqUXRwF3nHv t5uwzr3uJACThPIl+XzTv6Z+jUnozEO2N16ctGYjNJAwf8N8Qu/cUmuk9kbvi+wHJUTsuq0eyECY kMI0ryWbxwK7h1MPWsPszUDoL4DA47bSH+6PNBz8Rv9auf/YhORb8aaEZFOsPiWWj9hACQ6L/zht 7pY8WB45Qd7DOYJjaZnCXr2Df79m+MdEDque35b57YY0qyafnMc0SVOTzLo/6bCqFDDxOqXyg4uF chZuS2flnANllUswhSgmVm6+VhV7hj8iRpdVf1Ce/O4FVPYrrnV7G/rnap3mCy85llR6s1ICA6+g q9P5ztQ2MfBZmlgtN5G5mEJ0XjEeQFXCe/RPmW7LAtmmqXztSSRvzl6/evNu+u1Xz7/+2pxAan/d OQJFi7zkuzI7lAazBcsn83ryyB1P9fVMScUyMufVH3NYUM2Y29g6goS+eKT2JDqJHj8ajznu4RdB P3NFEvVSzotT7nwRNiJRI53o4/6jLxbKZav4/HFveg+ebycPRD9y6SFGZ++ffvP6xVn04tWzp++e v3oZffvyty9f/e5lwu4CV9UNmZm0qposRVmrcHHUnYyEV02i0Zdffjnauy0KoZtqW8/zA9Jmd+6/ +MUvIizKyI42PO7+PdJTS1MvHLiX2oWJ3bhnX/EQBPvRnL3ZYrC2Tu8l6+2nlB5VuqxgPfb90NGW 35XDY1JvFfg8TGVhfI1IuNFUFwv4xG49DJUtY9y/wvPhty/P3r8+e/bu7Kvo7P2zs9eIOqJtG+zP HLGpY2dWPKoXeOuMZuUAp1IdU50JJH5wzNSF+/IZqxDLtEc7oxyD+7gE56nV1Tv+tES/54IPF0IE rJqFypt5isLidEUlT9StCTzoysETy1d+9erluyk6971+N3335tuz6dev3kwfTzSiB3/u4qzd7lcv nr787YvnL8+CUPSvXSAvX7355umL5//5bPq73zx/d/b29dNnBkboxy4IJfnqbuqLbtPnvwaQZ1ON sdOvzt49ff5C9+z5vQvo2atvXj998/wtNPn6xdNfm7H9H7pdn7548ep3029fPn/26quzCR0h+b3r xxMPlArOqypllpIgdoQu64dp09a+9KUzpga0DUo/a5Bn2pJScxLAKtM0m891Nlgk5PglEnJvJpZc oHr986Q72Dl+c2Hjp2o+8Lh+LTI5F0/EAGRcYEcO8dU9bK5YnKZi4MANIJOoKkDUrTKOgYubomYT ijp4Itswkb/DsAuy7Nzk0Q35hXIgis5slAz81BG6UBwlkKBENpIMShU0kSfFKIFImPZS4Gd2uVSL f22kmkSnSoD63YLSKUuAsiwyUUQ5ADNkVybetiGuSWEcsZFZD+tIsaAj5fBGUF36Sl+dm6botQGf 0AgKn8z2W6jG1Uyd++FlP1FSmaZK+Wx7+Ya+jcUGNQF+zoIwsf4+KheSZoInYRbYwhzWxdnTYZ7i NX1vV59iRDS6u6n0iPHgE94rJeEaVt3ifwNCpCs+WpKjyIz8pPT009ZXiuBp1NXDNvGYEi9SoT5i b0jTZ+IAZJEmvevb3z5/bdEv9EBwTY6Bm2pNCJ16V6v4VhRGXCBR7SjCTjjEemxCN+knNTtthLBg Wj6J1sJGhu1VY8ON/xzHkLmPxj6lUkophzQdSDLXL4CHrib7a5rMtp7b5lrVue/Pcy2aPgUjTBwC 9qlQeIs7nEx1s+MR4rsnjulzHxvtU1aOesQF5zC3JT1wbaX2W6Z+vx4p1iqUwHe/059brPde1AA7 2Sx30QfXtvCBkgG19ZbSwafpnV8fT0CYIgXAZPh/AmG+hw9TY2omKZWxbAsSH3yD1vn8KiuLZm2n h12EyNjX9L115v//I9W2kCrFUGS5lBkp5r1JlKOEeqwOj04lP4lsT7wj7KapcajVKWEVIDDb97U1 pScnna0lJTj8MoiSmHYziRyC76GbvmZGt6rI8rcNE0CPJyNdukP9uGw0lvNUTmYo96DopiOx7LgQ RM84XE/Smkyq6u6ZYgZUNdJps696pNNQNRC5eElWb+s7Siswsbtw9fUJ/udIZHMxb6VSSev6gfxK DcJkwKUf7rGEuuCKVit9jI7l12s6sKTHzh0IuVmhHVpdy1ek1Hgmer9mO+PXj3RCbXbNjz9w8BUw 4dq5yZF51LOPhJiNVdvRCB10YZrcnUOmG4wDzJdbLlMlRWRzoLBrY96SgpRoZoR+r9m6+4QwUj58 Ie5QT0tWhqjcI+iBxaHG7FPFbwISPCUuDSNxFeXLPuDIlE/5ymNWTMm20I4m0ehb/sbZuVFXARDq nYb6qiD8ANsgX9W5XWAxCCN4nm5op/77WbUp0GMU7eMKEUugx5LBnlLuc1XsPCpX7TUG6qKbkZdA vG03zenDh5dFe7WdwQO/foiN6T/OsIaJXVEhydW05oJl2GeDUmA9jL/73T//4/h8++1FfF6/ufjF +Xej74YX4yFawlJBNIvzJuaLOFtWyqlyTxkqDEnLZr0lHQfqxnqWnP1K98L8HlTCfTQDaU2a3lR7 JtTDizKI7Wf4L6N+jcOBzJVddSOXn80u19kpRquTo0cguIBLOizQDxNrPpFjVA43FN4HjizAYHZ0 4LavcFGGwhS24guc0BXHjzQoWj24kgRQgsaC8wUB7kBihRwVMdhOFeWJ29t2vDcqG1ALCJ6kizW4 CTg3+u7xd09G8LLetl56Qg7cJ6Vzd0T8octtAu4EW8P348AR/X+KnXsx1E1ixPtwNFWDVYS+Hnxf CmneuBCy+88cuymzK5IqBot4675c2PegqKpUrXIkygXa4n3jkQMWhMiPf/H+zy0/KiSuH//d+//n z9iJikID6LnDymkNBRm38BxyJrZGVQxUaXR2TX8OHtsbSk0edqZtDV+AW4YMp1Gza3MMfU2PSu7W KlhSyREquqUyvqLAxXDR7UL9jZdkhHMedZLNYv5Y8fogkd6CNw4VSKXcpaO3MCUUPjq1hKypUgUC aJ6qxg53RMk2Y7u959KvQj0x4Y0ENDJDiEGTloczfEqVqYXKBVtfeEal4B5bK7gHnAZnlJ01bdFu 21ylQCfoXPXGFm8j27CMAz+h6nYwgSmvajoVl9vDkjK5KttzZ8FxzAummNGxM1ZqDEw0tPrcE3iA ES7duAO1yyQ4xJb4QXnLppsKfW0LILiIPaS2KNysZW5+M+LylfOHTOLXFIjUdooaX2IQbGT1GIST 0RHaXWI5xxHNAv6k2YbUD7gRcuWzFXZKq9nvMZiVOwSjF238KP3JP5ffep6o7nhiC9g/LDZ01hIo eE9u6Q542ioHcKeuE6rORJNATLMIhMVSio+S7V2FJHAL3zciMObeNWGRCy4ohJhWIKHMmbGYsyKP Q5xYlODpYFJnKxbQlSGpCUWQIAGhojjFH+BxURdJQ6QNZHQcc8CsWG8CDe6M03t3Xw3gH8ChrTP9 BrZDtMJx5/L04zr5SN8LjOX06BmO+bCVfe3cfi4RpjoSygtRqPDcq9ro3qG5qU+85/67s9d9PBTj qRw8snus5xFetMxzDL/lNOM3KLTSYdI/mLUci5x74XcCpSrFWqTfZmktD5T9fHk0z1jFpLQq+zp+ ZyXlbbt91DApvo7PsibXvXXMjL1NtDlWxjeps046PkIg3UDlB6DjaZQ6aGIeceqZREPhSaSFqgtr IgZkCD/bGK9GwSWvzl0qJT9TnDTqfGUUB3OfCyEaNRQbBRIrNFw3nIPMrTeCSgJOXAbIg8FW7VVW 2jpfNMBgnDSpMyRVt1GX8uBxOCf/x39PDvTodV5UaZOhp8im/vg/vP8//sx2yrdZO1kdXoJa/DgH A3JmKGbs4qHWj4m8RRE/wgbIe0nDkfarfAtjomtELL+klqMp5XdSKp6K3Qnpd9b3rIp1IWlgOFcB BdcBjVRtrUXj0XCuJNLxaHUg4rphglQp2cVW7SMzGB2dIUHvli3wsretVugUnbtrI08NpRK99Z0l RUxQsBN+mxzUedvWBZWoaTZ5RqnZb+oKszVjxru6BvTBA1g0A1fchAlvu8re4UhnAdn2CuDOmVZo A4yHo/vNaDiO7kfbbgD+aDj6XkBHw/vNcBQC2uTfc3Im7/sIlTPD70Z2/kzB3/j2/FTS696y8u/C YfkpIcw4+jJyG3mbKQ57j5IodtudfDF++PCJy/z83rT2G58UXrSVNcsCK13cnuOEbscnvz+96DZt pBX5mGHk3zlPH1t3ENXDPk2We9GvD8NtquCitd1KMi/BFwT8ARW021Pn8x5QqZ2kGSwLoKY0TbrM aytDpShKmQhw3BJvZmdz5mS6VSMHMnRpVAJal98Gskd6fTy+Z9UkETw67UwESlP6ybdETsX7QT1Z 1NW4H5DMel26TEuvFVQNI94WedDueWB13RX2rdIbUU805K82+vn5/QbDyeA6qjrdpRBndCtTLDgc 4aPb+7dfjoLhZWq/Ej0u4I8RLY0hLCoWcDHG+4u/da8zvBn9HrjOhYaWoevcd6WpuX+h73RT3dtK SRHllWYuR0aZPPnpI7skuopPpxnQQ4msIPSkvT+RrLBuxkQ+Cn7svuZEatGUbvR0GimWiB5iDPQ2 +dN1ElxsmjfAjIhMI3qC5gqZB8PPaA3FSC1lFEmSDoxIRyuOBL/XZMsrc4zgYxbIeqvh7cdtjiJK RqHmx9cfcxJsRHuX1VT7EteJ7+9DxauoHiBWtTudggaWtABmOHqS/lWET7bz9N+LMANLfmMthsLZ FalphCnSTM3YfG1IPOMJnoz3K7IuPb9xmP0kevxXj2zum39X2DAefPwf3//PliKPV7MCbhXYbHgH 2/zj//T+//zzzz6795Po4bapH86K8mFefpKkkoPBveg3BewnHMpP4G9MZYxJPmboSoZWaGI2rlT5 3ssCFcuzVTWjZJUgoGKe5KzNIhGxE0wnEK2Ly6sWoGH6XwZV12jPIbp9k4/QArchm62uo1Tmy6zG TDdRfFkB273klJr07yzH3b6HDgJZWRWLn4xTxgA6ePRS+aufRnkJXBSVsMAUrX8oNuSmlPC81Ucd 5QzQMkAHxD6DFJx9U8SZqJnXxQbuxj1o+1rUlzieKRklnjpSqqVRgpCgKbdWdVyoPS73ZMAlk2mP WFGPdkm8WfhG5pRDl64Fay52uFvow0ijVlo120jFQwCHYK2B8p0PNlULACEI5rSqKKMIWUgo8zGJ oHg/8czYQOJYPQgTm+38ilI4Yt8hoPUMdgyfgVW+uMyHvEIcYIaZL/ISF4pDLDiDViMWmQy1x7/K 59mW0+nS+dzkvPe8bmba+WjhPOYVyCOUMUrtL5d6pJ6Ii2n0O5J16QsYnmEXrag0EY1o3ejZh6cP VOKen+pigVwPFf66uapo/+Bg8wqDfPALzhWDfpaSXpetPWvck7bCbYOpwtzN6WCzatuqI9DCRYVO Fq0qv6OOjdHsOWXjwAM3l++KhENGdkk5fkpLwjwbktwUlopZPBjrCAYAI++3rDOgzIdXPdsBYeep IfhqvabzLnVRdPiI54i+6qfRhw/AUBCQkxPUmdAFmYgatUk3uw8f0sGAQyvwtUMa+su3r7598+zs 7S99g4H8ybdXffoD0F/t3gYiDztu5fXB5PsyqB+BaOYifxkm1a47JkXogRyYCmR+sB4WDZMG5A8H 7CR5Sw45IR1wfp8wBUxVMpP05SSKnyR/3VFToo8ukkp+/fCJJnz6OSPUk/Svo5iznm5gsEbKKNNA 40AROKl9qnKzwWXEw8tUdhWGhHeyaHGPyDEY72kaYjacUDF7uSrCUvYwHKUADYKdkdlRhzW6Oyh7 bvrsME91+OwcsZkTqgyt1qcgEeq2bg4kyqKsDFTsVfQOvuqXVHSdKVnLuYLrBX810831ZacKj3Do v813AbfEXtDubvYM5Nrl52QkETeGxsbyEZJ6S9YwjpWWXazJW4n+jk1Psz36y7EPR2dvQEJwv3ko QWXqW+vIuh3xxPKauvp4xasMOaBCP7y31Ms6C8uRcYoLjueV5U2HvozT6ZgKIn7MOjKv2QgforZb 0gmFS1LUuX+QZGbs2BexXTCScw8AFxNCJX2A2iKZZDGJSJbybRf/XQejlebv+hLYf0U27W3Z50qL +wQkJ6/rlBJGx8OzN29evTllXXNbVatGtEP09uQLJ5iMpeaijZ9o3WuQnH6B/uan1g2CwxziOdgn u6rm49PI+egMptZZzK+tMN3OO5ESOwkLyZp5UQwRQaROzQyf0UBHhkgp9JsY37F0keO1g91sYn7l 6JtFThBi9WKNVQYBW2yVWc5fE1DkXrwJH1o8XnugtfCFu9XfY7oswdjztfwQSEJxXmrVbqCOFrNf 0M20ymCpzrL2ElARycQvz16+e/MPvxSlqyyMfqW1AQGNx/qufvwP7/+DJfhM4Z1UvM7H//j+f/+L zz7D4kCsXYcFXZ3Ir5TvBLk/eVdFZjW9icwoTB2gTaWxf/5y8ij9GYiKlP9Hufw9efhF+kUUVyv0 UxbMbSip4gA4bOQ12LEvuwSGlneUHuTp0ze/xgiuF2fvzmAfPqXRp6wmmwNJwHB/iAUfEH+mC9Lg nCIRFIitBrbLXoBuqMN7xMkp/VkUZytkTKXEOXpaX+aNqAWydoDsxLooq3oMMJVNBkmFvb8q04zy hpyx0hzV6KqY+iwHkPlA6dNRzngqheY5+CQlGAgVDhXGeifFRhs1CG0DiZ7I7ZaovqcgJx3hJGzq pmoKlt8GqpR9oyqRqFhLSm1HOSsrpNrRUCqwPhxKzVP64ufvnv7qy+EAzx5zWYp+QJUwUX2iIUd+ VZvW5NiZqqHjZxxGwM9cVWMRBHwY0P129GB0yAdqnOrlT9zdGAxeoRiWOFKLWmai2fy6UYdyWamo GAQ0WFRKBLGnS4fTIIEhuZEQi2sJ61ou+KOZ1QBVlwXwnjn1uslRuoxBcHEukEfuuTqM1tegk64G A+dXUGr/ipVKUlQGfWURLd6+Pjv76tvXgwn/j9CEeGe4R/aQLIywusC97IP4Yd7OH+K3U/NtunjI l+LEgpI2V9F4QEEKmbozm7q6xPIdML9FzmlCcs7Kud2oUQ0zDwLVptikA1USCnYxJ79Di/iguE54 DY3p/mkBTMCR4E4y8ACf4Nf/8O43r17alGL66rcgZnH62as86i7khOzBJyCU7k7kFE4EuKINA+us 5fLalIppMp2NLu2G8jtn385ZOYHly5vBOkOXBtH9hSc7eP7y7bunL148/OrsV9/++tfPX/5aHaj5 3+CdXrbshhAvlIFK1kE4ySmVvoGYDHQJ1scw4LWCeHGC2M5ZbgvFXfXtKFZszFg72lYbtWrKiSq4 YG0KQFaTtW4Z7SSnbzLEzcrxOHVuiUol5tDWxKOC2DkRGuq2jH7PqUCR0DoDitZGbOdAM2EPBhKh aZHX9v9l792W3LiyRDG9OQzbY0fYccZzbB+nUM3JTBIFVlHqG0aQml2kehhDkQqSGvG4WAfMAhJV mAKQIBKoS0/3vPhz/CP+mvPqV6/bvu/MQlGXnrGPIsRKZO77XnvtdV+Vhz8TjT9TB0lkeYeU12gi r2wKKDn5mmRYxVVxgytdAwAAu1ktnYM5Qa8aAnGCD7h+AHJROQQENRvGMGZiv9NOYmEyWbnymtYJ tutoRPAzPITegOeVQGd3gf5fCHcNgGTI8HJ8XiW/wHgabCmMPw9E/CZXNsWP0MItyqrcSw7FWgbn rrO2zzY0u1qfJoAp2AKEHvIcY4ELD92GwOGhM0M1QhwUjViw+uYc1b2FYRyTlFp49uJpqkQHcHY4 iT1qjMuNxF3tsMcrb7OHNwHTNshnqpotOLGqglh8VlKarwt0wwK4OlLbxlNLvy4kvJ7ZUDYmSZtk OFaYRTbW84Q51nfyQtO/LM0jqR51i2zI3Evu37+48hSPMF1tqEXW4BiLWzmKGGRdeznpVAZ3yTfH HWAW40Gy52cYgC8jjmyISh4/9zsXyIGPs9psU2M5LR5Y/L2+WJzAM7hJp35iA9TU39eaem6R9TJf eW8DFZpMdf/wBHlJa8wDEWsh5QiD2C5xxQldX6H6ZlnRhRzaAfL4VK5b/ClrQqzt/dSLqKK+DROb jGpuxfOt44SqyHRwKagUmkaoWXGc0OuI4SMP4GHqyeI4PgwR9quVorNkxBml4sI14Ag39BN37cy2 anW3UgWcuT42uz4IE39bRE6Hhw8sxGwN9VFMkNroJdUGY/bpZ05GyDV8C1cruqzaMu5HWGbAwrSH +OEhm9I08erHg0cnyRco/Ux+lQ9CLv8wb5Q+2KSYuQZ2Ej9Q0/uHylPNueiGESxl5xVt4G5MB/a4 MEGtX7JjTmtbeyZ5RTBAkm9++Hdv/4PF0XLSYoQGYCvJaRaAYfPhr9/+8Q/aUiuIQ8rJ4GJ2XD2K IgE4kxG6iATXWiKCgwTKgYOYIq0H8OnGMjUD2m5mc1VRh8hZzYul8Fu/Z6uDx6oCbVing/PHCwy4 z/Lasxwj+wRzq3A+pMZIe5Fs1AAhooaXQOiczazFLoOD23DSKEogLb3/46y8cjUOcAvgS9JW8C0m Tn5AFx2J+YlltYZliedZJkeARkRNQ0zFurrWcdFZTc2nwYSUvyb9domROLfI3qtGGaVgdTmvRxTX grXo7FyDKoEiua+Gch+rHRm2RUdgX1MQXHKOws50lHdgXbc63v+VcO6k/VY+l2VsPJk7+yOSbMgy 8GoTPcrTi7R0rTwmLdYS7X3IjJHnShSXorS5V7xvnGzRlIgUr6BrVm8Qv5wgHVSw+QBhXiCIyGrQ 5mORfuY0EKXWflEneB4EBu01RG2mWRbZL7V9BA6XAMDk/K/dFKk9XgwyZACQhhqjkRmIrAK2Za05 J4QRM4dwK0cjLAvNkFOJSsdRWtEuAIa40EV5A+V4VWHMv79Rog1J3iqZZ+zOOeUlW9xWqBMXeYO7 36ghra2hIM9AC+7vspwYIAlYmawaQWMOJql5IMUaFWDrakyyN5222XKVsIGpxB34Gu54FewMDh3R j0zOcxYE1KCz2E93yw3R+LEHPfxhkvX7/V5yWlXzXgKPbNDMDoNTO3oO0ffFkrdV94Da/XiLM7Ru xwZ7ap+WCX3g6fRUnAZYIxT/3bCpAUoR7bU8sgwMMMgDJlrXrLwlsVKnak7hFjB31vyGVzgKXpK3 YbImyyAAL810860hq2VjKrpSbFmZ2ewetoCekuvZhK2KNAjyHF+XknlGxdIUkz6ko5RZgJ8dgpkm bEhlBRG/fHulbUPE0RLfZpgbnYZGKy22gMwWTHydsU5Z0A9qezeHOsBUwf+kK1EB/ctLNyCF9dJk LTlWpaxplF/o1TiGFk521C/Gm2JYUMfDTflq62at9RVbRn0x4w9HB2uh2QCPs0w3OZ8BhoYTf0PL xBgYrw67FbGBYVmaVOdtSjGztLon/eFa3gG8o/KCRqQHncpOprlMwJ6h2ZuWKHrSgFlTuwUK3Wya kMzGaplLL9WdEGnAg5hdcHdPMpKqgjClxbrKbkn1IJVcILEykuL3QPmIYm+oc0QFidwwo8axSt2j vjp/JxH/cQxe3uK0i9mfvbfHlo7VB8pYBnVrUEPKdpyVy+3CvM3CM+lxh97coolMLRcWM+Ee37sR TtGUQaRk1bA8Gc+r2dioeB1I8WEkcNDiuo0GFO503WSdKI6Q+jky84fRVqTE8cFJC1jtSQJrvngW 6JGBuFzqxppFBiVLv0pl5fRAOFmtdWzYCrXh1KX36uzeOifb4XC6lnWwfTyVa5EHHWMdEgdBgT6Q 4Q38gZqmIKJnN/44OstqGmbpt8steaDBQXOsih3zFkrr4F7PFL9H7kRESWtW5DEza3BFlCUxLsrs dkp2qugPJrRzX4mvLO5McZt6qWf1SLgwZUyz9u0Y/KAMtIqXOjC7X2EPaJb5fB/5UlonMRfHUazZ 15GGXTdfdlgSw65hcE1dKXM30y/ftyIQpl/g8LxgwA6qvq3wmKPXCiNsjeII3mi/vgw7zhEH4+ss j2NQWp8+Ldi4Cn0QbK74rv4HbCP9tRVwPQh0L4PwcK3wzDZYBK8w3iYNXTs/6RSxduzLO0IBObiS 8nF3IJAgdxzPCF+83iw22bG9oyf5bSABQ23fZO5l9w2Wfb0ux6OfZWP1oi8BZdoSlwYsGYpmMn+P TTjBFyiVdtCONGjdY7jyLygasIU8OEJ6HAbYGgRX/95aDFLIikPJMCQkWZanTrDhRpBQE6OFh74x QUlmHS/uL/+RtyKK/6B3Hv2OU/+3PdX2G8KZq+gR9FYjq2teO8uQhfjZhI/ru4Zy/5oXqOUu5PDd L/Ssch4cF/OpOpq2PlJ+U21om2N0i4AABfnrnQ6zFN1pJoKOXcpEjWedO+WikyThiBLH9ajcI20R XK1Cslv5bAubxndPLPbFHnscjbcs20Pi7bwgMZkhOepYBAziSR0Asm+5eOCLU+A3L4Kr5lGwNPQ2 vJMeRdemYW+7lG1AZWSIeMnhUtuSd399XVzv9KbObHeEN8QaheOjeTndYIfWK1LyY/e66du9E13K IziTdwgF5Y1tSDPmlj+uFZrOkNfGz3e/G5K4m9tkG4FmnSoakDrAj5eTXQ4vFNv14CoQ8LKTTElq ulrrU0gUWZQKC2E7Qm41QbY9AqXb9GE3chY0BFm73rn1BFuFIyfYPb2RI5dm6JmZslqckzraw0eN fZqnaqternfZqZfr/7JRP8kmwbK07VFnD+Ub35GboqUIGg47F2W5Kuazy5LXmTQDtRISw5Pk38P1 /mfR2gDpC7AG/w0woNjGRir4IBkTC4qcdFmuN1gu+xevVC7F/tzHOChkHeYEzoSRPl4DNx+FqhCy WITgxH3w4cueztA85jsAT+RyvxWCIptlOtWxGdL44t3tv3bAvNvFZMb4cdcKPtiX089/qXRYzCtg rQ6vgahcTsPvZ5HjsBv8P55MBP4zn2Z4ENyxuXUgXm9Pmyrut1b8Zjtvqni/teKT2WVTxYftPVaN c7zXWvHb6qpcNwy1eaxxPMB79BdBBDTgKCLAL3lQthERsHFotCVegbD0XZCKdWJvPbBRtIODT3sy 4WY0snN7NANoUGZitfeXxEtENNM+/XCimWf2rwu/WSfFiLKOivkcfVd24oClrCvtqKrbxTqWQsha KjE+whby9IcKL+52K/qjGNq87F9YDCJmVhFkQLZcTrkoGmimjS+LNYXotw/jdJkOuC2e/p8j++cU z1KH1i40oY2mAoFgwtr6guXR/1DeXFXrSTwPO35BcOsH+Tzp8qBPOJYdQmCZ1oLMnkWwvoV7SotG /AqTVFJya1XuTVBGh9pCXGK3Br45lmonNIE41a/G25ipVPbjwVAPAmj3XhoTdQScSdGMtuOrZzpL 79XDe3WPhJAyxp4aQb5T59yC10AD3lc5ZtBvaBRClH4dPyH6cx6vdcdtxXpp62aaliObaq3hfWTC mrctumpUxxp6bAPVck0a1mtyy4JNGlZs8rFLhnZC7Us22XnNPmrRqNLklmWLyw+ze3UeSg8Zz9qS Q8pVHrLS7q5w2lQYEzr7nGcweF8+rdArPxwP9g9POpFlaLsbb5MeAj3tIqSfWpEqYiZaM0sXwuCT VGtHdk+0Q0x0v9aTCdWptxC7gGveLf/5HoI7Pv2ZsM4aaM1eElHoMRH0B7F92oEGkqI/jxYgegFT acamfOvCcNrVYx8ld74zx65NkhuSh+0l3xQ3YnZpXFrpaLPjOFtlLorl2bycfBVTQWQaeNSkCeFv +IR1R6MugliUEHRr6VNJdfJd0oeFugBlMefvjbZs80IWpnk3jEROJQWN/pBNILtjXroRjoqUFV3A hFYPD5IGiGnVcwi8EV60e+jlPxFM/Sy2HgHSkCOVhXoiZ83sINni9miAeVyhW6O2Y1eEb4+t4JHP QOKO/FPKemOH4NQrn6U6YZG7VhiGWWKwdFlRHPOQFwV6CJJcM0AaLTpjnIaOeaq3U/FfYerwu+32 j7vd/lj9KPnO97/QVUMSxVflvnZPEsMhDgBlTH1IyKi0W+QVtJOCi0ruYmsk+Usjt5KbhJQz3UVu JRUtyooqW9QAeuzzlHxhTduyIXJxg2Rfuc3MSrWJJJ1k3tOfO62aLauDfIfbkPFF3BfrZ5fe6L2f nS133Hsoucve/3CK5FYVVmwX+/0+/oFN9LFrzAJunyIDMnDpiAoFzXFh5//ARbIXwMhIWC5P5leh +sQNv9VuNAddnLjl28zkdjCRgxZiFnIR5Guby/2FL04dZbAeF+ud1O1S9F8vSAZwqALu47bvMEEs t8vsyPQZyrYpo+l7sALwMg+KUUpomT8baHO2jdFUNqw0gSDs2VK3/cAUUgcRs15GVexIEqIH0yDp 8iF2zq8rQPKqdTtW2LNqu1Fhz+7VA7g18d4kyhKBfWwZo5fKNdWVEnV0skAK0IcrYUefVLrzUIbG r9m/FV1b6LdysLYLrG76FCbqaypgwZoAKtmTY+cpAqOEk5NrypJ1MsnmGmVz2ah4l+DRiHcdfBCV 87afdXPOpZzjJUzvA1/f40M7Ar4HVbHAa7Fr15Ij+9KOIPCd9pEmtz2M1aqgoQFaEeb3Pv4/oMAe f/sseZg8NbFpMLrxxzfIiWfURmq6V1SIHIaEFlHSyUpCFhU80gUBASxpQyJOWjCxJzE6MQMhN9Ht 2elPXVm7jIF83BmWMQZlPtgd3h0YFPdCC/38EOBSDmc+fN0Jpu3MCOLZ36clwrxtBrVZuxAYfWfd zAfCHgeLRXfTGcacRpc5IkgQk4f8e5d6ZENK9DcuJzOMMky4C8MIbJLJjBPhYPP9JHm9PTtD3q9a Av6LtIexBpCVFIxiuYFI9CIhhvAjOgrAZb2/z7+HcFRmy7wbO6xObFgJyLmozzJJBhfN0STfQr8t k1FOAc9TFfH9Ge62apTBViCRwgJRRofNKT5nm1O7QBsk7qlsSvqkYQPqsuVrmIIXqJx4GiCOlUjV yFqBs96c9jW3lfcpEonAyzU5C/rnGcpHjjQnyYt7vV33sKPcA94EjyDxFFlX9yJbUyKULFXqgXtr uhSve7mTDfFa790PvO8pD4akDjSDxFWtmThSVfr1aj7bZOk7O9MGlTs+OEHpdDdJvvhCGd2qSztv IAawGZabUxOCZ8rrDYvfB6YdjxjwRfiUiP16Y0v/UpdrG6hDkjqs7zUzn9eb48NfSR4J5WwHL4Wk QmruZyYu2u+E2HXwE6Jn/+4PwuOmKjxualKrkWe6iUIyzUIfm19a8YAjnz8zn8+zSOKolAJ9pmL8 QzRgF7pJ7mNrOKxfCuqTb4R1szx8mU3F1QLrARI98MpMubkzXReTnXxul5jh96BtVP9OMewqfDxw P1m44dGDzx58DuA1r4oNNsBACDvXJezj1rtW8zKlBK5ldgAaVbWqVeImLgGXWC8ZY0KMXvIo/oUH b3eF2VmOsUWY9wnN4XN3LOl5OZ9X6TF+Jyg4d3pNz7YXrAY/p1WAbx/+57f/oxWlZ1EtL8qbFXru fvibt/9Pwgl0rbcUbATDmVRjyuHgJCHpJ04m3QpOBQZfI2mriY6jQu2MMP6M5DmyUxVik8X6DADY dJutyw9blH1pt9E3JH0QvPz+vVX2/ftEmsCoG5czzJgGV7JQJpzJSYdj2VR4MmdTFcamxshtPCMK zYZOHjoQ1WDQsc6z7hDDivtp+4Q1wksF5mfdRH7dSTn3695eCTpEQ7tsUVCALqfTxm6oxl27gZln zowA8aEWV8jlpr6Cajt0dlNTxHPpIMMf8ZLjcwxoxt8lKMicd1GiaZqMPtvlhFIdUlhcFlgRHCnB PkladShXDIk4nS1n9Xk56VPomvfvZeDv33N4xgJxNzamg9dQ7AATwhAhxtWzSSohSTEkOaQkW0+5 eYirxWJmZcNK41hWCdyccFO5GXwWtASYZcc6HIoCoam5yVa5fB/XwaFT+H1HRBSYneOyHPHBxIXN +JEiXevNU5eskxE7Tl051a2DTsi829c5+6xyLZTYgkODJsVpXc23JtgoVtPxp7FFIsoarcycUWmy jUTtYoDFK4443pTk7TvH2I/8uSXfG5wuqDyShRyNMq7BWTzVv6gkqsaoI/LFgtF4cLLA1qL5wzAW c5qqPgesR5IwR82iow8yskf6IQN2BiNxUtMSt255gy79COsbofdaDfestfJsQ2XyIosVcF4zvQrz 6SWHgYv5RlmJuKqv0ABK7ti1gsFW3QFvH17+WB5Tpx3GFcqil6WBrKpVFree5W12krVypJWW5uzI E3ZIET5a8dHc0sOOWv2PAwuJinRvrbCR0aEK62NGlcesKUkBTcGEjFN2takV4O4QFqP7xZIqfAkk BT+RoSA+ZFrkbeFBkz7uJQ8e7WuJYIEWx2i3V6EpFq3pQ7wNMXXYQ7l3VPD4vpMn1YnU58foG0lb rgGn/oQ9xD6NrwKDR6lTXJZqNH5YC0VisAzbPllyxQ55hbyb1gkRm7wuN9Y2sra7WurWFuWiWs/+ qCJ+VoAWqIzJr2OirAmSdmEvVLcr0Up5PatVCC/8DwOcjavlZbmclagPvjERxsdIjKkEmKi2fP+e Bwh0HUUE1o2oO1Uz6hzevUgm1QafrVuiZ+KuUZguxG26HcrIFjF6AXL2qc004X8OpakJv25FuUxg ZwGpcXrz5HqQdB92cyEcaLyEaRGMN0RacA0hV5WmmT9VNbxWAcN0Ax5FIjvoUiJCVhBcSpRlStxg 4Rx3phK7oJhjwEHM5EwZEJNMNppIZAddcFjmRVlQDkPeBYKGvG9DW2dn/CP7pAJ62kPVFhlLC3U0 hzJSkGxTHE0aXYu+QBGd2srI0WKiJYahu34tKc/AxsQEQ5cGyng7KrApDbnrGyfjGgyTwB6Ih6hp lpCIU6NS9JtZWjjb0Kx1ibnT5tV20/pwGxw8kGs3bEsMM2TdxovE6Tq3xrinAnkSngcujoJ7Y9Bx Dn2J1hlj5uMeUhl+bgs/xl15IKHXQggUZYmjsxOF6+GgfysTjLeM3HJu12sGMoPrFUsY4vpdkPyT koIhm1V+/x6rIppBPtxgUwpq6KBz3Y6P1jcNaH2F6USrbT2/CTA8R8bUfc9qOwfHcmJj9VjCY4VY dkPvGrsbAajC8s3Y3RmrjVZnNSPpij1CcPuthKlRTq5jU3wary5mNTb5sWhxypTzz4H9FMg5Z7ER 7bm4y617d+S3Oyb8AQhPVktZ7jnzDNa1kSiPorbbOJXdkMVuvlGt6Nqjw6N76lCUJBFS6QrGLjoK KUctF7uR1CH6cMNJYULRAXCHELbnbfUFjyGateYB34+VUwJ14WDJ+Phvx40uRsR59ZNXtLVaiuOG xo0gtx8LYVDUyVtQhcIEwv/DgO8KsmpeuwPrD9g0AT6zeQ7QoWjQJBgM5IpeolIFfCKBpUBrl8V6 RuGobQB8/54aev++L9sjDVr0N90zwOYB2t1g7imKsE2BfrdrjMUc74TBTuN3uLqkZSHVpdukmKDa TKVA5W96DKbbvr2xirRDZZ8nvOUkFdQP9qlSl1rC6CiRyH8f6LoPrBrHbj5P9sYSLGBKtVAl/tbd 9aRxRGS9xuGhsxI6GSHHT3b0ott921lklywlTQ9WTS2JewMR6HvybUnqglIzd+m+la0D8IGPCrpR Gyi/MSgssopyVWJ4LXaw8pFGKFaIOi7GpA+qu+PBiZOZwkt9iIBLU7AmyuL5xukdkZzFOXeYfgnp BJUF50ZlczIkI/Wr2/mWBDYc4luLCsjRdXXDQ6SYYyr2dRNSNfKYlnVhcY1m8DPniCp6gmUMXZp6 1yMoaDy8KG2YF3oIFBu4nCi698VPuI7fwXtNgBvpFeeSp1wHGE59uyhrB+ixOeSdxhd98iwnwxhM tFCXUB6Q2mxRKk6tnE5RjLZdzksrGjXKaiaoNsPkip5mUOtZqBschVl8W4yxpoMm6R6Ae4DOVAY3 Gvp7mnUOPAqcojHlBJ+ZEUiaIzdfwmRLULApi/X+pLpaRjp+UW0kdz0BF6JUR3GYTGfXmy2PDVP2 JcV4XQHvaVLp4pmel57aaLa8lCPYJ/TkNKmaOq0AZE9vjO7gPGiG4+BzdP5SyYK4DI+r7jlLgNNV C8WojlYd109FsJeEmIuCMrsZiRcORnVcx88HxbfzFJraRlaRswEdYgtsomyLzQb7ze/i9BzoSxu4 ckBcYdApQ8I2TwsRe+u0olOKqh0sQki6PQ5TaluS/Hh8e4NHABT3yOBNCetId4gWcXWFGU7OAYVL zoR6hlkUyIZql0X1Bqip7ShZGCxt01WDMBBBq+ZqMcH6TcVbryYjGI+h8XifGrnqsnkjqufsRf/+ 7f9g2UVsl7MNPnz4X97+n3/DRhGTWT3GlBA3dGJV0nrUMGwm+/PZ6RoZpa6q2IXXN4I55KLmbESj 6RaPNrD/Sv0mSk7haztNuZHQsqLj6mJNoiT0ZaIsuOtiWU9LwoyU2XJdu1mQJC2W6YSKj6Jl6wvJ B6byykOhpwgn6DfRcWw40MVijqHuoaWLkmgleVGttXTs9J90Gi+8cNRScVZCSarM1C/sK+rc3Mw8 6LH3BsofFXX5VSQLl5KP6Gj7hDLsLOhmd076qqU8FhrEttXShpS+vkqmcoNWpXAe4WSmmNKEZg2D tbXv30G/qkNhozgdzFCvkon/4hSWrTiiDB4DsVYXc5daJEg4Ct5AggG5PNAxFNgPtH3jF17+qMAX mHLEwhDWcmdW2zVcKLP5ZE1pLp2UzGoEja3ZHOB25dMzGKNeUIGdfWQ21QIPKEG+umrHRgiM5LRr 2217CkSMpIowW05sCex2Zcm9uV14+92K1jRlLb0XvQHrNOMzmpHtlVeskQAJesEPT+BDY0e6Zktf 6BlqG3ioOrkXo9eGGhWrV43UkOoMbf520KnXx1FOOzb2vAJCYr3DtlE0bHvy3dGItm3U7SUeu+id IIs1JatqTD6tALg4U6m2p4WkyxRGQ43WMzCa04DxXOjRZ7lnk6mmAOPlQ6gOGXuH5c7cKOUL5Ucl gncoQYNsIkOx6tw3Nqv2Ab3dJH+HQX7qv2sLXlQRn8KhLuCouQYI1wBbswXZzQFUXfsBulyUnkn9 XkL7wkuQR7I6qEGrtOkungpDvwYrQ8LswBfFKeUBwXYpnq/hOqTwEUcUHBsl/5K6jSeHeJ+NcLZy AZAUq7u5An66nPSBiyzm+qbvxjqSzrYbxTAi06m6/nQIH/Q90pcBx2m5hiW2Zumss74LghoCquq3 coUz9v+BGUGIfZn4wXbGmBFQjgMPAFc/i8Qv5zouHLrtRMOee2Gw7dIpjW3ESrw0FihcF+7bRTM9 lMZuEP2IdVw32rAyncM893PFbDlJNQXL+kvXNh9VZ7cpeaXtWZndQ1t6BAGlGpTKVssrHTiRzFfg qhBQkCrr4sp1KOG7fru8WherZAUM8nIDx8CSoREcZZglXQ5KQgdFX/2UeNFKraU7sCDDvMRL3PxK nQG15c5od2eJNSLkmlZ07eBi3sjEkXZYuzDpRBQyhOx+rH+nviUy6754+ebpIHm2tDLU6tkkr0ox wJDIFs0asy4wIKt5cYPIViXEG7xbvlt242NwrLu64uORY3pUmplv0OstY2ZVN4vfQ5b1tALIJaeI 9Xa1uVOkliaf+2C8T1+9evlqAKQwJ11pWLyWxVo76wrrxLYHFmC2L4Xh0N3p7h5ZIImu4CC2Jq2w HuTtE2sFwImizM/SkTlfxye5CX0tIKrxA6AHVgu5+KQBTXB/FkrxwV6atF3Tf1ijdquvgZIPmyyL urKDvgZH2OJdMyndiW8MFmnaGB4levhiKdgbh/dVKR1wiHR95y2VjSN8YIQZrIXrAuRt3PWKMpze vtpqmYbd7g4rdU0nDgX7slxN63XdBsl3msp3y1Im83o7Hpc6MZ6/z+4EuIutrltzXbK3xdIu9EQb brw46021ustFKzRgO2WV8c4PvfRHoxXULvX1Il2GJ8Uj9frt9ULX25j3JcbKwPzhbiBkZcCIlPQ1 O1b2p5IfqJZs7JoTT92gerrp6A3et0djRFqd38nkzqvqAvjNeQbQSaluhZ+zREuy1CRYYke4DOVL PRKJR71k+bNPOnuJKlHdrdCmO3TSYhis7JQkI/GDHUIioxiYGorEU9zRjpshbi9OhkWWEB+QqluV 6+ZVXK0rzAA/p0W6y+qRXO6dGmQaZ6JSkqwbhstMymfFjnULLJHsi3NjaqTMguiUSXZC7Ja87Ku3 VjrKcnyhjx4KU+ccu2lEQxwx6DjiAIoVeD2Gs6/RKWIsNq9m3w38jQ779s9T/uHBzAp5iH8s1rVv 0aDjeUjLLcFkmTexCeqG3O/Nkn3pCcfc3JEAIZcaclJLPb58l3Flqrq1ZGp5djgd3tb6i2/WXbUZ N5eyV916jlJyDXzBR40mt8A6gEhGuwRUHYf9v6WSN4pIxABuxQq4sgu4oz/cEIhCfdQnDkhYgjiS Av6xWpV9ssCcFmPteEXCiGe6D1PcRQMzRlFS6dkrGYNJDWCayHwE0zPlhbiEcSpK9jDvfPhf3/67 Tz75BGjkEeVWr2vkyy7KCcq3Pvxvb+d/9cknHaXP/Jq+YNPGJbRIrgoyNMDQEYWtzcVfVCGRljvK 8ueMHChI8yAiZoEIDpxDZTiCSgI/V1sKu3ZVzucSgibBIFhwh1LB8hraAX5kW2/rfsd2nF3dGBda W90jjwuA6fNi3tGhBuAuPt1Op5g4fTSrsumkl6gYWCoXLJowwNIRXae/AXt51dXu+tMJirCmHD6r sr2/q7o/2a4eZeYbdCAaNImEtt1UX8+3teXFh2PjMDJioVdsCg8NTiXODH3yvkyxNQ85hxm6I/ab XrLsqS1DlW96tJnRshgQ4eaevn325vWbx2++ez16+vbo6bdvnr18AYv4WacTdw7qIQRR0O1aLoeL K+sHBXqYl8CkDw8iyIv0KqNqSeGsN1JHv0RI8a8RdDpFlU8UqYsyyFXR8njiFeSbTkGv0TxMCl3R t55sXko7Kh/6oBviB/cjUBKryWxN8R3Uk2Ow019cTPCTz+S+evrmHx8/N/X65bJGnieFDTUhnnTx 12+evPzuTaQ4H9NI8aevXsWLw1FOLTPi1UyMgRBBuKZA8GlAIUeXIrt1sIfTIbcC/7rmQFKbtv22 ykG8fNFgY93MAFvPgywPqGwuhKvKsdq5AVuIyDlSltUV2iI45jwGvXLwHiLtrVJWI4tiRRYsz16y 1nFBjZ4T4u94kaoqpiLVQ4gJD3s2QOSdMNIV1+eHsP6jng0huX1LAthNlaicwbNPCLZ7dWoJ4AwW gbIHzbz3bGqteUiRAMDhZ2tjdyCqZlNv79qVIyEaiiiHeeJq3rCp2X2NDzCSuYUDmiorpC+3GNws i1Wd8bc8b50FQtwdJoHFs3ynIJ+7C91MrD8rUBoF6xGOEO8olDaO1wVeMJEpOUBBKxa7bIxOEXW9 cz+qPEfqG8+r2s/jLCOLfVI74H9D8xh6dRh598h5x6tqBmyhkKtituHwCYJG8AUwn1ALnwBx2dKM 2YSMMTBfFBFBsBZcPlNorpccuHp4q3RwfKCT7599/frZH148fv70SWaXzWP7rWgvRuffv3n66huo 7NZLHiSHj36zA5cVNGfWx22xxf7TaePAsjhEipFZP7NWf5scXP966itXrSbIZhwNNKj6oNN8iG3k la5P0x0wCzcwQrKNpG34q48WaX5G8RjkmgZaQBQDXAh+QDW6wg8jl1IMF1HXdt2r9VVhLgN/vOY6 MAg/KCPKwkV1WXpkilCWr0i6k5mN6MkO9GRoilXoSYf2DWw1HKoZbQKqz+F+YgpFVYLbslWYo9Gk nIee7KppJCts1Ip3cbWc3wCBXxbLBA1glgmGlGqmTNyVUYS1LAmbYueDJur5Dks28MPGWgfH/PCM SfQxogc/NK1ADT+4H20iw+vYIh86H/7D2/9G+FGJc/Thf3978zeffGKb6+nTtMY4WWgWPNSPHRFM oJGIJZjgCLJcBJbqwxb95V1T8PBzsv+lqoTySgpsnKCxooQ9VPbBqoIhcF9J8IagepMNvVF/c1Nk paVGNBqlce5Mle7bZbO8yV3PafyMrVAjbfuejUCGbMm7A7l8tUh5osPJ6GF0g4OsR6XmbxbXTm0Y FtNw7nGuDrBDW7HDC68JAX2IJZDBs8eGNRjHBFsIuoAxhAfcWfX51K20LK83sQozhQh1v0HSsOTL 5CBCdCb7w+QwfM2xMNQsj2cnTZkpzDRnsWuDgkxCY5GNf72pVs82Kqu3tzawZmeb89E5Bh+9bYms SZsTi1FxhvhvyzmFrxkBgpvbEo3CrinakXwLiJfrQdNcHR2hm6fODG2OuAv+bRvafP5xQyMdUOPw XOs3e8xmeDXb8Q7loWGQgjRH4wWqV/HfPc1DoocyvilqnYENjralraOG9fx6WFgJYcobeZKjOjyw pg8NS4cOvcCZ3po5DeRJFqtmeTq57XDTaJx302QTwctlzTy7Pj44gQrw726+EHfpp619BKBjzPyW lSyQzeFGlidO180/bFA5aaHDzAq1WOPpxYd/g9Ggk5uBWHtrVL3Gxud9BIhMyrWRi1LSDXTBcOIX lNdu2VYokWU/VkuHy5iNrHVFG9Eg5vLcPjnotj1dV38slxz8yH3RcJJIEA+fayV492p19tiVRAI4 d8olXJJrjIkM5JN6tkbx+6IujY3N0P3dMAa/jilv2tUpF54iWz90fze0q5KBWSUz3bbnIEeOcJYd G+wT7qE4g/bYpwzJIDRwrxLUJ+O7VVXXZFdkiaWIy09QLpBYhkfk6Hv0LXtQPOr/MoHml2z5i8mT 5Ytx9gX4IXcrm4IipW6wGn0Mfol6UdIEpXoSddrpjICSLNFYOAuMkXrJa2ISsYle8g2Gc2KHop7b fG7tAsrnyPF1qB9brhFVJHPtlwV2FblGFrvd0QhLU5y7DnPvfVkCUl8mX8IUPkMeX8VHLsdJxtG6 cdYcS/3v6P1oiP8qVQVDtaBNMcLYS9CoOEFrgitYEr1NM4xLKkE/eaGt6BjseW04kk2FIYZ5+EDq VRP05BVNL65DHRHCW5pyqneK+vWIupfqN18ZbEkL//YnJcJZpvrf5R5orKzGbePAMG4I+8U4wbBN qzXvZ0AgU2A3vXKzmuYdiwnsxtzm5bEr0pLfWg+H17GDUauNowbhN/21lTPIJiyQnMumocWHryTS 0mngL7AOeZaw/bfTIhZEe7s7tWmygkXbpB27Y3tYJ9YeHhPU0WVTKIcGO0r/NK/GMeilInGoFCOd xoDZFI6Eqg8TNiVSFkLuzQkdmxKk5amDSBFkBOSAKFWLjksapK4NHbtSCk6ceHfdbTEm1oHmpytf wBMVWEExX1BFaYQQxeBS65wS2DPhqR4qqzeA5eBumfkuKSZjEE2Btwa20BxtFR9ZCRLgEgDKV+M7 QmKMqtAGZjlDYIigNiu8snVu7PLq7KizpKCH5Cj82HhH3P3o1yp+5Z0Ovow3/+Ene7ago/2XP9hN 6dPbTnpghNlmLdbcHj5Sk+GI+eLN7itVjmhxXJpqAWzxouADywYKaFH22YXc1jpngx8JaEXJxVIb 9aTwluzDuCNfHLLSOmSysaPS1iIsJ5KswGkSXjc2yVXsJrG0ffYJwFP8azVCknS7Fn2n2FhGCxmq 2aP6eFh0Mbw/xmv1Ojf8N9fyuLJISorLYj6b2FwwCbh0XgZX8VZsRPHn2RrrXqPp4CkapNQMaQ2c vtJ6lStf3m++0fy8bNRmOJ7XnKkHe+JdZyOmT+RuMdeZ+rErhBJ92QCgu8RikwHEL6Vb00uo27Ig l0nPpNbfAZ5dM7Eo30073rWqbtDGRnQD/gBwkR45C67WejciXvQYBLjs+EkC/M2ptUu3LraEdlbc BLWQWrVQ8usFC4eu+siOmUKZ6ti6WIXFgI2/bZytY9Rd6lodBawNa7dDozQ2JLnhWHrV0TZM8qpB CzdMHmT30aypNgkRdJaU81LsK8QgHnOX3hh/eokqq+FfJavA1jq+Dyu9bbm5rFDnXmSxWyKa32rS GtXtkYTWMho20TT0Zt7XBvAfEieEA3Dam/J0tvzw6dv/+7/lEA719nQx47xPGPUF4yWgI6c4HpPn G3p64fOmwuBC0gSUWF/OxrKI0RgMlrke6sOIlHIiJBSTScXeY+TPrJivs3VF/un8Em3t6U3W5Ri/ gNjYktMER6Tvfau9dH9fDTTFoM6b4rJYD7sLuvXNISOSYJiSYSqUm6DzdFdVRBKWnYk84+bxeQUT r4fHKSfjwqzZQBKmJ6YIMtvDbo33LZf5Ewqoabcxfzh10V+Wm3A5EcpjngAYzDM0YR9Xy+nsDA21 +MmYtPLvPq+H3nhMiNKFoXRteCY6nkqv5tuz2VI5maMzOL3IUrXyyoQ29RJMY6YGd3PKdcKVEfuK 3xkFyiPP6KuSQldNqgRFT39nNbbh0E1LMXfiHGf0UlunIprYItVOZqr1HCO+LBU9z61QrS0F6+WV 2r+eALXdYzkuB7R2PTaaZZiyNiO1hkIkKZDuvykRxov1zdfICaVXDzzzgWo+YdkZenv0R5srvuY7 vhR7U5YjIRyitKffnlMsTNkeGbVFl9S5b+NgRkaTk7E45xW95pvgTd1U/B4vK7vn1DGSQxNiDS5Q YUP5pJHI5GA+iea6GmdSl+WF7XQi+GpenRlodmt4bG60jM/jksdKpKDjNQxAjGFBdACw2VKCVnnn 4Uc7cTgq2S/FfB2ntFuWp8ieCGzr7WIBsGl1zpsMfCBg1CGS468BTfHAHVz/LU44ec14yWK+1EJs 16ijGMO6QmvL8opXKDM7kYedUkq9roX0qOw+FDZpNa32VSZVvw8FM+bmp79HVA7N2qEotyNIwMK4 CtEyhT1QTQ2kvPrNX/m+hY84WQnIR+UmbkE1Arnu1jrXZUAsfuHQiibSyHo+n52q+vALBTk9fCA5 ZhlxfbDq9cV536sfLUq3qlVQ2jepfcgEWldN8Ws60NM1d1w6B0S8hk8puyt9lsYmjAn44NL5jAav iqZWK+X1ara+wWYOr+BQyyc2wWYQS883m1U9ePjQ7GKqEtesqiWFa5AZZ/CXzeyHemoZzyrPbRSw IKsTQCPFGjNrpefrcjrsPlwXVw+zd1cP8i665Uvz2jtgESZ7u1c/rM+rq4f3akwpxt0v+kyvHOYt OS7T02KiexhQ1nH1y8G5Cg+M5CBnPmJwMxIpSo/Ri8lC6NbpN1AHnwJ1wPRKN+oOs2G7dbcx1Ymi hggBril3pU02+0P4gVgIL3Joizrzm6au2UdTxpTvEPlgUZ8RUKz682p5huarffzH+ImS//xygxF3 MGMn/cbbADiUj/Fl5P4QkZtMmecAoYQj175cYXOFWZWc3e0LXtQgQku6zhp2uydBQmeVJ43lTV71 UZ7KNbPNlWdPiyO96qsGcG3JisozXBQ+ioxzci8AaPulEVAj9n1xr072979k8U4Gy9Zz7gjgcrra 7gxuEti+sw97b/+rvyYGp3Na1LMxcJFnZ0GuPhIPY6RJ5GvWwE+Ny/VDiRi6TurxeUkh8t++fZto ZzKmRR9/+2yQZIvi5hTuAwyFg1YBAK019oPxmW6+skyTmCp5Tp+yqHkCAv0Qxo/DZ9vMXkMkxdPt 2S4FxxVgCxVK2h5In3jMLiVJxGN3Va3nk65bRCpHSsWnRKOXZx3XaNjv9/OGkO47T8Obh8NqcmJF sbD8BigJIKFuNbEUqWHNXkq+GaX6ikJSeWz2+bEiiNHV2JTBSck7F8UKSe+eaSl3RM/ldHbd1Mbx vfokoYxT3YE05ww4d4xc601zQik2dOXO0LibfqsZGIvVb+U4uAuKAoNsgmhwDOd3kiMA6JNDacs5 MQ4yvjWw3bQnlD0HzgkdDePuQ9KEVJ22VOIU96SFDTJwJFAn84QFFhcTWM9cmf38YEPLzbiffIcH uryG2dQUDQbze3x78+3N/mH/0GQRpAcBGQxkIU8c8A/Y4+oqmRfIwo639aZazP7I9nTkJSYr/kjj CXIYux3e5GnBzugswkX2LR5JydRLKVecf4NZkEp5r3UFSYWc+xbbbaDNVjxmdA3+cU6RoRKOjJz3 8V51Hbfs7knQBFUoqISr4Es8De5h0HN0DsMt7pJIuIxSJefbIYuPK+PTwK+iuI7o/Ehv1rI/SDh4 XCQTjh1OXrUX2BqoD/bU2LZE6t+PqKqYBSzUSVQcDKz+uoLDVTC/Q2AMV7Ab+hgdhYexbaQg4LqW t/DWslILjVIV/Mq1Fep2mxIErXPc/QO//4aGMNgtOd1tZxUmQsqQNlQZtAHIcnWT5XY4OdNIj7Ur tw6kjx4Fa9+tIiy2XU2oaWrUGbizAwbPeACg8hDqbU4WSkyBgHA2Q2stjTo6HhE2Y9w9nUmih0VF EvUZZf02TQKKvSrmF2RrQ8otIrSA5XSbO2fTpB5noJP4/Wa7jcw+HGsRQ0QIWzr7cTaVYOBksgGD FowhSCpvDO89w6O/xriwGZKteh2BR+8l+4e7MA6t4HKs3hwPZicnnTtFvMZrGWjcckfAJIZHJpxq 4fVIfXfz3jTAT0+vvgdJaHxpgdGUMg3gS2sTXYXiHpx8YOQwRCshHrym6gazMdN9aIMVXHUSr0cb N7v3nmfnFblQNY5puVR1s6PgtoyZj1lgjEO8zSkDbWbvaZGznb2BqhOhp5t0YwvpHbAwq/Z0MwnG +9pKMbKfEe8SVQqWhyWJO2TNilLsmOROci4CzSdO/Mp2hiIxz8t9TF5Hk9TdeuJoC2GTVN3AcDvC 1KfthEWs9FLld3aPAzKSFlnLIeM5EZxZDEOB2neo+NJlLFtMqVBqrk/jWW0J3LG3B12KTNiJUk4w YOeOy0T4aZ/VxlMabbF/S1Xdvtxf1s3V2J5dtOPcofnADi8Rb8AU7nT2OnvJkQylhl8qBsVsXoZM B7KbGiYooBPnVCM7PwKnXBiI5tS1wChYQO0p2KcG8A0CkzLWOZ8yt0GmL/bxweoof/TDKoxEWTRt JNsMFN5CtOEShKnFPLUOtgakZteJgBkEaMVKMGAKLxIPyUrNqvAjiiXE7HLtO8Mx0mEdWJtD46qZ 06N0NW17IwFZegnHt+EAlBGpACa/uCknI5YhSbGEIxag2MGPhS5R+KhRZN3pIbKKkqHbCQ7jFdOd oGWhevb99dzxxRYXF4gA1+ZT9EuPFkWVtabDZRa4tmmRIhCmV8b6ywS4cSZFAa7Lnw8wA79FDj6M HcYjD1vr8VHATT7e7gbdDtM4Y5Y8eReBC8wGhK14Gx6ixyAEjYg+YTfqu3WCXrU73yZ8Ol/foOzx 9h7I5ZXKJpOiXGDEWCUQiZxKuNqqNUpK2TvM5Zv1x6i4wKpK6//85R9Gz158/dLdY6uUevzxIRLI IljBPk9b/mRO95zFCzuABUXadoRfkDXoPv3m6as/JI+fP331Jjl69exNgnFyvn/86sWzF39IXrx8 8+zoaYLzSp48/f13f+gqOlTMnaiZYdLF2XcBeOlFmKhDiQJ4F3tcrKetV50JyFelXGpXNpBvzYdf vP0rFScM4wzVl8ur8Yd7b7/6v1hEDr/3j1jQKiJxHZSsUDm5i+T19lQUe8n3nKzsCDhhQuzEOb6+ XH5/JM0QthfXIvaYJyiFcnaMr6omGW6PEm6hvo1IRcBwxToMA1ZvT5XXPakz1Wx0PDboGX2r9vY/ /j8kSQpmOVH+V29IeV/PKB8bphmj2VOuG3i/j90D6ZJksE8b4akXlI4PJYg6B6JK8TZzFrXOiQRC 5QK5XS02+3UxLX/Y+AUZjGESchxR0kPMto5rJTZn8ksUWuYFVhA5iQpesKqeLjW4RrAEaT1heXgj gVRarPwLmPU+8K8fdeCS3f+9IFmqGeT51POuEm6Mc12hOcHf3asTURqpMfR0tz2vp9ye7pFZP/ai K+k1LWvCxhq1Tn5UTmwoYZhQwfJg+2drDTk15+UEanI2QbSFneN9QkCCbVM9ymJGbnSWNaMGPola sK6qTd8xPVCNDZNHB+gKRqnsaklHx0L1qxL5drK+oUuhTDCUOKPMgoCdO+nsJl6jWXOINaMLIbnW rqVX200zCEVcdRBcopeNlzsFVd4ahKIVfAgjQMgsBRcZilGK39nSmkDARBNgD7koQlgkMA59ioN0 vGx4KjRLwj4GXRS84Hi6Pa4SFDwF6vOiLdIOTW1oDncWO8SxGAywCDqYOlZ0C6kBcgk5GnqUtgDT bLy1xwiO7oZ8xH70SQhZI/7N9L7k0eBg2N8XwQ49MLgBTlTcoVxNlCGPM4ItygnJ1J9u1subxq2x UJUeXc/sfOf2svuHPs5TrzsaEzFO18iMVHuAFS6XOmkFm/08fv785fdPn4yO/v7xK4zF1R0l+w/f vRv+ov8vD+51gQeeTEzi3hqdsJYlXsKY2Y1tM0s0h1KG8Su4N9F+gwxNr2bLzx6JJYnbz4Mh6m7c zkd///I1Biz0Sibp7wapWH6j/OByKVRIBn9NFFeHnFKBScv18cGJTSY9A5i89kikS4nAKBFUx4sJ GphmXVyr/Q/J/r70ZzEdl2QJYcc+wkbSfsraqEshAuFFfjx4ZHm0QFPq8FwGKp5LmWVZj4tVOWKH 3QxdxNQctdsnv1WWN4Y8NOv/KYyH1j+1bXDc+niE5sW4zNJfoA3zu3e/SJ0YoVhIxsSxdaHl0WkB vC0ARE1t9FhdWsq7obN5KvAqHN0xHduNMx0l0ezP6mK+3C78YE6B+BsLk9Gv3eUtdfwYIm78EB02 GGbFkzKoAui689VFTuzlhy3bUq7h2j5VV3Z5DYcC7rA1HDkgXc+2s0mVXPW/UmTUpkL0NmO6R0Ci O3j4EDDDodk7LMeGV8ggm9mcV2ivDPUl5SM8KbB6mOoWeKAcpArnQYuNpmU0G2WLuqyW+yrKORr5 bRw5fBbdXe4/PKG5iXjO5sjrOHTIyL0m8qho/B/Rlkhk42rwOHZKUCJWdTlhsNEP+09zy5dLZFEw REPGjENf/ba4dPzpUe20vlLbJ+iN+kOc/R6mrjMkzKNN1QjHQyf/ZHoZafFyvbnJpHZPBOr8bxcL ET2ILAfwcMTcdW83BXE0g6J7cJPDJNlsOZ5vJ/zlch9O52m5djXEsaFbPZ8X9XkjjY4fM7umNehl eaVU2q55BIk1SKqGLH814azYiidVC0GLkDxOUhh3qr0DXTJhOZmNLUthRff2A4XltEJUg6sQuBvy CG4oazpmn6ZjSmdrMOh4lzgasMLBxyOFxlUP8ZZ+iBUeklAK0axb4U8NDN6fLDnobI3SvcZ0P/5/ f1ItIId/15rcL6C68s61dQv2LG040pEbME35iIwClfWEMqbI7cJCHl9cscITt9mwdW7JYkuoUxXF n6osPlsm9byYPb04PWeyGJpPx07Es3h6g2nZPQ1YV7WiqzltQBOu3DJVn8TVNqBlU7u+FCKhLzQV rRPHqMpjVjLJc5puwa0XV23uZqtTXj07r5IzJneZ/Dizm7A2jpxWMw+TQWy0HhOebSIe6ahYwNEN E11AI/on6OLq2Kwu6gJhJlyqY4o4A5O9Q705P+VNJdELu6fCuK3cWEhOt0EoEYXskMy+l6l+6nvk RQx/9DrWvDUtO9Pcmlc1GqrEQLAYrcCjh2hRSiAAg0kAcC+U7IExbJICKkyRu1Z3iDNAkn6R9Sbe hgXGU5pYOLJPQhVuFrPrKkMOD08zjQXEDfYL6Ldc67CNNjB7lis31TZZFDdS5sbD5Iyj3Rp3RNA/ Onr+WOT8Q1FzK2Jel14Afd6uoXPlC00aHgfbhRY3QhGvPf8si+IN/wRslWLTqQgcdnVKY0Y4Wiyh xsLMGA36eLB/eJL7cYTslvWxbW2aG8O2dghJpJpkV1auFwkWOdQF+2s0tSJ0FxNWzHCg+4cNqQIj 15X5naYh+oyO+bam0IrJ3JLHs8FJVKyiVtW5LJoi85nVbbxLwv3Ci+TWBoN7pn3ifHXqkF9Z90m1 TDcsJMUdlDvTHZ4OlmrnHB2VH7R0vMLwanHqe4OZypEJRLzIaoXLpFCqnDopi/E5W8HFKG925ET6 GleEglRRV9iSP7/MiNuHPCL6gRE8Yh9ce/Jl2TgZGYpSwepGTHVtnxs3UdV8CBLixFVlWnFS42Yr 4jwXITa6B1cLZLndSepwvjAKaocxPtw6pzd0V9UprzPVXiIJ328K6EtWWUFckGgEWfEIYMu0Y/gl OEwjRDaVW5+pWCMneYBPHU4IOF0gVZzEIbA0ctHHbIxdTJcHKg6X0lUbxk3a/gfVykhlPSNpL7SC uAuoJWcrUsWrukaAnN5LDVx1Ej1BVNQdEAXAjDCvpNBCj3rVKQdpcLtWo7Q7pwaDnqWkZR85+2MZ 6/eVWQMsohaAbCm8RSG1aCO/zIEe+tiI6XVBIu/2bklPw7yv0PFYyR7IrZ1SNzpi4HmBCiyUNSac ddlGYyyJFJgYLybhwfeElVhGAtDtmYwqi+IawNGe2Z4HVVBittgujJqLBQ44L2qhTjIbVXHEAf5i hBJ7ElXcxG2+NO8VOdJj/adSIowQIoCqGOE3XiBrhKZBGGBGR4ryW7AUYjLSDOeeGzbbXgGAd9Yl q7m1rYOldd7Xa4FDt0QbznRZThSIj/YYvcRwhhYjychN+T2djaZI0AWSrLodA3DUOu7j4NRlxepC 3QJgaDgJh94KatH8notNnXWluTngkudhpRX2WVGUe3euBqXSnKk12Fb8m3ntqGzOz15KXFBP8t+n 13lkyEapttekkNxzaQndR3dMJrFsIMZulrjWV2q3E2e3OZAVXTSN0MWCzCOUvJbrWkkx1e/cTUIG SxEL+H2rOTuto+CNC4QCIcLTeHLnPoXa7DeYs9sNq3N3Va0v6swP4+583HXcZsBSPZr3xhrli5dP X7zZMax3M+HoBPy2ZxGz5vv4RacoGj98Pl6iT1io+oeO8YcMKg4LdP1jmIJRsVqP6FZk5ax2dtdK 9LXPM8X4pFAkZk4jh0PgA6c66RgLgbXpCVkfFSUBiE+6d0VXjajXHiac93v/cf/eYv/e5M29vx/c +2Zw73XXVa1htcUFVTLt5Zb75eo5rMoTDMeIIT4srUSR4Fv0YSYVLNLE0xJYBOAXJLNFhvmaXl8u lU2XMl+Gu3Je/HE2v2mxw2US9KK8sUNrsUCDxLNO4WOMTkl3iRXFT6qeeNacFmb23PM4k4VxRLE6 VeSjdB4rbNPtLclkHUKUoFcRo04j1kzrsLNe4qWDdUlXPvXXFLFMG8T7ivGYYlbFhHh+NHr8/Pnw KEltWAHmvSOxnZdA/qGmb7u8INoIjYPRbLSaX5aGi0SiAMhRpRnBVx+2FVmozeoaIKTz7Pnzp394 /Fxr/dP7yZ+Sd8nDZJB8kXyZfJW82yTvlsm764NT/GecvFunSoCTwEnjZFM1x19wGuNJOa9UIh6u kXeevf7+2YsnL79/LZHPbJsBWZoOkFZnI9Lzjiaz+oKjdahos+v0PwGrtf/Hk3eDd+/yr47/0+Dk wS8oYEf/WW7rq+n6J/WS7MV8Xp5RlhtngMcixahXinSwaSmYqx6xpbjmptTc0kEa2CR7c+gTI5/V q9tUoCltJAowsRXkK4oZ+/DNUTM3yKUr0quLprReuTp1fE0+SksRzvbJXkV54ahqMovbBqTWTRuC kPfSktaK4p7gB/ThEdSNQQir0bTW69/D/POFBDAT01h/i9q3gOoTKNNXJLw+dbE8VU3v1b+TWCz1 qqfLqkAsqqFIrb9/+viJqueg6nrF04JTNULL0wCqeJ4y7mDi7I9ABfEQlmxtgvYaEpCH3rZAGst/ hg3gxH1ZYlc1GH4wJh7v3qGNx0MXTKkNHa7G89BVLaUP79Wypm75SOO9W4XPNF0Z9jG6XLpt5oOT vE0lpUdltxOLs9NSUCRuMSAykzaAxO9CYIr25oCS1HTAiSi5wcOHbuO5ZZnweBtztBE8oHwvUbNp h8ohuwRjod1yw2/rUpSdaByOSu0eW5+OsFE6osjmYtoRIDMuS/vQGnteaQQNU+TRv+65bToW/OgW MF1SSG31wy1kDQOzIZlfltSkuCiBc+NQRgExu1VuPfagDdx22e6pmzrhzeqriaEUeOytVdaUmMTN NLyNhBMoN0owne7vq8EMu0B8cvAoP0AAwSmOpq0dNULTDtfxGtJOMmap21pdVvtYZJ9Kp/GWrO1o b2q5bxVNA+oJKAoWYMLvneOYdL+Qk6Lhb3ivTvr9/pfG3lsBeo52kdej0znDgkNJvKvvZ+8mD3L6 +/pBnmT9+3jBmuPoODW0WAutQpMgoNHEYaygMLQPXcldRfaYV+xMAQd8NSstmfQz8qFSUrmkni1m c7i1xcdFBTIiGy+grDTx55breIF0TNq7S/TJmGEYaMeMnE2XmFRzdQBolkEBf6/G2JmEMCGc4Vlq sybAN+kYz934EJZbJbfYw3jCoZsyfzQSLCQToWAjT8nlXWX0WLCztEUUulNq1mDjiFoVrrTD1Wb+ i5lB7mbyJkNlhlQvjB/ORU/Azx6uBuuFLWIs6+DXQJthzAm02RkcmNNJkVwPSLt0bbrNPUs0MSLD T5rPvYy3dM1iAzichFuGBznrKpz2lDTMNWZrUarZ8gRrcYbahYoqAObWH+M5ECImerOpboT7TkdQ SlWPc5sqrrMRu0ccEll2SwJlfNwTs8JMvRFhs2PVFLok67Z6tvu/lQYjjy4S1uh8nKnh90eUftDZ m4/UFGj55FYSvvYSN6sSIdbZ+ALZFvbvpjhrtLu4lYgCm/QdeqspvzZn8DEqnstlZK8tUbzy2lLG nloK//3RPk7f1bO0bLgK4CPHVDpWm5zvHgWJ3Paye+ucUINjPZnsJT2zr7sHA1Mu4eZgW1WRskKU 0UBaqay5TIo2e+XYxgf29mC9vke92d3jd5iygSkOCeRfNlZINrr/SMVHimZkdC2ijNJX2CYiwQTz hqOCo6D+WYFtjdEbn6/gppSCKV61TO1DoRN/4MfchxwghCwWplG6UKUzNi32KbjZJHOjPs81vaWo QKdVB1Zsw3H0p5nOrlU8IJZcJaeAmjHfJEfpTjeMba/w2iJZpRWBTbzhLakXemirkHfzlhREUREz BkYZkhzsm6evXz/+w9PXoeHKeTWfMIlSLi9nayDGolI8sgnQZTAwCNoBpkdhg+w1F3EB8fEn5+lo yOeNURZgZHHLknAgWPYOpikY89lrpBPK3KOaLM/xK0g3cOxZJaGmkrI6lyjD71Miv9Aki0v1WfiO LMG02mIuGZ+hdqkeTy/AKCW0yrIb7z59dAD//XbQ/cFto6+DM25S3LMWRI08sdI8uyti18HgqsXk 5q51rw5/CVN5NNi1QpePnxi9T2ZruACr9Y1aifz2pXj69tnr2FJQucBIdGvbQFzNSFwZ8dKjeFD0 GbkMNv/47tXzfiQ+iULiKZcHqukY2jqxcChR3ZXtCGqS1caS26jyOqg1joGQj6LunWEoLOsy51Ar emNZ6nTbV9nV9CYUevgyZo2HENbujRUzzqL/POc2sulKD/ufxUyfcZjoQkeSpm57DtrGdluavTdB EsN3RoxjJ/taTffXaI2NZAUbkcUKEYHSACXjKpXAfwZAVAw8Ag8EipTka60yKgQUrmez1zd8qWqY 1X4fCQUTw4zx2HTuQhBQBwRBODkawIkvDWkUhGBVNe1uIAnpNi7DFi3MsbK1DCrfFBEbbGvEkV2G 6VUajYuhLJKIYuYTQqFSKT8qHJbIeTUkM3fndGTT62JacatdH4XVUniL7fJEAKHo63ZDKc/WzSLp ZQTct8ghLHs3izVZot8elA8oWCBmLAMx11xEy9+wSJ+QDtrYO6mzTRt9u5c8IJGbq9PnxYVrrRCw 5qSspw7sFW/MUMdF2cm/YApyH+kxZYHPt1aSnd7okGeFm4CLI2vBQYAZoDW9sqQvAj8oMgfh7aVD mPo+VEvtM4D4E7DhGIYhIYELCzZoV6MGmSu1Q0RT3ncpX9wjWd9QdKS+CPIrJ0F0KN1Hv5hMsjzG vqzCzHYSanGGCMHfUVWrASQ0zK0iANcKTCs5k107F4c3bD1kIx6/ULY/8XMqtMXfxg+sQA1Z5NLE fUvZVitZe8MCIA9vE8NspVQ4zdvNb3F6OP0ID49e69V2TYJIEbOGtAn1BCVTC1uIOlddNuPhYY9h dngYIDgsKScloXCYZt2Ahiv76II4TmEUqL2YeRnuzpYVGl4ix4qhmmYTCiRSzK+Km5rtwjPFhlVT l0ZZQtn5Dd5p5M5fLorlZjZusGYWgRGMpEcSBOTo8M6S4eOVBN94kPObblxl4B0i77JVwT43uOww CVnwrFjeLGCSXwF2/qdtrbp0sacju6SNVBr1vC3Ax3ReRMg62ihPXYgFLWUEFQmi9BEkcL9wou9T JZtExYi/DBKbAuOn+GcISQvCcCh0pxJ9L/5UNLoA1btXqxg1ypqfg1FJT7kDnKjOaBsJlzDWotaA kl1GRDAhq3SXkcH+XcTOIUeNxa9JBhznfItglmPGBQ5qI3mIHXJra0y2NUGELaR54B4kQBoE6dhL AE0vJaRqyRaYzBnpNPK3iOS3S/T6WHJlsqK4XPI8RJFiSz+3y6b5b5e8AspudX5DS0IN3TppbjY+ bYw5Z3tIQoVBmv8Yq/BUfcugj+PPBw6vNi+L5XYVl5oyOlze0OxqZs8ad5kDX5lAsdPZNVInJISe 33z66actuauJO+Ml95Mt+rRZbVmzY+TRba3YTGIO6uEBY/kD8nNCdeG8dmg0i5QFYng+L4lyz5PX 1JiSSWvZcGiAv6d8C2GHTqsKs8hM9k9hGcnPkN6cbxbzPfTfH5/vf7ZfQ4P7n/c/6x9abdj/PXp0 cMgPh799pF7+03ZBAT7qjbvEHdfDlmd4mz4Kt0auCdgOYmBl8fKk264F61J+Pu6HuK06uSltv+fw 2t877D9SQWnqgRklSuv29/mi3NdvfRtYq3Dq8utjny4ZO2ViyTXH3KdzKaYdD2gnVcmhl5GzpOQx 8zlGp1OmF/LX3Pd7gqYi678XTCI2Y0d0wYDriS34JdXftk3RKmg1GxwxuBOwCG96sn8JV8L1Yp6Q WQAPjy8HEWvHI0FLXz2mPfR0vOSIEcRHqqGPEm5Gxv3zj5hAqao2Moph8v3Ra4N68j4iRpYsI4Zl tU1rzle7rbffPL9Tc8prQLdh8/DTqSVViYjatG8eFvX5djY4OCtQEWm8F1AulglT6buEq+ic6MKE nTUQrDGBnUjf4qkkbOFSd3+daOlV3n6/4qy0uKlNFEqGI61BVFQ6Aw5yz0sFLADsZsm5yZ0BZ2q5 ekRNYNKuXoKpruJpCuzB08BpPI4dTY08vLNoVAbbxMUkagGtd+mFwy9S2gQq5CkolRCU0+b5FUlD 1QMeRXUjEyCf/SUGnkWZXXDK/gh0jBlZz/TvxwXi/HxisyOmjrpiHotkv9glFAYsBKbrwkbQhLUi PTCvlcHr4nB7u7lHt7xewW0NhAvb4ZFelhcj99mXS5XhBTNeS4bAOmBycB8VKGez5YbEqKomTT3m eAyVOioD9PWIQcq3c+rfP6L3m9I4biVs+dQX2+knL988fv48t9gerGCC7w7TVHjigP+hHklKoKLL kb+dfY9KqTpCBs6Ssy1g9oS0lcTXarpwgnLZ03KDNseYKvirT7/qeNheet9fJKj7VNwL5hRlk9X6 LGa81wu4iIBiwPYfQAfJ/ou0szP6Dy5TSiKLpi5kGEDq3kB3F88BQvSrS/SHp4SHYjZeDguUjYpP EKjsBJWOv23tOACLt0NcboRsjON9i+idnSyqZcxdkfrxzZVQKoSJlLOW9UPx34RFSSl14MmFlFzM c83wuHuZXqqmhrIAdKlilnaVa+V+q6J3YqQTu3tOnwVL1bxCHHPDG/eZHnfs9FNsC3TlRS4Rlq+Y USKcZXmFCMMdJ8Bi8zgl+fIPGiq08SMNVft+C4fWdPUuJBlENfW8wSkLkHrDnlH9zjPiDJCWYDtn ElBbdI52rFLNAmHPcZ5JrLWleAz0BRrzZKERliOyQkQq7L+KCzfRImWkUSa5rOOY9DrUrYRiU3de X+rCx0AZ4tPzbtlQ5vhaSR+Mhxd9Oz4ceOmMZAqO6xqPm294W44FPFL75mIBY5KC1pHLM0VYaWic eZs5QU+ojiXODMTVsS1i0skRBFLvzh5FV7uhZtp6R/9/I8Tdf4lwd4dASqQ3cqHHNuD1NJsIHAQW LcDXXP0WLaou16Ix9SO2NOoZ/43GbtlhD4ziypr8j7C0ZHGl3XDYAPqwYVWXCbrx4l25HW9Qn8v0 9SWFcr2coabFcgCKmqOqPljNpGnQviJX8tCSYVrtYKYnbJSD+7Bq2uQMvoPsZjfjNCXK7Bujqm9F tcyp1BxzD62Qa7ZLa7cf63FPDcGorFF0ZQCknNMIG80n1tW8+2P37lpvGUbq9T++SA77n5HfiOxR tZQ8ueQFDpw8Mb2SwIzjdQDzhLyv156A4cGnqPXBDE6nUI78jzHbEmUPALjfolNypTqbqW69tjhn Gi5Wvx/YS3ENTWageVIaM4wzgKdsEi3rwyLR6kmtcEh3N5Oz15z7yGP2/OJXrz2CMlXWm+8Rme2t AUiKU4zMDFgLgxxi5hQYcXVV01nGLWC/IFwgMg8D9jewYdgxuLftWYNnnBDbpz5muzsIdpuWd9BN HrTekV2Ut8IIxJdFj6rnjcnP/efxyuIj0QkYWXhnFJAS8kMnExMjwrpab1pFm3X5YVsuxxRCCTGJ nQVVGuWMHCoM/wxtoTF5B4r6WO+vpH8m9wcPC8U4xJosfb+w8Xk1G5fNl5idcm42j2XFhNeU4pC8 0b5+8Q0y/SWlLss96cp2SZY7yl4HSBscE10mz3ELvrVCpjjhQWDjEbNbns6+mQnW1FEOEShReGgp FphxcuSSyEWYi3cWuGqojeTO81AUsPutGwoJaToUHy/JyGYZFpFzUsLrmFUQAYSKThhYDQBsEZdK xRjWQlMcggkNpzo/m7LdW6eN1z+WRdki4mhNV7HlItaNGs2Z/G86nJxnundb8Ne4B41dC8tHYxC5 op2GUESReCMxmzhydrFjhkRD/ahgASH5i11pnLV7DCEdTEt13xLkJvMQZs+3u87vElzoZ6GVomRS mn86bCROmsbrNH63+/gjegoJnh2DMbFxypnRc43IasKYmI8w1+RhD4d7CnxJYCAYVfM8r86eSi4a iazjBWnr6J5UEjSdGNsI342aTDv1Uv5r1o3J2FR9J0GTX5etljEqi0zDE3BhA5Exw1Qrjm4qYYTQ OlhkLRNXvCVmZJY5WE4XDKUuA8KwpgtuLcsAtMRsZbsXqMUYJs7C6OTFXTJkF8N6/u7U5tyd1pI0 1LRTe7LaUHU8VCUlch03OUxi7iTwtVrhYLvdVgGQLoZKx3ogdI7uVMOXk/8Ft0fqqc2ieexf0iys LtmjChq4dD2srPudggKdAlmINIkm9c2uwT0ofTV4vJm28Npd9oQ16CmmgR2tVnitfJZZA3rQYJwS /y9l66kzsSNQmvhEhyy4U2tq5Xv2cvb0ZHt3a6zBN46VS/aM7zCLHQaZRLJfEMmBS437pdMd9r+l Sx0dDKOIk3dsaFd49u3TxrKwqzuWPS/ncw4Hor9bJJALJ0MeOMr+FkBwjjnJs1uYlT/aQ3lTYS6g TDd0Q2bVgtiAJK+QdrZ9MoFunU2qRe/pNawZ3YrIGlD2R9iPrNXXsMTrUhrokxPja7aZ4O4DexPT x22xkZaiFlC4+Ra9PNO/ZzqVmZPMnsyG6RI4wkCYfQqH+QLot0hYBNVIfwnfMSk7YjP98unzp98A STJ68fLJ02hEc0vRrG6GTNXObxVg//8lQO6uqWw8ktvlUew4zBgdl6lmZcbDDWJ4AdZaDZMsVZL/ tJeSSTVqrWH5pvPZGDWB6XYplzT+UHZKaXiMU1bpUTFUBo1Mw9gImbjSIxk+jYrLYjbHEGGxpmZL FGNgc1gD41IuZjXpmvG32LOnHGHhgp9E7T4JXW7zxozDKuKFMkki/sX8oMtrHQs40veCfOyUaJTb RtRAD2HUDMIx/NCJpzagkmr3fEbGDhvBeudj2562mM8tNyqSVTDV5qmFJiY96136V/HyJRAcJ4+5 uDrGlychVsBmFVd+Fgw9b3BMPsYqKKQ5dNzeJ/2L8sb3hYIJenqMPr4LHVjmKj41CjBY9FiPUS2L ueRZ6ogkT5nWymXiEfCxBRK1p+XmqoQrVEeoUg6XexLb8hyYlUvMiYosNUnROKEcaXu5jRlXV3pk 7IlEpMt0o+Jml+xIeMqKOvheV5hjB1DqusKo/YPMWORo6z0v8tADtL/5035OT68f0N/+g6/g7z8/ 6v1ZBSJSwGIZ+sFpLXpk1PdRxyXQ3ShcpO2Z0XYbOwGaJ43nBokaOHojUoNR4zDbLAiHzx6Ozr0f 0TwL9gBHYGuoBzG7LyyshMchiAb5AGn7JHen0EC48ZzZgawQAvcRUrzjNY6fjwe/OWGN9vFvvOQX e8K/jav5duGa1o8PeuPD3vhRb/xZb/x5b/zL3vWveuNfI12PPbjNYOan+6nStPs2/QmlVsfhU9Vu j1K3ZeyzQqFz6o16ic+ecBqDQx5g2+lXb59FxMfTpUxUFp7h6LBJuABtocD+q4ZcHBonG8hg3doU WI3itB4e5nFhgAavvlxTiljx4xs5ChkZzds7jMZIEhtl2VZpT0NoZtEcHIqkklYToWwyMml1p99l 1s9+uj2Q290fTfNpc2FWjRKh7l8+TSkA6ec05tdpBLwlDUu10Vnoy4nYb67LcTm7RKEogLsc2vGB N5KFhZL6FgIWyzg+FLtZkOK4f00jvd+wunResMlo7qIf8xx4NNptoNGI/RT/gGfcFdz51tyDNsmg g8LZVLXeKGwNNQFhqCX5UQYnt43lX5LmyZeN4kQmHciFkXTn6AsN9/WkIjPSfr+Pri3nxapGReZV scSvDQ3VG77fFyTF25S2JpUcG2UmcI/0MEHyenZ2vmloC4Vtsw2JzViut6lW+3OgR+bGbQbtBcWT 8mo2LhtayirUWkF3ql4vUW+AJ10vYH0SzSeQK07e0JLxM6URATlFimTJB1p7/jx328u95KIs0dTv xvcGiBto+4HZxVJbXc75TjLggPDo8TFtMLu+6+HcE2GoFBVxaCd+M34TwRux+siZ4j2CWSQnqD1m 23LHq5hz6smOKnYawTm0VbcQh+L52hCGfY88ZgT9Gf14kCaDtsYJTndt+Una2pYwq7u2dtTemuKX d23uX9qbsxneXZv8tL1Jw1Hv2uCr9gYVv31rcxRX/KCZanbIL6UPaG00ehB/4D2O8z5sPETWGB3R Rts4lQMfRTarkAlE3z0Og6r99tjPIBjJIxrJcz4cv6Qf/9A+LBaEtI2nnby4w+Ufj5mKLRucdgvo +PKROCaJSktieMGTnUTueENADHakfbhz8+N2bi90fyOaTXPSKGhHk4wxR9nNzBcdAdj2uFMPcmR+ fK6cL70UW0qTDLpWIfa0QdeGjSIp8sMm59g+RVJr9j3KrTPcI2utnRp7TliW+hyd3YncGBAZYVWl W8fQAMbksEeKKyI6qMx0O+fvONrZ1A4zeF5y6KWrggySiTwh9yDN6ABBZnsXIhFS2U1MymKu7VZI 0UqpLHDwsBzEoFB+i02yz5/JnQvpLKsR42mL56dY2+STeCsXSBDCPCwyylYoGYqqWrKgSJS7lvSk rtQAkyn0QcKUGY7/p5eeKBVJcncdyaQaN6hIEBp3VpDcbpYQEH3ogGM7tm3RjJ68oWFMqBN6Kl6U v795U5xhek7NqriRyaVik/ush0a4MCZlxT4eq6ybZMXva3Lo6KBqpJyTYKpxXFQoDWJEEXkpDXi9 USxiz22JhlvO3TqR3q7G+1wW2K0Dd5UJmhWIqQa9rrFMGl4edtUh6gm0KUfkkmoknsUmK87b3l2+ E+UwiJjxhqu5w93Geov8p1n2Y88vLv3ZTfLzEVKfnddCaWV+gm1rEAl9/FCNeumnGO1OpHazCEuy SsaPUQRfxE8S6/ISCe5rfYCbMJ54GntND0L9mabE0q/Cj5r2in2kmIhDPyF0ZEe6ipvoxuwi63oH BkDk7AqHbSr3CjJLTj7wt6M7LhjiOkVKSztxclIvmSq22y6Gi5q2fB/xvWV3Ebu8qGxDRxhUTbc1 aBQrU/Inig+tC8OyWBYDg1bbbJnOAxgrGRDQdRxX8EUBJhjGLVPGVmjj3rUOa6fx04i8kXfuji46 EZGMdQTQnFmry/HMxsU1WUTpPpu8u6MAJ7iFYRxKqYu637AToU0HjjFAWMy5vC2df1hSyUu4oLE2 iHWN2EqhM7fAn8m3yCxjz1pSf8k3lF1RaZoNtu4508+DSq3ML/l530b4UKEQXdt1RWee8Wx7esHz j5dE/Jtj0m3ZHGMB/OM7uwDwTeYlZbGthRxVcU/QGHJRkcR8WnkOz2pr6lvRvt1yuGmmocjaWZS0 KRe7PtYOvbxuJ5gjKNuuT2Cj7XY0DskHP1TF47uAXuyyehxDLrAeK5eZtJB/hBDrxxSw+E5VgybT IHG2sqNnoRHZwA979t2r5wPlkIwZMmtg9S/6y3KDMdgeojMVOSZv1oANH05m9cZ657b0CiFvRqj7 u++ePRkk08nB5Nen00f7k+npr/YPPjs82P/N5LPD/dNfl+Np+dtfFcWkcOqLIi15dPhLO54b3nDJ P8xgsuZ2sD6/hktmsp2XAxGVWJ+eo33bkVwhj+ncwmRXF01FYAjY+8FBU4EnAHJQ4uDgs32YzaNf w+Pg888Gh58nDw6gWpJ9g5IeeP8SLjMsZtsff8vxFWZlzY1+RxA8Ue0dwhIlh58PPv/14PPfOO3B +xfVpbTXZuekbEGUl+CPbw1i8rq6lg/pIEXDB78sFIJ/tXJSh5ZJ8LB7B021Sn+jCuKJygdx6RBg DUEPKTr95DjF/EM7xpBhaYujY3vR4J/R9YTlvqCmlzRWFRF+aHfH+atxzEir4a/0RCURF9dckiJS MGWkspySt6yH0T1DLU2/n+S7rYzVBMnQ4umKnQC10A2Ja/zcxmTraucWJvtYRzaVomGqEGoUtgHF SJEBcfSHyciZm1f3pLFl4SyaGseSI33ruw1L1ZOmpomCb2p4IdmwOWv31RjvezLWdfugNk4iMXqk utXW/eTwgP77iARgoxEGTeFMcVROv7Fzi1ujdLOLG4viGtoDnEHZ91DMDdfBGBiI794cGSNilCoX KFv4CCTKUc6UXUqK5oD78n8C/w/k/zzJjh/sn9BT/z7gGSdReWi9EqrVpQJbunmRzpoyn3M3f0RH m0B1vodKNGxBiD9dkgLFY9yknpMb24roBYt39yzqSTyLOjpnLCfFmuDnbOFmUlfJQWPxdK7GSLG0 Z/TjG6e9zLq8ds06u9aNWC2TlIw4B908AC032pA4D+9/aUfPMZGGNLCZsDwmHE94MyJIXEuueuzE 3Krs8E+tWFmqZkt19ZGrT3Zg+VxwHD4BUdcEI242dbtNh4S02ifrxqhxhyBfA3Q2yW7ZeeMmtggC sSNlVG+5YFiLIBnDMJ7RwYkTUBn4XF+KL615SxW91nXP2nlYXgSZ/HRJgPYFGhOdF5clJ1NS0asA lj61Qnfjjh7zIiDh4MRbUuoj3apzXKhqh0+G0QlxFJLjE5Ovnt4EqJXeavI+gar9CWq2qCGlOHK/ 036vUbANw1IljeaoY9z9JavZcUSBdeIdeRyFsA7Kc6WRZdAeLYNOA+WgPWaapIGuEmi+ItdFz29H N9LqsINVXW8detPuquNUfEHgh5JkvqzjHKXrvMC1LaeiZnEfSYEjvS3qs4audHnTfrPcjm/3+uxu g2oWL0fajUgpmyZFtEiD7SBd5Ae/3n/02zdwkR/8cnB42P/lb3/zq89+/X9EK8iFdfeJceIZlq0w VVKs1iOHJtl5QhRpoA0kxD3Jw4aBB0gcwqm/RvD2BWkBqK92APXGASskitw+e6pRc3m+a+rM9Ivn yuUOrTCAnhATjHs1ibTg75ehB6fCFD37RPXMnqEv14e/ffvff/LJJ6PVDYoOoPQYY+5/SN/+57/+ 5BP2sxhXa4oCIsH4occtEWJYQadxTtDVf2sCOXUEWc6WSFFt1M/VjXqqb2r1qBo2hUiM0en8TkZ1 Myvnk9F0do1hpDocgY/Gma0x+kltpZnXxMn30ugrGn+51m7jnFZIQlCRDStc6ZKkWsLC3U/ev8fL Eb1AzzAxEFm6vH8/0O49KCtQyQmItFAZKFWVvm4Icw4Ao4216VE74etpU9HXZalkPpNqDJfzDYxo 2a/WZw/ns9M1EFkPVQUKuM8RjI0xCzUC+6BGJQPRGbkVBXbFUeL95ZH7n32KnCiDuld2kZdTlYqf qyUwoF2iynJF8+6N6B5HvyQl0ZBF/GdoYwWliV0EShiVAd4bl3hNcSiAIWhI9Z+lF69KhhDZFPgN FuExky0EBO/fY+EgTtr798Cvz87O4OYHQHoi7cMay6L9NAvKfmBA/CJHxgmw0LhPnzoMwCTDsqLP wVqiE05sGorxXOkmhkkWzqaXfMthfsJPDn9WLG+ydV/BNzHSVtMIjZz/e+1EYxmNNmvY+tNifHEO 5w15Wo5u4ZLbvCvQs5DcyOTNhOZeV5MtHNtweBStgLZbxQHW3r6KSiRIyVSY69GVmvJO4IGyVx4f wgFi7Nl4i6npmXgzR1hCLr2mJGOzMbOPZDO2xKhiv/P7x+QU7HmnX3CLTFFKZKap+xUpbKT2Ccvg yBack0g8hwuNkKiNDNWwyPWfoecy1qd0wpT9Ec3kMWyD3jwuTN3mMpc3aADGqa7VDtRWAJH37zUU y2Z8U9Z1cVbC2WErsronGKlk4yP0KVTzoTWd2D3pa0RWZltjMinskbSM18hLLqF5uL4wYtXyRhn7 k3gEre1YcA94Wy4y2jYYjdXgwIr6+eWXX8rZJAh5tV0ivaLg3sAv2vXZZ5Zune7iRr3p9hKvrosc SNtqoQcJKhSApHvUnPCPssXcVMdYO5gQW1ge+D8/zBZCSU9SS7ckYOdiDqk2XTOfiIZwGDmJfmcW ZzonYzt63Z+OSLiIFuurm8wpIxqhzMFIBi3SjLyY5QjZJLbEp/5rks7SEHMto8j9FFwqJAPSICOZ jxrb2bw6JXNRGE7eCYlxhDxZI4dJbxqg7IbBuBhI2MG6wtvJRTCRnc/4WOSNrN6CD1BPkxAUBq40 ofOXFb+RQPoeRyjVUerAT+5njbeHun23gOqLQrXM3QCyLHulIYjwYFmFtaVmWEvqmMgB/lXpLA0i Yf/Uo+cTE6KCO8yBZJh6PClWlMcAOXeDm8ZImqkjVr83F3fjJlSotoq654/4m5wK/lEfp6rx9ARP r5RRAX4Q1OSd1xg6E2DCvKEXMIq/EpolLoc+/E6FAXfCBUYCSbzBABKCotcCf2apGnOUYhV7SeDE ozpYr8rM7eUPlBLMb5/MmJeT8rq9n+PZibP6sAwh2wMtPNtQCg7MQ1Jtz84lE9cOU8IWM9OfE6kB 4DraGa7bcrs4Ldc7r9xcxanze0HGQbLczutheKNAW99WKytclt9dkOQs0fmXMO2pMxhJY3Llpi2x xhVIcdDq/JTOYXbVN6hmHNej+7tHMsNZ/iOQdzrlOhGNAkLYBbnSzGsva9s6smtHxE5tdoZ5CwgH J9bxEt3MMgqKKgWuOrHuIt06f7MGQibIChxxejJqFFUa5LqAU3fDGvvIwmmbPzL/YCLnM7rpy+so Duv7deT3sRUQQEJEnldXanO8DqxPHSdqofUh2+VSazYRnAkq5qI+Vna3VMlY/Gs3ND294z0bBMet NxhOVSWWq4DntVdJUbLFfLa5iSXzsFbn48c2NAMcsuohvtHe/sW2bI+jh5ig56o8RweR+5ZChACX sXS9a9zOYvxsL+GN4aSrnfYc0XAKr63b+L5ywnDPo87r+hOdSRgCHkkV4pg6oa1FdN10RttP1k67 48NHQDAp5sEnoJqJSp/NMN5cMTJnu7Ial84kIVtfNyx1+Y+1oSzAzrr62qqZQwUYgjOyX29uFCeK qsV1mJ+qCzNhn0ok4rR0ArfkXt3NG8ILh7w987FetGFyHSNDX79CVGXB1pMkuuzPar4uoX7eFn4a RcUMSbgU95IN/KZKdiIEim7tt+uxgp5Dki88GCbhpL0ugjqNuedah+6Ny0cykZH5r+50tG+BP6lv ato4rFpinHJittEytUzXHDZK/PHgI2n6yRVxGckfO6NgVlmhSfcpRcYmeAkGatMFuy91qywt3paW qkXi/94J3RlmmaQj02I2z7pPnj1JXrx8k3z/+NULOF8fMlIFAD8NDP1ZX8bwIX/7n//rTz7RonkK dKgQUyiTiwgYW1je+qwnQa34cguYWsIp8G/ctimw1orxqDuoV7oY/HQyUNmiVRc9u9EHhz09Jltv U2+a21XlWRY5KlYzEh+Rml5s0GQR4NX4gsJoDB/1NA1hI2gMc4HX9Ayz2tQI0Ecvv3329AljS9YW POp/bpQEq5u0TpQMVJu9IO+mmGtfe+AiVjMkX650u3SI4oHYEdWY0jcSIxLujKuRom44RorpUiIt eyYPVNuXF3mtBv7pVXs/w3hEZ8rGvl02aINNAwhr+Dda7HRdFhc7+Bmp1QmOLXfxwF5JewPUvPHs twT6dUbLLfHBArhPMrYMUxk/7tU5ngEFlBpORZuBoOQDrHnEM6JhVz3kRhIfVD2MwzouvhIIR9Gp JayS9BLqUkVwRBmh6d22EiLcoGSLUHRdXOGjKc2wAmSehUDcBQ1zDcO9Ua6D42DBmG/OaWyL3JZE VKmaUiZ/DkCoSRy27Ldph8dmpKDxtnQpT7KHBpQjUt+NRmQ5Ka14ORyVWEy+Hps6Jy2D1NW6X7Bh 35fd2PZKo+SVAw3jF2hYS8tVSQs0lnNLhKnMnO05QYk+MCRsJ9UFPDnukm4keF91w5wVvoyUMgK6 xJfbzi8Q3PCy3KExY4yta6FRNqLymOjayBvR3XE0WhSz5WjU3SFNgNU3glqxPrv0nUoEVrVJUUMU /72kXJyWE07mBJwOXP7E/0wqjAFEtmCqB7w/y+R0e5bs/eaz39r+BJFhpWo6qc/5hVvuVbXkrVEj aFXUoDSmXSPETEigdETlgDjHUQoBebqaz8azTaYZEW0+oHiZAMCHGDpAKRHJM6Xn4auh+uoLS9bl 2Qxq3wz9wSi80a91MGpX0ACQogqrRgBqesk//5lnBwj7w/23fyWk4Azuz2KFhhcfHry93teUYFVH LDmMeQcmRSVtQEcDIMeRqJQZHQdnePayI5D2jF5bYEblVamgFiYLQMiS+4lI9OSLJPusp5IxMon6 BiidZy8zVc9L5sGZV5kapTARUacMiyriGCkYIRxVUoOYe3KBwRm4gBR3g9GmIxUcHA/3d2++3v9N mptow54Lhhp4Pxhqx2ADniT0a5anadl/jxxAy6rzqkmpj1+2OyyZz4JKwqZTGAIbX4uNLTeU77w8 nRVqfwBGlAnxwSBJKUsA+sXwc7XFeNSP+Ee5Xqd/VqzN10+OGOyN4bO8SGClN9VDWtdC8tlUtQTB Q5iflPV4PVttqnW/VdkE5BWSCxN44sMi0plldSVhlNUMolk9akSuqo3EdCphbTAMP0XHda+DEjcc TbZJZUehgftJ8gwBXQ0DNs+lH9muATXy+lz338hDlnN6KRTzUL4fL+9Ywno8JLiioX3YfULNYqgn ZKN9My6TN0NXAUbhwLsLsBl7nDThr3Gw6dXpA++AqcaHyWTLM0K5mZzQYZfOp+dZNIW7uaqdBAE0 C92SPPnCdNgwmmNV96GvzJm6Q6KofY8Ju6v5BL5Yjsfwy0AKGVerNk88W/erWJ4iJPLtdND8wmNo AyoCpjBFx8jMnlpA6b58vUsKgi7WnnhHhxAvHP8ZHI8wPCAGGUxuqi3RrjLknJUoX7miQg++AFgI fLQMWbbKgyDZJUpcMSkvl9u55OiCly9Hr568fPH8P+b+gsCePsrwOB8Enxhe7BWS4Z0XtXM18O7G fG3rxu12pnjSS54Af/+qLCZfA4Z6hhZIWd6Wi1WN3F4ONgeosryXNEDpTzh+eyAWYAJJGU2esF1S a5wjdF4Wy2S7Ut47tc7Lqk8n0X9ipJRHUZKzIALajeugNzd+EAIIDNGVs+5AIl/Y/is7L/Edl1da ieeEVeir49z31fosfuXjJlAJCuS2tvJBVevZGaah58vGHO7oshPKXjXj7rwVG0V2jBvUoJwHFyF8 ZLLBjRA2xSHP/RQsXF4hfrE9NTcGZcPj+/t0O52Sxmh4wLp8fKQb3LpYLHFHEM6e7m4LTMm8D1MF YIdzSk6D2u6ppXxBsykMGqe+TxTtSvQJgI0eVKqyuppLnr9xxhMvMxdQBbomJx5MZUapTRGSL9LV ecm5JZe27UKtTXYwk1eBiS8pn+hmdmrdkPZsKQlZXRNLSbaJ0iN+kGVUuVDMMZSqG8rBrCgSXtVy 4hrlOeBDqH6qgcRd0SH/QeEAWvxwd7dwxma8kWvPP24cIRD23KYLFP6IcThfDm0WR0opoGrWPViz 0UKG7ikwfV2PtNGbHRhySH5GuPcndC3SoBnuLZA3EI42JXBWpkrzGzG94ym3tpffbZ4yyqdYsJx8 7VFzebj8Qu3bFW4z1EORf1ksrGZ9SzEuALOTJ09tpmYx1C14mFa5CJ/+k7vPFlMF35p4KviEC3v6 T9yT3EzhGvhWpNRkmKjViZUVoR6oN5Rj4HCjCyFIlr67EyU/ROXqBs+eyZIw02nKPpK6hJc3x0Lh rhEbXoh627wcMAIBNmve1zvL4iGBDWH7Qrggd4Mx2pa2+RwEGB4DzVMwEICg9ToXc+8r5MQ6nv8u IVxMT4bqK4pmztcqecw+pFSdsYTV4qAT8c0JJNdWTlZdnGxfcQYPeSJuACPKxM6MsDMO6XRGAdeD /hyWj4TO87rtRl+T02vcr6H1nlbrikBZ9XHRIul5nB3o6LUYsvRDQr3gKwuiuKkI/UkfCFOzQOGh pJTjRI3i9EkLNlF5xotaCKW672dO9qk9at0n9kIWigLTzgF6Jzc8oK5/FnmYHlaH8bAlEQxYeFd2 DyNaG+gokTx0IsvbpevDHru0phks+c1E0yTYJ8RSUgIH7tl1O5VdCb4arJwOev50GHQvn6Ld8xRU iUj3TuUQgjTwGL55W5MBWhRCGAokNnC9LFb1ORonMFjUaPy9AFoZyC9F+3qAAd0JTLNPXzHhN1m+ 21bGxk+jFxz3ejMRNPf1k0yeLOqUfDS4JBmLUcJ3hQUI/9Kbr58c0uJ//eRRx8YXiwJzyC+XHE7u xXfPn4v0CascJFlBvuIlICE7a2oxqVl4KUdrtsxZUmW5fxz0DnuPfO7CICwMYrwkIQIGViaqEAHj tNQn0vXligdtEmEcJp7kp8XsupwIRW/6Wo58qR3/VOK8gEyQJKZBfLwu9NkdEIi572EE8B7+9d7T eOAL/fW+wbDgC/zrvVeDhI/q0SsB4+5iAKcr8/7PEYlWtquQCW9L+4amyr617XKkLeFkeY5TeGmp EhlxeEVQjmup4cxRMUVQuntiBZq+JoNarxC9toqppQlLqi9uwBkY6i5ZujlZI05Vi5mzg5gY2IMx ly4TKFMP0RzfUQlcQNYx7h40yEWdCN3eNUV4MCUUEBP6mEYqj0ZpXhjeYLMwh2Zh5G9rTBOzbLct UXASBY7UZsOPvi/J/ZilBcgL9COKuCOAa1u39pHMra1AvLDTVtgZlpuNUlr2v3nv+OSZvXv0M+4d HXC1YpjV/aP3zpWFI94KnQI8Og1xVMw2Hd5rEXtzbQS7WG3c99tr48RjtXENAvE+ZsKNJ6HlL3Iz 6lQFWoSHlEkSIU0aEbyW1/ZIVeXfgRZhlPm0C0ua6k21MsMJCCIDzTE4bVhkV/hvnasmItU/hh45 1bAbbjcWMDYRo3Y3WPzWbiIA5yENBL2wGdyKmFrJu8oNmehsjA1HmgZtpng1pctBtKpp4rJIenNv 44OIJMpjHIRiboBalM4yf2tblR/USGvXSHXlMe6hqWtru9u6VlyUv+bHirew3ZOCXnqJvebTQHEg DLTP2pTk7aqkHjQ9EQwBN0cyaU/gFmPLI1nQiYspUQqi4q5bDOi0j7FKKaf6Qd46ZsWdRxiTj2dL DGv+J4E7oIr3ieW66TqMCnEI4n2H9wPFQNtgEA32QC0mHkfST55tyPbclhujrrwOe/0T1aAI0CQ3 5uBdKpadEYVUmI19u4Qqc0w6l6BQMnliuJskw2R3NsdGduKoI8g/ip0xnIvN2LTwLfOJnD09xbCE HBEuYVMcugSshSkxW3Yi1BFH6LMpTTxUaRQRiKGPJ/bQYobbCLIGQoyn4ROvOgnZjrQXtxIfoZZE dCLsAfz7cdxVC+Wi1sVrSe+lddsF1YKVMxts3V5BtYAt0rueWLcVPkd01/+KKAoNUgEVEbvWwyWV o3MLjREVg0UUwxp8AmKjZTQObzyfBLxAQIpEpWJNo2nZ6KF98u9CZ/xc9OpPStEwEARXfuNxdM8h mj9Th1keZxJi96vLRTSDTyNpg5DU1jHROW0dEwMSv+ON/FQ8ifxzr295bQQAK7095ese5YCYkGx+ w1plhjAgBooxJkQvJ6QhFsG+Ag8TwpWVwrB5gEgIaFZVXc9OoTXUApDWSckHO6KwwERorH9hywa4 jcsSrn+mQUzTmHdidrZdY/h7HATGLmCWV2Wp5ZQn1YKU9BRDDZawRvkkpoIrNxsOdzFeF/U5edxS bYw/TOEVpnidl/Ob8KYnSk+86zz9E5M0z17q7JUFKSCZlqG1YwcbUU8gVSXz1/Fqi4mE8sBH511t v1QRHdQ7k2eQFey+o1SgyIA+KbI2LM5rtaurutxOKkYQcOOiUYLS13eNL9YMr+KbBlcsE2WDIwoo ix2rJLP+VjRObfYlqnl+0WnR/yPpUveXKqLhcpPadrN2e+mL756nEZ24V+oh/H6IL9LOh97brhWp 77JcTjCB1WhVjC+Ks7LWHrof9t9CuU8+9N/+d8qGG/XECJcfHr599j9xXL9TWPrl/gRJWvbb5viN a4krNxOHXUagnewoT15Vy+VN8u20WC7r8fliNoET/PfVHMOz/MO6vCjnyf5+8s2zN8l8Ni6XcAg7 CJ2jkbJfQJjoHvy/1L3rbxtXti945tMA/DCYGWA+DlBNwYfFmKIlOd1J84bpkzhO2vckcWA7iPsq GooiS1K1KRZTRVrS6dP/6vwjAwxmr9feaz+qRCd9zp3bQMciud+Ptdfzt8YnsJAn/Z75xdw2/PZ0 8GJdPsMRgkv0DzAQXNWBEYGevfwOMBef/fmLV6+hhYP/0hei4Qrmz8XhpN1ur/34MexO7b2tPn6w 0m8IRUzENe4ZSYgRis2HRCiK/FSgTfenGqLw6wd9G+iYRMZyghDC3zA7FPzh/8ixFwgbpFBq1kV1 2Wl/Vy2PVfExQR6wHV7auypE9sWcB+ypxOpy04g5adup78GQ6EZa4T6wKanM/7q2+d9hFzyOaaG7 x4Y2oTm13Z5h2oSHgXC4przIQXvhVE6Vw69af398ey8+VPOAZnCPIRi5qg15znkUWHBK1YNuCBHS PxOYZyacpte6+amtGTrgp7iCPZd/hWnHg6ebrgy870mEJ77L4MuCsTjZAZ2LdVlozAtD5JFFYG/0 2Pcc3Zlsi8OHVefb6l2xdjYmJMQ54hhdBl6LSZeHtEt6rHBKdgNTIex1csZBmSqCE6EsGY2f3oQ4 aT6L9FOU+gSopj0otIXEOUNkAI4nEVZvIz/TQfSsdwPWIZc+BobWSsVr86iZR4ncEpeDYUrbSfM5 9YZ2FlNrkbvxbDbtQf12zGt/VTrQjMMJONdOaexRPXjkbtmwxQCiiAv+ceZvUruBx85r3dLQrxo8 Nokjp93ee9insgXvXUI8Un1iV85JLH69iYtU3IB6IL2n2zVKh981ivTXo+KNIfs+0rQjxp5eQB91 yfbjsLhSjaOpC1eHPdzUhYTyWMkPOXTxluAg/D4C5FaHVDwjSb3IlKodkoJmKvBJeculRfe61FC4 XEI91jWcTnSMOLqz8+wZ+XB7bzcHKg9SZ072zkM23HcRiMXARyNcBM7JNO9ehQ/YEF4FGtIHrMNu LfghTGL1yBJLgiDWU5k6ALuly8wYfgr+5PMKf58enkySaUxtnfaN/tVzaO0PBjZpy/+JTqSPmp/X jxpESbc1JFSw+zjgbCHOO3ucRUGIzmZhaoQEBi+zIzIJmJOD7GI1X7+jjBy+ry9kJAXoGiEIAQFh cVwpk2Iyr9A3x3WY50NlHEtyh+7Mq9GG170kLvP0iLJinQ7Cpgy7oiBAQ0wmRGTSEl68h3oOlCNm AelU4vno4cBmQVD8Wb8V1BDLHcO2jmIPB28JZBJRppSDgBBbswAvybhsPODzTiZQM0d+HrdpnMeN 59qf9GEB2wlmpF9JOgm1AVK0jrVzvGZQyfHu0dk+dEGy7gyirDtq4xBNgbdr1JK+roV0x7fIOwze QUhLut7TGUoaVi/gMaIoyeVexeEwvGSm2kOBD1zscXackprDN30P+TnhmE2+rFQ67+Ll9sxjxy3y aLoE7UCFIM8rp7rtYLzpGkj3uZ/IiPsPNCWqx4fF9KR0rEZDMrLV1bQIyvuNAA7tvFw3dlXm9VWs fjBfRmvCiZPaHpaFXOMVH+/TCUObyJ6HxLr3y9Hb/5l0jKCT/OX47f/9TxYgAmEhYMAEBoPPgwX1 YHWpl+9DzEWA85azlhOKQ+Seu5Su9VFY0WIy83jQG0ySiRzgJiGM5Rc/vKCcs9mmKtfbBnFJQKk/ gKKGRWAtO1CFA5izqBHGm/veLydv/3elhgWIfNatPn37T6xbFTAliNgaIYq+IHuaQQNaG4L6i6WA kqagKj+C0eDRW8wNRl9T2TXmyyV5wFHyOLm7mHhMkvKgGQe/gbwdF7sr6pt5Qvxh7NoZHB7yBAC8 k8CZ+s3WrNxsW++Kvu/BB7Ob9pelof3zex6UOUYXdhGA6bXJYCzg2LivO1ez6B9eQ1zB4SE03E8P AHy9t9M+lUiMBjA0vWWnqBW94DiWtjEMDjdq6sQF2l43q92VuX59Sz9RSIzcGm+K7fz9vJ724fj3 o59poMW8Xt0frqr5kmNwqPEsv4EIzEN0aimWw3EiAh6tP2+qbP6+Ks2jWJFFB/Lw0fhGkPIAT/X5 upqcg3/9ZXk3yorxVWtzUHJZLWALz/0N8k4H4g0urLqevziUb8K2W3aQ3p60gzOtDjYL29aUy4K2 DbNuQEd4+Tb3bJ/oM25OYrB43vceFGww1thziFidkI/Q5sx3G5vQxx2oyIAuB/42XlVXA1hil+To uqregSEmhz9u6Q3g0El13Rc3aHNj/QVf9mq3NTQd2DB8SIiai7aefwQSMCMpJbfhpaz7pdUa48gm YRLDqiHwpPlFA//m/WAafa1zNt+JvzcoQUkFM7gdJMpw3F6f6UTDMzx8hIQd/0ngPhDQ4SEIc4vb 5RT+BVsn/vHzGowjvQTepTJCQePeZz/oYdynWMOb+SbHFJ5hBO5wOApDz83KmrEAo8nrOQMnBDTB DlUyDvwJz/QY8z42xRaXoM6DNXGVdutlNZNDJYaXMd1wTo0wLtZga5ZS2rvIOnzIUsM/0JLaQe+Q bqsM1lEyIfvGhN3aDNh14zMwbgahGrptJNW22GMcnTnWVK8+R/fQevt+juFC59GmGYIyQ2QJ84B6 yzDspe4mMi1UVeWk9K4anyh12SKYMnt0CfOua1/RB6GUG6SwHEf88gqocmpV8+QdUSeXjhtGn6Pn KH3mwvC1zNVDsLGVYiBmUZK2lUlOEis9zvpmAhHrfuSy4vjLDER6Eu7mzGy18AIeho/hGqBCNB2p R1m5Zrt1qrYdSk8w8HVbkvgMN6Nuu8pAoumb3LCi9Q0Ye6QOk9DtLars6LvxbHvL3/IqyVCZ7TPL wH/R5ZrhmIbSFAojeerTgfnYFJs860+BG+PHBEm7Of5ARASRW+r1T+kcnaHzgIS2gZUHcmsABlS/ F1JyOHam9L9vqzv81zRtnu/FJfU06Ycj64WyVjBdYNMx25zbc5jwCPGsNb+WqIdQKWRY1MhTkP4x qcbEX6ZZn+J4lXvZBtPBIbQqgalmbAmBGsMwaXE/yx4dnnzciGXf1CaJQcVG8/xRqTQxny53q9Vt udxen/GSpHeyX6zfl3W1BlkvM6xoCe9EI6tqvsBEmrabvP/DX948f/1m9sVXX7384c1r2HezbTWk 4Lq5kTzDGe9sXz2DtuYP3/74zYvvX9OJMXUOzRGa1+joxFwpkHZkdzlaHP3wdptka189//LHb6At iFs29eihY95KHsVKqO+gsWyYHM0z77ywIFauceqTaHn9nZBNw63ovi/+ooO/uREnDe9frnC8N/P6 HSBiwvZPMhZNs8ND/j68RlF9TnsZNyA/hC3kQHzW4ArHiTuhSQvhhq9JVc+WZQ24JhKTDB+DCyqZ FqQq+FrZFWUESaJEsKiWJgEqGOO12txI6JqQWHIB35yYe/DYb3Nsc2HUhYYQIToLxn+WAlQYLR3m nBltJqUIoSoJYli+oqTafBYH5vCdEdnuet0mfgJzTk+u38YkTYeeeSRmzZstNmkZ8NQTSMm52fbQ R5q4rapVw5CfmAmGpzbp+x4a9LWhdDDdjheW0rdJFIjUcvi6IwSc4B+GEWO1hRODNM4w4tl8K1dm iRmC6gq8MNhqhF9ZrHObgy091wyPAXfgZc0m84hmtuiUzMjW37lHaTkHD7/3tRJr2zZjh7A+TlIx f63Ki0Oc/oNMlS93aB+L9wB180HsFdeYJBaTM5FzCe4lWoM9Jgsi8vsiddTQh6fzwKPOj1mZ2Ilo JPewXFNbk7bw4vhopgBEgXfGgpZb3sP9oSZGyp7yznOJb8ORdcCjSdTDxBn95eO3/xu7XSIzb70y f/82+ydSD+7WjhQDo2tWIJtvStQA/vIHm4ShrFzlT97+n1wZU4o+YUddeJ2AfmLNT9/+H66msI8k 8fzyx7f/7xHW7/X+TEk9Be2FUreKZAjezVyTwpPY/xNdOXs9rXytNOrv5v7pOw7m0cIymAU/n2ZP e5ykQMLGMosSfLcdIdKrudy35frpycx0OlvAU9fY3HiLalXV85u5OF4wLtZmNd9iCiYw9GFlNvZ5 NgvuSdrQCF4R9m3S4CEN4Ji8XxID9sBVurpxDseUG8Jc/GVpODVUhYh0bVfJ7EjVjC4X6+1qZBjO 3WKrQWvw+3FZLbar/HjEpcdvXrx89s1Phh37b6P+z0dHR/2PPqXjel2UV9fbEXKQ5O5m2hsDiuLi nWH4r83/+iNqe5idTk48GwBXzrB2z76aMzk1M/xBJkClTSfS2VG8QV6LgJkVLIXeMR14aI5AcRf4 AKmy2sQOCw1H+9LMCXIlUCqNXhzzDaljaBgeSuNB9vUX33775RfP/lV/91HWgNLNQd1dI71QCLhQ BiPzSDwvbuaLxt4vcLlfXDPfZISFo5GKkpDFMCxtbvaSOXniqp69/PbH775/bR7pT4/kFTnI3r59 i6KWOZRLiIT0VhERWC6K7KK62kEq1ALY5WZu6NA9IC2XW3/2n2Ufq9nLWD490geBD4C/7/SCRYcB rC8wvh12iBEXs6JZzDdABCH/Ku0HnKW5GfBsU8O8iTiYciOdCW5d3GLWMwpYvFztmmsPHZmTAsRC m4Q1+RGJiE48xX98jwIIE2wWNrRKZ5yCEYVJpqAsJGYyv0X1PWL1O0usLH0dc+SC5pBpWLlAn50O fr47vjh91NyA2XtRLcl7okKIRNPP2TDLHse2e2gl/praOrqBXON4dr74/vULopCUf7dPCFI2JTEt eTC6x1PT0HrQC2cbUcWOaZpqxzwDnzReQFq9REIUWmZc/Pz0DhfhjhuAxu5geY/PupxguWU/66qp vkVha5r9LYdVmWRfv3z1/JtXL3/8/qvZT39+8eb5KNI+HpiDUd/M06lf8qfHo6HXyqvnX40SBQ+y OsDMdk2cBE188+r58+9TA7mCYKSWRp6mGvn3aGAH2X2x0lTRb+XjoJUvv/0xsSToztSSeip/+vtE G/FAgF7v6s2qrZU/PNAKL9JBtrift63JJ0EbrTtsaPS2bSB/3LcRvE3JRpybLnC7ECDIBxEpPRKa sANPDIDD7B9vbOffp7rai+/fPDcX/M1fbMHXb76avfzxzQ8/vpn9+Yvvv/r2eQZJkI6935+/evXy lf75xMuhwiTWUVN/GJhsDa7TN8X29Xb5Z/yYh+123dP2FryRK/yz1RJJWEN1nplnr1oVL0CAoraG 41sbs9X0wgXLXf1/zo7uji7Va/zaNgch3LYRbneEbQyDXFWQHxjo5DD7PHt68skfPo3zlbDOFkqd TrDMWYhRbB+nU2rDV06a7ztb3X8GdvJJnNawVfvQwusblMPv8qFVg+9WS1C4g7YLoG3LlXqoQ87m h7/MDHPz8tXrAeblGhwPIr8W+yLsUf1o0BEGKPwsC5oUXDigJ4rxW7xHK/u5F6Bght2/ef7quwEm LhssdzcXg7gGMBK55gYoDpkyBQ3+On8/555N0zMdRWjDud4wZ/UTGbK8gJeZesVAm51frAyvO316 RCo08yDROzE17woT+6l5HdImNiDjU0P1mRZPDfFGgjo19Jeo4tRQ0XTdL7Hfj02/r0y/H5t+v8F+ Pzb9/oX6/fhpa13T78em3x+o349Nv8+g349Nvz9hvx+39QvUEFKKrUCggDx6F4ZteTf9PSBcoGvb Jx63vOR8PwVjcZYVeE3tbgSFMBFApPhQqdMF7N3Jj0rkCLfTEuZihzYVBtbIQEa+j7Ak2hUdrh7k CUpgdqDhTIlWIPrBOcodcAKeXL9l/+agbbnoU+ngJyQJ/WEi/5UZFp5kAmomAABZxxiwWOmFuGW6 nP3UdSWPHxL6kx3Lj+MvjMjxpvoJ2Faa8XhP1GaQ7SySDtEPldmnv9teeplDbEJgSfnl/2KtOm1C lFfaLASRVErrnKCyYdrzebM1bxLK4O54sxQmCWlE4grgxUWO8TqepJ6qf4jA4uSTkHzD7270PFs9 dgAJjqQyFcKjjYfvbifJEBrtTmppalvaIh26vlu/W4PlhdeHsxahrnAYuam/uyVrYwIsplmI5tEf Q+hVq6M47U7SOpCEBDupMWGKjXUE3iyu57UpV24tRbMHkD8Ha4lJGeWIpmMf1Qn2j7TSiCDedDVf QRPbijLEwXdoXLwoABp5VUGW3kZQGXT4AcIiYflFtV6W5C1yPd8iu4W+rNln0yzu9yGVoesBswdn qIEQ6zUGyhhysbuB7OdWw2KKzQEEe53NE3FRNJ/dllIskeN2dju/h0mDbv7y/sm62G3r+Qphf6+D nEsHWX5boNoGjiOcKxxKcTdfUHgBKWDCYKSmYuXOBRhKL0H98x5xdslNkEKlyD7Ck0vAh7t9PNSJ JoHjhOPS7oR+AGtyOzcrd5I9zk4+gk0xtGg1NJ+QH4bqLTvEqz+GbFSZqs9HdfjR93s3Iv+LGtB1 skPd2mF20tII1srbqw2zJ0+y3O/K35Xvs9/YACwhXin8Mfso+z4ZCPQITNdiioM6fL2RbVl1yVpu 3zoWrGWnglU1c9FtpAbq5pG31tNRGuhTb+hyU2537ARq71RdVTeUqhtQ7sFZQVqfE1R+jcplv7WN 4bnLxW5lStFtFxdTIiUEf28bWpXviqw/y/oWUoYJmXkAMJ84hvjIpSCVPSwlD6AAdv7SkjgvpsPS rMd68lYP6R/yRGTXY7uYTncZo1BwNCmS83SiCUxzGZN78/VD6RCxZo4GHHqChwn7HKFdIEygB6Ch cYgcPwOcRvg0Yyv4M7VFMBf0/LvB78EL60Z0WnGU22FFZoYe5o5TG7kaQbSPvKTTwSBaO5WWognH Rm1jpnq4lnmTzGYBmlUPmiqKJIy3yyKAtbBoMcOymK+hEjiK1wV2fMhPCwAXba2pop8coz5WbbPz A7S8CdaDdhbV3gzFqqols8ugc4WUl5cnHNLqN3eomtMYDrbC58mMXOxbae79R66sFcRRXGCVCgvj vmyuUCj+f3LVtIIsBem95z38YMXcb1TQKR9k8N6bXaBTu6+sO/r6KCrPGlVXLRVA+e4WA58HoDow 9zhMs7m3ZrWr7br4FU2/ev5VLBis9IjNNf7wZkFZ3t0uqog+vGHUune3TCqnX9n0vz+4Nk3R3WJ4 ZI4+iXftwxS9HY9G4pmz/U8+uFulnRXyY7UmD2He4AApo027kqo1L5VPoFVbYNN3n9JsRZAm0EIO cuNBBAGF6SMcTSpvVRJYOBpWmAaKtNFJTK0eppAOrZWST1mTctBSReS+l/YNQUcXNnzyr6YL+p11 j2IWRahCwRP8iYXKBfXRe8hME5lolI3Gu+9fPPtXnPSUDv0RIQ4s3pEuJSr+4/NMFz8GRheUMmId pthTVA+Pw9p4UXXtk5baSGOi6uZaZ17nH7dUt2lbQtuYrvxJWMISaynxqd98SQ7ERhIA5yzqAFw+ OlfSLCTEnImukZY2ruqv6nGyamJtVRvh2p50t6FWWDUSrvDH3Y3UiWUI1/mTo7BEuM6fJjsJV5sO 9Z9fvnoDqlm8IePFrLk2F0ilJX/28uWrr3L++TU6LjlEcLSBXEIAXIOggvngrXlssM1h2mKQD/5i S5ypbl5/98W335rVevZm/76+LS63D3b3pto8WOYVSKwPlvqy2m6rm+Ton738/vXLb5/PXj+DMzP7 8sevv37+ymzL1y/3n83y9nX5b8Bf4Iq3jmJ5+2xXN1X9Q9WgLu7BCorBG4wsZRz/1FWnqYk4wmTt xnQM6bv5XXmzu6FK3jQYcG+mOVd33ECvt1qN3xX1ulg9PRnrUnG98by+Eq+/UzuRr2AmZ4nSddFw xIgtS4TbPlUeO/3OjCUO6p/FZfjipBmI9rm1VOhqLD1hmkSwlWed7SSW4suXL791e8O1XiPE7peY CfQFuUc7i2r7nrXUfqj1zul1hyG64fzwEqjfq7z9Cg7PHhxI2/qog5KQnXQOLVyrDjLgGKiOcVju k+d2cV8XlzmFwIYHE75VonrSmfVXyY48l/SUlTLu9e6iAZd2SMZQEBNGzpBLTNoO+sLbkuPhF0iy MgixblQTIO+ywg6Y4J8ha+OuQf81pTcHfo3BDsapVRgT5Rz/ZeR9fJsdAiSL5ZBRYjCygkayI6s0 qDq3JYSn9M1PfXgoK45DY9nflUDuBd1IhbWsbhiHjxOfi8p0bK4jYVTfFuB+S/FUl1W9KCSL7J9i 19wDMG5s7k8+wcWZX1TvC+spjvohnVuD9abrWHg4EHzsXbMjzO6qfodaW+7aomNgtmfaBJvpV+P1 zDfo31ABjKjOA7pibY2Vu9hf+Edqn7L7Bh7YMrk/APT2Dfopg8YFxyZY3Twzwh5q2FHdt+y3iDNJ 2CRvoCLl6DaGSXimrlkoxbbMotmCveByXq6yeDVxjryO3YnLOh0KrJtPGlxLLbL4XE8yslAixLrs O6iuzaUtVMpGq5uV9elz4UOq3x+OlwX9MG8WZdnvPAd6qL9M3v6vCrnlr6bd7d3N6pf/8vbZiGIr OJqNQNkRKgHNZP/VbMD28O1332YURTuis9uQojT7827ZMM4JeFAskbG9YpiRpqghIMIwuC8pZANi ZkwrZPzcbjfN5MmTK9PM7mJsbu+TvxZr866biT25g/EdUnDKk4tVdfHkZg7RX0+aevEEQsyfmCES etSTqr5SNTlih1p4gtT7CaTVXj25a5ZPcN6Hx0dj86HX+3IOedYRoMLc6/mKHICRgL6qDDP57fx2 VRhSl0SncSEgddHTsD8ct2CIVABk0zvIfkAEh+zE0ERYsqfmX8kHX67K7X0vkfYc4kg+y55OlIht hrmwIjaATSiMIDgx1xhlfV3bLygDunklKEasQkWH2SpRqfxXWJd8cz82Z2L8PQQIgl2HaTOHahxk P0EwMwD3V+CkQUTWvD3FVow8km9Uuqzn6yuS9m00JnjDm8N0PD7iGAAwI3OW0jVFCxDMBZ0nQ7v/ DADEaKmar8BwZTi1Ayq4vF/Pb8oFklVQFQOeewV+MvVS7vwWsxQUFJmMw4ES2J9pBa4gRCdMsmdg 7ZpMptnB3R+zfzf//QL/+5X57+nB3cnRofn7k6+/PqPPz40EbL75+uuvDbt3kOKJsNjxEZU7PjIl vz7rzVbF1Xw1o16nWW4kxD+OQE78Av9rGFouwes2ZbcjU/DkCIp88pxZf/PNp/gNDMp9B+OCb2Fg 7lscBnxN4zA/2I7Mds9qOBqnvGU5xTX2h2BHpaOUr6rb4YjPVX5tyGwC1pa8S6DoKMMiCB2lZ5Oo AmbA6tYcbgSwmt/xGM7SozOd3w2d17teTACn9Or0zCvgN1EXQGI2oDWUqQ5O/69Hzdlg+ADShi0+ GJJ7j9fTEBBqVt5o9Bc8d/UNDxDZoYtyjZ+JuucOzIzsXptVfgMJICF5vGJxwQRQL+1PYwK38iHz SjCfwkFIws3ZKR3cPTo6eQtLkJUPgwB61T7W1bgAE5B6fpv7GzA2dCKHCY2kjJoyuOkIEBDHdfdo AYBsYAub2lC5entv2vhlZ8q5PGhfUwWyXs+Xy4ZN4aZWxrU4gxkQqO38ivOFITlBEzb2S5rPaxtx TmlAyBWQXrpcYT4OOXUKAUBeFNAM5zUhcoTNmSEc0jueyLRcrtdF7bWZzLDJ8x1LboI+LEc/QrTX hcZQhGBbdo0Zk1s83VvAcwwSi405ZdbIANYg0WzNC3lZzGF5Br2WviGMPYcpTwfPng5GwtxOwYDX ecsuG0B+QVwqaXJtmhnLtxCL50Wc4gL+FjS4vg1GI9YHkCxaYb+EYSLML2Ij6KMHpuVjnRGklikG wbD9kYNF488eBmUvwtcyMik46NrOMspKwowaZXvfCnYahNs+MHxCQdMzsN90TMIO2nAPD4/ZtAjO e4y4hrl8gMEgzAFDtd1kyPeqH6AIWXAZL6idl9BFXXMgN3/PAiBnUUeGCG6k+XVVXQF/16zA0w7O k5Gy7iAs38apSdNhxj25cAOsi4HHOvxaXTUzqm+rK8PU5NzWKBilWvwIV8cPHxeQg1w17y+Qxt8J l0ihGtjRz+iQOtAnmrLOubPSk+ke325tR+hGZn68AgwuMzzcZiQzkoCJNt684HdjtmDl/fHmHpBN +uox5/PBQWyDfMiZxfF7xFe2f7p2nphWBuOBRxWwlHC1vC0PWQnNISHLJe+RwgSoLKIbA8EZYmhO ihF/6tz/CnBVci4/DIx0cTMQPIeAciHAXEsLfJ2mPET/RwTuDNH65fvZxf0MDn65xNQIFLmHHw8/ J7Yfyy3mTeCSvdwJ6mBcb1vBWyAlshxxOh7Dy/fYMOH1srpdR6mCIDOZuKc078rNBj8eBX7gRnB3 xTgNaVTKf9fKQuffwDjaxNvnAGXj9zbd6CnkQkFsNTh+AasGv1Ez2k0HKI+sJvdI1Fp1JjciujYM /UKrbOGkJ32No+doqVwIwPCOrMx0SnwmwdUdG1kJ4IuPRrr00IsKwyX1IXFsA/2Jgwp0rQZGiT6X DNaNBm3GHBaHU2+K8yLYV/8oABftg1xtyvlHFGOQvPUz4o7q4e96hcIujs/anXpxKU77oPzsn1nw MV1XxQXTvptS/rXKP/oIm1HbmDi/tBPVZhb96KPWRz+HoQjUqTjRR8WHCRohhaXysJOOnHoLfYYu V0xA3E0gRa8k0pvRY992JTA6Yr6R2IQcs5Wnc7sbEqMwePoRvB5dcClioZkQXU6goPM+Jw+GnKjL GL9m3//xkBPOPGqUj6cymtAnxhVKAM/Pr9RrjucJWBGESzkcPJae02FTspvzqzwUMG2XQ023VMDF KPOFTXcA4NJK01DGVU+f2jiN6CtG56b7gc+J2NsRExqb0EIbaJbMprorRgYMxOyCMY1wGdf3I+Te MNLYKxO1ONbDiajmA1fLZsWh662mGm3DafI8efVIGpuqB2kaCGbpo20TSKWHPKYUY3ErfraSRFqo uClA/QyTJvgZPxJJAsJTNYOXv+3ia9bgsQ63UL5NERHhVqKOgHcAtrilrwP2nkahmqk44q0B272p ERMKdPVj1B9EHrNOIIe6EPM3b+6gy1AY11ewlz4CzP7kIhz3sSECxeO0qLgoTeZSP6zu+8PErgkn 5a1erMCJJmAnT65lNWZc7aecahlEXL19atWwmqDVxQmAlAdv1K2o4TCadPghPe/j6m7rJvbbX0ZX NCCW/EMQjgKWJSEBcuKskqOthpyHoIdwXMPWgwSNJH5ldvk3X51FtVoBbF1hE4j9gy+QngutHXX1 wII87HtgrxBPAcQR3pb+ME42D+IErlbbCsjV/E9ZA+nsN69Ceh24+WgdPJoRLkTnEfiP30YkfihO /qptfGD7fi0d32e7pJ29tsubs83ug5NPTDumcZgBmjKTSbY2M7i6mDeY5q2LYAK3Y8tqDIb+a5qf ke4S1NhrPxSG7W+nf5ycDX/tc+jl+cUovtY5PrjIYPidCswy1Os/VEO2w3USVei8SL+K/gqe5w7V BrNVxQCwbQfYsK3sRjSnW/IElC5PROmSyam+KtaYNALMG4YhNutv2Lq6nCs8H1AYGhGhgWDjdQHu 2PP6fuzCAoxAXEyy5Q69fgTBGOMBUYE6IhMs5GsQgDUYSoFmXAQjBiWdA3eqaogxRKuJoL6hLRvd k0g1O0Y2t7ibQ0buiRsJes4QJh+24h/Ow8+ZXkAbx+FPWCv5i12z5K+uyZPWJk86mzxxE5BYbjUH WCVcx3/MZP4Rw91vfQLBiSkN8fARzymk8RoC24y8DmPpT9Bh52oNyUPoDEtXLcluPa2aXKEOyZdE jrAgMqQ8IOKbEvT+4b6CWf3OzqpzRPRMptpL86+6rnCZXRNiSvSrZqT7ElIclsMyu83SEJCZNDYT 9VtM1lpLtpO1+WKxu0HvjiZUL6PwS7pnJBlk8WIzGEj+1F3j6Ql8HRwRHkLjv+X2UQVjKP3yPiNL 2zKtHqDS031UjmOFm0XVHjstjtDmgbQxCGr4HSTUbNBiL6VwTKnp4gEOffwsrt2q+3SqRDP6Mehd /TF4ZjtkOrvfLpvatZVifPAVTN3j8Ej7ss2vu4KhdND2jgsIv2aii7sFMsGTdi42CAMLuCtpoENx 24uZKruCHaooGiblgrXcqM3nhL/2Wzgtq/cXJquFv6Ii0mZ/GK9ZYzqG8w6MaKg0JC5rB6wU/j6T U2j+wROZt7YHSezi6LdlWRO0mLXE8TeRIU4b7oZR3lgpXTamfs5tBFxzBT5N7wrzY2NLpCyLm2Lt 9YY5o1S44gCxlHTAOC9ItUmth18KvpwtixVl2g4qHqYX2LGAuxuxLXqaOq186IVTkhj3z/4EHCY7 Mk77x+OjvpsT40P96fPBsKW+O8U4vDwmFPjbqBeftuSBpPs2VXdvFKlpIKHEVM3NLwGXn39mOjCK 6GUzlTULfithYI/GTy9BtAm3xpUdjsXHqlwvDRmcHg3jBZIsU+HJt6BZze7mxjDzFhzKT6bjIe36 P9HazwArqX8INnqWI8ymw2ZiYhoRz4IL8stnb/8X5WBMPpy/TN/+Pz/9T+hezJ6vKOIuIQ2nORn3 I2ZcUX2/W6MbKcrAgs8+1pkhnZ/t5Rqd3+xHKA5ZImIvXSO0gHCdcNBlp1zkKGY242b9TtxqvzN/ fwVOUfNtVY/wY1GjA7oFdJ/BTo3R05UrSezsK5C6e9YPnn8tzOHoJYDRyXllfnUznwBQEq4N+7S8 XK/uVT4UIzXwQj4df/wYMNiM9DbHCMONRAtCL4JyIJOd+bk0Zb6YpeDqHvGm8K9eb7HbGmJ1EmXk moUpuYByIqUccp3jOIsXtmmrCE5Lv1rgQ9CDIb6haB+Q1zk12fcv37x+DpGQ5Ldh2i8bORDotYw7 OnZfmt/J30P/iN/0rAvfNIXx1zsAR3b0Z8bIhzkFac7ZA/lEwZtjLM6qmL+D/cN8aLUy0GFOgIH9 ZQAJ428ulmY7aUoH6FqIcSzVpXJF5Sk2woQVd0ZUJBGatnnce/X8m+dvZ2/+8sNzWSXlyToYwDrO fvjL00T+gezzLH8KdnAoABsKPUBZCv4WRRgvGZgXjVBG3n3aV4aTZ0FGvxxWPI7Ma1wrY9sGldXJ a/dsTVqiklDQfMw/kq9hyfk77oGTCJj5zDYcimlooCmkO+DG4ZvxDO+tOY+LCootzKZvuRVzUCHH sdXj5pgq18Yo4Sc84RJuYsORJPUwrsaQNzZDGZGiUExN8VOjxLsQTKUc2B2phdFxUciGJIESF+X2 Yrd4V2zHEPHAaViWxXvz55OyaXZF8+QT4iXr+e1MtGcIaACjvqwhLThSLPM7zF2KEIlqZm4E02zw 2QCt57oloNKDz6Pvxa1Mt/Aw9qxaSiNDCwURLzz367g2L2SVM1kaqqwLkJl+BhuaO5M1vDTmNwoA gwL2KZEd4UiFnHUy98OM0o0upcAFbZN9U8YYKwek1n2FIFrzle/VS9DHcq1Ma+CtO+PWZzOtVDU/ En0bqwJuHa3RDBuJuk02BKX0+prv7FJdNqRBVQt1kN3d3QFcXraUN67Jiu2CM15BZoRmDhnPQFkl 8WzUW7z2vUC3jsMeoJfebN4MkuOVX3vs/CuZ4Q2ZxjMaDhvLAf9Ze8BAUub0+AyCDrdDdGDwrjyX sKtR3uDAFXHw4tV8SgH/8Nbww21jeR/KnaIbKm9mdoP2aCuoznjS88tiJi8OHdYgmb26BN+CopYL IxKjn2g+220waus+ey5PHKt+Xfw0Y3Qs5mtDscBnpEQ6hRZQUMkMivflaiD8CL9kY45+Br2CIUkn xx97dyS10t1T0ktvxxq1waV74vnJUQFf8+Un5q3VAdRwo5AiEdL13TQJORZc+w2jIGjHmGd4sb2T z+WySWLKYLPwMMO/oc8DdEVO6eaPwMBG3Zlf+S//Z+leMh6bP/0CZjzACi0b5Y81g0fGQTnzuvja GWaa8sSvSQi1dB5t2gCbuA+B2XYbTsSas6mA8TcvdwjEoMMYue8x85vcjuL/YAapy4qcoLziWCnH hZ/25de+bDFjvAbbGmwj3KJcXvWhI5PwbqOcMLexIpdzQ6Drezf4HoeTQIyarQcXyUwdOc4c9ZEV ZiEUwDkcWwHxoEPkDYpLgUxUPUkPFKyCzzK/aGER7A/0qeb+y8t7WdQQTIccLwX5lhjl+Z79GbP5 NcfQGWlsLcExzQT/wTZuquVuVeBziBtdEIGQdOtKjhqb7+QU5PyH04FQAkiYhifvYWPmoTeEwJAa aFWmRV6v84ZygNGyMGA5BhZQMCFqNPVqyEPBJ0VyAasiPX3szGasVnRA/4o2Wd7KiemL7vGEwh7x amPyMOwXbWEqdKi5ntfFcoQB+dVlnMnbHsksF0I34qsDYjetMqX/RG1WX4+DDvEEYnMowsCwOTbH oz1EPDKcEO31jemmTOUWcQegaT1NGAQP1iv6Hc9F1BCmCISgSzVavmUToDCUtyhsH+OMIN8e8p4I aGo6Is0ThHX1YsfLNXLGGN354pKYyyyHdmU1oZM1Ry+tykW5TQRr821A4asolnQtZCB6lHo6hkpM 7GoTQD18lxVzOH5VbU77plpL6lG8Ex6JbyoKVTO/3GPsKzB1elVNa2OYlOGGoF0sUlfvy6UzpmJd OamOa/ci0Nw5p/55DvIQgyexIN3jYSbQeH6XGOGaNl1eI84bpEEE6KYKjSuVyVzY/tQ7nHfcB/sK S79DHp5NGmpHKFaLVJoqaSRfkakaE1ap98y+v/A7l/biSNID9xkFGSI9Heb/HBCDr/LsP+sRwt4O 254iigF+/vaH569efPf8+zdffDvUr9N2/k7QMlDCsxTVENrJ5n4CzUzO/djMc+AnmS0jaIj4fYLx waGZZ+fnOMDzcx2hDV/TrM7PsSXIm1tgrmZwNqDj7podI0dJSfWMMGxkYR4RCMLF+glaDbdPsCOp cr29ITb1psJn4LIa/495ARS/iYmA9X3wLVe/5uju56vkjSA47kBuYfTm7FAgCT3tmOaBboCNYDMc vh+MqvRMYK0MjDVrRi0AnhZyw87BqTu3iXvvyQUc2wkMNMsOs6YEioGQKaLiElMC9xl44FEjugB8 1rG52znAE6IVUHiInBk6vK5j1In3fFPEeFXdmqUfjjzSYlfAzIQi8+S/S8gQ/JtCWukxWLUHggpH RlGgvG/mU3gOvIDQ2dZsO8Z+QjwrZNi26bddQCgRsLAdigqFKoms3gDng2LBxb0kxQVdiDmia4t0 yVM0kzAiGyQhLlTf5OUFM1ADOVUhQ9S9PNci/Lqs4pXlyNlBAOAnKIdzun86Iqj7CgfQC8B6p6cD 3MOPxpt7WO6PZmwZGUQDvFpVF4cU3YtWwY054UXN6Wm15YQYQ2dA6RwkM+it69R/g2ayaDR0jYnJ h5Ex7x2OhQS9/YZiGfz2wWx/02A8PtUPCzLsNKG26qEm70f/8JAMJIeAGKNGJ2HNapMX11W5KBoz cPtb1idzfP9Mrgq1Ro31koHST6iKoEmhPhSVxlRVRDCRu0bR3ORMU0YRbhUiwf246pslaMFmAJ3j xw1HybH19VYKDfVtlJObCduR36cwpnjsmxziyJXODSBcKuAQVugagNm2m02BkAzE9S6qm5sKEMxJ 8TBn1WS5IFsuMuurgo1elFsF4nJJNFxtZ661aXY6sIIRYSLK59o0rT4W+JliZVAQAfUZkCXdXtKf WKY3lpPIgMn+40Pu4/2/Hf0dKmaDvx3/3fQuLQtUmKFJbnxmuP2EHkbZIxFQi8wl8TDGM8pHPuPx DGM9HD3YGJMa1VbD2EcJqhCwkPciVqBcSx+qU+lK9ZB/xGoBIA6AFM8f393CF3shBfBZJvKDsVIz zB7Q5wGoe9jXPZsOkLCMgAfGes1wQr6T84DCiBitrmKfbEDgH4Hy4BpB8wsMQvO0FLA6Y9cFC28g rqnGQBiVt2luZU2uAV5rPFa5EEAcwUwMDCtqhFRbcIZtEygGNQ82ZidI0cK6uefsnJv9i168gWnk 2Jzj0+PRydkwu8VDvAJeH0Tg2wrX0aoWVHPMN1vXd3t1Kk7EAMM7npJdaL4mX2H3/clYtSWmMl86 YNFAjTYhGQSPRp9dkBtufvjBJ6tF9XU8ytSnk1E2Ho/NKUNBjtQdc1JFYFp715zSu8guLS0TM846 Z67loQM1rkzm1mv3xcIPfLH401jkWoaEgGzC9MV39IWt5jB9wEfcPGer3FAdyCNBcozudy2IY4KX iTSuGVuFPxqGSAiFcCr7vearXbj6gMc4mMgqub0ZeNK5KeF9VuVoCINswoNRP7EgYCqrPr/DF9p8 R3+YN+UZMEjmC/zXfH7B2gnzlfypGhV5zfz6tb0Hg2/oEa1q87X9W9UCTnRl2fgJZjuSLaao97+b jQh0EaJU1HtAxzvGV1JqXb4C1raN99ACucNzDfcIgUINL2FuD4vaNmZUIwX1PuR8bO7RDgdkJKe/ IcxVrHdgJnD2Afe7Fe8ww6P9dlY2uOfFUmr5ycdda/lHuhq9QbHYLavv9y3feg1zsb/93Qt9R7Xi 2hsib1jJ2Lx4P2LvXGju1PwHnIOlP/zcMpuPpJInj2JW2V7szYtCTk6ANiR78zJRtkPGPtnaFOjw reFtAN0lcvql+mMhIqCpK7foPQT/CZNjmjUxX3O2KqjHtBeMt0aoGGghbJCIVUI1oRkdu4lBHy0Z Ny5qcOl50Bk4APYsMeplGs7qCsSM6p2RH+/uaV6Rbwv8PraHWhYa3ESJwcdqU73mU176nn8fWqoG O8XdfpcokLh+8Ad5I9SpK6i7hFOa8xfgHUc2W+deUO0MQUHnE7xqPBg4+/zLmLwIIIo8t7pdKJHU 2xDL+3pbbV5sC6VoA0waI7Ob19LXz8Am3kKatBFnBFxWABEL3/QCY2eArXeZ2VmNAejIEEYpxqom /3A8Y8czVwtM9BRLTzX7WKQfpCPiVUAQYlkHLMggbbz5ttmhUJ7ECO0FTw3ywLA5i3fAIxDsKip0 st36Al3dSDIG6GGw1n/8ydOhaQAkCUzMqKwm1vXDc24h74g+7XwvSt+kBxasm5uDQ4zrPzvpO0f0 WEfKGbu4avaotlDF5VbOzdyZSPtRC4/4nHpDDeeEpx3mhFcgCmlyXk5VnZiXO+j2tW7b0T1iEKgl tFF4B2xt9Sm5u3l7nLC6ECnKm8YDrjDKJaee3xJuM9RAH7IVhBD+c/YU0p3YFn3zQ1pmhMQY5I+p zL/XhNOGYNPWDY4hys0JvUGz3A2cY9hsZ/2qFIiy53HG/iA/gO75GUCf3G19PDDWqE1D9XSfiCbf 28WqSRTRN9samuNiwuz1h95wvivvynWuR6bU4eZLzZWgV0NCRd6Ktu2lxxU+6AO8j1Q4jrhs2dxy Zhw4vLZOdXc48KaQoKAQeSvsBn+Pzp+s5CVqzKE50Zj3MSfu6h6egI12ROJdsYPX7vIygWRmJOfT y3468MIjbcAvyINBWy3MAbIBI4BlUZlPdKjEWrJerHZLfqWnYf4vgt7me4YTQB1gXaxIJ8ZGZIWT Qw2NvRi1xbX5UTYI6AV+obYIP48BILFudJQIWJ+bRJpoNKGsqVqCBlpD6xoRPOSEJ4ghDLxc74oo TgMdkg1VsS6kXR3QZUwhLZFHIFpbivWSI9mBB42Pp/Rq/jmdHD49S/GNev/SLCMMT+/opNWEhmsr IVppvKY0D9pRkX6K9xH20IKyYaE4VbZCYDwFbfVpP7gU1uGy9WZ4JcY+DJSgqF5G9Sm5w2K+AFbt TwFPIS2llKrkSEoI6TP0WK6bLY0g5PuBFWyKAE3dB5hlCFEEmyZ1+im54NKn2ezMhiqEB5Iq+yds kYJJsL3QHz48HwbxiKMrdJ2cWRfsQ0M8vG0k6SXLz5pMl82nQqcUzl/kTStAC+BIG/nYeX2PpAf3 pD0TDiV3z9tI1Db2x+FEJagz7z4cb/K6VxCNiRgDfCRQnCuaGRmFZlU9A5PQTMybobFpwK25HssG TgmMKIl2hp6zINsJRrSwg6g7x7dyxH5V4LO02axKsl7q7Mj/Al2MyWObGHTnt5EMMJYpBv69gN7K 3du8kW4mNgDzH7x4bDRMLZ0na9jla+vUd3IgghFsOFYEwx65rbq9idlZ0CzFC9QXv9a+LBAWhFsh Wkp0foD2xKfDxdqFcyN57cGJEVpasPydU1FUtnsTuG/8MCPOPhiD/+gXi3eN5DmhqHh847gTUt0R cixbTw/ZsszepUuVawiSYGRiVaG8Ocle4WpUEhTFi+GpZ9TwY/EJH2oFOkOFh60MLCqnfDqP0yYn OpztylxYRiaZZ2xJR7e8i+ISZF3BeZegQb81ESHR9M+g7+yFCI/sfSaolOzgJyoGejNGQWtw+rgf dAM1EtgtDBQ8pdYN83PQRYyVlg8+wtAaXltwsP9T+MWp+oKO+s9puEAaglWAsZD4IWvtS1GW6tD8 wweeJX6Pdd5HnuZOTs96ilf4/ssxZPuYv6/KJaTsWALkA7XckI9WUbwTD/LZbFkugECzd5lqJwem o6rLKwjIxAwh29ps2kL8d+bmzfrhHu0tI84bBH4ufxqqaPEFMcfxxAbSsSGUf/v70OeeL+ZNARJj 6aLZ4AGuHdsEMWhAQWazYEWwSwsXR+2MpS8NAYCpwpUieRUz8aYSmSJNk5MWpFTgwaiMIEcm1aly CaDfNMOb5PNlqKdQH7TU0XV2Wg5Oa8+6RafWSA2HFYWxc9eDo4lTi6MfEohMLSpiGt2p+ScWGFag AIedqjWw7moMbk35u+J+SmGgGUxpgv8dKy556HIaqMug0DXsamjwap9jOWAmjp4dVC8LC8pLKnxb Km5C1WpX86b1dlM3pqkd2DR47TxNlZ4EfOtPxOphAnc/lvw8CcHcCTOOuCzqYzRaNmpmqTAQDvoT mgJq6jEDW0NomsuinrE1N+cRjqDSiEenwlRuLJR52i6q8nJZSw5IBTdjx5xYUcmuB/Y2jHwkTMXv +E83LtXISD/D3S6dpv2pmtE0nJgohD1iot1c2LjZTzr5hBIRtyb0jDUXyapJsFUc6a/qytTMh3v0 xNUSGinvWvgtYAD5DCEec25g9KsQpIXiW7edqfWS6kL/e2h8iebcA/u1H0oV2yukQD/S6FufHeS6 g0VDQ49t3Vd68yF3J3aq/u6a6QFg+VvbZj4EBwmuaggMGjQCU+mJ+tmXIJbLGTc02zTFblnJlZ2Z snwPZYZmsDdqzRxIuZk2ZBIDj6auxSAAlgvWOPUfNaePmrN+9oiXRdoZa1CmjoWcclv+gj505KSX qfxBHQOdFiryUBMtW/ZgPfP23Vb1spn+TU11Aq//39kA8cB2KNui2hOPxCpHQgi+8iK4iJxX9Q2G EjmunRyRwHPQGR24FRKjKOiM3fqtZT8vx8VYvnW+RCglDXu+IHELzuLrLYfeofhf3BWLnYRFgFMX OEGbP+sCvbZ6IjuYgoYPAVmFfWq+KjDGiPJV28go61E2VqlTMT8e6sovTPP3zD7j0sxXV4YN3l7f 4EU2BQ0dhhDvZ6ax12ZrTmQdKxd6t5hzhwiNJjiS+uqB+AYMruGQhfb22mkFJG6R5Ywk6nAL0e1u WXH0KNqE0mtvM7+SRdDuV3VJ+85nD9OtV5EvnQQRnthoIOan4TsJ3uWv9r797NBBt1Uc/VCVLhdB RplmuJmf4yaIWVWVg3hhfc35t1OuCuy29O/3YGc8w/WYqm8MO7Nlj+LczuI0gHR1V3q9BB9o3eOq WOdBB8Ou3uW9lpFGSG/BQtitSdBb+Jqwb+wIZ7a8+QER8WRWv/K9lraskjGm37ZLvS74RXMq1R1v FR8Lgd3nwy0ZlzIAf7gsF5Cn1JGHQWMjCongzLcBzZHLDYBfTCSY7gDQDZrWNLmB3MhAhfAgS1gX ojSN7d3QZEA5Dc9Sz693H3CL8dDxVvKpi27CAVMqvPtzDrfFWQLmbHkFfqDm41qRfcpNqlrAELl3 kKK0xpmjjyzodBjuEQiuy0zqxp1VOoWvWaOiPqQBGHm8bMaQBnV7vWvYlQIFi/niuggoJCywVgtT /iQy7FGoqQ0kdoo2oTrxGQqjojzpBQxXWBPgSG0omX9FuB4mQoGyCBOp31kVV5YIpkrL2iJ90rCn EsKMi6JkbNXLd4HA4ZYHQ5Tx18OV2aaVkzWJ+kLLvBE52ShvEzY+mqWtGsWFoScx05SSw8BQV3lC XIjbwElEt9TZ1nf7tKMRW+6sE83bHppppi5j7jM8o2wwGGX7EDDYZHoxZ3jDLGuFfFRXzfjgdRa3 F5r179ZOse/Sue/P2k5eOoxPNvuhdXdxiOZbhR7UujyBC2zgvIrlLcqIKc679cJwxa34Ii64AP+Z AYAfOBvjR700EdS+OOdPbRt+Aa89yQkmn+OiAeUOvxIoLUpEkhPTDR+UOzAl8WlQkwe7RCHCaA5j MF1OY4LuwRP4MOFTQVjft2VTjF0EMrxH18gEoDjOASPOuCYZJPHi2hh5jJIrm56gF7xDjTylgV0b yrsoxu24M+i1hk73zqPNzXXsDO57BbvE0FbYCrn6Tl1n9A3MAj9RTItfgr7jXXhYI2UFIOD/kYPm +KF6joESAMnOfhywcDhjDrNk8yZ8JaBk9AO3cFPUVwo0WTxTsMzYvuvX1YqhzPNgTEm/JNJV8MJT 3bH77kOwkSL1ru8z4hpNanYlMomcrqXopE1XrK8Drr+6EVESAfOTFBx25+NJNu2Gk+jA/ei6YEok Hr5kbP8aUWSVRV7d32feo+oCOQs6mwHy5n4uU2xfLm6q8t+KJXrpD8Cha8CKyRkFM+Lo+fl/yKLU pVsdY4wpIR3YTGPRmHaGb8slFgOLjKUvraIOhxb7roAtinwP4a+aGUm2EwKpAQ6RORd3IG3kp+jZ nJE0HW06bL845vfM0+aba0NV82INlL65x6+nrtdheJ1e36+387sUzhj6VmPjfDZa0J3EDdQG37xA Iwa6hRabOsf4ZYz1rrde9hIagB4+gZ9+VzZonkwMqmA/HYDUZFtJ4Eez97D7AhILT8YNdzn5ed1v K2mNu+BhDFGaSFrFM8h5gqTbyLJHTfIH6zYCF98hbjTBoybqI4yowXl9YD9/fvH9G8ijeVO9B/Po 5h6FEzPwJxk4LWEveNefmPtPGB2JVnbr8pcdSjyE/QjE4r7a1Wqk7EMVV84eZcXYi31xUXR4pTZ1 aWbolltFOPfxFQkys6ZSEZsvm3IJzyNdW3h7QhoALdmbjjJsTGbMlzNre7oD0GlXkG3Y5osfN547 sMhcunZSRtq3fVuou4M0K3xg3v+Jdn8zp3bxDhaS/A3wF1q9QLkOz+aWQWDmmUNPBW5zhKo9p0+U IDCCKdDSJ0OVVnB2IQTWy8HIgyev3PANTIG26jmn8hCpn5UX4j54/qqisuSh32zCwA9JSb6qbtcc 16dzaItTIKg/U7ve2SYkOuFhdDT6n73Tg/8eW23mmnKhBH8Nw0hAbKnAKJvvPmizdRuXwWKQZLVc 2jK5/WtoASQpFmdvFko04B7T1O4sY9YCBEQ3pYR9D+Ni+s+OwVM3iHxR8Bt+EMw1ooEnyLkIpMA5 k0GhqhGJ3vmjEErAsMU/J/wmbTp0kQ5kturnw75nsxqe7UWQBc47SS8HqswgQS6pcusd8ntwl9R+ a3pguNbBSJcefnAzEiC1ZzuhUzUf5EQnMUGh1UjTk4dWJNWH/c5bDfvt8IMaUOvQ0kJ8J9XND1fH Sj1y3BL3tENoUW7nLrwjj5gHBFD+z5FSbDR4u5yyLm6teJsaRGd8jhbTcFpOfYUIYS4QCf9UpO4G Pltv6AVlbEZYFvPafK0xd2y4m1O8dN90aN5MHo20nPARuwEgGw0GMQ5TjolzCOnWBuBK2xT1+2JJ uxkGBuiVCYr6qbSUAkEdjtbglvgY6T1KHO/OLYqfseQx9RQeNtcBvT7trwlQGHZFYOJJNQZBRDnT EinquJWgdMojJe5DNnDfXuLyrh1wlGYUJ+9V4MAs6TzxGgS1H3gW/NIJlsNn7bB7b0YfytF1Ej6P 5Fmqtql368JlKLBZptCXZtJ1U0AlM7RwmVq2Yuyny91qhS2H6rZloaDZn4HhyEeBVwP1A5nA81DF tqBpxjRBP+CfqcgX9sijGUIGA5rd2H7nW7Z0UZeCd7Hb6nB61c9U/R0bvFRrqrmE9UF3u27pN+m+ uncXyG539WMWBiLRsDubIiGZh6ulEQ5fCPNeDNtC3+DgrB8Ycfue9MIwVH9Xk0MbhpIMRKo//cPH jJsDfh6Ab49bimcbIEQyzHYBnj5BbdTdERxhBlhNYGwEwBLJAo5+/+Dpjw1EiXPjK7O9ICkJjJ8A qtlP6pHBLSKa7jD7PDtJLyEOA3JgYORBWPH0GMLK2hefsmc0eEM39QwHmA9QMTfQlAR/5cRXs829 T0pGGSv0IItw3ycsMqKiriO1e4DQM0wqvqUBtB+CESAmOkGCGa9GCx/lMTTCTEWzlPn5dBjniv/1 Qxpt1XB1qp05nXUI/M8GcfpRtANGgsNYBPpyhwcNoeENP7IAbwDH3/Bh6jhp3hPXdfSkKdrAtM6+ bW2C9WCG0UEaBCud5r9bmOYD4u9c5D4q1TGiwYF4wNdwrQkme9VU2jUEDX5B7lhwt9hUm91qXoux VseClGuK/KBYPWFi+wTQ2QdLKOHvAWw72b0IBiMLXIZ9jh+HgNjFY0BenPMpUapOBOfyVmvsUp4x 5pa0MSsbx6HOjp9+HOSUDrjXDu4wCAaJo0WAvpSj7A7Jy3p3g87D9hXPh8GtdV6raMxulOs9giiD b+7dMHXRLcYy/JEKPUI1PiQBI/V9/1GdMTqTqb+29enMPAKlhZJ/cUTDYS8ZrdLmsyJOuaePluCS m5V76JNsncGjZoC1UmHr3VEyUf4MmKtDbycAOD5660NWwGOTbtoR3PHDETYrcbHDZQv8s61/QjMl zEVxEMbt6opN0VufCqWNA21wx3LEIGSzbFKiwnL6BhGC/5bvaIvJ11Q6PTob6SxvMzBeUChg4jhT BLapkxgC/HA86fLY4RY8Jyzvesh4wqYEfTq4UGzzF72gW0r4GAocA9HmefoelAjLrZ/RBWr/TjLp jaVeMgiPYMBsGrSVAzD008GA3A6/gy0N0S6t1y26+rUJ7wGwDBJohi0jmFJNtB9wAdAeD4CHCNnh QUTBuKeS0TAJnJ48SMgZUvviWdeGqvhr886sEvs2ZNmLLVjFGmsVx5IRmhuFet6yJyC6KdosgtlF uSV02pXhM2GYYz9wyE764eChZMyQRmdFFYX9As+HL4G6FQ5Ckcp9tsPhO76iL/LY8VV8o2besdFX GEVW4H/8w/LXxk8jsi5uFZhe8FwJcb0sWxDxVG1LDe18/F/ixVH9qnaSIPvpyfZ6M0Pv0HW20bkr xZ4gvvY++lDCWSzASbbPvwoGkz/9AumlYweMJbt6e1yBTkQVVYFI6vmqBIWLm1lLmZllCrb5MFkG ++lqSjtq43DYJZRCsRvGwlY4rkuIzKx29SL0iZPYk8Sk2GGdflF8qpV9Eou/gOJu+7y9ULGGjXPg pnT0ubcpXkn2etbldAoSLiXz8MrJl15JnpZXkL/zyvne8Lq094tfxx4dhCHTx8kvp86LfziSpWaa jfS/TZSX0xOdqPBdXeicZwgUALSi2jJ8UrF0Hpk+r8IYnPpOOGRObycfSIrWX+6AXQH/cmLbwMA6 9CGjsIM0YkdbFkE1sICE8Vv5r8V9wo9GdBbeOoI3i72Ge/CpMXSRJ0Pq7cBS/yKAXQ5fY9niOdY/ ZMiim/kmN7zaiDOw5iQ2e6dNL6IhNIhS7WDFIKtAo11t34Nb5haSlYxsONrIxm8kvJrJFRjybt8N o3iekWkOjsK/lZs87COJZ5Y8fHDseoH/NAwc0uLC2ScENJyKj+PKTt1KmxvUHAoOrPk+ESvqAnXO JOkgzTQxck0KpIZ8Dg8Xrkr3caJGi5uNGS6eX4tgHQgrerNFZtHxkR79E+rl6KE+G+CB6AKrSbKB c4ADCDYXZeD05e7Yybth+vGVccV0H9hxa39oW7CH1kASYD3UjkYFaL/7ia59euvTWIVV3LVeXedn pjI1OiOkXKhn6NMCXL8TNSBbRsHRHzbU6TsbEurZIH1OlTP7rAdbjAxCOQA0uwR9Q1D0l6r3vg8e 5hz9fFfymLrpRlJWTvOygV+GTawK63h+rpDgm/NzAj2ui8OT8VN/HCmkKDxxqr51AxaUgPSqOgkO /5XSNgs5paNrGheedH6eDDA348Xoc3bjL+5xm6ASGyWjpAlzynEizQjcvQ2/YkW9ghlnECJ4hjlb gaMc7NFOk67E+TZDyN9s7lqy3aO2FRGPJJdf+X5eazT+ZgKEA4JD/YyTwO+XtdMceu16bfF3kyzG pGyttFiZfnkaNmN4XcQ9qRlk5L9/fg5v5Pm5NyGGJCTnfu2OtV+7Xlu0DRMF8Q61JzjayTnnZxUd 9TP851x6Y48BD4fcphAIVy0W58ZjpRyfTDJzKTxC82NTxDeIEYD825oQsFyWCQ9Cg9EzECGDuA+G yEil9mUk/CnXCiQ1cfcMfMLtQ8HwCx5IriugZuWCl9D20RHdM4vjMsOaSWQEBjNjoJSgTYqWj4XG GWUYVro2EvzsiuvkIGEIlE1+AjCDFIUVJj8c+fGQ4Q4ATf1iuQRB3UtdyidUXT//qFN2UigCz6vz B7pUCVnE1YXQ1GTU4yz7wY88h3vD3isq6HS5q6ULtmNA0c31vCkoU+l9tbOPEdkBHDJYSpwFrABQ m5iyW8osw4HwEKuPmOYc6yNhv9QoBPuOnbGV8rDKLTO0GXM1HDZgsUDdMwOmLQvDGsAfmLaWE6QI 2kCbtZG31SaaeYIaXl5VrMnNN4kR0apPMJmxBOe7zVhCQqYbQ5uaDCy21eUW9iRKgwB7IUFgqK2L k+/wE0KbIMlywiBF1DABkLx7aNxYICQtwA+g1r5PNdNkt0BubUPq2Gc3u2brp/b5/pAy8/hCCVFs ZFnw58NiRSkyXaaeOY2EzDlbeKzw9TWnKTWocP3lMEXLTzMAILOqWhXz9Tj7Qv9M4BODSCHeZHmz u+BXVJoZYjJbjBaUmydgxg0a7zmfW135wgUUdtfvOayCRVOI0uzO1zqmFxXD2BFggXitXlgGZ974 MZ3IvHhLaJvUiaJDxaFlScst4W+wRxteHXe3ycin6EPse0RkgrKj4qnmm40RjfOtJiip692Sl5gv ppjRxl6/L6SkKYbnDOIxUymM3eEN0xdHuMVhKuOwQxkJOJ1LtCG4pSPNsdc1F+8M2zX5LQWJOPBw y2yrWvhjeC/w2NE7jjPwciM7q1u5ZJIfpJm2I5E0y6CKjCaTyNG8f3Lm1HFnwhLsLSceB2WOY4G3 RK4lfS/GxfPauyTg/ojf2IJmo61uFbMg2lzvmItT6ltU+6ChF7wuYJjPIKVijfl61/dyVw7t/RDm kvPPok1Em/Fw8vgYmp1c3oORb8GD5PeaRQIAyMe08+0QpZ6PwLI0+7Gbr3ydsXuTii0FH5tdoqQn yFib01SAu65qqrq0GfL8PPO3wGtAXVx0viCIL7DZrO79AFu2GW2dwAo8qbZ8pNXW1IEZ3MzdwQjo sZTnxTfnq0x2wcNC0dPWeEoFR5hT8CuBKk4Y680oOXrXK8n1x/Dbh2GrcEU0zIBLk8zDZvxrGQGb aawySKHWlIjH2VrxlP+wgz2jpryN8odncXRonCGgd2KHfFAbBbittjBRrddhPHf8c5cFXeEFnN6N gS5u8qHTctn3tNmsym3eH/WH0JUtGUEwMJoPPeTgZ3Q8aVkkPpc5nCPqkY+j/fksnJ1j/3rt7Tll lWn2I39AZ70YACUdhceoKg4apZcADSKInjGqRfMADEW0sq3Ju9ImSTYsMHZRJN7t6SOC5ui1RbrT XjAq2Wh9NRz2fOM/ywoloTVMUppnmBEgEI7hRTL3qVEnjRJk6tRF5Cev2g0Sou/bsKgPo6bdgZde ug/8r+ws2DzLCKdcN9UGpje5fe/sSpE0aZ65R/VEbSNinIF+Ek84bOp+lDO59QloFmdIwOzmtJvu iCwv1wkgIeuxBRneg+NMNcwPwddNoh1kjMAd11xZaAr8UPj6Jl+laPkGj8QpynE9KN49AratGTy4 XH5vIzuSYZyqKkQApSmVSwCQqvO08sIsxlA/4AltSYgap9Uq5qdT36w8PEvlwbOmGjE37ffIKysA zJstVUDDPRqaeijtiBWQmrWRd9YYW7tct0WuOVXzOtuTX9APPiC5eUtj3vxO417qf9rg1zorm4bF zXLYoiaTIk4PNl8SGoZvi2L1YrmcqteNRqO+CRReuVOIjjBsX7G1Q1SHzVEhhtiJkSbMV8Q65rxd X6UF0R34RX1fbQtfThL5WWY5VPj5qmVm4IPmN3UJBHitUxAsMXm54c6BezZS/WK7Yw9cB2dnRvKX aieSI6pyEMRAxqCvtqdtQxpy75Ibu7zMbqbWHSgQwKy5y8kPfBTx2YGI5vqeJCpK3g7aqEjKCXXv sQg/cVKZ4IRfEZYarAqg/5HycbOrN1UjGigzTR9DHm1ezQ6lECPhnJfLc1SRiAiasXNpuYwF1XBQ eMxAZ+iEQhKBpGZxB0NZEqgqYRDKCxcpuAWuiaexvTai59U1W5o8dcz5eWh/01p9Rdys1xNzfkBX FRvh7L+wUX5clqrZEhir3c6SFk/t+Ls/l+fAfDBYIhcWBVgCaAUPgSiyXD5D9jruChpM+4BZ03M8 xQTTskT6RCw6SOvFsp+wYrdZntEBCJ4YRRtVdXQP2tahUbtcuucxeoy7fGxMRWSHs8hTANoB0oRd dXlzeW5M7DyQchtIUX0LNw4OCD2AOfjhL0/Zc5dgZ8Ax1fNKKprFfFPMIMNhA89kS3KXF9a5YgNX ad4sSiPa1oy+Vm4zDPWHpTQPnwVWy6j1RhFVvJcN3C2AKjK0joosMceiWumLwc93i6c/3118bP79 /c93yz8MssPPs93gZ/wef8Bf8KeewqPc+mcKvWov3pfVrsn678dLTOSYDwzNgT8OqfvBsE8UJNbo vUcvst328vDTjCsxfMWleSIaygDJFmBS/Y0wVOTWU0YKiA6rBL1JE++/vsdPI8AEXVv45yhHzJyH Ql2laRF5wkwimAww50wkN/tVVY2vVk8uvmnWt8/8mIM1THJJZ2KUzThK0hxHPixUIPeUCcofwKtv FxyPzKAbXR3dcnhRFvW8gaxBqa6z/OD46NNPkr0PBj3X9AcdcYBfO+HeMcHTtkZdqkVHAhZyBDpn yZ9saON6cT1fXwGBvNQJatE+A/GrdFXsyQivBuaKXbOy/6LEhxs09umNbXPHA21Q6zqTQ96PdHS/ wlIp3C3XEm/vgMZsb4jAMZZLUwg1Kw5Jt1zesQgysd7/5lOHIyEJNJfr+BSB8qQ99i6cl43sC8D9 zHvc68WBGThs3OLY+y8+KL2UKgCbyC9X1XyLqekgOq0eoXGKnN0hfGiYgKUzxLG70VfPv3n+dvbm Lz88j2vDxnC2LNcAqooUvxAC3WKr6F37HBxp9xoSoVvAt9iaBG1jUwPBZRmkByg/u/bMA3SSHBWT Ui8Qz0ZPAEeO4ib5q5ygsWFuya/Yk7RafFGt3xsGrGQse++BkveJJjwUr5AwR1Ors6tepfhKJS7T QXZpnmPmJ+NzGbTNt2j4mDiRu6G+aODKgLdLxFUnwKr7BqzZDLmZ0wfuZy8R2qvLildp2B1rY0NH We5Y0jg/pKHQvhOk1Dh104SXVmsWorn24nHvpYo46ykFMi1oMxxmn1kVjD6EhtsFPM57iqKxdrR5 djFfksqJBI6bYr4mY5fY3JBXRlGm5ytuTnFjh9ljFLjYxleO5JM3ahiOt9Sg3sLFhTBxG+FBZice OOYPEw+oG0i9y9we6PRn7Oek29Tf5+JpNNMdzKAZOYjRD7YOtzH0eEzfF6tHPCr5WrE9euYgZZDR 3dXLsiYXHgRkXBmRTITn7S3EafjuXYSYPiN3jPlqdluX4KXNi4LVDDG4APgx8YkCHQ0eh7zPP0m6 WU6elA59IpD590YswrBPq07zcOS1oxPIZjeR/1MMKS/yoq7qCHmoEVTFHoCe9cC7Ncy1NhSZ9aUo vhXLvrkrOSZPVtoTZSySNRAZI4fLo6pBeKMhBF3KrqATleq2qxaNZHwBwZPFCpPGmmHv21Fik8Qw 4aaECdLsWQRXHes0Z3dDMumBBCZpp3hMo9RRQA299OAFd/hd/E4c85LIBJyjSqWo7MtdSOX73d6O AT8ikQzd/NIUm9wQbrBB8GW25nCkII8a0Pnz3BIq/HBpQozZS3vpPptmRxra/vToDGEBZv2HgZOl jc+zo7QygVTB/UdNdnjIY7bLLxuyj1KC2uGqvXAFValRdlUXxRrzpw9/yx1aYpX4FpjvZzPQFPky nPk6VgAhPAikSKwWYicV++nP664j0Sec1sfYglTtWiev4qMGgB6hV2a+7NGG9TdLMEpcSDNJXjTB uXdrZc1FvEjeC8Ju23Tv1tHDoLJYAvSriwGl6VhsHx19DQHiINXYsuNEmmtQw0Fa+tW2yr1x2YGE P3tMkVmkR0tYj8u1JKZ+fGwmf5DxMETNhiqkhoMJaHHoq1zChGeFyDWj7CNS/Xz0EbshuGgEfkTQ BWpOQccXZonePfFzF3F3/xI3TnQQPJlQqWVEVgLfyGwJjZLvYPI5DGJDGUxB1gXX/CQg87l4YXP9 F5fsSfMDM/fj36NT2EX13lxg0JED82Vz4DqX/YZ9LcX5hp/oycQpfz7//HOyyfFq/reirr4q35fw tCObPtRO3WP45/jJEdV/iYjC6IMjynnnqEZuSBRgPjfyxeFFccimBQbICkbRNoCRxRA1Hbvb95m3 aDC2z6m9KjEqsPxelNsadAV2gDhta0QIh4NxIfndcCJn9fjJnV6JPcd+OcoeGPTe7dxN95n+F3AI 6iUgxDYSCFOiazVBRTMxojxmHFa/3H8v+pf50bC/xzjMWUHFomv5JzCs0EGWqBS+1mAraPA6eueU YW1vDX27Jpcnhwa1FmOWwLwEdbN6hyjZbEJZWqfHzL/Jop1eZh+BW+9HsCqUBgiwdeXpiBz0gt7s afgWfZ2rS6Is88st+X8awYyzrT3UkufxCuyM2qVx9jWgSt3NbzYrvbCpe/zyNd1eWNiirpMmDKaF x+gXZPPwoVKXu8TaTAJ7rR4T3Fdu+llX4+fP3754/eb1KBuQ70RV35N7hMZ6jUdhKo+xAUCL0w35 AyPsKQKD6Fk1JGolyE/0smIHRdj7ugKnWPHXBi/VdZbz0Smsl/kC9rin/YmG/2Oubu83Lu2tv7Q/ kOgJGihlJDgM/0eFX5c3JUA3YXr03dX1Vj+IHJ5mzj89YSPGhCkxUyGkSxNbK7IrhuTyxjTOAmCu aMuLad9L9AfFZiiazewxP5mluWT1pkbrp3kVTFu7DSqQr8zDAGhezrzNj+4zHpVpBXhrNaILI0q/ A3Jlv8sW9wtm6/Pz83Bsh4efx0sCXyJCnSHIAJwHey1r4FEpqs4A3boGfE+r9d4MFF40YO/pPYkG MRQVDOKH86K8K4oNevDL6tkJLZ2SBOkmzg8wuACsEO+WqRV2LjF9NFZuAbR0ED/5HpwZtuUKi6yB 4EGb5SKxAeSu8LoorJt9dclp83jg5+fb+t6sLIJuoTHfcNn4jJNZ+lJCX5bF1nBnPB2Io6pv5mqP xVAwc7iJ1+USUi2oyGZEywu5QHhSv8DbJU9jkHDEpoAAa5Q5K35hVbYuNqs52PV2NSScpVBCC24j XLBWcBAkGdikGjBKmaK7C3Mrbp7Qm3q4LN7zn08QarF5cvzJHxxPrjVfcxnVeAd7w7LEl9SpP+Ts 5yA+OWvhjW8aCKvL+/ZbFzBTrZaHBGon2DxV7WGd982O1eassHj95bwpnjuuHmj/I/EC9I0BKSEA vQ6DWHHzMwEyhsWTqgRR7ZtSeyCfwcQfocULKygTgd9W2LU2DHQ1GdUb9nq+N26cmPUVvlfPiMdI tZE0raCbNIBfNVvN/wPlHZECoAm1cl6uQCgGVdWhI7gtyAgDciV+zo9D1QB+Pb6cIWVpyGXNK2NB AwLvcklIwmIbk0kKuiDvAr/pdgNGgJT7Gi3AOCUQf2825SpUFSmRGV7PGc9fOqR4fCOMggYuMHkA CNayXK4Hb1A3ntnSmFWMx5o1FYAZI7ohWXv+FDQj5gwKBTYLX92bG4TBZ1pQYRvMQ2efT06LbJoA VGJMIz407UuLce0omQOgmpLO/wNG6DnnfPXiq+z7l2+yV1+8eP28bxGd/LvxEKpT571Fh5LEKzFt I5Kq0oLhvFBtqnovgGXh7uOupJYFhlsXt6Zwck3SOPLchtflnZrwR9uN6rbziWQqtN2A1jLppdS5 H9qMbQjE+6IGgRPTRmWfZfnJKPtkGFoLN/cnf5gAZKgd9RCOz4ziCynQ1Cag5nDFKGzvQLFZBGQb /MyOHxe7q2ZMltVxVV/Rs/rJp79/mn40LCU0CwIhMd4zlnhIYNzkKIGDGHnI2dtNrJ/cEKI2V5K/ cgqzU9WTh8aCCJrhRScDZnahsjVY5GLy40gfc9DX9Q6Ib4UMuwtJP+NCpQybZsoEaQtCEFo+JC9M 4VH2EACG4als81ADzh3FPTZo0UbQMQ66ZrRWdkEF9pXkmwS2gw8+AKgZaCO2No0EZSA9uiD5Kf9g MqMFAfGZRpsEgi6FGbfTXIzXz984xKOpACmhta2tMQUVEMEdeMjKFlRZ5uCPnofMxsp9w8BkcGLb jJENmpBt4DgFgOsUIx5OfNKWdoFL97rRhFQ6HHAX1elwuEdY8kQnCZf5uFDYm/Waj0HdTG/y5eTh hgIQJJt3wME9tqSp0niQnblMAgDKNMiTnAKHzyvoEvFRsL7wNhPBrGwY+Fcuk7aWUJEQwdJ++odA aMCRZidkP0Wk+j71nLY63bbOKwnWBCvhZ2zoywnpG7KcyGwoQMk2aaeOEhhmnDUK3SqSEVeJrKSt A4jfHXXmvTvQFoYicNBetvsWuDAhnLZ8uUz5XctopZjErPVb0rM6FD3dto9yJcDoLfCn5DHcgQSF OxyiQMWQQAOb7oSZsAjlKZHuSeel8lJFdaQ7YqhimwPaHVDOAD0Gt9q8f9ofAmPkw5x4PtpgOT88 TgIho815Up51zsEBlTPsYdsyzjb3ME149qOVzAkcCwI/KM4URS7iKnh5QYtxMj5hAHzZSdZSJcG0 9GWPbmsaudBH4+vjK9Vn7F3PscQlE9ittwkSAsyIaHS74Gv8PEgE64cgXIzQRWuGbum5W7+pOq+t qZgOMsS4s+hyCuaGUnNz4J2RMclh2MPPiT1NNTVIQv99SK5n68DX4lzQjJz92SZXumzou0jYRhax eVdu8v4V2AJwOi60BZ3grAX0EaC2ZdbI3OuMw7S+mCM1Jv2CJRkp2g+dX0ihCvPe9VAVcQLXRAJd c+GZ4I1UP5/2OY3oGSrRKN0uOKDY7KJeYWSo+xagL2rjsWnDPN/9UVBPRJS4qrQINW2pURbUt3HY UX3VMjRhC5opCJfTZ+8GrCe0g/INErO7rBaai4WyS8IqKLBOHsIrY9igI2RgA2ZHEeVda7GtyEEx vEMqqMjWw5gWNTtiseCLs1Z/a5tOaZiIgfHvSQ4uOai7s+5yJRzaQ+xiKbZB0F8lzq5Mmt8SMlxF Ep1dX572iDFV6L/ancbzzPDW22E9+k/pgzLaF5Z4E7S8jSsD7S6H7FVxuNlYTNk+6cco7CaAs+Mi IdCIddO4JjdmSsEyX4ENKQxPg0UHB2prfJHxQOyOxh6RcPDVfSJHXiAVOgoecpvqcURNo3xw1NyF mMOykeUGFXyyHubPiwIfywjBLOSfw8Bu0/hrtD/b+Io12qK9m4okw9IczHCM1Cp4vrpgGYjdF8Y6 hU/ug91pVAZPSHAL5IkPvwk9L1QtuzbQOzox2l8pkfhSmD+bTgfamKdaVzHNgjum2A1lQ1tjzA/F 40I+BWtClCNE5KINmxSeYCxhWTimLz2fXQVLnltXHypQm168nUnuGEaEW6/ERA4+z+s3kVkZrG7z GqxHpPqWrLoYHKygiTi+OqgMLAcdVnJ5ljlwsieOmDW0ZD034wAIqKABIOPv1pDHyHAckDnUbMiT APKrl/a4dWvSKrRDqW6wBLt0IY2xyS3NidAxlq1355SbOvPdoRWzqYeOiGVge7i52W3xCaPk0uD0 jkrXObwldTFvGP5QQVbLZQuun38UjobZYXb8wFmAVyQ/pPY+z3w/62aYBKrgt+xbw4HvNvQce2vY Sh30+vjzEQ5ArSUBJLTdadKzpW41ooDdKzRdeQPNM1wtSkQkYyuxexd8CcO7z+o8cJABj8lnwoYP S8IwOA+DQGKDLvV7zJmsTasOSQy72m+MVtMXjI/ZUzdM81KlRkjsSs7wYCTTtQHo3rqkZeBjpYdn Wje/uOyzboCUBMDcK0ma98zPiVxecuWk6Yp+UrOMAfdbcgXD5OS3YH6VxNnsPb0DCL7ZEuzoboO2 f0pHDw4G4iMgRcZvzH+eGTbp6xAUoDPlgV40xJ62nNae4qPC2w1EdsWx+O+FYuXFWSOND+BbE7Xn c3kDnahcOd23hTilZIZk0hbth+XcsVdtaxodxO+wp2HrFVJXHIXLNuoDfuJgjwM2FfMyaVxIi9eN WHoyYpf8eb+x0wDaroCIi6kBym9PBNhPoXgIArBijODtax8S/iotto1GYr/SW6zQscUku9cKSKSZ BpxxmYQZdUY+h6j0y6X7zaVRtIeJXHzZ51pcUd3VwyyrOHDlmtoiTUE/ZXPt6X0snItPUcCnYdfs ECQTj4PL29xcz5eARgGu4Srqh5VKC5BEoqRCejnsXwwUNPX4UsuWdi3hSPw7lVPLiiWxFOPrg8i1 bZ+XR9LrPuD4+OupGg/3P+V/1UTQd5nOtyQ3wg8hkDa5OPOPhOLC0KsBULzFbXFm7jf+Dhl++XK3 EuQdgqERTza0Qszl5vHFcxjca/QJTHQWgaFSTUCkmWzuQzR6hHb0wCnFudN308FwRjxJc4uYZL3K sZHvv/jueT4ej4eAsL8XNEBMDE5prB7WZDDxPV6wCP6E91FplqFEgb/xTjdXwTZLuEnMtjpvQUKp 40zIAQHC6kkpI8EIu+Q9NBR1u2L9porU0xcpodgIhGh5zks0+Pf1r/1RLHYPQ9hGl1CuDauntDDW Au5D7047FJD+WTP6ki01KSSqTGTzhaGSM6ek5+T2Lsm82PORgDkNiyGy9dwcuxRUvmcTfEUvCSnP gE4L6jxHEOCdOD/HXs/Ps3+2LZ2fyxDM14R9A1/iQEAbtgb/ahmG+cJitxMiln46vKYc88J4Uvzi CNA0IooDeA0bD7Xs7cZ5i2hgdUEXm98impgZ5k9wwq1h6ClSJ/TxUYGClNm8QDdxbxuGFF4iQUGi wgOxdAVB6HPaDI+URSpJBq++MtJuQZpMpuBZiFngcLC8l2BoE31YQiiLOHG9mKEV5XuKmTJ7jhg8 kO8c8cXtggTg0vAjkNN1dWjRzVw4GywoNdhWn/wkbWgQu1DtEAn8/FxaOj8fwcoCuaY/6eyen/v5 V2vcVHwWMaXHEiHPBKPO7Av8vSovC/Ipry79vfaHJsdxAswOQZShJ/8aIS+oLfMztJKrRCTyyrdi /YSW+rFE5w/ozOD5GaTSgnFovCpGuQ6J8bkt5u/q4vJPKqWsKQEjnGZ5SNBG7RyHowdDv6kgsbga RvuzRgjIWOhUxrNn9jmVP2tGlpeWSTA4eMAvud5DK5mdkBtRIvUZqBSEre2U4Sjlrb1qad+BZbFq XQU/IwV1GePs7M2X+svg4F68JILeU9KmOQX6/xVpLpGlrsEWUSAnBiWXCULFJEBRmy8wJM3RT4Tu NwsKSrkCMRwty35RbLfMRZKZBYNZwxdcsNLNUwNML2r2BDCmXG92Km8HCxZhCgZnFJesKogEiQTa iANLyZtC8YLzNQ7Dds/JUnp+/gVQsXbFw1IoES0fgkg12E/r2LKLanmfpiGhrnw2x4wTyqZhmYMx P0aGxO1WW/CQ9jToiZptZ6Fbz5LS4O53y6N2I1QMO89A328ZoMCdFfqK2co2dGYyU02zPj+c/fT9 JZ3eD02xW1bc+FfF5aRVK+6tuxDgUYaBDbG+aE+48cTyhyNKB4p4IT83FRxBREqFUwkvPf5JSt/r av00DlMFvTuYTVfmjSFVOltAgTCog8mzdZ4UmswoSI8WU51meqmxdrNd2lLQrg4PTr6IERDOFooS Yq6iiTilhQ/PTFHBx5Ne68kVGYPbA0cf93ur4lBBkjQtT85qDJtWNynkEJ64/5itBAYmtQf+lPkv I0OhZs9mVveWL/F8qJYnXvJuyBOFjO7uIjCpXxSXECgHZwhTwbcBvx5k+Qqx1LSYkZqJvc8JSBmP wj4kLMolVM34fHpEtsQv0Fk6xIXJpuyNCBYTq9yX30dKWh+mOyF35V4LHLUpcNSJ2yiJrG9KiAvl QG8E5LpUYXKSplohNIOKGOBlO3qO5y/5pQPDWjimS4cSDA4PGumX0rtwigZOHiN5Y4JmCNYTYYqp vEDmWD1FJ7wwOZq5rA7xbPws2GpO0UX22+pkIeW4URKJU6+mylOhbtA0e7270F6lI8mRg5VHPvS7 vispv715dm2OQlEfrgxZWWXsAWQZHmTGEDYEAH3rjEppxw43Mp9j9w3DPqOuBwLxzhh/A/Ek6HvB tEGwsL2ty9mucbG7+tOw550hCKumMH0/xJtyHuHJgTes5QGD3rG4oqvRTT9gnd9DZ4mED0VB2E8z 55WaukXTHnxrYIUn8e2IeO1LjC6GadE9Rh2paAkKpZ5PZOp9UHesUY9Q/b5/Wh7VlTsVoNnsFkoi SU/jIfIpmPEJ4lZByxJo1Pdi6gLUYEn/clM2iN+b798dE536nvh7tGK6kEkAArjcBS8xgnRYn4s5 oijYoKm0xylFrqHn1Hc8xgni2IM8sVTyEpzJR7Xc35hx7KvsIeSTq4r7j/MoVR0WZoUR0jjusmh+ XhOkV1Q2DxatYzcBCYvgKXFxhsMENtWG1ohyfXoq4XAFA15O1jvIq+EDvzlRymMLg43mrmJMsHaX Yu1MzNWDHU7Z9+V2konSg9K7DJJucOTIjNAF0I883RGug3CBBH01oSV81LRs4UYmMpKpKy9lDJ6N bjT24rOKvidXbAOzyZemWuaJrhjaipDOYdo4zIC5rtbOwQPj8JZFsynBqXKrU2Z77F+HRVShkmMg NhwIHNvM+r/p4pHKqSRHOesXhKjUdm7kPZJCnsVoS3OLL3XIIsxBSx9qXK3jtrEyii/iueJ3yl/U EKtEgK9Ao33mO9vilXlUf24zRxE5F89cxYr49byISfMaeB6512Z5kO+/4kjJ0EU3zsT9hAuMuzI0 cx/7MkSRg6wn9qAg6hLCtzi5dkgbwgg+GGkovH0insjnsNWntEesL6mEgnNaXMZSmgMIZqV+6XIo tkxgSqaKvHJt6SieK+Wk60q3ZaJOOOLaSsFPHd63XpXEMgeGRCmuv37IETeciud9u9f9dFcOXnB3 Pds1/con3F1czVKQ9TWMFSdP+oj5BM5DAbu5nMlRSXTT6bHCZHHNvnkkSNCJzYvx1dh891p8WNYF W+vmytFPVCXo906CEmjJxPGFnYJoXvYZYaxNDiAx0tRMeXR5Kfvc0zN08SGWI2SlCFOUdXGrXzF5 TXRztkj2uf+DbmkYxjZoM7j6W23FAk2VQEhqscVaRktayXIz7oaT2hpmCzJiDDtJpmXNLO28aa6S qeudhiUkdPjzflSTMKTUNYg5L78ewfqY/7obQgwP3JLwjmwvEjyfIWCIpzeVn5kVcv3wmE71PEK3 0DO/uJHotsBO3cw3OeFEZneT7I7hZKMZK3aJJiRz048F/NKqK5BB4r+Y85RVHuhPJVePvTXWWcEQ lgUgGW7MKDoSsStZc5sxWqFyyGq0quWSQ5zY2YaGEwbWAbvaxglbx8YHLQG4V5TURMHIkr0Wf8vh 7NTFfIU3O8SWDTRtL1622AJwpWa0K310PnzEbDxC6bKTAwaLeiFTsYzEBy13LRqa7K/G4+NwdJGO TrcUjae/R5OyTeXI4kg60HoSs9LGC74liDpcM+xwsqAdnoMpThcEIH9obWXxjx069sBc5cGw3YyC cHe9xP1I4BFYhW7b6+qNPsaI18uWQgffCydeKRIh59oyGlNbbES8e/MFhjdMMcohh97xLbKit9LR jGx/iWMAuiNqK73OEVR8rM20F8NqDxDlvtqtl47nkEckrvp4CjK+WnOhihMGBIcoL9IA2DLD9naA 5Rhs7scoGhweWnT0U/gCbsXZgAQMwGHERHFmsVV+b3454zf3Fbwm/sUayXuBT+LIewSH7a83tvSG 8x3Ah3ZsJ7jdctwsvLXqFgmJxMvFdlkckHvy+K8AfMc1QSic8il8nVdOoKE/wwJ2gFjGR+Pu4BHs 3LeVJIHg2W9vtbXIYpgn7Ld8VLwNGCnMcn19aRWsZocXJY2XTj9aWuc35DWjFq4dw92DYU9huKfG HOcBsM1I/Lhl7Feaq1d7gE+AfyC/Y8htD1aIHcb9nAIlAYBg5h+HVIl+04bYgAu3+YWNbxqeE1J2 Qo/s7/EV5e1UkWeXSOaawlEtnefTptME7wkUJ7BwT3t7uHSjaqCovndWbwsiShMgJy06dPMt+pbt Fjjb1nGCK5jWNMB9Z/vX4U0BScPKRcPBL1uIgKIYX4SB4nEgBrWNsQBRBycKfgAQioQaGER6P0Tc DIfO3tKG+YUSYorfCJo9Le4UNNcouQqonDkT7xEC+rJQEc8kqaqEmNx10dbzdbVaNt5BIH8Ye2Zg md3qS4akVfEe3LUp2tps5LZc7ACVV7nbfAH8otlDhLdu0MnPNsr5oUCHdXOBUO3lO/KiYTzkQ6h7 KAY9cBfnqvwrZCg13x6ih/NSjXZVxWlqzZaae73byEkOjDiHuv1MAj3mEnzyBE+9w+1HixhX9B3f rWqDgIqtPypGKFCnOp43vWV4kqqbzU7Amuek6+e4X3FktOMFT1ROXEvOSZD2iNddCpGOvRxnxTiq 6MzrCh1IHTA06COzwONhY5o3ethgPms/bugZxrU5pDFhIt+GHPe9SaPVz96z5cidf2wLve5X+DDw vMs6PMhBhDywbUb8Md1gJnNCPOGNmc2ILCZc26eJL1vKwhOfLA8/tIbp++mYQuOcS3PUS3iBqiRI KnFTlyosioGHa17U5s43RUG9bZNh6WQATLVArOvMkIMZXz7Rip3mfXGjdwmdTDt5X92r/nCoJGpv NuPNandVriVMQMyaOvqOfuvrqPAAaIwh8ggSlVK8ABiqRQ/DR3iSzOoLFE476lIj/XXloLAib3/T +ANmfhB8RM14vIcI6FXwkBSUtwtHMygX5CZnDYSt3oXbpZpR26/Jn/Nkona9PYzi5YnOSJPSul5l 3XbrggXtqDpj3KHHXomeJwZiHE0bxIEGn7LQCchahyAONyoInsvlutNfYxMPzTmRCS0gZSo5X/eA lVFUMJ3wCs2cS4Cgg+D3GuQLr3F4xGIXpyizD7U0nkFgTqHxDn87MhOmiCTGTbA9Cxmo5a6IP9px AnF0IAhxGSAKxHEC4D1cOoxOxaTAijVZPgeGGPINLIOGLu75qcHnPcQyACsPplRD1k6n/wJyhkb8 zX0KV84u/Wa8LGs08Q45ZZEmnnVVbb3cVF7HTbEBdLX+kxbnVdsJ/TFm2Pcca46g3jAyOGmWnbZ5 lAmKg2ff1YRfUVxTLoghs7FDAI2uOD861xwxCnvpB4+FD4tvx5cUb7L2jTPntzxOCbB1XBS1aZwb L+kyTL+l17nk5OVcP70Xxd3W8J613Y3TclI+Pj5rU53Z8vgiyQcOKOtP2racokuDdG2pJRUdtl1A 7VAFGRsy5DC9XYBrBDn4iFPUXl3g6XaEYmPAuXhdYv4+b1QQfOY06GlkkLszSIo4ln4iwqm7SLEE QsE9d1UmraQ+W4cZblleCHltxbM2mX1mr4JYyBizhFev8fhxw3WNMUritiAXLnMRgEaBo8NKt8He J768fn87vx8h+szKJbqeZ23WTtjSzQYV+pXLSoTSeI3xD3UB2jXo3Bw3i2EN41JtoK/T4bI0W/G+ qD1IlPkViFWY7QCy36iJa29eqQoDQaWmcv/l/OocTwo1n4hTBeA0rhvzvXIeVIpWt4mhTlWvvzyg 2k3do2FWleoBt90U9VWRYyQICDbDONUfxIyVnIAtrW0l5zS5vKlBpS9zqqQoa02DyqyEg0zHrXYK BGA/WqEQcHgcOLjLT7+bamgbbyzBYrjGWiukFi8VUdu+LsrRr1yHk2uJ4Wijhwk0pAD9yBpI48OR xgZqUbV/GNiRp//WWysZYsc23XNL3EM3yxhxjFfFGi1EiJUir7nowYJsJmr1rad4ezC0s2bYwl0g XHFURJsFw3dsoVJe8tzk/pBLzQPimgQLzLiwE4PkXzdxC8w5UD7sA5aNzLcgspiPp6fwxdlZmjc4 yABb1AUJe/h/NllgrwOBq2GfdR6yTonRnS3ASRk58mcjVN8MO0xzqsfTO1Fu48m44xvJjz1pykf9 IXRrS7YOLIiZ1xugUtTKz9JN+zjtHqnVzBMJgPlIfKBMJ6iMqEuQEMwwauRD21w2uoly2exjLhbq BkJPKVlEU2otCIu3IYsRCXAqUsj2XF7ek4mTSAH+7XFIDUT3QNC8d1bJq9yDZmhOJxTVVdXLop5R q9SeGoMvdzhpYlbVM0J+xofdJioQfCj2C570Ir6+y+/OKsCYGedeOqTSlhpjXSuSuKRQwJQAArlt zkotnlKu0209UR789HL7zXBPGUrIuDnJqrLfN01Z6J4tJQko4ki2g4QGmVFcQgVsxrrZ3PyLCAsY fxQ2h09OkfX/RZziqfk+Ked9cZ3haKaK+2csG29ZxKWASrdG2zG1DEV7K6XQ8IcfyHRwq5IRNo/X /MEm7DTN3ZnvVqICpPEEUDEpyHVgz6JZnAW0Jn4rqOWR0BabSCUECNJCxxVk2+P8UiQnzWZ8mswB UAEsgKu9A8+/27pSBur4WFnjSG+v9WrxsXHJBR7a3vYwT2cJ8/Qfcjfgmuz1ADDeD8vT/OlDXiXE nl9s76ZcVz7vV9vSUvljhC8RtxW9Qo6jS0OqmjeAjyWneTk964h1HV/Pm5mkG5+0OcM8FMWa3mQf MxQP37rKpDMyZpEgfGnO3DZRH4XlEu2/5rg0OtWkPgoxzplrAvOkKjEXx4K2R1DAIKgIqdmazBzq RAMcEKfMbNgEI2svEUeadY3NuNemmjq9JO89ZK14B/mG+3uQYFFlE2gV8nKUte2DJapjfnkm3Tqo pOMR8IKtertOFZ+0l/MzbCY8MMy3LjIcplREKOsFLrGRMjPOLfcwwPAHgiKwEOep4+OzzaWQX2dy 1eoh1tiJaPVtUDwM5G4Ss4+Dp1ql3qRuVV35VjUr0i0vdB9dsiEMTow55Ozp/taoZe0RWK780Cb8 ZWdwdLQR10rlVonl2P8zSs0YNagD9tBjLetPfl7/vAYnoAbwfghoiNAX8uEQCtCvMpSHQ98I6mtl l2IWr4V146YkhyP7MvAKAcYefzPpRUKhqAGq2ptgKNB3bEbMqTRXU0o4NLNeymaMJaj7aLddOt3S wUjq/HxbHZNC6RyjHI6Y29fDdoOs8ZCf8G47m/UT0N5YI8n5pduCb/ta2wJXHr7MfXWhxfEZ7gF3 EtRX5OH1ttq82MJmJJ9Fz4bW/gB+2F6hwcbfK+vNAsEbN/QMzSlQY4AlB96aJBDIZD1SOTwx/+t/ 1KHzpQUljHB+K1B3n5/jJM7Px1kabKXPWd4NUwrRhQTHRqp2cGhaF87J6YmdR1tbUHtVsObdjAS8 simkHL3XcLcLxDcwH8bRYWu/ATwkcIjy/QAtUg0F83BGyqKWxBiRZaEzWMQ3p4+sCc7pVMj5QEXf pfhXy5wGQjxxnanYkziOqsWyj6VpWKYQ/4FMgF9E8zuuoE6/5Lu/Uq5ZL+J3n6CYjrg8BTXhRQlR FThDCVLoYgIbCQdsekmXEYuwDSfrGNqLZ/UBXiTTlEMJNiKbaRqRP/0CdiRuUEE2qiWMwPw32nMX kHh69sFYxUEjToCQoiqiCN2comiikGCTVSRod5JMUahSK0j/myoVT4GX+UEQCMBpIqkJW5tbFIgG LYAc6TXfpjBR2A/Vg1B7MHufgrBK+S4Aph1n61Il3YIK3oUXlutpD82BEz5AKbh9uEvITY/Q0rQ9 2jwt9tay9tbEliDiGOR38U0X3hXogHLyQtXa8dYC/hzWAwnjDJdo9q64x5S5fnCtv3x+C12YKvIr U9pQ6+wPhtaiA2ArUL//rhMSrSU0WHzUYaeUjfbm3s1frWUqkDnETQtQ9/0zmeDn/Pqt5h3ZGr0t df3/sfd+3W0kyZ5Y755j+xhrH6/94GO/1YBHC0ACq/Vn5s5d3qZm1Gp1D3e6Ja2kntaYzQsVgSKJ SwAFoQCRnHHfJ38Pv/mr+Mkfx++Ov5mRWVkgpL4zc+3j2bstsCozK/9ERkZERvxCkSqTa4E6bTCO Q187aTPEBm+9X7LI/6uSbPb9u1CzySPSol147sd93nNOBR7RFc0LPl43vmVy2afE2NdpGEKgRQK6 RZdfRO2ZQmu4PxXMy0O+LsqrLPZZNAQS8cFteUwDRtSJr/Utq6XDuZFFVY+chn6qpOiyWmxdsL3s FKhV8P1PMfpJ4cvF/1mzVKSnb0uXc7KGgogVd2iw1UUuhUFEq6PuVNxJ6R2wrU0EcrrXnAF1DKFg x6tqdek8W7rY3S40ixRVR+0UtUs3n/+8WQ6niNJhuLR2uVe106ZEqvULM7NbPSpUovN/bVmIbVCY wq0+Ui3fPcW1EbEaTpYuYj+ZRzOCoWQAcMvIhgHuVn+QyBzY2d6mMtOw1ZA1hzxqV5yDvgMiwSAf StKoeEX4gwV2/IXQB00IoiAsMYQg8xrCQEwqCA4wr+CUXaJRTJB0NJrYq08Kp7KZn6JwcmbEFvJD 3SzRJw4bMm/6eLAubgY+CEucnmLfavYh6LrXwREnBhr3sjFdjPpH3z6kVeVgFfas6OLz7rD53OXY kQL0QfdFai25XxXyB63KS3anRYnKda+VunUcubvCIVQhEvuWOZ4aiPUD382/evb1k++/fXMS6Lf4 QfeRgdgGU6qLZEr16otRKhkym5xqmLlhyrB8edOrQTZeeZfyPXMsaQD6tCbtOgpjxxh0Ay4RRBOx zqDHmi1J5qmrFaolk9GoG2yBoD37Z26q6DoZva9hzgp0Qj8KPrv8MLyWeL/jOLfpxC/8qJJt3zvc vomaGMfhsDrOGOSuGv000a+qmtU5OW0XMzNVRoU1IAH0cTXYwt+r4gp/ujb5LBlYHxlpOl6+6Bv6 85gpkapQTIK9PGXcH3qlCT2aLoOXV7xjtpWzH88Zvbd/eZWyo33aNPgZkOu6NE+ijOMjLdJrPbsS NUeu2mikLlEDSprHowCiMZ/GSdU/Pd/zRRoMiO8/3KJ4gjzYN9VCHtJeB8p1QJqZnVcrYAtzWib0 VyY4lYVklQtEZpcDg71q4FSZ1p09QTmXQFdqRWw9h4f3M83APOAoamZ9nE611s9BGyRYi/RmEHOg yGZ8QY7EVTYHYXqOgKn+SOoimicX7Xb2xBuHvqFm2Jq5Zsobh+cXpgbIsR75LAMdJVoPaQrnebE4 L/v3vff3KDoyG20dO1xT9Fto6uYMfcYQaNFOwEYkTA1lNLsITujCMn0DzoaO4o27SSyUMGccYz3s Fr4PLapmmkYFg/fwdA05am4YDpLwbZszHFedni8qccu0dV3H3WWNm/LHh82Zxp2Em4aXL/sie9TY IvSq41yxRpNqYYAvGkDWXIgVOnH6GtUM3Ui/ycWZYJB4BNDUj83Ytdl0XFrKahmvJ4hBsgOx05ib xK3SczSE5ETrh/WWT48fN962ZK+YEIAwaSvtGmcawLiHwMZr9Fozc9ps6jLXrM+9YBDR3GAJDd2w xaI5xKPAD+ee7YUvqGvo1lNkqi0ryJCho2A+nWR1VWbLKSIaknaK7I02NUdtbRhIOLYzSKqGTqCU lgqfiKxLsuCyPQNzg1HU6g1FT/xQcmclsGIpDhR7Mgns5bCg7GQads4zsajoCtwSOX7M1jazpTsx GvgBlp0ElhH8C1Rn9CuBA+A3ZlF4RVbq+mh9VFYEy4A+rjQayS/TieB8lEF6OJ9pHI0gvdNLhai7 JPUzDlzT9kf1tqrnvnH5lasxCeQ1po9Bi7c+8V0aK5kl0sOMeQgCxXJd88m0GT3BOsT1dHqypXDN dzfM/reU483bwAuyfOHK0CHeS6FMsdLwfCS9tDUiOPe2ulx//Lq2rDFhk4bTy+7U7u2PWxlsVFcz nNH6H+zAmnHS9TZme6fbDZ+J5bm9SXtq8Y84IXuyNLnWhoMebLPG9j/2EA3kU2G3bK3x/3W67u7C T8NyoQyQ1pluQ2azlkgD4bnEIhnmAdH1OWOm8mZ/VSwHnZNVvkiIKrj3rWYVmNLGelw5tP3ODrHE zgcipJM9aI5TD6xLh9OFnA1E1kk1z/jYrs681mTd7si0upBoNgNu6bwHVNrCmDlEhzkvXYumET+T dcWG8rLGo2su2SxQil+uqtPidHaTuqEKUGvJw6926RSS0GN4A1KHOQr8lc8vvPB4sJvTrBU9Dw+z +wfq9B8GdxoBHe2Bqc4Pml7FtuUHdCywWepjmh1mJpfvLd94eMCpBmKfmY/5hPwxnkXOsOzDhMcY b9FrNKpx3jHnJS9LhVYXo2EnneinZ03Pdaw3aEqksqvxrbeENVzeG1wgKKKOASz9Oioll1V8R0bg idmMlFlV932wh6X5YHRdya9qbOGNzNneHfK0AhX1CDGcVpulOQy9Jbrd7r1H4PsODYpDYBi2i9GE FJ+0T563Z0ALl9l0TrD9jVQMJMhyGlq+2SAEHLlYafgTdVK+mwI7C6v7kB1yQN2lgj36s3eQUeZ2 Nqb0mPzhIWfRlqf6BXguvkyIdD7s/OTOAgNRzjAlFpwWQUl037t+kKhgLok9eElIXAE2u+z6ZC6F AHEjyvtqcs92N4vLBdo02DYRHHkLsU9JQnHaYu8fv/0fP/vss+VNPiLzFRDSQ4f0//43b/+vzmef YZT2Eo8jWlLODLL/MP91/qhXZ65wvrzp7GVPf/fk+TfPXh/Az30ilVG9JnVMEBEmQ6RmUe0kGyjs ZLoKY+C3urPXEYJZ3yxLsaMI+r7bHCPMJ9cvscSQfS38DvyaytJR6sqTCZAOI9NjD9NlPCPEA9zX xG+QuMaZM9UwxNHTp3yqoMkfg3JHrrB7QrVy+opPyrEhzdfpStwGD3/Icd0gYnEaML7mJXw77u9z HN5sdjN0Iq/6m9U+NzQ39g/ZRXWFeayGOIGMj3UDRa85Ts2zGkoZ6FqpsQoBiCHkId1V9jFLLF+s rBD+bTKAQ7uGJUWntrXkSWnAmUElmc6aPsvMhb5djcm9f2IWQTIb26yiLB75tdBaNHuzq+KmduC8 Zg41K6HBx3JIVXuMkKZXsRcO7Vku8edlsYAmME82r5MIbuSH57ReykBCiHrIyocG5mTGGeqlI3aG hXCkhcePH2vWZir6YCg/HpKu61ICc3Gp9JSy+MDQas7gyhrtKZQkTIG63pwiAfZdk2a1B2o7oBFj Wtsrl3jRTzCjENZsWqhW0/MpxU2ABDWDU1lZWd9cIMge/LKoS49snlXG+tEoS/s6P5Knb24QxNtU oFIuxQOCTeKY6OmAARNXzYvMY03QQa4yyChGjBJsWYR4t9X0gUP+kMu40ekEPtowl3wJJS3Yqdz5 63Xi63vZ0ZryfBWyK3hH/AMS4xUsRUGRyX7ryORTFVLreRkiCO5ARiAg1b5HslTI0+rsDEQmdCgl ZOEBJ2UF9uRSA7Sf/C1aQALSlLwqv2AafNwN88So9thDjDfgU907eAPLsMuTHxc9ig6I+j0IjIfS 93YTSvydLLtTc8tSNW8AkUrTPD3bjTNjOCDWIKlSsII2KNCmPfjM4PiAmzlxcMydlB1jsc+NAIcD kYN+9lGAAoZWnILaM9/QzgaJdymAjzPQYucpfPGgS/3+OAfixb/6fN84JsfcrMeh42NSclyNVOco VSswiBJV0WLMyEHFeAy0x13hAT5AmWVZ1SYVXusS3Kn/kZeg12MUYtMD3wVmuAaGPmhnly0WXmNz qhxOYnQ7c3Dyg8vBroq8O1WJ8Pb3YfnwCIZprBnlKimdqPTOyXTXaNcaqUTU508qx3ESgXI8pD+t F2Za4kAajGi5w/wrsSd9uYNMywZjRQ4az5RMVNTDg1YFRKQ2O5J25tGa2zacitt9bhwXkgZ6X2wW JJEQ6vWdWjSTx0hrdGxw657Jv/9tJPCyUQU+VM0m75+8/T+fffaZiJ8g0MovEOaGeuPbISkYsUKn COmjZTGufgjHO3DX5Q22fA7ykgjM8in3Ja30JfslPtHnkpxy5MgJ5KsFO9x2cOCSi55z1Bi3Ruhe ee0iEkAYc3guieCCCIKJcZevNZsCTddQQZ3FycW7LoXVJFkSJz7ir/9hWl71eQ38hsKHDC9noYyP zrKnLAXrUYt7DcsO2Tb0tH89EB2hJvfK6vpGAXSLFZ6EzmQmT69zEefJDy9zjcoxCtWFtz9FLshx JDPWAtFns8jualfuYrWnKNsSmjbjcJHNGd16gDHPqiv8GDDGD9V0QoGhG6eaXTHiU/YBB869YICr Rn/64eifDtGOJdPAs40sXIaXaOlaJtPZ7tiyzI4ntQeRV5GYv1oI3hgK65p4vJjg7fs1CxcvSCwE DZLjokS3rzWNlPkYtCTX6uVEoOD5I0OVdcM5xLxhflpkvXT5iBw8hr3iBlN7isqLDYwQ7WE0SiIu mzkHIhUs4mmdWMrRCMtCM+SrINf3ckNWEe8BGuJCl+UNBtHTrEKfv7xRVw5WwvhD0LL5+LR2jc0r OEfEqjsO1xvO/6o2XcEDXrGAg1WWHbOoWI9wjUxFKNSOFCu2eI7JR9XhpbHO3xGgCUdMJa7A16QK FnMCpXnaJ8xWRjhh/QKhgCWQST/LDVH/GWlAug/yR57nIGBW1WyYwU8WQUiiCE1ffA23uJEoUfkC Hn/pFqeY3RkbHOo6LTJ6IckU4bfOEWqvN3x/TLEbZi6fSs43hnumDPErvk88ZWFbllV31YwCxzEW QfXtJHmhjRoamKzEJuAUq4KPDJkty6noPKGIN3nhF3uILUj2XRyEIUEe4+tS8tHIqmlwfbmQ1si7 Dy1cMUwzNhQ5nNiZtpHLowU+7SMuJnWNYRayuxzuinFxkzo6R6AJHl7eqB2jHssGpgrxK1eJCri/ OqEpWQq7qdmWUFbK+kb5gZuNY2hhx8DxlqaYFpzOGNxdmVyIdn4dOIfGw68DvXbPstkGHxcJ9GIK HBp2/A1NE3NgPDqCG5KS9hd7zkp1XqZeTd6BkcU+MjDb9ZJO2lH4+U87GNvqft5sC3T55ZsYZuwy LVMZpNFBFhK5iOJMJ52YjIPefFWFK9K88JRKISGQAyFf2zYdmpx39vFTKkgihe+1eEHhw6e57rGT pt8+NnLQ2S3gRI0NJkgvJjw3g3Zr+k5Jqhu8sPFP+819FyXpiMaWACEI4Gv8gId8tiZC23wZZDym hv/y+KKiJOpurxtKiWkkjrGXugftSUntcDvBlRa6ekn9AV+dpVqREta5NY2xPD9FdQx3nUvGIXWT WBOotPR+05OZcx0ZAr8e7OzW37tT9++sBj2X1SQYrkkya7enenpH1IH3BAfeNxFfEAYw/AM1fUFk wSGKBbzzcsoibpdbikhDoAp8xY5/CqVdOj+6vlrCaAnZiaRlp248YW0MjoGSAa01E/NZifa19apQ +djdsBlVS0G63VRP65FoWhoFuwoTBCmsOMZWm9jMDy4FT1yBc9LuU1JanCe9s4FerCQzgc89kjzQ sCQ669Tr/Jmr1A8XMy5vsw/1vsDuPe6ljjZm1bcVHlekhIqma3rxFJ5845AG8MMD5MH4uD9Ic1Ca n5wmbFw1LAGB5nuwJXaGyydKqE7MmyXOpyidiHit6MWWLBqP0PJDXXdJEqU5s1FXm8VHUoHH6did CPg+U2KP8MHr9XzdP7YrejK4jSSgq9sXmb+y+wLLul6X49FfZWHdpC/QrdKsVAuXTBha+vEi+wyi z2Ew/YDvSIvmIMOpfx7k45oyAEIbK3C4N7075OJKZcWPBs8xQXTrEytno4tFP2izq/HMw7fXoMz1 zf7i7w3+hdciyQARcYR6v+PQ/9891O1HRDBW8eRzS436rH8cTEO/yaBNqF0YEP+veYK2HIb1Zlmu +s/dqAbcOS4Wi3UMZKFbKm5qG9/mLHliBajmaA/ZZTNL0Z1GIvw4FE20P6tBUC45SLKAqM1tSOUe OgiFatmUu8Mw7h4fPr0kQGR9Ua3W4w0b8KaSnQt0Qi9z1G0AmiEB2WMu7TTKKUXjs+ZhY2roafNQ epicm5a17d6pM/q/bmO3+Kn2NYaN+Q15ffA13bPdEZ4QK7SAj2bl2Ro/aB6tEFoTP++avh2PKhQ9 GnvyI+CMo74d0oglXviTWqHhHPLcqDSTwM3awiSajKKNWdwmoZldRR3SDfxkMdll80KxXTeukkAC vJc6oLuQRLKkGNak7YS81UbZtgd63xnTbmIvOAoyq965dQebwokdHO7exJbr9XvZvaxHx5bc5tru I+Jeb9DTpXqx2mWlXqz+/4X6iywSXv1vWaPOHho4vl8Uqxt723N42Lksy2Uxm36QKDYy/9dqCS4o CzDaxnG+/yxXMyD6Aq3B/w6yHlKdYSr4QyJasdzR4gM6skO5/j9HpQZS7Cfvfi1elkhN1NMnGDea pKomZbENIQAOjOnLDufQ/xzsQDyJw/1WCkoslv+oSxzVS0/ex/1vO2F+3MHk+/hpxwr+sIfTX/9Q 6bCdV8haN6+nqIHshi+nie2wG/0/mUyE/vuxzHCvccYOzIZ4vTltq7i/teJ3m1lbxbtbK341/dBW 8fPtX6xax3hna8WXFF6d7mp7X9N8gNfob8IIqMNJRoBvBo2yrYyAhpluiWegWfpjmIrZsbdu2CTb wc73hjLgdjayc3s0AmhQRmLa+1vyJRKaaZ1+vtDMI/vXxd/MTvGmrKfFbIZJBXbSgKVsaO2oqtvN OuZGyEyVeBhhC4PezzVefNypGPfi0Oqyf2MziPhSJZhBmMOUgjhSbKBdNv5QrCguxm7GM4x2obZ4 +D8l1i8o3u+F4XMW2rFpmLB5j9gg/XuGXknIsgLKguQWWvxcUC69wr7sgMTsW2tm823MbxEB5LXy V48/a2flzgRtdHhdiFMc1sAnFguyaJH6tb+tuVFkPe45VByU3Ye9lKmjoZkU7Wy7JR2y+1jvTn14 px6SEVL66ACIBzt9nFuIGmjh+wojiDAxoyZFucfpHeJeD9K1PnJZsV5v62L6lhOLaubwLiph7cuW nDWqY7qeWkCdrknLfE1umbBJy4xNPnXK0Blo+5RNdp6zT5o0qjS5ZdrS9sP+nXrQtB4yn7WWQxBd Uqp0uCqcfQD6xLkYoPOxfVrZK/84PrCZ9Mw0bDsbb7MegjwdMqS/9E2q5m/COTN3IUw+6s+utnuS HVKm+5UbTPM+9RZht4du7n++g+SOv34irrMCWXOYJS70WAj6RhycdpCBpOhf5xYgeQBTaeamfOpC d7Zfj91KJDsp53+VO/jGWspI+03zfTB4G0k8ZS9K5zOHjjdl7X2IVR4ZsgeyBlxgLCOMmdDAGgvQ 7+kFSzRXhCmIwAcIKMiG0IQgKvea8SpqzcZabrnKw2GMXNTiYSQWNwFeP261/2WXO+4r+hN3Ajun ef834gBk6HlV7k/dLmWHDujdZjbzLhhk+9FLBwrT2OnegUru4gMigP0JZrEOIuUpKj3FLPayejpf zqZnN1lP4EFI55D4Qf59iJ7SPbsGfW7Qz4lNINSjWjCbWrs3cJBNYYdMfX/k4eTHaU3j4tBo/Oj4 wa8O9h+emJFRXI8A/RAbK+rMjfILU/Vxr8Wnh75xu2OPtokyRNytztarFPOBXdLQMCdMhv389c0F jqqn54sdqRpK7kLVP/8IvPXOJLWKQOT4DyxifG6kfK72of9KXGt1wi9ojEGUJYNK+AnwSjkbgsnf p2mvN0x1Xk22u2nBJ07C8tscs3ZwyoIWUj5ZiWPFOmj9jUUCIcivpvW4WO10vytF//WSZIMOZYy0 7DsMEMvtMjpGHJivt91+0vvGDMDDQaNYjl+S8SvIJgYsjs5kwfTb0Wjps3nD+c6FuZqHyTtd1Mcw LuYg6/ImDvZvaLGIqnUdDEe9nlSbdU55pPoSAuuDYDGW0bg/lxrwGJolOAMcZgTp1zLbFtpaL2ub Rht+zFGTGOBBf/cN+qUWULjgr6mAoTUhVPJgxo/3kBh7A4v/ZQEVSBgN3YAF8jdlTyR69PbEgB8k DYvb93oDMCiIPaXnjQjSY6PuNqgqnbqseewaw2WsXjMFlKuVUoCPuj0jmBIfEt1CrUjze5/+P5At n7w8yj7Pni1gfrNlNcWM8nvZpzfY4TSQspBOopc7K4YwoUkMcnRzAFiDBISwpI0e8v7ewNDEHktd XcwSzE3AljSwYRF6OPcBqBkmPWdcDyJpAvU42J3sQ/gKjl0zXOjn0JhGM8Vk9lGkbQhSsIkURcic rg4JCacQ0QA86zOrlMjB0I+JlLBmUIZHoEJC/liVJLCcJbPedemL7NmHUa7lZIrAShzrT9g+kymj 3GDzeZa93pyfo9ZbLYA/JtrD8HZUooXjmMAEkyRXXqLreo2wCAj1ej4dD7qpfRyAdgmu1rw+B5Y0 xkXznDXgbvSuGUQkLwxBObiAI6QAbZQpWohUUBHgu+tTQn9Yn9oC26hzT0Ej3SbEBvQc5hOaouXl w7mjhWM173m733oFX86dijnILUwI5w+ItzqUT+x2CtTtpEOwrocxTA5JXLgtBSjMfUWWppwwKgkD F91Z0Xl5PQwhNa49At7PEwVwFuTwHYTAFTXLTV4xBe12zdAqYbnj+ydoKe1m2RdfqAOonueDFjkB m2EbLjUhvIfzkIqskJYTYnMympugWqA2hwrdge6PXqDvX7Neer0+fvB3ksxAI7/goUhbKOj9leWO 7cdF6qT4C7LsWCzodKYUkUyrgaabHgYDThejUU8hsSUU2sNenPWbAR+/8hmpE28fubcX/etETN0C A8tZD2PZsAvfyO5iW9inXwnfk3fEbfuD5sP+mfj8Yz1MBRKVOePmzl1dzCz+S1tiiu8bbeM95Blm PEYc0fCVYQwP7z2690ugrVlVrAea6guXrUusJ6x3rePypUy2ljNE5e9V1bLW5LRcAg6vYYZZnx4M s4fpN9x5+6l5cd0/xhZh3Cc0hl+GfeldlLNZ1TvG90QCF8FXe+ebS76PvaBZgHfvv3z7P3/22WeC jenhV0ByJNnw/dO3//5/++wzQvyRtLPuGH7y+g2iAixXQNfAtpGRCXCdoNTVFFQvwgDCz8lPKLSo 9A/EIaeUKu7BfKk/57CzLoqZ/lm5MqvSwc6AsDteGxCaCBjR49SQmbsxUJVVNuvpjHw9uQBn1UOR Ake9BhljeTOu2VQNvyjB1CjvmPgCaGcIImG5Hq2Lc02h8/KPb569fjN68+QbJJz5Mpf3fcq5vc+v ux0vBtiABQTU6S5vljcj2FMoWBAfsNl50KyJXBkLSZAm4c0iNvmsWGPoFoFm/lPxoeg2q/0TwVR2 UxqFlBgvTZEPhDuOjdv+NMcJh8Q+6pM6PDwssMEhtgAnEv/7QDItYP5OQl/EIp3Oyz8+HT17+wab yWFQME19zNxyujlHLBPgCN1xl8DTYCKo8JsnR99SaSxr+oF/UFOdzqtnP7w6evNs9PzZD98ePX/2 OjGK44OHBE3cfzjMfj1w6JS2SPZF1n8Eu3XQefL66dHR6Oj1SDJDjZ49f/riq6Pn36QahhP4C2Cb HVmXoMXHh9jkrzTbSb0eoSeRcSoylGHezor56aTIiuHpcHzgyvaFdViobu/O5A5e3scgv/yuqi4b MEQvn718dP9hdsSb4gIxRxhfUvhBLfufw4LT+EkxcpIAssbuJvROcoCFGVg4JFNzr45QchgtL89H muOmtiAcNWLPmuDeoQJDx904WyyLNUfK0/sc8Yim57glofP9LpP6CK2KdZzn2A9B0WVtwt7JiIeh 6FEC3ry+iBNIOxcOaS7p0GK1AN+J2sX4x/i2JCVLz3RMgthFr8KCLHbDCeq7bdIDqXAXXrVpPqcF 3TqxsAn7bZgZ4QmxVsQYy9mM7J39ksCmgxFRZip43AokuJe95nxIkvfxJS1P9ih/NHQ1i2yElmXC yHsJz/CwJXKNAQYKSvghKJG1A0CoyMeewW0YCDXEUaNuExpEE9lbQBDoRQIBwQ8bS1gEBBw5d785 6OSNyBmoumeLIVBbPZZjxBKdzjxPS9KnkrdzAqmljd5Ukp7ckiRzko9nVR3HNK+X6MwCvT1+2EDz wHc8hpd/HD198d3Lo2+ffZXMXBserLzzR3QxSsdvtyWy7mwhc9So0T9bfExCW2robBF6n7gzFsbx CzeO1y++f/X0WSqk8CtC7sagdSBMgiDCC/U632kVmn2jPlWYfW59wTraEuHgeWMSwC6pkLA5BzD3 KGPgIWpUnAVIL0LXoOZQMxInurAXpkc197Tg21fkib9pxpkCv0GpeYrexRfYQryDf5C8v4wdhZBT BKuJwMF09epQeYk+a5e/iKCux8UiTjS7mp6fI2JUNr4ZK3DTLkdN+9bCfJGFvxPgMyJND7gfdPqg IAGt4PYftKcFCTguVUBeozOqBgTY24N2f/FmpOh2sm3bzsl07i0H3BYKvGVIfbTD+eQciPs1Zxzd Ax5u6zijadgTNHBNwSRHFaI0CdKeoU1CBBQJBRQKRBKnbRZm0mCMObK/FTMHdi7geSBV1AfQfMGZ ldWqpI0qTJ3gRfHpyjBrro7XFcTFDem/mEHXGE4sKGNa01MYiZ6wzGn+sIs3Y2pDcW6LKwSq0j5X sGKnUziLb8J0H3CqEQD4Yq26jAzPqTOETyg9x9+o2uQOp7ETbLjx5U2Gi43NTqYC031VUqZSRELn /FoVqJ1XbFv9UKymxWJ9gOtne0X5evFTBpe8IIzQWblm0NXphIf8wocVVWTclQkIcL+q+RSKvnzx +uhtr5a/YXwkg7BfE3TuAoZ54/kEr+Uhsy/MGVUt1iN6ODqFqcIVCHPAjybTVcxxPROAl3zwdo1S 2A1c/qjxHc54+ML8Etrru88mD/IXr1sO8aS1KGdFO8HIKJcCvc2fPXt79PrNQUsyqWdTwuhjKEg3 xgz6B2pDBfy8mCEs5g2n6aizvt0oDZSnOeEA1uzvOEVstVM4fS4ZbrIg2ypOONlFs6NF1t7YjHPX YGNIjj3QiySf0pS4uawqklM6430q/wod7LQHj2Vunr949vzNMHN/vfnq6NVJ21y9WPjNiUcs0jZw YUphVLAYVfiZGxIXm920NKZHI4xtJWzhT9Mlcbv0iJS2OZzi9qE9efr02Ws3tFcvvn7dMrCA4wsG 6uzGD0QYe9bYF4NP6mfruRY4TDAhKqi6+zIC6OJDENoenYgJAA0EXhO5Gcf72e24oWnVHkTPqzVn UwNBoUTwStzXfllwSvbDKRlmR715dl5Zj8k9yuaBdjoJDvEcUc6recEZzIDTI7TqvJgpYKdzaRnh x5CqPRciLOWhXaWAAUG1pKYRraoeC60iiUjTWG3o+sKbDM+YPrU39EvRUJbaOsJz81LyT8G82Owb cr6Qye5jFJcE2yXXkXlxWY7cGUwTKR0PxkczGqAxbZeDGHZSFjQwGdJaJyfVmj+ONQIAHYyg1nZY TDy2mxaHADXriNjQijOoLJg54/KKqCEAq1htgrl9ZjP82YPptk6TPkW7pFGB71K+MDiMkTXxhgib zrM+4SJfwWYdRuLXqsQW+oNMfN8ZPxcpnrJUjqsVbp/ZTR46zdNlzsJ2J41Y6N/zdHbM1hnKxreT Tukb471+BJ2qL+CfMaUA+acNmYLxdAFNjyZeUM0npMHwHfSIjEZwLF5QMuSO5eJon0IBDEQaGBke as6Q8fDeULQsaJ9TjpyWJLJg8246bHM3WdCHPPKfa8yBqMIINCsEc4sTNfrVueEgPebjaqSOdpE6 ZpPs4CicWzn8gaPLEy3zHqG2LZ37AkxkDjU2NMh4PHfvj8fV2F18sNWhDi3NTSppP2PaCSuI81wW 48vivGUrNt0JtxtzFlG84nbzTRBBuaPdJmGzSdpr9MbV22t+/80IxJ9nT9+8ePVHnoHfkm2ZgSK9 LXib4TZEs1RoSfzfs0WNqcxkNl0+81qBo4kwJhqsAMNjSsmz7+DYPFUjpt8QiiNKKYiGlKYcQX1V taDAhkkJMwuc2hwutkuNxdPLJDukaFMUY1S1kOma/cBSL0p/5VnJuZmoJc7CjH4jcc6S4BM+M8PH EUbHsI7XU4w0EIUQ/8O49KKIoQ1oXTrkZFLlge4piWeo+mZfMfo3HNgfphMeQLFEBrdCfxo/keEI HE3I/iYIVyCGYVQuat3Y+fHmbFKsC9lnKGNEew2W7oVC0ss9hlZCd7P0GpNtGdPS9bVFBAk7RXf+ OjtLx1vnKIX11e/TqxoqSyBbiuUJl5f6TTm+WHBGgaHP7admMv4XDRB47IkAgZnaXFKs/tMBnyBD zLjCWX6BtrqoxHddsi68hufTh8HWhW9qSmmimzz7nWY+I2Ghh4aV9XqGm6+oYYtMyg9TGhAaC46y C00q7nN7iWWPUhHAT7HlRQclGtfFRjIH+eB1qa0QpDtohWiqILA/J9dgbrQPZZ5wojhDXsXrhUJa 9+q0G/hRHL2ItgPstx1040Cc40tsFYlpEaaMII/uL1TxkO5JuA/wYBAlbBRdtFjcZOKigbPgTEli EMJWQxkJ66zQuLK4kUXAHYI5Gcg8tz8pF1P0fLO6+GlJ9pwgiTf0tlwb1bdxUERzKo6gekNNNjKb /GlOi01uV31D2Tk9NzLt9E8+bJNL0KP/kN2//lr+1/wqX+HnyPn73S9mM3SmxHaH1J7tBbsD5JPN fEln/9mSXzZsm9C2PeRk+BRl1Xn1HK+Lf1z9uOjm5YLy83Q367P9vwdC4leJF51xVV1OUXcgGNxc iLu/6v7jcfbj+sezk7t7+V2oA2txfHB4gg9P7h7v/3iVn9yD+l+++G70/Zuv/578q67Lsx+vT0/h /5/1hIekdSl/L/tmdYMUROo37ka1S949W9yVB3xcX4ghUZIMJNOjYvukNpOHXT8RVnm2YB7XXUXb 69niw3RVUfRHtM+MNjb0OhkII6235VZhoUKSD0QTTGS0CILFKFLzwzz7ATh2RZlo+K1pZVKCQKLQ hVqD1QwyNKK9krMu4gZDk19tjzzTEpTBxBf0ivu2wvTKefa6mDiJ97QEdj0FVoEJO0jcKq/XmGAi 0AGUVMjohZf17C+mV5V4/J+hia3yTo30We5eYY3YM8z4uP8AmOiTdTYrMb0FlLxx+oUoD+SKNx1T ukqaPybeOh9kb6ogeAxOjhUdODAa5no6JjqbWAmCE2hc2p4rq6eJCczikmJDPoupbBbkdoAMKuxM nn2PqTDXmwXQOs9oYTNfz9lgvVmyT+piMz8tV2ilvtiwAVpPTDapAOGCXPCBcwrA4lJqExv6Wrct qRIASWiLyhBd7eYxUMKYyED5oqQwc+TzmBUUlh5dDzjFZJntPfy7/5hnfyw41aXqfNHt9B4KKHLV xsA4/thaTB44VkoqQh8Z08AWeJgoMOSa9+zdPAYzksmbyxp/TGVLzeBFx+9yvuiSUPz7B9j8iUsB vWs97RRWf+irD9rhWpkHdin9NXK0bhKyVVerVol6ApTJGdPpUoilK+GWW01Iw6YhiYUC14M4TrfV mJ986Plrzs2hn+B4Ou2mkEKI137P2eO+otItdn+ehW8xIyM7riM5U8ISkfFuuyMcfsRNISnQ4Zx0 1PStJC7+TbUwN5RmkPQe5r/mK6eSsnMVBAxfvscMZLCHH+UPvJ6xx4E9K8l3XWd3F9Nrze9bu/yq sVNXAl1JpluBtl49h8Gi493z5pFIeRAODZMT4Gd79hnDpD26vi3lWn9ZLZFfEfEpV0kuRWg7LFRI pg8fpK2F6RVTqUHuI/s4ioTMTOZaPYawzJDP/hXbj7toTOnuMtQjvLLhi8eZ2P/M0TEVKAHKfn66 0RTDjXtT1L6dxZktaEeyUclRgrJJnuHhBropTgwcELNbZ0/G95HzJxkW2agtsthHGoljGQ2lU2ME Js4Bj+9C+btOHou8NC1P7l5NF93AmvsD7Lbqqs7O4cBa46k0nm1qhB0VYwO0jhoRyTCcok0ziHHC ZrobNe2tJHUs8EcycMq9+QKnmkQh1KDDm6YdldyEKyl0H0N0kAlUaPKloaA9pt7MS72wndbuRvcr nL5IjLUHOfayEAuFpoujjpMlpRLry0Tak8R9xADQM8CbJ6DoiI3C+N974kCKMRcVZaZfTif9ELhm lzmQVqOzqkIDCA60rwVkulT4l0sd9TqgAkThh+LreX1gz0t01ORdKFkJC3fVD2ORHOUow4RkKBnb XmnipIBEkSI3RE/ongPbmY539vXxKdJu1cdXt+nj8a0NGWDOlltMpk3lk/XOODtxoH2S4hn5pZEl 6BCVQ1JuHjxsZlSN1BsUaRvX9wza6BbtTj04aFYUdBZd0XIwuNXJcy976q4H0Y8C/SEQ7X5DfioT 9PJUW0QeyHboh4hjG6BL2oOHWAn/PD745Yk6qRmtPouAFJinkgq+WVglnNr45cEJNdsPVPJdpqR9 CITqYs7XbZPSoAY6zNQSQBdKagWw6+iTte+4gLZFOc8+YQmbQWbIIjjmE4EGopDP9u6ws4BhgR8z Z5p9q3KR6aGYgNAHJpOzN0tJ4IqBdoEjHC9YdOtHXuTlqj+geCZsUc2hdQHqLELTQMf9Z74pcUD4 Dtnxig75hV5EMnKwygZhDIlJW2oiQMkoSnplHyM38kSWmsGA3MemK7HRqwQpNsuyHhdLEB2cEVVS vjrvq/FFAUuDNnrakMIE9dLLdyZv7QDbBdhUsJFRcrgOnLogKNFETCmZuheqKuXflOhT/Em0T9xp DpZE1zjoOpylpbyGXvV+XPxZYOcJ4IcyG5KfiQxbLhv0qvc/vX7xnPqh86wrTX0jJ9FplQdLqvKL za6Mtv3rdR/L2MuvMAczBe81BYSoFJk9rHSGjToZfs1aMOwp+IG/kOzSkT20Lnpl01we5AyJ5EaU eP59EaZE5zYxFDeg6a/ZNE/CCq+op1Ah3+wc053K3H5NEBQrUleJKgiXyMkntSdROhRhBf+5h0Ka M420UxrZuIw9p5zb3KlENmoQcZoUd4iTsPJGrOP1JkV9U+O9G6a5jWhkj9ZmNj3FG6ASEVT1BqMg +Z9VwHlZUK5edLOlPPE0Ax3nrIi0jq6A0i/cEGQVkQ06zC74loItO8oy8Kq9kEZyl+lvIN90zboZ lbS6nDAKeJG0nksTv9NvAPthlzeyB13B/xUIsFQFk6vN5lv2AlIKnn3hK6JuQ0W0k6MUr9N6JLvP 2+vDLVNv2ZlhC85gke5k/S+3Wyk+Jb1PF/8M+9S+uiNv7tzpDgY+qJ06HY4ybDFqMtDh9PTh4G+i B04TRXenZsqlAhKCGpsoa29Xb1kFrg4LmJGiKkHhvjTTAXtAtMZqGUBeDnE41SoZ+N3tU1gbFeCQ Ngpo4//Q34N0OoruoLtlLW389b80D7bB5n5Bend6tBy9O3d6iggzwnmi6R9LBqlqWQ8FnazmKHH8 pxhfjPya0AlLpbgE7sM/TZd9stCSfAutDAZxO9scLSbVQl19V+aWPhYQk5ViOL5Jw4vCe+XDa2LL dsxp7ws5Iw6b5XF0x9MTPy3RH2g5PQnd+ritVi8PFQGpWLyScGRuEPEcNALU3oLcJAcZBWDfqbtx KhJ488/B4+9fb07h4X748MlkAg/vwcPOT53O6XRRLRvf+XK6frGCUv+rqQjP3mIAWvcfw4dPFtje fzAPv319MT3D7nzxhXn6Sp8+fmyeSm+6QRoJ7HQ3yA+B9e52g8wP8ORz8+TrWVWt5LF9/l2FHwBG NkRrtMiUZ+6gN5Kqq/LsPdQ4PDSNwLzTw1/Yh9/SEIMHz/CJLfMNDTh4gGUe2zIvqyscnR3eESKa TIMlrnntmaCCtceni7Cz9JBz8dEq73mntl/eI0scsAqOTbAh0lAb2CxG7D2tSD9aq51rZB+aHJH6 yMTBEpOx7/rjJg6Bw5xDe854wPBP35L3oeopGDdKbi8oQKHHOaOfLCo068xG1dkZlPCy3uuSsXsz rZOhKwGuLZszx5sVmuRmN05X4hNien1b47Kju1ygi6yPHOBHPrf5QRN2mUtTeCL+CFryn9i1NV+D LMX6RwCeNr6YzshDCOcSdb8RPRkRjhoNMtJsafBUJjn6jivTOkHheT0p26KZS6ItoMxJ+QfQvdfu 4MVMx02bM4Wak4LLJ5rXMDGqJSsRlIowqehCumIHUNJzB5ImeWGgCj1sLlvHULAncXx9QTZZtEXy Xwn9mq/u950KPte74yV7QKXAiti8CfS1ZuN3pDkjdJG42Fys18uDzz9f3pxi6HZ+OqvO62W1zk/L zx/ef/Dg8/u//vy0vIAe7tfjEqTk/epsn9Woeh9E3H2vS12s5zN3UqMUDicCwvChdgHyuYy6Wl1a fb306F6ZeiPrNJKYTtOEy4eDwyZ1pjrO0O/MEOGc4xRQPrMCL5kcnqxJDDxdq2vIpJYV/IC0oWuI YWLYy4U8Hwl27SBbF5cwydwdud3E+1nQsoHjkJJO2wEkACImmCjsge0ueWqwzVkHU62m52RXj2ng AFUTJYHaubuLgcStANNWdStdeFu3I1WCEpKvscmVI/rR2bUOPiKmF0kF7gjMiq9iNyDtiC77PewV 3v+gwmK0XSKLeH4pFhvrfuC9mmmeKBgePQqoAFFGiMV4/FFd7VwCAEvkMEQJXJ1Wm9mGO3cXriGa Jr5gWPGi0nW/HSSf3UAfX23oEMdheJLEgV6iEElRo0AmeMWnWM6WzVKVA08XB9kTYQTYF0MvZjcY upF16dh7rzk5q3LDFGl3iv7wGu+IV5CbGXlynt7AvEsBJXmeInmozZJ2D6XJzOS7JGYHNoyhCy7O qbizwzrx3b/rG7t9TJy5yrUT93U0rjZIuQfZU/5B/BW3EinV2WYxfb8pXSdRgS8n3q0X+mnazrI/ uHIodXM76AGAi2aHb7wUnIcloaNAh7u/Xd6Ihed+V/uLQBCCyESsrH3B0JR4Dcc/uc+e2QtPv62Y TqG9mngOr5W74zKNjVGmIUAbM7HqQagmJdrmvHmJlgJILR2AIeeRxuOukAIzdJXHS4SZUIktCcpI Mfe3JkQ1d/aNtZWI86KaTaAx3UjTVbiVOgYnVtLmOudQvhVHPZM2XcTkdIjuekPnSokUYzZU6xan G3ZHohaBZ7kG3N4bX+Kg6YeSZ3puaGJqF9hKH9R+5MtNfdH8ME5Aukvi/YBhsU739N1csNHNzSya oVldgHp4uklQpZ+nRenOVbQbKhtCmxTdq5YUXM9HUXQQEk8s2W0Q57EjG4nc4akfwoetCTgBqOtv DdT8qaJN8trgLpS/G/gqkv+v9b2W2xK8YDitJjcHjfgS8uKiO/UqT/m3G8+EBXcBXQ/UWK6oAmKi XVdLJQBxMkajfHG2pnM+8PCqxmqmxf6PRmcb+Bz62kqTvjPFbFrUBI5yjOcS/dm3lhT+tzY4ecRv 9Hl3kEzP5dvqtkJzdbkpfDkqVt3BicXzK8frkRtGbNFYVtjh+wFUIOkS9wOBH5MK6gVQc33w4rHx IZwuc/k1pQAChd5tOpl5e2VQRQGHGd55NUh4fsEn8UbYFc6Tmbm7ggf11Yvnb0biMEQqEVRv86V6 4+kDbcyTaY1nyCTlu7LNuarxSib53iHBxkAHBtl+9iCVJSpeu2akLEXz9qObRj/ZHBby9aqaS6A1 zNIMOMQse5zdT13/ZlxGhv0LSuetNJ/yu3MEw02HGmg7cAXSHYz/QYQT63YP97t/TJR/ohrhYVMx PLyfjC0m3QTrkr7AO/MkgIxHMj6GbhzA/5fgOOyAvYKv4GAcrx3MVYD9TD2FdnyjzK8TUOKCLU1v KNIw7DF2lZ1wSHwN1Gp6ktSoE+DCLPwiRlELDgmeCUGqu7gb06FX7cvFZk7aGDe8Bdok7IZo+V40 31JTttmqWNQkgvFM51vLwyBy9q1mQHrW5OirW6BT2oPJbbuSH4sb21q6fcyv39wyYEdBO3yulqRL bBZhKoGODtJB/f0mNWiXWvmtRyZiw5U4f1mBjX25SfTvrfU+rbWxxm6JR77O0t2kzAJtlGvni+nR yyVOuI8Q55yrAdK9Fgqkjr3se4rF8/f76qkyxZBtsmOChr1Yi1i4FlwUSqt7EbB9wR8wGoT6kC3o do1INdJ84hBwp+roSMMQULV+YfitG3zhs2zQTcgqmgD0DbyLz+/iRCA4lJ0A6XXw9X4MeOe1LM2T 6LN7HDvz6kJTAsM5Xa3QI+tEOjRoNcn6Os4gq+OCwxYk85vWgRH+YXjxicJvaIcIxmoC6POLcrYs V/2uVu3KJ/z3pYSF8btLGQCbvSiksMOskvh3+3GgCplrN3grsYWT4EQ/2PqaTEVtCX1pCS8pkcKa U9ic7BFjQkITfDz0aSBDOAnMgDULXTJ2mZyDXFSRBu0LWOBdLHw3GK6USI7ZC7y39duM2jY4zLbQ TVOFbaMgGRCzB8Y/aNNv2b6I2SB8HC1pX2xmQJeFW6vGLtAKzGSqudiRMj/Ps3fvMKjw/qB+947N k7ZZTyOLCTePVg8q4EJ3wy9o686cM10bCBWKqybVWjYRci22ngHTSyq2Zi7s0jstmtFoP54LplXy Y/fzRDLFxATTvUOX6f77eEteG/01pbg3j4ynbIFismguTkABZTy3zkUGTadoUC6CC3PyIAlwIcRF RudEMu15W4AsZdMskoGe62+8iRbVDsttiMPbRBe3mEzUHubqpQw+6AvEUR8t9gwZo/945QKT1XQB urU1aKhNupZOeGNKugcthNVOHAnMWLLy6IG1paphHYnROt4xGzUZiPH5Splv0GCW3oIRDbnmNWQb V2uhKq+3JzuLoGAfmOXHHgT2OLV/tlj11PaIlkbPSiYKXqeUI/EK0vu6mLrRIVPwhtFAujThp8r3 /RjE6hLPVsuS6/Qd2jUNNSiTCnl8ebA17WFIML5WgE97Wd44JRRmH3MxD2g7ww9Cb+Au5Viubwwt QjhkUdV0W+M1Vq/l0NWavBvg0BoElaXWl9PFC/YfGvlsRd9VEwwSNd8YJAVPLvDxLNev5MeLePjN TxPxzjEB23Q8Yg1O5I5Q0wVi+J2LY3UKSQiVIP4vRKzQmUAOaaaAYk3K6Rum344oRKQOE8k7D9S6 mSHTCBq5yq1Q0I41uPfioXLfRq1SVnTPEF4k2otOHVssnNx+k2huEf2G+rTbxCic9VNvFOkUCxhb +61i8oCwuUitqSNUsLa80z3CJi3OR5DTs4RiNL5MtGT4YvNl8vbAKKRhbgWNcTrdLMYXuHr2Os0f wMuRg+QcRh6GxkYiBBflSt3LROKJ7pZ8+2gp05b82DwDKs/1Y+T1he5kwMLEPwj5VtDBnbTLo7O+ Njuk75OyEnB9Hc28Pg/ZvvPQ1j6LKteLPbh7Q9vIoC1tOuNAPJYFSaXaSxuYbD/0NOl2t37mlm/A RGGUYBkcFe4zQ/Vy6w+cvbwfJupz9k8/OQmhRz9jzqf5OprMbtP1HLE67DTCdm/qf+ENZYsGWF6P uRIrrtoQ0AB05IT1Vnv+J/IsPD7MHiVyaGqmyFf4B+a90twI7cu4rV5cGylVyZjrBftsVhYrWsRq BXvE3GzjXXbJaoY4/lDDeUPK8ff8QR8DvrbluG63S6oR2sFfuyZDa/GYxhAkeHUlh5EzHs1NIhN1 c8tTq3aqvp5eh2AP7bk7jU9F9Cnj1Ic1/G7XWwT9O3Yzi61F/hPxgc6OhWngxa9YEhCRmuOcSLOm aT5j0NuCnAhnXgE0VzJ77S7sA1T5Fpe1NDJGD2aybvqLvGpc201EA1EbT5c+ijeOsJei/bTwNfOn 4pOs3ITsh9MJVmOH0D5KgMdYwzQxqSTiIDS1pYfSHUYZJiTHNzE4OHvlJHmxQq52zL0byidOBnHC Wj47nl0vKdW0SGoqktF3PGvUwSQNrK1CXmQmZDKQjjIhcAhA4Ihajz4Uqy12VhL3UUmIRFBijqg7 4CoZTmlMhMtlw0LoWhvCiUIbrIXPctgBR9MaEZkHkFdLrvXCqgsqC6DgfdjYHW6TgogwsmUSYgPd QiKh4R2ofJLFzfA2dCep6aVEe5NbEwH7LSaU/W+13h9PV+MN+3qeiQ9RyE6mw+xDeOMVdqdx2T1N ZA/AEU8XC5IbEzdsFN5EUIzopUFgwcsV4gXNqmopfo+cL3JWXaVx+dNKGkhK2PLQ9IBlJY1eu6Ut DIJ2NZu8evvEC3VLoEYgbH4IS9mTMalbyiZpqJesR8Uyk3RpixBjBaCogbFLrCSG8SVQ+rFpNmKJ t6wA+jP0sc1BA+h4mn0hdN6kGKKHwyAgJbhcHLVhvEjFFlkb3zbP+S2UuV0KZ9oyZHVbffiI8IiQ oprFkD90bqHKoAytkJGBU/Io79zuMDNMkGZnM+coq0HIdbdQUPC5dgNHQLjCYbedHrPG6aGryMcH heMYnqMesYeZC9Q5pl/AoBFFF53gRyO/rsL9RrQv9Y/m/tQm6P02M4ilM600tF8ZpI0k2u87Wd/2 Ytg8PEmNkbMTY4RsPOTN/LTCnrvgoWP61TL2WXm2FrOZ/oyGzbXxpek1wm1JNfc7WY/etiVL7fbv 1Bn934BQZ1wPhjIM2/ptM86TYsajwzaNrFpm3qqO0Vwjvxs9+pXMNjGtNAQve0+/04Ry79TvWsGd HuW/4tgD9JlLtoBA02ebBWhK+N/ElOLXc3xnpJnVORWM7DPYFF5ZNp9eXjWfk+vP6jyTC8ocSxzs cmRBwZC9ue4oUwxXznbNaX2aJVd7clneXFWrieuN/L1bj6SwJP5tfJhHbzm2VHAV4X3qCIUDxpRo HjONgZvSeK12qBaK6GRG5Tnb28vu0lU5m2ffwc93+rna2Q6pKdCIGpBjye9jzJr7ZMzAu3fqvm46 R2vDrAf/x8GzrjkzDTh/4zDDYt+TrC7r0MzzVluxtBaUCWh+J3Ox4+EbdP7yw/tx8ec7+En89RON U5sfZv5XzFc8R/DtxQwBE+utyommS+S/AjUWfQd9TN+vhpiWgYuxYxsFBFDMP4u1OIHEEXE+OrcQ uHwwJnAPxoVvYR3v9mT1kwxtVp4X45uPZmqepz3Kf0ncjKTvd/+62Bk+x4lAD0ItEic1+5djeVv5 2Q488V8ty/sEloax1dh/nP3mjOq6pAYRVLulH9277V/m0R6kZ6H1wzG7up2j/m0Y6vA2f0yZX1fj /0MceM9NUobdL9DBGt0QF+fsgoOc1uOi8M0J+WRwmcwBqmC+BYqLIQ8mqeJ5I7BKXG4OHImAOTst 9nPJRZz9yrBR0+JhKEsmICTaCjOf7jRuRZ3lSi5G4e8wIDpyGsUC+Xh97XWuQToPDK5veMtMbfuO cnAB/ZNg6fSdxtGUEtf9EDReAauyx13SbveziHNJlo+AKnMmzHgnY8kWWvWDNr1tVygaB6+YhuXQ hb/iJMvbTUek2lDrLZoaNhkraqxq+6uOyJ7K1jyCvXVgIdQMIYYYNRGzC2gmY2+C+hCsFTX2gTF0 zWfNdS4aqdqbURvWre1McTFDhBPfaZ7anIBT6BfDhBQYoxXy7fhO+2YePRG8FHyok38S20FRv0S3 kZGo7Njt6To+gK5l5ehXc+VsAw1bIXbBuTdLS5Gp7WYeKPxpVV/HaEUBtPfBs4S9kLcLa+cJ5dwM pVm38YmESVG21Sq6N/FEDqNAq6KO+GSnazFrKDXUdjw9OXE7eRX1JL2vEmsWOcEnIdMiJJszchzF C6cPxXQW3jeRtUzO/8AwF4MAdYe3RkfguN9slujRDyscWtY+orLf5p/chEAUfWJth1CUPAIka7jb 69njOHE4nzXRTdiTBV3w+8FtvbymFnxZm3x8V4+mNtOomLzff/X2f/jss8+WN/mIEilSLhIknvfP 3v4X/+1nn6ES9cZ7xXs8NkrLtL6gnIkEBsmZUEJADgxExUj5p/iOLQp8Ep2XsCEoKBYl+SHHx5Zy gE3KGQFOkPdep6NSUsFBqtUVduJser6RSxfy1GXpYj0t9Bpe+kOcJ+/gMDjhFCLQCpQg/S5q7Az+ VEiSL4t6OqYe9xmibmDwakaYJXs00kja4hp7Oi3rwwcP/z4+Qv1bAjrVP6JzdrVZ4NWVXOSZOvum zud/HzneqKvin3/yRzvdw8c+0b50zu+NBXcEI+eZ5uHgfB8k79CpgWN4f2JqLzdx7SEjhTQ+T4OE lQMedVWiAbSfGg61j+7h2IaJJVFyMJ9B9wxY6EOKqNwKHoZI99EIIgSx35c3CUx+2N/ykaaBjbPL 2YRWSsymi0rSWzrHsCrCcf1iENnv1Mmwgbb9FK3Fxn9G1ytec3rKsrNd78YqNv3vMypEOMFKx2Qz 5GoZ18tD28xm7rcJ8lS/XmH+SF/u8WG8w+KQ8/ID7o9iPK5WE/F4pkH1aulDJw6aJdGqzyPnIrwh OtucbvwcOo8W3mvUovUwdp/JawyNjSy6i0l5jQe9H+J+yB4ad5NU43F2P3GZjW6afgAsBMKHjw+o UmvWYyj33RvQZ9cbSdlN/pvMzbM5toeu7ecpi6+jLsu6413q+CvS5riq108IpJw5rWe6HvApe8Jl 3wBz/pwL75MrJwV0JI6bPHA95TngJAQcVIFhFnBeE8KHpLhZruBcG2OpTigmb+b7DMrPYErFPjdx l06N/XW1T1tsH9rYN/tEgwLE85ZInzKuUoqfeoPwINQtxjkhKjXBGAw7ImMzRwGeszUGB5ALwgYk s3HoCIEQPeFcZGez8lrTylNuG07WsWhA8bulld5kFAuCw8wjkFg6MJ2FWJBAzgjiuagZYEdmBVM1 Gs6xA3OkvAmwBeQw7gdqPmoUXKMf5M1Jlhce9gPNczl5KhTzjOgSGqPEOvv0vYHDIUuXvu38F3MB TCqvauPgY6I55ILhOyFPZd6uDcSQ1d82ShYaSJ7tUuteo6H0Qe57on3jnFPrm77YShSZ7RymYcvm 5Ag6olRiUpSXSR54ukVaopx5VQbkGxLUrQIV/V2XaEKDv+/n9+3YcRf0fSdZCh7krkHf1KAhlkmb LJbJH7uKReGZ25QqMD07HSIgI1wvMRKnP0hEtoRCbkO6cAd++N6ezx+3v9p3EQ+HZtLsEbevMBwl nLa27hi6+ajtQ9NETIuSEB7Env23b6GwBZvUV5cg2jnrbZxj7eQL2Ujvv37734OSpAAu5+WiHq+m y/X7b97+4t+TjpT1J6Ajl5R7dcChMRyGiOffrNznLCfQ5L4oUBhXx0ZbPKAk5wduDNFNqlp/1Tfu 5/LyHFWzjvv7Rn9J1zoCiUmJiNfVkryX+sa3lfxvb2pU9TQVN/72E3OKYYgEIUzqIHma9qWGMf9N T5GYoOznQTppVIqnpzllcutPpqvDB2nTLhSKEl5jW3w70b0DfbpBM0/oWQptI/AHt43z2db4XFIY 8z76tqouN0veStwgzRBMJbni6iSBsFJVa06jRGPlppcFo5rQZNAf/cExyqhaWh8ODk4sxmUvl7uW Y/3ACeyj4+t8uVmVOFZyI8bVuCawAmzkxHcN1g6NZ4j0bldP20L/quYKdzSe7GG9GvuYSpQppFw0 eZicj7T6IBoNa7teB/1F3cy9kMy5xnFAMz4HVsnlDZE+BsJqTTYz9u7CKveiFYSh42TL2rAnr18h biu6VdQeQ6UTIlzKqmJ6x6ILSWJXFyU6rS5vNLMYRZ05+QfvKU4l2jFIQb3nkAbZJoSCjmMCElGL +dCGnIXpFLO3wWGYx4Fs2tkhYu4GfTgDsYPjju+sKD0tpr6KJiAEUZWmmGRQqsUwK0c08q9MrzAJ XMe/+yXM43R8OYOG/6TbUNLp8HNKylprC8NMcutImT/R/pbPUa6aYfYfgxL8Fcm7yvGhnNPGFsJ/ NHtej7Ln9YLh4ftONDYhr7rPdjMemnTTk7sNhaCCBybrLJXNN0vMX9NP7bOgE62zyh1TLj9iOmDV cai7QDsoA26OwpXjrT3nG5+A745GSMyj0SAHXorP+4In30Nj16SYgaynLo60mwSjHjk4NhhsUnoK /3Ww773fvn7x/aunz17/tscpgtoLPnv+5tUfsZgxFzgY8lIWSvEwJpOKANn7nP1P5uF8VW2WxEnx IaYxoif97qQ83ZyzRU/Cq+hF7tvp7u+73Ya+8KR+HHbJpo7ZjTjJ7CGF9PgwBujLYdfWm5fr4kOx OuziTBo7Npq6D7sCXeknVg9l2eWwKSkDSAZ6A6adoGXqDoKhj+cTDE4ZIfJgn4cU7kCVIPidWEKV jxyKXRPnhsV9032XXME9MsIM4kKFTec8nBEGgyIcwEjAlaVTpiqF0/S7Pzx59Rwz+QIrQ2TK6ixk cF66yRM3ACBgHSIunQkiKZd4bGbHPSDLYdaT3uFP+XVC+SFnm/PzG/wAzCxGhUy2RYZlX2T9h8Nf D2IL39K7RcDaEIFFgXpumLpnJ7qsDNW6QcVYIIMe5n+3vxQvyUf37nW3Geib05f+AOUuiD6SdZNm lO5kQ1H7PR1KT5wAgKHe5HrZs70JqG5EUF9c8dxRFtVd0Vw7R44xgws+1nMyKC7nP4i09fqmBob0 7BoOeKVH3hM57YnBoDdsLJ5/4vtgd0XIE92bRGFNQx69T6y+7m2/22VTyQ2ja7JJ7Kegx0YzJqzw fsgI6fRZIgMN85X8uXe2Kss/lUDT49kG+FTvIIue/KRyfPi479Vvk/+PwtCmHB4utzR8ra1YqzCB NFrSxh1IBTMUbpmKja9H/L08yh+FIg/h09fr/oiA7fBSkD+FGJnu1KSC91pLChMID1mupSnHmq3z KTmk5NrT68NeL5qDIwYdF5hvjdAjjGm8zpR2eOyCpcLClmCzEFMXWV8+ZXMAsC757LpA45rf/O2D y/YfByRz3Gvifi7KK5chPNoQjlXm42KJbkXt76vmyzwPgdtOgqlCTeBmWeqcDjTpCAhpQcDChc42 HddUNh/R9eBodHz/ZGgeMhQqqDag8CRciUjPPAwUA5TPRooBNXXyEGlBrN4ydqLO6zG2cRI6FPlq Bw0sRgI6bS5PxYoui088RgkoFMIimZHGkQCxuyFoR5mUe9l8y5EQFSX1+P3v3v43xn4wL1aX74/e /ud7bDoQFyeQT9A7bFrPeRxQSIFYUbsYMzQVu4CpDbbOrc0AFBeEHHU2ze+giXLFqq9LkzM4cNjA nN8SpgvNuGQmF7Y4p4qfOwR0AuXYkbdhXWBo+O1vmN3C1wc//TwZkRn3LJAPTSNuAXr7l2ZLNAVF FAnFc9QIjr2eEQ6fvX356tnr10cvnjdExGqBKd42jAKu0OGUHN1zkqzenArIjgGyiw/q7pNFhIyh x3RWouhXUDiwLRI3cEVpGMgNmtgdGlndp/epU2jJxwzWyPlxVblg3JCH/kb3jsWab8wxqZwyvWz/ MuvRsvFNPCLRsrkqaoowqHs8I9glRB8jvHSlViJmaR+mr6olnDpuyDkZ2M/28Lv8gD+UmNWJcbV0 MQs4NTohiFEv36fEE65nLV3gdVyvCpk9PjRgsnr0dCQfGcmYexgfOmzOMV46Ery2+SKTDwVZyBKS rxB0EpQ92Mac6JGhtjssHd1C/d39efc26qetfU2QiUr+Xasbfffk1e9xC9xG/DRgsoMQ1WOzAcE3 5qB01DTPiEk8cLnZ8K+HvdQok4PcZ/ZUx6rgaA1CWaPfNSY1kRqZAhEOSfOgXCTAq8vV/nJVUTJC kATrQdgTYUbQFSCHftd/XH8Suw4JHd72UOREQag36PxsJRE9ylmv4+nI5dM2Mzy9Hk2qkXrHWMv2 z1ARcXScznFhFNRgLqITk8/2FSMBkPBfL2egEXQPYF4eNDQzFtoVT5OGlt+pD9QCPExJ3FasXwWA OPbNoDE9INYjFjasU2KSnBifWKl8vbqhzJkKwR6uKWNNo6IKAsf07Iav/+m/wyxYZOEY4m4Yrqq8 E8MWcpRUKd3CHeNebVv120paiF165DZXDnvSEhCmiFyruvtdNqERfo/L7okA++tqUtwgehcZOX1x AdE7LWFDLchkiPIEZhXraupSaeWK7ttPC852PgeJnRuYzdYV0BRmMKgr79luBkXhGOsarbh9qGII LpxPymWGkRHm8fEDsc2zGIX3u7MAjD381PE+lM8Ooa2DbnAVZeoGIPxhD2xLBwhNJ+LRXE4T59QL /JjaLCf+GaUjqmaK10/0E0i+reuscTRSe2hLNgwm+mEH4MKVtlk6GMJGp6ApIYeT0AgLxMubJjnG 6SOwBFK3H4Wr1IIsvcNYouB7IOpNGV0bydo0mlDq8F9pMNyLqrrMhQv4YrzzD/0Dc43FrjgnBB4g Hw4k9u/YyOy03JeM8ObBZtTkrVoCHkEsDhLdsNeKauTV7AMnykaSVf8SrkVphjiJdL7tTl4FKbME 8xtsgkMprC+Tc4kSf5uFq6wOUU00Dh8YItfBOAlHi7OKUx4kX39VgvZb+Oxw9n/SNzyww7tzvrD3 XZdf5hodL/6xn27oESqQuXvx7l6uGVnD3/OIP2oZ3SxR6W9IpPJGHXGCxtybxeLGaBjwzqcWr1WO lMW+1dfCXqP4+dGICPp329xAN6LpaaBQjaILGGUkXFNvaBL+lTzPAZeVZ8y1+fBN8gs+G72R6A07 olSiqGG6cJhD2QHqXr5eF6oeeE1OGs29IYwvPIAO+/qdYfbnn4Z222pXXNikS1O5K5tu9pm7o3GZ RilEO692FfmMpgjhZfsBLc9u1A67qjrL3NfZ/Kce085wNsX84aQNCkW+QOFf9TpTDL0mJUESerNx vu0iO6CdcPDuKf7zDrcxA9no869FTn7HrVu1beg+Uy0CnWubxoXee4ymfZNp8hSncXEjTqdyWhau dSC0hxsGt2fp44yYz4kc80Sgdt1MWLxuZsLoqw69EZ2aZsrK+OKu4WJ35MBX4sGdP74gi/m2SDoe q8jNR/I0Yol2HMQT6QPiCZEaDoM8w8Sx3uvUaFSdZYjVqjkwu/ntMKgVbcQOp9GxbX2KNqgDZna+ iBegL55fyDLLIrs0iSZzrSP9ntbttXAwHYSWy0fk7DUa3TK/Zhj+cjo8FPq2krvZ68L/41S8livY YH7Nh8VY4Sqyk08POX+CNH0JK1PXkn0c/nqQP2rkUJBuHZuvnHRcGpI2qZsk64GkOU/19PiXByfN s5Lkusb3sOxJg6uaAsxY/YV7qG2p7pZSn83WaqjNeG6Ozc2pVTmlWaduBUKZM2V6/8evC2S4NzT9 ytgC2eSdONqiLzcMqappWzGjyt69M99+9078xNbVwuMB+2uHA+Ob7F2/3KNAc66BJNwEZHp807wp JcdSGFIMf4EuK2vKutLThnrB6FAwe2c9iOVoefcu+MQ7LZOHSehIjMCN2CZiTVncQRBQVMFG3QSc Z+biddm23f3On+bZHJXT5y/eiEMx+f1sFoiqjhcm3cCfTJkC96QnFNBLuWuO2HUqmdIlWHW7/2nE XDE52EZAiIzeCJexnSehyZsokXBiEqscycKiPRxms6Qor2YfmYGdjD/ODHC77Qfvl1xxWHEt2qei NtiNfA6Ju14PYlJRTrRlwtJUc2dFVQuYy3M8qBAThatTjCnZngbi4IHv6zVSN0EqhJceSkaMldAd UWwd5lsjZvmjuadeh+X49gxNiV/MivnppHgMdTBpm/vT8iBHYjZAYqIPE1ZI9lrDR86mn/1AaS2W MNHiazEVFwXxf2nb6/6640bvjg9W5dnBO5gDkFY/8BUyasOUKYIEGic6fAHkCZr3qprVl9PlYxH7 gjE5tsf2+upsjWKtpEGYTS9LypJhOSHbkA8DHv78yXfP4rAWORqDrwWNPEw0Qqv/4JA94sm1cQUP YKR/gu6ETXU0jwveLlOmcEwAwTOMU+FWqG6KnHY8v6W+dD6Ba/OatswnBb1wph9Y6kklePJnFcoO JrrtQZ4dnWlJQXnnQ4mph1cVxfIZZgKvRWJHaBIKWhJzlO9i4aR6p7poWVC5MDc0C3XULOxdJ9vR 1+rKZrjBrVP7Sd2sKxD/p2O652E5SOicUnia+/1irRGg3M7D9lE6WXKHgXZMarOPGGjhbBuyq2TM vjntxDAzF1Au6by26tLK0r3HhEH/+dbLpnbDOgFR6Cw8yplmlC5YJ+YUsjiF1OtlucK4Yex17wwk eJ/ABIVmqmu8D6Y5CCyU/1xdUjABTwtJurAozaXu2wlq9GrOuQKTzj6bE1/VTwZuBFUNpgaOk9B0 eIc8r9aS/nlF3iDFKdqeQY/+gG2HvVR+R+HCOMGMvoKqI1uRI3JBky2RLLBDOEModXitV6oJ8qER yEZJkE6VrGUz+m4x5wyxQs2ekBnD9NAfsZVHgN0D330GRWEAK/oHehKH6TqEK/kBRTQA+bcaRuT6 h/xsoQjbLXHF1JE9OrtOizG2OtlnL7Ws/zD/Zf4ADtcJJ0higBMzesKiHsWtT1xojqhr+bha3vQb GVcmlImmh3/1GhJd94uQJu7g/z32YkE2CXrC572sw10GSrp7V4CcwvBYEFqEXj17hdp03a+LfaBn hk/XQfer6AMZ+vfQlr1C4Qaz/9CXP9cPQ/F9SThS+foIBMAeCWH6ZqqhNwop4Cqkd6GMWDKb1gzw QSHs5IKST2t60g8R1QxuAk0Nivh8DdyPBSy2/XK7bblT+W36YsBI9yxuid8puadsSfGJ7xXLGyvm vtq2DKqRYca1sjWha+qbx+6Pk9Y6e8D/r4obEMkqWFU8sTKkcZ/fkpiluAvd1vk9ZnSFhJXSOoIk V4zHlDpzp4nyv+8xqk9736M5tZWTdbZnfm221vL59mYkz99hJJ077hQniYiJjKsDf8Ji7T11n1EJ oL+VJMznHV8eWh7cWrs9Xr1uGyD3bfAJ8881STFLd3PQZtvHTvgb1Ctl2gIQGLHsyyuN2YhblePI n133smB2gtBXhSHqm7HTEcndlvPy8moQmH5wsbzG9Z245Yn8ZhK1tdiAnF6T73Z4az8siueBs9w7 l7zbz3OolRI/mCuV8+X6hhkX+j5LZrVJqzBgW42F3AzPWfwKRr+YhtfkH9TSdiRJxCvOCwZvlC32 7dxI6cHJ7eJAcKCT5H1nxYsO/8qK69He+bQdaEQB3QitS4kkhEe10QScRMtXOe4glqE2c2TptOh1 dTA1cW443hTRItqtFm0sS6DoQztKYXywj2uky0j6hlU5EwwezHwlXqz7JIsHQxHQU9dxb8KR4aXc ah3zjHawG33n/X96+18JnlG9nrz//dv//d989pmJpJWN/Xo9CaOTcVhz0HJQSV/uc5SleGSqC7mD zaJUmAu/F70axB9yiYDQU5d8hvhO3l8wpdlA4y5WJFhkcDd1Lv34CGNqw76IKEPwSeolVAqtmWJD PKK3CQNi2ooGMw0TfQASCIYVkBzEs82BFEmD6bzTgTrQF1wGWLNv3/574x6tc/L+u7f/Ezze64xG GgWEU9F7mP99/rDXef/87b8ztZaT0/cv3v7AkFWsEaN3IKh5FGB27pJ6vvzqyyHtN4HT/IpewymW OZCo0ehsg7738D0ZTHFaVzMYtMydC8CenNow7U54BfGXdHnu7e/Dx3uN8JSUR6S4fm7qEqoYx0+6 S2+0IG6TZD3HabJTKVM2kSnLNC1gHUfCtfuHY2KnNbRX9g6kMCxIf5C75z/tdNdz1gyWk/ENGj46 7Os5LxYFLrNae/svJ6dHiw/VZYmAbD2oOqW/esIEEW3lMOvDc9+3oe9yPgqaHbhdeRbe2u5YH1E/ ZpPoYoqKuWsp51QVNOmNl+5RJ2oh/lBqWjptXzVeqOpEiThiC/TO5fMHBuxAQ1wLnqu+rMvNpMJt x/a4CZpJarX2gfw0owG5w6HRXTfuaCrcjLuBp84qXlT6vJ8zxxJgM6wqvqRFE9jRi4zDbtAbLFSR W31z6TBbsQCGbBqZMv0NRH02QquGSdS9hGHF/nGaHS4auATnNNUK10qiFm4HfoDQjRRAJG+6DTWc 20mktqHneb2pcXmllf50MUr64O7sV2wvkW5z15WnsKH73cd4PxIuX//oxb5bpwwZC8Iun50NuknA s2CCrMNeiaxtBNRnPo20+BKf+P3Up+X0WoFjHB7YRBvUKJuRck2TGJfB7dExGknJsildUCyVJ5nW LsvasqS7LqeZDd/bHEaEZiPX6048ZLU90zngMm6PURqnH1g78rBw14qExkpFB3r39+MivlDEPQXS ArSvnuJHz988e/X8ybfPXr168eoxgXqDqIGtDtpqns029YX1hz8luq3q9RxGVc55oXGz9rXPniIq jEGhYv31qfoiNKbLzpQMYS97+/Ytej2vyv2NpHd/I9viFc1niTZu3Sm8UdTjuhwXXIeyjqGnlbPv 1NUcMZbGFblukcSNBnCQERCbWBogX5ZqTUG/s3JdIvo4pX+E7Vk7dyfawDvRnfZyJR3vDvLR+qrT 3MDBxnXz2tWoz2W+rrSt/voqUYdmFkcGu16q7bpe8VrpJ3GdMBJkYZ23XQTqUtd06wd0TZ9kk2pM DO/7RXm9JP9eF16nbBuW7mwzYwgU36e84yF7kRjIMWF2w1FGrgX2mRfAHpRH5Xt6CCU+22l600q3 c3GbTVRqqslBHdz7nJH14UkitjOqMpIfWFhmkzBqZpiobQEc8WI6mZSLER+NlHxZZTmG4erfHzL6 I73CJIK8fFcXBCDDgZCU8H16gs4CZyNOg4k02u+O/ILBh/hWPQYHnWb7h5KaUDo/VRndko3UcLy+ L0eCvWRg1M8R9UeYHvxfbOil10MaoLSRJ2vFJ/NZuz0R27p9YpNw+tIZ3ifQzEt37i1zdANfu7+c yA+KBt8lQR/fv3z7X4tmTbz+/X9++2//HQMEi+8APF5U+2LwGbtAO9wDIFjh1RpfReNllglbBTY9 hFdDrq+HrIStLj5MVxV58tGDAEtsu8WHUPWzOysM6c8QTSc0AsIvVqhHo1tBoRs12XHj4+vBRt6h WjfrcpzyvFjCgq6MBWoHBOs9nBZvjh3cingdGH3qdWJK0U7XPb5Tnwg8Qv/jB/bJY2qmFep0Rldw 2iCxoEv8YfZnKvLwgAkof/b8xbPnb7jNR6mHD37tnj57e/Ran/qyX37/+o9DBJElY+Z4AkoCaL9D ioKChr579tXR99/JobxZkF2I0gJwP2xH3nx19Iqbf3g//fjvfp18/iv39MnTp89eDxmE6oZtqqcl Juf7TeenYLN8V1yCmN2was2KP03Rk0HjD/xRZTco2e6ADdaEDvLyxeujt7Ifdfr75MtyRtB1S4Fa 6FGRnpjIBnmWIdo3wZw6u7dBbDyV3kabOnS85qj0Q/6X9T76ykO9Y7SQ138Rf8LILLaozO0QdSVO ejye1QGKM5bh+0+obA2ya+NuyNZLqNqgcHgWgVH6BkXAXlTbzHzBrYeZvGOotyP8NfRBLhWYDInl I1wXHbeUf7v7/eJyASLVMyxwZ4J8AZ/H+RuoIk0QgU8wG+9L+8OMHwxbeMCfe55N9w56cPhQe70W jtETTtQ7gAMFvX1ZK8Hp+imlGsZzw8Ol/qYm1L3zkOvo3FlOyANAT3S6XtvuBUCZFkyyNZRtmBSL hRyjRh48Y8+nMaVsCKwSDaknjk1sIw26aI/7GFMGzVGbITgu3H/xmlcyazmzDWU55E8S61FNU1Gz 35CFUJjWm3ypJVxn0AbMbp+kZshHfhoipV0ucm/A95LTmL72l/79AOJZdVWnBh/yHUw449lcNKHu 5UEiHfVVSW6S+H2gEPngMCPk7+ycvFrZHyeTZWlaedp5Fv5MpIZsNJGcle1t25P7mH6cNAWUrYwp nMEQFNY/hx4gkOidlcuC5qW2LLon22kj4f86ndKeTXzegmD86u1/Z68vGNTs/eu3//RvWDxmObeW PLLiWaaAZ1mXy5NrkLtiGnrXns4ZiszkHoUWAH/F5CpyYouLUg37mbO+c+KLjlsovt2QjmoPHCRh rnBsLJffzWwS8o+qam9stJG26yVq+NYv397++ze0DD6TSTWfV4v337/9vx/yMgToukNWO/CG/BqL G0jdzl72XYUOzfRhUjJzaLUzrYF4Hz0UjoWgi+hORWIFveiSx5wKCviJHpFcTzVRLNpbECAEyzJP 6fRQb/UR47yNYFTlNV5RLMi636M/6h5DSlziv5PpCv9BcMhep82lwKDY+mQjiscEA/b5NaaNpCHC nqr1kWLKlxNmI+aaY1Z+QrVJtU7WNBILrZ5iztoQJMRm8i1hJht3194Mk4OHcd2DOKcizm7eY5+R 9q7Ah3DlsIz5OK7JJ4xfx5XseussNL6PL3h0H9eQnRJKyehaXJWzdbVbY1w0rH62oIDM3RrQwmET QPvcsW1tiPhM7QxyVyVsaSQgSjrLl1eJGD8bpH7VEp6++FBSUoKmxICYRCmgg+SZKIXPG/L/IHXw bwvisSrNwaMT5ijVutfiBKn9bxxltx7hW7t9/OjgpMVdbLchJGOSFCcCv9pq/+It9gY0CdbV0gCY C3LzYeF8ZRw3GGDZ+PF6WhrsJPDBOaBK0Kq4Ivhi7O8AnqLfCmUnaWYCMw30KSASqki2hUH2j7JM 7bMUhL7v7qAHXzutqpl8CL5Df9G3f95nVeJXbUyNK5l9QKYM8wRtKoOUKEtvsjNC5sbJAa45XdFt RbXCYN5hog4aYjBG4xIEX0JIKNG/pljdoE81nJrOSJOoKwZ6dskha8dUUVmTqXTCgLzEGd06+1rz 8upgm+8wcB/UqSPDxUcTgvFtJ5ag4IM/r3PsDv6zOmjRHETweV4C6b3CrTzpx9cRHNck1nfYmV/C 0dW0atUXBUW+RDlvMA4OxIuaYGgZflK80xyMgwpdME/608pQk+kHJ0KRDN5ykJExE48jLsTsY0Qe N9QEeVrxL4RaenTZIgNElgF34mNKAEoNgQdmoPQH1h1YmNMbNLn3e1q150Invfjgk7zoM/Zr1v86 +UAMKINAPGzrrLz6hL5KTd9Vbcr0VB6FHZWHiX7aTAXJxGSYo5nSW6gzLeV/IhjvHXpsm/fdDtI5 mL7b5+EA7JvEKFSqjToPj8uFZgvRfmf9EL8DZdydxgKt+SGQeOt7Dn+GHYYHaaogQPpdYl40rQpq qITPgGHzNADcRC4Qb3EjLrD0ykc+Za0UtSivHD0jMjBvyoZZy8i4xWR0OkVP5dQk42s2xfE3iuyU 1F26iyZlEEvobDeJnYZBHYO5XPR7q9PegDAf0yY4RecPu7f2eo3e8N/aze8XU8oi8cld7SIepH7u 0H13l84HvdcsTtCZw96q95edX/zKR88v+imozjQO89Oku6ggTFTRm1q4d+hyQ55a7EpJsZxAlOTg QlHVp6UA3U181ZJlFrpxoQj5OBaLvDZie7zEQYpZjYbWW33fS171SmHxqen9uOhtg3Y700aFauNG k7JwMMk8qWGtsykFpCbSE+bjWVWXdmEww21qQwZJleSLEnixWXC2EplXPymD0Ms8GtupGVubbdzJ rIFxn/2cc8mRgj0eZmcGLiE13MRQkRaE/DiRRDRkAkUknx/iguglScUaRCKPvdo+SN1sefn76Pkf nnzb51pNkbo7LhakmVBcLGeHIgf+enPqeTZDQ8G3ultmUZaCsyvxEOO7At+rt189+8MBJ58ENWU6 Abqv6np/gqkIS9wdl822Kfgjbtl8maZ4h0hRczQVyjqxJCHisTxJh62sRVKw4bt2UY4Hg+hiSE/H u4EBgi6A8DUa6XGq6f7VWfwIkpZP42mpcb/6vx+ABWKaPRNgbsRrxfejVtlEZQzJzKSiBmXW1RB5 0GnuV8oW5XSngh6kS90PNSx6mPURMoIUOzzbqVdN2wHlCsvMR+BBoxCSQ9CTBn0wjeG4sdye/A7H 9MdqQ1AN7Kdyw4msESFCzQV0yU1xUzB7vDZNGB4DcB9k1RpKLwd0YU9/ZEuQSnxITDB9Cc4fK2QU HPdntQJnB9mDn5LCkCozfcmD6GxgFNCWttNB99F7MyROFdcMQamQ9fnZZjZjmB1BaaPApVl1ut+T tnqGwJi45AXMb4FORQkyu+tiSrlR1A7Z1SEo9puoGIEhSgy1th3mXqjL9ydRBVeSdfr3YYVfcI24 gseYee97fuQ2Gw9PQct5V+/XJYKGYPQ4gYIQ6AbMHhvffeg04++Sn6A05KC1CUQu693tCVInZYGZ xJgRUs1M+zTsGGJ+LHpr7WCyf1rYdqzyoH8GSd5QQ54kY7UBPP+Oqq76SmRMmGmLM/yO7itS3Jkh aKa1RA5goNkHr30q5/NHk0Vz7Mknevm2zWcuc6X8MGN3JTVFDJLnrDdIdtHjjNmfonSurCEC3SS0 aRust17JU5RY4EDRGQnCBHwh9obUP4/3H5wgcBAxAljY2A3RVbvny/iQTslOFzV3uGPRh8GX7YAI 1eXQ2ewHcW6nliu05A0aBWHrBVoDNEuzeyygNQQw6cvXB/a+I2beqUo664NWiVdaPmZXVVfhwPjV zHipeEr8923pzie1rK6NXXtpQoDmeocnqnhsPaBCXjQI1G6KvZQjl+W8dhMON+Q17D93oVL3gISP n8zWPkWtjvsv3cIQtF13d2H3NspHKuEHs9YHWgQZiPghIi75/g/w0aTUhNsYddSUE8lUYPpJxEWV cGsJO8D6nfi81zRCk5Ld2EunLWL1NHtJIb3x9uCPtpIbEOl4s4qlIcnSKuIw3nP3Jw0UfBkDliUR W7rNCcYx48sCKIAcR7bQeqJd/OpD2wNm5Pgk1kZnE04CQBPTVkymgppszoMGOtHrnC5Y+spsMDfx gx0cVbCN+yGYHMaUEwPAuT0BCWQR90l632xtpoFvUiLSljk9oIwZOsmUNksq6lz4Y1D8Gitz25W0 2b0spw5seuTU3X+jBifytdVuu8IP8swaE625sEbsJeB3h7GTfsAZMMvuPodQqx2GPOfQrxQlF93y 0zKk4eVsU3t2xzpremMqkuxhyGBmTSgRjkOIbvbQCR+DJLmV0GLjWpZfPolnAxCHWnEFmyR3uiqL y06SCKXOIJZkZH6j7ubyuJn1YmZ0V+Yo6TuQyKDLZVkGkzsZj+5FgGKBSEbn7opOcxFTVyXri7al 9FLJXAdX7pRBeZgh7ln2p+lSfQMoJbP03Wdojqf9GgWXdtsWfi+12NedVEFjbigmk9YrJDN9CJBm BEOet54kUWIUZpFgVeDeyQ5OT/Sve/aGyiJWzZe7dLFGlyh2k+jvg257f5jdezDItx9taoScy3JA F1iQ5uWQPwefwPWoSZUmh5kZG+I86lW+X3f8ihn0bN065q0u1NLj7ItwBJ/Itqnz0Jbvve8jp8YW P+LpTIDcgMfJr+k5CKvlobk+HWanZxLIT6uV5KcEnsEJubDjNYgBCBxtkbRdQLUx6DhzD2rLfdTy nU6JoHcCWwYLYfN3iPm+KTW5RKggg1CHsPPisSjGEWILfa/9Z9OUG3ap4Gv+8XjHrgoipGCRYtYM XIDQLYyiITnnbT0mjTvVzbAHvC7UiUUcYMHfhFdcaHKlyIvYGhwJlCwzPBIkSYHRaTF11Y12Y0gr 6RzEGTFVwjLjuTk9w9Uh4yDDvFJQaUEnymR9wWdrXRYrCdnA+w/+bpQzhj1LJ/BJrpRnX/GzA83J EMiIlI/QfpieYPpoTG2ArA44Nl2BePMyp4dP8n7i88jk/4A7BNRsWGraGLoncB/wDhjk5+UiZRFn CJlrwxGwOE2/iiS1NBF4E+KTxtnhoKPhJaqpggGYdEov6xyLUdld/KpdBcMZamDmTurayrPVEMyn 7ypAW8BWMBBwrWdOUTOLa9X4lPcdHgYMiylbFuOgzQV1yyJF+Tyd1YWqwJeieTzjlE3OpgR/D1pa oO81WxBNZRw0A38PQr3dhhtQS2Zp5WJw3NowozbThj0Ife6aC22qwX9DN10eLfw3fCxc5lBmM3wZ bOhDmOjwdbVc0w485I1I5iPiF+S0LB2/PsiuDc3pPmr4EjdOS93X7FpMeR9Qs0hHlHDvU+djx3J0 p1z6yYE2a3+hRwPqHy/ZeIrMQbrR5vK0DPQZxp2Us4NOngq3y7i/HAxOGuJ0Y46bmWf5qgz7gf08 SDqTLZ0nGU0u1WjxqZJEsp10dR2+DHmQtC7kcojr6PRZf9me47YBS/I3GbQwGLdTD7Z4uUc3GCoH 0uF/6AzbbXCtEWn7iradwLauBu0cw7AplzDbIoBF7j8I0KE1YsA+Cytr+AG38AtsIZqZvezVhvH0 baCPte9fFKQ/yTsWtpxxvx5GrUm+16C2kMccuctL7FLcSJ69KglLNmqMYLRSFbwSmO5WHsuH4WrB rqfPhRPEi0VTFSzItvVoZqZUJqUq0hYeLcXx4GMT4Z70QA5FxveoPyx+kzK8qX15Whendb9JqM3R 41XPPTdI/hncyngPBfRFkLs8507Pzmb6oU7n/R/e/pcUEYNONu9/eDv/t599tpe9/OOb3714Pnry 6punL757+e2zN89GL35PwTFc8CDbLKbrID1uwfDqHkKNvGU5uGhEabbR3fGYutnDnHYSn9n7vi7O WR3SJ5JTU/+khAHLcmz/Rp9O/dsE+sCjk05nihtYso7jbcCIsnNSxOceWe02BOBeZPV4NV1SqiIQ nHsC5bc/F9ians9ICfyTsMw4hyUltURK6KKawOjc2EKAmS9hSC1ZZ/hG6DW5oD67Bn3OJRdAZLAB xhfhBzSGjxsoJ51OEGIlWFfSfF/yCWHqWj+pQyi9KtEXhUFaMNcozy9Pn87uMNN57QyCryTiqTqd qM0+kj3Ij8tquUGgGYUbu+vDzBCtH2HjZKQDAiaugQBhd5jIuLaosfd/fPt/rDlG6yV98ztGnyG3 1Cmcz3gbX8ymfypcsCxG6yFGV6ejgWFs74NFBzEQdCvM04AJX8gtlXP9MqYNQ/jztWsHFpawdB78 6r6U4mh46XCH+gOtbzBMvkbMpTX0R+aKMMK+RMsckgTmbj/X7BV4cwrtlHVZklNy57vin0i6mJWU oQAdN1cSIJS9xeOx+zb/Y/6/dDGE/ugsu6k22RV8DOcd9TUd5KIDb1aZZivGYvUFAS+uLzY0JrwH 4YvixfiGcvCuGJ2Vkmh0JGbw8eH9/EF+f/gF/KdrcIU2qyVMIHmd+HkFShyXK3dhhKSkqK7jgpMV 0LPQF5tBTPFFR5RdGNrXCPrp/DybLUHv6SHFRzNyG4xqSUp33H7eeZL6Ll1zTBdnsw1501AqO4HB Zcq5WRJRlNfleINPD5CnOCzPCUIWcaZfuozEv9C+13WJUk6JZbBxjhspOyx1I7RVgZpx9rvqCq0Y ZBmxTWN/r1ZouV1hiq6o6x3sOr4m/Z6QUvAji2qxbyo25iHLeCLkfYfzkGxq7R2TODmIFhfq31ic rYXnuYmgdJKkNBLfABr4XXOB0C6C4gLsnKuCTBSUPwc4w0rxUl1UOyUl7ZxWIgm453SsqhzicujR kmNuC5/lAnPag7ZAX1/AdnyG9oLUmrumoXsw74Q3HLgsaKKJcDQdn26jJRNio1Mw229s4rUmDdcd JIwPmHg1qz7IJM+A4NdTwXDW/duyb2CsHYxOgdNrVtbht18sysytLwIJoxHZzBiqdcKmkHY6RWqT Ibz7ZMIeJrzgDsoZdoekVbkST7NTYXAdul/CSqlOA7Fgdo3xRVVzfqFVVfBl7rwUPjajtGJUeVJS DkacGvSPGsNCn20wwcYpfLHD98AKKkxh7mU5YZBthEdwrvCMlwaz8uUN2/QKhLZWmJF9FPAmHV98 XiKPntbzWtILcVI2Ssi6ZuEXTSNMmqflRfFhisx2DZWkB8MOzbvjqui2TECxMKIPcGYuNVWHHBti XKVYJuhDvSaa8lLVdE3HxEGnsw+9wP0E86T4pLS0CfLKjRcg89csWl9QBhwXpaOJL34loUs5yfl7 /CF269TDj+dePYW2bTXsxxEKPNPa48bY7tvzVHKEpohRnAVv6BqU8ERo/sl1jBYDdiCnlbpSNyqJ 7pkSZnTBKyfJV1BOmGEKEplwpGlaVOjt63K9ZqLPuoyiW8yw5a5j0ZJT1U1rNHRi/3xSspzyB+4k vGMZtyZ+H/EYmqH5tK75CHxDuUyQfxBzByoDpiC9Iazd85Xs0nJ9heKDzKMsWpd7jA4SN2rEI4mO p/hGnBtnBSzTRfbg4Lk7RzqZTXS2dWn5U26/0BJiXsZVy/YPa5p9RjnJrqpsMj3j5XHHr+vZQdal 0xM21Wa27gq5lDhv7KmAtmOWcep1tfRUwGdu1BGTfghOTbJ7cMOocD6RI4d5Xl9s2gM9yM43oJvC ApR8ChRrR3sxt+tkThSQFEpymk1X8Xc1Na/sumhuukAMeH09thE+5C5ae98V6gZGFdyES+jzvFFn VuW4RJcZ12lZeGzhgi6LCYP/tETBVDorLIBTwqRWfTKtx3iIUTIRFqPDfHCFBFVNMiL1GuZ/ua4q AqzAp2ifupEhyRckIZuI8P6DwSEsL730zqNhSwp33uZGCuHk9Kdko+nECOL380f5g55VXbuB4kGI s6kd3g2sKd3fiX7F+Sex1u9Ez5InJ6hN3TwSyAjtAwLdZI+z/qNhdt+jyoaN+UhHn4UIVaxSs01p 9nc+hFzGvzp5ZLC5RD2f2VQOrNIkGHJCCSnXlFmazutJmDvsqRwpwXRh/o+R6pp1hkriimlSyYeI knIrGrLtGF/VoD1Wt9x9he3YbRD6w6B0wypoh3gYFG21D2p35QbW8Cq9dtU9nLx6tfmevLTpslHX lNdONYRas6lqSet8MpYrVMxSQKn8ZG4LOXiDReiLIinfNnBGvhOeV/okknL+F0ESQ3Zbj7vEy7yp VWY2o6g3XDMPnKXN1OGRSPdUWBGPAq/19Z/Dp50cvpmfIsz8meF7HZ98ZstBNJBbRzwygAEefXH4 3B8dRz30KowHtOXssMPQ5XZjcIqayDd6NMxLkEzIEMH3Rks4sk33USWnKTQs3Z/1qUtQwTonuDtd 6RFeBNicpPaOUntKtjw/+22oCn9ARw/xYpZ4IBJPCt+SXUOSRGLXwEaKoWDP3cu6I+x1N4nfhtku +naDmd9mm+mPwaAN2SywDlvdMA2o7u4726aWotO32Im3NRDwd380/Ez+3lS/2hj8z+fuTqL/6zD2 vw1fNwYU5etWR2jJlUFXoUSlWknMRe4s+BsdBi7JRXwO+O8m+N7HnAOW//uL4V3OATuvjokWqiJ5 L6KEsuh8iJgp+G2+EOBEvMz2jjI4M+yTw6/oYsZ/ANvG95QvdhB2UtfVnFTT5N4T4ZuvHcpihWYM rxHbHpI6c4F6NZxnz9O2H8qKRB3TMTe6RV6IH9Urstp/eqei489aIs0pnhwOmk1qYyjFUDokdXMI llmXLn27pBuLndIrKXIjDF/CwfD8yls0JEe20YaUIxVt297yGTTNj0nVuq1NOhR9q9yMqF9Ebe/e jZCVvtisx9W8fKc5tH10abxnPNgn3RLQ8VpxbfUCmy4W5UpkDYP74A22cXep6GBHUQIXrlWU2OVU xwa2nOqWvZrfEZO1f7RjQjuWqz8815V/P0Ey2EkqcLP0cbJAOLksTDDuPIYe4cVWGZXD/8gi4E9M RSIsre+vJxRWsLUY3VtsL2UvJLaXDCxmrqgKN6M3xfkbRNBs89Ro5DZbF+f/D3XvuuTIkaWJ8Z/M INOaZDLb3zEoqw1EERl16TbbMQzBGTZZ7K2dbpIqsqc5SqaQkUBkZkwhESACqMycnn4hPZSeQY8g Pzf345cIIMkdScuZrgQQfgu/HD/X77wxu2hJgM7eM9Lrhq7e5DsEhq09hnMoN6V9GvuZl8KN7fvD FZckW7n2iabUuIs7wJG6cSH6EOcURFT57maYEPfs9cUUN3pwcuqH/a6SrLmmUAhAKOkVz2f6Ybyp pB2BvvYRIWJs9QDh1M7aGIDYX+ipdO0RwIWY8S3ReN497zLAfsckK0B6oNpUup9m4xn3DpOlOr0Y DUHu4RulUfdwIBLeYPqH3553M8nz4oagmizieAZoRYWemK1mlva05dW7UEkNZDiLMiPLxJF3lb+N VA+x9x8nRspzDhGCdopjyAr24JxD2xfJHgYBdAlfS10CKj/TlG0q4Wm1J5JT1OjqPLM2+Q8NyP7a e3CoXOyoCb8DWPjBsBJYSFIDzcbFkBDGoalRD9hQMRqaRJIZaLwJkmbIRq//GUQo0TuHcwZPwLnT /PEfyAuaP8NJxFMtlomNXOo9oJfm7jFcnNSyuLaj1SzDxTyd6qZS7tJkuUn4VNFhShmDiogF3EjX VbOewIcFu+uvgV246wQNadnidvSelzfNAng85Ybz/rABuytrNYLyoBmC1O7d7PmKMlukmI7JsgV4 R8brx8/gie1/NxcynF/AxYcx2heiy5UxZKLXUcwWyId/Btu/WO18aYvFeMoK6SQ0y2AjE8p4Xshi Z+C14XGoqIQnwUB8nmxfphCP1Bc3FRQSmME1Wys+5apx7s4NEpEPcIwjDsgHaI3uNpuwk9S+3b6D XDPIFMG9gGYmshupMaFmcN/aXFa+tsAjlBvAzwomukBfL5Ln9EQhlfTG4No5uhXHq4bynZL4QhQG D7Fw7nNvvoizjgcc7uEOo/pUO8UTxnSLDv3gueYNa/hVLQqrhFmpzjFhEUkkE8Xuqfdy2/dbJ7Go nUtJ7+qGHA02vqxjYeqdlc6poWAHXF66ARhBCtBL25UYvGwUoohM0I7LAeBLVvj7StkP7dGqOjbj uTAITmYVpZoMAxx8YakPCwkHN6ekC9EtDaASNmQoUd0NJUiUoFnXZS2LZENZwLQZEnkZSaA+Cfrx X1ltgICRF05Jag6LUbb/QT5X+ChuM1RpgzWtT31dP5y/viiBUHrJ287fBFjFC94jkxf1Q2Hh40fs tet6AJ3FBDYE3UxcSdJXQPIKyW0rKQfsA7BHauEIhrMCBfBb53XWp+fU+femrOuYknoi0nsGmVLj jK4uPIR0JnNuMEgSfk3cHf4N4kbWKyS+QePlAvURKLbCPI0CLizAUtFNTZPzUQy8WdiZBGv3MU+o PsB/US2RysOu5gR1E5xLPFHHqarSVJ1CZ2bebE16R1AkJn7CLVOFE0Yi0BBJCi1zctis2qTkfcrU you4lKdajR+j8X6JkQPebqR6xKXQb53nbkBahuvQqwAYDs8gSF6+2roROUh14BkmrMzlZbVa4a8T ThzU7ogLLS4vy3RDwRgmsRdUV6g+sJHLS6tjp+rQPPE/34V5fK0DswVdIfDYXX3dPNj4UIrCZDAo Vs1aR0QCT13uE7ZQf/TgDrpxHkWGjq4PZj+Yq0d5HV2tDW1ERAXqAF+YGD7OKoP+Uys0SrLNCQNi t80edfWiQqdX4AUC716XbH172IF7XWd9kpCOXF4axvlqXS/Yw2Nipm0UGDW6w1VX/3wgzzlgh6hV 8OpF6ZrdtGBKKB8wGc6e5hswRWU1jR9tQLHh3hWA5SGf5V7HJwdSKrCfy/Zmg0tOprCGocQ1cprr wY/APGrV8qVZ+OkNb4NYncYJkN/AIiKfs+v6Sy1W6OWJfMD5RSC4cr5xJxlPCsq+qWnKOKBxeJJN JSD378FtbeIaI7ETmyBrciinqyWYq9kKS4U0jOMZiQwTz2jp6Cz7yWcH/giR3UDSJ0FJJsjWlFuU bMbw0CWlW+/yCVpSe+uZuIyh1544a9G6uKR5pSrvHxg+IjUB4IO7JApJ2kwMYm1qYtIiul9mkh6/ Rm1jqqfZFVICpI7Re6GxldCpQKQ0lKHdgM8xw3J74CA+gr05hFfrdvlBJk+GQo6V7yl/mvJisEB4 1DH6XUIw46OaCKGk/vnjs8AnTwbGIYz7hR0zlhD678ekqRZs8gB9Tlt77djH8TlNR3XqdvDwqM6m EEE4kD6DJh5SKPBMygLyE5x8SDO1WYEBEi6D+Nrudxv5jteY5lnNL6hv56DB7VWzOH2L9zoyvujN CzXhFIgHzrdi6iWPxw6CrNh7FE3liINmXokcvUFavqrrjT6cGMazgiNE+hK8b73g5Ggk52rAF5ZT 1qOznIZv3A7Npa3er0eJOHcLPfqkXdFtncACIrJ56vyN4dmeXOTrrgvNUvqwRyBGfiu9zjaoo+kx e3nfimQaHSP8u4w0/ePRr2UqwN0DOZlsDW+LUbvT7Ej3fJHpdDglUUuH8l+kksaIo0N6MlTTeEd+ ieuo89NY4pzOudP1DQg+J7LrrXlIpdn+6I016QnGps4xnuYRx6DkGpinovddysVd9XhVL8BzxFRF h63HSX89qiMejFDmSGHe7GIl8t9UomTdGnsQZNG2jm8yNSEnbrodmoCkjOyoIVt5sF8Qca6LzE0R KGmXNDQ+y67BIMuhbh+DlIg4Ns+YipuA+7N9RSwXDiDIGhYWirAsA+bSAmV3WjZNchHsitXHSrha jpkQGBMwzHGoFott6RgHx6cjB4GJzkFMWlV7xKE8LCGcp4sh+ZGGpo4wKzwcjyHLN83GGFd/bfkH LmN19kZKYPemejVOBp4Lw3GEzUiPzAoEthn6hfMbq+spxVic821GG8fjAVBjyvzDLAQj6WVSEumD VvW6r2PfeOyxyL0XYrltt/Z4nl8kbjkqWC4IJF7mI5pYj4B4FrUFv3ba9IUJfKCAN132XicJkmiz 2szAtkT8UkIeVKcGj4hPgHoXMFDnNt3xd0hAyuOONBVvOs122yAvfMOK1AlJMKF+RthRnnjwvK/d 6H0nd5ttxFPz+O8iQZKJsAibzpyVLbQ+QXNOEvvaeeHuEvL9I/mFAT8pjpTARy7NJ/DUWgewuqR4 GWTW+l8MF1zE0phjc97LQRM9rJtrapBtu13+MvZneYT5WZ7A+kTLPHWjfipbtCyekEXvmd3jyk/f uV1KmCxELorNCgbW86ZgYl94u3Dy1PcSeui81zbZxLTMpuYdmNXhqxFR5ZeBrG0JHo/hImLHd2/r CusVXCZsRcEisyPCohhQAbcFvTmfc+g5vBKmaRyUE7NJxF7FxKBIsX7ufCQpyHEe8MixYpp3GjdI 8RB8fDyrmwBw9Octwd1WB0phG0WSBnVj+OTE/elB/C5cgx6TFul34uwjobql91rz7tmhm92fl0D9 cnx0gY6JnKw9DrKErL01h1uGAjgkMLmq9QwfNivkQl1cKzbMOmywwQtfZxthDBnmYtSC+QJFCfAC 7RUaHiIFWIsKjmilEfeDDOWaUby8FETHVFK4UJwZC6yO7EXUeJkCzWriK1z87dnPRbwXFGen8UJW Upw7HDs0kDMwyUX64zhxE9ilj+dPKR0puCC9XT03xiQz05NG2PLphps2VXvVckHAiqbKoWUTRWPP FI8ytDm3Eh41KSwCCxQulatvijAn413j9Lqi4Xu++2mDFyB+sCFxG/DQMfU5DMXDO4mpuRXyS08f Y82gWsWHh3YHRiD3SuZ74qIBftoU5JQt2Fi64JNfvncCLH7Gc0oVYzMO/7QZp1vhDeFyDbF/a7q0 y2AMXZIVo1+Remxa0VUw7V+/IAubGZZrxDIChkhMxdXYm9Yiyny1AN4AzHuJu+ufcFv7EfZiKUYW mkCCDW0IoVycl0ESO2jnkBR02quBJU6dbnuwSSm1AG3LYhFtMcyD/Qpzn4wX49kTtYVJRhkDLk9R zAkLiNpNZP9wqJoBxB9OYwFVz7je2tP/SLrfpx4eb1MfNgT3wacI0zDL2TrK+8E2d9tabfYiyCu4 cJAECwQjICwCm2JTflkkbrA/mPrMHHLqx58P9e5R8/m0PxXsgWsx83MkvXcsmwtrhhH2cWzY4fbD DTh3tIfdErR1jGtgLid6mQW9zTT7CtQNjGFiWJmvIaTN29o1onBGNSf9M2ATrSmmTt2dgKxHioS/ T1qpFItQb4mcWyOaUkLIs3ingSKv2QSJ65PJKK2myzSGuSSLVL7y1BSd2Ct7ryUYtrmMP+GpH1jU RWKy9U1VeJaIXWDg3agJvbfNT+HjAUlB0mdI0Zc8Z+gdz3GHZFeWjZyIuB8SLCyO9tFBI5upmMfh AWPaOR7stmp2R3tPsGMBw6gEiyG+EUOkNZgKkFZhXt3Z5676WdiEotIZbYtYt4W+bHdGYAGeiq/Q fkdA0XHR85cc3ci+Ai5wXBYYL1t3j6pMtxt0GdPobeZCnmYWrh7grzwnF1KiUswvZatAnxAdL3p5 qXzsFr2ebUZSCfF0AKjOk3t8VBtG4ibAm5QHxZRT9+o2xAro3CwsCt2H+vG+3a0UlJostO3Ue62E 497g69noUA2sj0HwCryts/NlalwBvte6gyCA2fZxhnqGWTquNAgMt1GmnecbTcI5BonruRxM4pfy 1EzuxxL2js5K5vl4pRKabyhU3eH8RKub3Jb+OYM64pWkeDb8aeQFu8b7sN9Fx2uZXJQ4gu7TeZBv yhbTLXs+M/Z09+6Y4YEAkj87eg76WfujGVOcxdjraHx29rn5RZpjH/ETXvsMXjtJ3Ppolr87lAkF XPuIAi/oxCr9wTTz7DJdnz4B1PlKX2yPsz2z0NiK5zU4HOKK6kBbkJKFujPhGfRxbW0CcH+Y/pYE pMlT+H6uvNi3bI0CWwD8SAC0a/R3DHrSiSfgJ27zIrYIqnaDfR0q22G8LBXiR6Vxp+9w04X6zmHe HOv1aLEj0YU6UaIL/TAsuliGL2D+U1KVWF1JHXBkepSm/lR3BAskjdT6Q20YbThBH2zyaMU/AFBy s+9p4gbgPygcZv1o08a3VioS+1/CEeuYq5CO5FYGUus+sUwGzN9GHoOwNi6swTpOOkdwwXmoBMLX nDCbYDnAh+1eMuUrndMuOXJtrC4WTvNigS2Qi7+DKm0IX4STWGwYVOKZwm/ORBnVINLmrq46wa1E Je0GMHrNMl03S4GNhAZcq5SeDPNBAkXYrk3Bfb0GfBHJSw8JiA3leVP+rdRuYS+Qezke62ZvfgOc l0rQwy3esoMcN60dEByOW8EIafY1JQspbL7m+vGlOVeggN4q7N7aiJHttux1e45ZEjIywemc/+Wv YYCAK84HjL74hagdU4A+pB6ej72VG1+ESfYowQwPBB7yR53TkOYgYCCgPTsA1WMq2qmz4U6htVVB Wc39sZBHsoalVJc55QEMZipmHhbsehYURB+FIoUDcO7e6pwVaxei9RS9lG3Hqt4uUm54i2GFr2bw vPhUV1fOKKV6LaYSlIXLUSQ8fnqrxmk1j1iZm+thrLLAqSiRPAnW2uXo7GLrZG/7rl1oQx8oYKoT UBbmkj/A64+fE7/RIUCBld/duhdTz9XLpo/CAzrmDsehiV+an0D7XMgUN33YLvjXAnKhUvkoXfBn jlJnzy0NmD/ffY6jpVpTfZAkfPljtcNdJtAv4AYGPKEXMaEzdgpxJpgx0C2wtc3BXYk1lC4RlZ2N Cdi7DaenhShSNq+CX9dYqNpY7LGETc9hKqUNQeFbBQnkGF5qDKZfMyAF50AAOmjJQ4xtiFEB/TGE wkqED4oeV6AlcmGnNvnFbyRKiLOv8KVBcqNfjc+AMInLanlbKw6RpnYsimbDoBuSHIcJ29hcU9tQ VlmZ8cVoEPHBxvZCPAvBoZZNh9M6ORa9ikFDFLZayuT/gqSHE53lXDZQJpKU73khadjtSC01wcE6 l0hbgOY4BVvEw/fn2aXz4uhdP7+6HV5SxvKGb3ibSXoYTHD85avuEX3KTid84+k8MpX+NHqtwji4 ZYAhkE1x7gY6U4/N6cT8yRen9ApNc5f+EjEf2blXkV/U7jCTKb/6UwjNPpzPzoB+SQkWYLw3i/e5 zbzKA//hcVv3bXaesgfHq9roI0ezkC+/bddgyhckbeAdCSYdGDUvELGjfAaQiKJTWnyJY+xF8RwK SENRO4ZGYo0GqzH0K4jQpgMwE+0qVRTf2cTxBXIcO9xaUS30uqXksi4IJhinFdriUDEtv6Ueq1gt PcpR4JQWjLefcWAv3KQjW6yZj52wUkKudsSyE21Nc+ns18G9nhKexz5GSzgQrHhkOLNUuDUxHNZy GEx4ajbnqX5G2r8wIKHpYckmcV0Kc5rNHQchzXlcRHgjJTpQ1hF+Wb7TWaC3fYHsVW1A0EMLdBBo 7UYUiyWfkvnAWrNjAWWhJBQfAE57T3Igo0C6pxJQ0uXDARF0MLTPlfXdOG136cb0tgr8m3tsHBTN BwUnPaoWDESeWnYLEiwa9g4cWycDyhkzJVSjdF4v9CnNzIMXuDR33lwMMfxeTs3GDt8nRz3hb2Fx rWEaCJiLvBatjZpECWD0kI1mvYqXZ9tTITlhPO28Myy0CVc7D4jvAJpGWEW98SjZOWMGJlspzVk1 p2/yKhX/Y2OKpJlEtkhpR4XshI2EL/CMXEMR8RRQOS0oa6DaxfeAsF/DVAjPnZ0FqnqS25vs83n2 CvlILmm2XM+IqdmzUOcfTEhj6MdrPSlHpUYnlykltpXGhJxOi350sBeRqSC8CDxHsLRdMghcju/t T4OtlogGVhSoWSqMMeYsWNJMsRUe8bKmcdbqGLrzl79SS4r+PxMM8H+VCEpMRpXvQ7k9zWv86vdE zEJxGe412iAeBuJVifUQxUZMwgVpl2xCRfDlqHbN+hHEU3MdNaCrVMCwcnwdxL4zOvM8MXKRk29D Y8QavJa1cVwRval+YH/1nEYc5efB+AeEb8UI4TWFhT0NoLKL0bFYTQ6i+gxmCuxWojiIjQr0Ckf0 9ZF4qw7DxJ4opR7cgE44dYerSZzGrLCZc3VwU3GQegcl4JS8oxtfyKLBRfBU64SqT1Myo7i9BYLj cE7juIhhZgKlHZBM6nNIe0e4Ju0SFG/nry789CawrEeAj4LQXKc2sqq0kAUm2E3xWpjHcOkhA+hY Ul0zCUDkgrl9UCTa9/6QUvUtdocKRfX3Emt9ysMWsl1NgrcM8HdCHzsLG6Y0cTxwwIerbRotazhH mCthI5n7nmY5pGOrIPIx1zKl8wUNtCtygQE2LF5akd6lFG/yaaBAsb2Wtk9RmkihYuQ4gX+nccgY qGXY9iAzvZCfQd7h36Kx/fy///g/YlJdqxL7+fzH//s/UvpS8ysanvCsPK6bq5lhILdg6eH0uRWC 2dhccdlh36wNM4Z2QhJ8KEeCqbT9cFNuMT+cYYD+9fEMHNsQtf5wJT6JI2gON0jdMfYQDMnUPFtR 1s/KSBlsYpLLoxvBjJx9TlC8d4QdIsoN+lFw/zk7oM3zOlKtYiZPm/0WUhaPRpNlYc75GlCP/nFX fzB8PQwQGzEE682rV789e/Pq9W85b7CXkul1+dvyN69yToJr3lsy09JMQNLcriWboJlkxHgoX2hH HlDeNssPqEnWqaAANI+n6zyXqjlok7jp8ot1U3V/xCKGu+cS4OkMayxfcqpnTqRU45me2B2GmQ/m f8m5QD6THgwnA6kGd7CFu/lf2MQHKR4764IA77GqdobZbdzyYgrkbr8yTeVGhN+vZvBlmmwAM2UD +MWmzYkxoH1BjdDosRn8OKs5KTOnWd4+rppdnmGBhbkRKnA0mdGvnIqZlwsa2T7OvMTMACdSLeH+ WPk2VzHqkj327E35CvXlVXa95mBR3FdTMJli8lpYCu/1MfUwGtVbBNnHcBtYcBdoQMPDrM4ZDg4/ Tt3PJedg633MOam9x9w7xZBvBG6q3Z6t4fh662W4OLId5wyUCy39xdKM3BD5dmnmSX7AWeaiM3no CBTkyIYLOlm+5IczKaTqfWjW61xROa8ePITPMyylan3dQvYWCG7N41rX+BCI4EyVo9p/ld3D+91/ aT4eubRIhWbysxrAF9uGTl/ulXQ/B92ZJig5dtDju03zJf/uXsQWnrnHqu/vICaQkjem6qjHwSCA 4p20zKZcao27j5v7ZR6uFWZ+hyez7z9u/vzll+3dndlm30Ffft3DTq20V9c8gco9VdetYRST3eKT 2R/g37CSae6LA7xu/1jxuT9Fz8Tfg29VQytegiXijOGBgVv74rt3nBbePDgyndIxFE2eGkMQGthE ifIlOdDPuIxX73t8pKvF9biMqvUlDjhL18IhYgl9zkBEy4dqUAlVxfJ37ww1zlNV/BKq6g+CgJr3 9eZKqGqG87nuCMg675sMXcavyramvKdHVULV2wIk0uLq0KwNh9TliXpBCVX3sIlqB3WjEqr24gtU mtj0rV7PlTybBaV0A7saEUS2hhFdmPspTzcQluppIQ8nLdlCUHu7w4twVw/U9orp6pysADybqg2e yDzdQKJgeNhhJ5EFHMFYWNGByBAy93TU+dspxJOLpk671UTnifLuoaqxA2+vrl7lqR7sQ01m0Qks OD9SgR+q4tXmMSYiUhwe6rL+RR2U9e/nzu6M1DD8DWGY53+tN52/l6Sse6hqeOjTeVDDf6hq/V4Q 3t8+NPuwlv9Q7zfDi9cPPRPKDzVh2EFQUk9xfugfBlTWJ9fXPtQV9rtHEhTyRAX3UO86w3Et8p61 oIe6A0iBCzFHm5s87kA99AbV7uuHfc854Ie6fNNdAcuafmt56FcY6IAf6vI3kLgelBWpWXIPgyrA MoK0mKeq2IdBJX15RJXCe8O7McIKKXIP63OtOIRo8fCh5ijYMSlZwT7UQ+pdiWgZ9Bp4JdX8O+La bLaH/Vl72Js/iHYreuK8aY+zTcLWtilCujpsrwO2yZYvl9UWNDQzKaQZDDPOd9+mWCBVjwtpegMT EdYLq0khzT199SU9zAfquUKav9uv4qphTVUoWfXrr/LjVU0hb4LAiaRa/xlT5uR+5T0/pHw6s6Cs d6t0zQKJXWL0QSuqrM+XLaTg4r5ZISPf00KirL6JKpC+t7s8tXbycGZLhZu4uwM9BVneqk32cLd+ ebu/W2dOHqAtbR6csKexX1PU1E5ta2g52JxeFXyuV6u6CYt75eG5Ziaq+8Hi8FwV/0Y0HXm6uHuu 6VVntljqYHIlfh4Ipus2kIufZeYnROQ20lY2AR3F6gBxejmuRQ4ulMAume/m4wZz1Wcfm0pi4pRF oH8hTBepVQBZ/r7abfJE+RIemGHNbCEtl/MgkxWhM1vA55TkZfJkJV3A40vqPQLC5j2d2efBfTVY 6SZRCSXr1LaxrxWK3j989e2ffsj7K3ABv8rb9++Hq0ABXeWxw23TX4UKuK3212L0808//k+sCLfi 1s8XP04/fPKJaIUftSKWARdRFyDa3S+/XfzTF++/eP/776f8+R/f/vOfv33/1fejEV+IKLygD/92 NxrBv6AhnYMWmEuUjleb5ER5spwLgsIW7GqPXSn6StBsAnDD5/OME33gyGzKEBmblXmY/11gjIkz TbCimt9+sX18c2ITbNIB/UCcSUFSq1Y79CAmZ2NKXCrpCQaSJLN4XUQOtWLy4QLTbKyyWIWeSs5X 1bwevp2T3KWFY2nqpG3fQVV+TZW3GbTCKu5B6NKh/RNVFa+HU/yU0cfH+pNOxgjhoid9RpAUdvpC nHrzuxuCdtuof7Zrg2aQnjxpWH9OReCLbmJTH2tCnD5sE1T9HyiWbP+oENAYwDUdcl9hAfGFRUwI DlcizQ/NyMRFZ6lQtrvm5pbcTwj7AqwSpsXl/gBWdLMKDRnAYAcUAdg6bTSnhZzInOgto91A0KjO rh9m+1GYHXr9af8J3vrbEp9MImQLiDSjlqCN2wozj62bDxTSfl83oN1vb5pliIjBuGvaYnMOOxR9 ltmSi58vzBjrzofH2IohPni/CBStbxGvD+s1rcfwUvLRJdWldnCm5Fdgc6JHMAIJD7fZ88KAcI/a CX2jBlSCZMzuAy+ID0rw3lJDhVeOfJGgknKI/bUvpg5t3skb2ujA8K2e2VPoCnJTYGisdhg3702K LI83CvV6GmkCjMh8dD9WO5sTPvlaFCyDrkKIqKAjabrU641C78bc9JFTIpk9J1WHiFQFFehlkzGl G4zBrza+J12MhYAYEAwq0DOPt6YV2lS3ZmcsD7QiZg7I7K2D84hYyoxpp2GMTiBCquMV9Ik2o56F 0XNU7VNb73oNySX/k+IunlbD8iBhWBgVtlEWMxdQwXc6avCjS/3P/p1eya1+DaUxAgEp4wKJH+lP rxc36/aq4qjLhtE4wIxsVqFDxSob6Wsw2UMkajkUaIBdhU4z9rrFp6UZQHzN0uUso1Fl9fhUQX4H 1Sb+kLousYT/IGA7kEWShojr6CGKyGnDZk2RDvuQLgqadoCn3Icw33YQpaOyg2ntAjIwHqd9LYMm S5EN7Ih5LRT5gHXlxSOO7cULs/FCR0NZfbGg8d1EU+sNGKgDiHwKJE27I+IyWZrQjRIvm4IT4f61 u5V3a7j94O0PMyHbR+WXan9nNyh803AmcUZoLvxdObX1Cz90eHHCBEIQyi+YvL8bmrx/v6lQUg+9 4PB8ZF7inq1EDngEKrqJUM+TA5+3OeO49I+ADrGpz2CXFhlprbFBpPI537dDSDJm4EpJJCTSC37Y myurb4CCP6Buvl9wxwqmFINeTXQCcYuQZK+9Uy9YjiWNLlW5SMPL59RL1QwbcEYjiHBGwXSERWbB dB7m0k47g0K71uUasCD9LQnh5xdFEkMtnVJcYu+YFyB23FxP7dLsHnpRcmL+rntctnFqCBiPXKHW LP0WgOliAbkCxIUbM8MIXIcRQEp2t3cgud53+8d1rXNfwAV6SmJXc0Nh+5HXujwgLgU/9lyq8rjc X+mL1Yv9coN0SNR17NV/hzz3JpuMkbsC37R1u7kJM63573xnRdGEDLETzNz4jMmV9rUt494a3oVY ib6WdzWkSOxrW8/QGW86vN7pgnSi/hOCKPwNQ8m8IZRiEjYPAuZUD+HT17+MnzgigRx2iAjtuA4v kwPVmccvb7mDaNJO4hlOl/ZRyGeHNi3Y9wHYBVPoUV8iGEOrneAD7UUoQ57YlqacOoV9/7lke02I 2+sKsTexybF3tVn3iMQLv3dP6X6vGswU6hbI4Y2Bb+IK3B/XmBbC5pvU5K66AsD/e5AQYfiVywnB ocO1D7jt0iQz7UnHltuNIahRdnxFCTduCBvyoBjlhTcD2NJUTf+Uc6At4NXncHNFsBxBnqEHCNPc FX3xcEpX5uaWZrBeYagW8wioNstMc0WRymxtifFDcu9IAW/LWSqR1hU8A8Sk/0oCFrH7SoHIMtPZ 68zcftUOM4yGPd9VD5MByjTNXvlCvhrG1BDsPWp+UvmLROEh288dvTIQptkbFnFX4QrACBxpGo4u oZRjQgP4fb+rFdf5DLUIjc60jrOMlkGtIPM12CLtkGpHU5sdpMRbVApM8SlUrBGtzqAg5QVqG8YJ slF3+w3Jg95DgPeWqegNRaEWkuQr2PhQcjCixQ1DusU4X1MvzHmCgc0q31K4Uwd05tzJNFsAJjGn mogXQNP9KU/r9ChQcuo/7nDOf6Os9N8/bvbVQ4LXo9Hpi/xTpS6IYzhPnGLCezAlL9zKpy9CAreY mXFw7LTdjPo6oR89AeO2Wa3qIchZncRCbnHW0aDTuuGvDTtimU3TXq0gLzjOql1/ZKU5Biv7kaNt t2cFo808Zg56kvsfClcLLtXzPBpVfjE6iXPvExCinli0HO7qJEGBW0dBTbN55saIubwYk2ajr0g4 0NHWtfEhiQFg9fzv//7vcy8RU4JWeDr5aBiw9Xvu6nV4WbsZuWqr3eodrPzusN0njFBBnWSfYzP6 iFEbZ9nXoMZ/vjPcL6bP6X7aZJRSwLDC15uA8RWIEBTo3Sps+sWCcH5YGWqnyWWppjPokkJZbo6L h+wcNAfcXCD/TUBaV4KffWANofVmWW27wxr0XxhoBMlYstvmBoKWMEzDCVI2VsY1A4S1kVTLcvTe snDnSxW9+C1XYdZwm+mdblfKccKO8PvgDaIsg2Kl3V9Ns9yIWhvwBYty5hnxbWLIU4I5oxB3kLmP xmg+NvWa866RoA0tJktCc3P4t+QRBZuy25ehstm8QDEU15+qZKqocOvDXqJCzQnnYHLau/xFcWT8 C2e6txX6lEBuA1jcWJtBWyw+yDjagj4Rv3qETf5xReF8jxCIdNWQUzRUJSmTr0ZU5WveUePJWhBC vmT2LXMQFGl0dlWfWZZauRZA2jry0apX/shw1Igy2cEM7iVsnDqRd0vOgOFpyijSmKSfPen6EDsz myCEBrGvZsiHDd5jHNx41SDktJGLVnW19sEXwK4FNqI1oz0TeiXzpy/t6xVp3akZzIPovPytxBaD B0Waouco8M6zXhZwMsESkgoVIOlsrTkuaBEZyeC/idpyurZ2uJCW0CVlvW9zSIIQnzOoIkVLLKgb L3r6512mun6w+qc578Geqloq8uqnpR5oT30tit573dHvB6c3SlpF9OUPfsTmArXUwDCCqgtSg3YH c7NMbPt0oxWlrgzVNEFVEi3y63sjt066dWO+vyrCl+BeKCwbLyPTovkxGjxqKy0tbtYuj+31Zr6u 7q5WVfYwwzV9KC3fWTyFIMFxWZp7tKKcHXed4AGPQnam6RS6Ip0+BBK2elLROE91V+9Mm2FEtODm A9ospUzXfDFqceHUwnCkwBVD//tkiFRLaqGQ16MWzKRE5JRx4Ih+0XsiHfObeYfTQHZQULbQtHpt mVWoHaNfgKbmY10MmSXcbuV1FE4pyBmx3FXdLW7loZQVglNDA1BEm1TGuDhrndiAp8oJ6kifbb2y lxo2CA4OYuHkzDBzZwIHWuC310UosxFTAyVChCXW/ZB6181d7/n2Vd7qOJ+fvb7QKjkGNEagryMp DAlSkW8FJEAvvWXn4HQfJFmjjcP9WyM8urnIDQe6a6o98530gq4uGSV0VhM9twLOqRJYMwiWNTc4 DKzgpdg7aOU5a6CtG7ixusYUGW123+4+sCtAUJW8inBVAR2kMm9yYyYDoQjZNsmJZQEToLkSBc62 CRqiQ8J+1RgrrdwHcRdini1zR92+pIj/+udDhQHbXkOIxY3ZqitEMEioWGjfRFr2ZjWJnoB7DM8j 31J+b6ifMlIC+3Fxrj5ZtgrMHqZPn5GEax1VMgrgHCn9+UWk4kzk3bv23yB6buRrcFSI3Rj05kCX uzWBsazT3DZgGpdi4rwu2ZK9wFnv19+A6YNfH1+SB7F4PTcfnl7tzVxGWgxkA+Nj6W8pay3Ui+qM 7ild3kjeDzkvDLud5L1vBPxF77jz5Lvmfw9+vjCVuRUevXDYtHNth87AhuKiI7C5JORcWAnSrTJE 2nBeuI/NTWUZ6oBACwFZoOQPATygZMh7hcbD1oospN8O5ZUGTdRpfSk8mAfvEO700NLAEPaWFzJt nL++mGZ+ZGtiUygNvWBASt38rrvJB7I+D1s7Eh10tvHh9uBd5EuJAlMH7NIkZ2Np3rO5GQdTL5H/ /rMsD+ypknBlDrPu9Ouz4NIOcDOhKjCaVO381UV/TVkRvzKRZKr9eqA2XC12Kwb9X3H9NwP1cZAx JhH8rJVi8N3i6Ay0ZrmdiZilYs42sFi7Os6W5VgyfpOnIOp5BCB7bm67K8MazckizOB68n5TB6Lu 5E/Pg2gJ/qAWqvcRje9DHib+hKDOmOxgowCJ0DCHuTSYs9a47kRpPLVpqdROMY35fsRi+vM38ZR8 WNGFFJ2vVRusAQh0Bt6OktRRlXRqNRCTrk0cGFMkUFJT1hIKqcD0FoY5gzCfNBuO1hG4YlOREm65 pupgKCuKUFpKSYptRU/hT7kLdbJAYXn+I3MF1lCEJSAcCfKiujp3uftUjYtwp8LPaqftdoo6c2bK h+VxK4W/Pxw9AV7aPEtJPEFHNKfUnTpnEPABoAEg9oSHjc+FkAc5JvaA+PZlLXu4c1b6MpVycNPq swR7GXjN9/CT/K7vzSuAWhxQTRBdWbcOSnAeuy/rKUc580L3xIUIiCF618zJ/cZnS6qrDnWPgnZ4 RRLlnE40SOiIhTlAPuAGLNB7LDiHopH0Dbq+ws4NdYafxctiy+kAlSAaQLKZF5pl8EL/huv3b5v2 30Cd+VHxOVTKJxz8fjMQxGtRpkNWBBDVIisRgqbjxgjUDjbZA83snLp28yf6CH45aKe52bQ240NI URpuCTjKnBrLk4Y02Bw+vwi/2NvnG6wap7E1dLfbr9RODknXpJ/7QFLW/5iO4kB16dPwFE63Flco JF+Lf4y9bNp3QLC+JgVvvXpLjM5E7Xf3UTY9/pve8/xX7Xr5oHa+fIhDQO4MhYZ7vZZhAME5ahtM UxZUQ/jyW0QGiGbQiDX9ICRfj6rFyVnhlIIMpcd3AMSoVf3/mzHyeHicEpwQrnYkHzHRIX2D9X1i hyfxW/na5hSFk2nBPhTyLOXg2oeGNoqaXLf3i7tq96EGq9L4c6oBbatf3/YHMhyhyHZHEtU9lQiT DdcRmbnqJyjE3pU+QWROlSnW3PYbg5Rysif5GICU0uDBA4I+BY/F7QX1U95lTYkaZY7I90H7RF03 NwdwXj/sM87piOE5aJ0M/HXieE4xdCf8EJHboe7OXhf/7W3eSf8Ef0BwmPp8lYc6jwfQNwh1sF6F J+235jzSLADiOH6wHgBFwFHhMfbcxSIfY3FloRPve5fZ9S/SvlVpg69z1aLlW9W8V4q0e40asvXW t075SW/hwK8/CDlYKAf98HXFM1JOwyyZF+0iMkwymO8UPpCw3Gw8VlF5xBM7mvA5Ms+1Dzw1yJy7 vI60XxRFHwsB5PAL6CtADAcoDW+txS0TyPiC0l+cEQtqVUDT7KiIeS1EnIA0gGRiNkBeZpSByqSI dX7R75KXoUJZxgWh8e5glyRX9eyqMAAKnFOKyG1lIUmTXukxqCefZa9mfbU+1aNRCgTAy1iYK+u6 gZbHOFHeK8bSHU0Pr7rXwKeZfttz1/2FON8OOTRc8/yhjVq3M1MNxXtwaDjkmdNfGs+Nukw/xRkY D7xIcdqQXY1PX89+1aBRa2dTFqfJE99Gc0NIZclwfh0DK1dbsPxuKEaUtjMCp07YIu57yn3M6c8U D021Zj/oIs4kv6k7/xj7iqCw2d+6FsNzmzp68r5j838v+Ku6qG/YSX1Xe6obzY6ZS1zdmdIHD6tH HC+77brZT/KfNrkKNUOOjsdDG0rxYZ/y4M5fz/z4I9k13PfACVMdpDY0mx559hLWGT2+YKbSq4UX jopJmLIUnLhzlLwcv0B87XyoH/FX4NZxEtjew0LpNXwCVJG/MSv7D+O4bgmAgZP4CEpmTygTz4Bo gtnPE3OCppTjpK6dA0CPIJ8tFnlaD+6t0FhXMB19Jt8+H8da+JjuuX37A7raO4ehJfoHgBH/qibH H3NPXT1GDlCuBVTtTgoF+U9mTNMuqpsY0aWESzdrNj2trJru5tCgXIBU52O9AxetDTLAlGUyKV8b AZOBZgIWINA5er3BssPNxJULc43951fiAaQUbQOC/bMhJ210gZxSuOIU02z0We78RX1+9voV7FZE xWdPTDvInncZWlxrEMHQLmn+p59Qp065aor+qoi00f+YFSpbNP/yH54xGHRd3c1F2gUCR0hlvezY H+jwsy7YJwxWIl04Tw5mSn0+LMWR2/tIc/GBc9ORUIdfzzSlUiRZUSEKN3DhLlPlsPMKAmT+BT1S +7v0NA5nGBPT348LiekhoCI0UxMqTDHW2vXk3WSh20rgiYqJ8MhZqCGl8AxRD3LxYCttdzqxtBNh aK3l0lKcSpxjUMWAWBkg4v4VJ0EXNf47xOBEt2eCw8Uwg7rrqhv0FUdPcCACNPU+kE4/TXctCANH VldiMayB0FC6sT99rL6gw3JXfUD3RaXLCi7AZl2bq40Jb4+2Xm9F0Nnz2IKJwmPPDUULotdslnLy cHXVqjMfwf0Hrg6hIhkJCi7X1O6hqWp6ql+WlVYpTnn2Kxjc38bcbDQ27ZDPIicNRacs4mVzHtgx oJjWV52gstnEIE9FeQX4t/Ua+4o3B2txvv1+OI4k5dALl/JmC9cxX8/UfJGKWsf9utmOUs32XB++ IOBFqzhztj0skYFeOFBrQQmmz7WhjAzknajXV/vXJWLkrDzg2RbfHzb75q5O+XuYOmND55u7w51y u1qZNbjFtQD/tTFKi2Y+pXXijlKLEwzPvUrgGeheCd0nVUlPSy72Je9ewYRsHBbjvT9FWBGRjf32 nLU/cJNkZ48JjYTvq0LTPiB5EXlBa51W9Ce5DeEzcM9E7plNrVLWc3MRvefJnAfTm/LbcRMz/pu/ +RtDB9yC7gnic9IBCWcB5j9h/hhMJTWOWrsyTNiHFGVxrhr8ClPXs7Ua2Ts7ZMe0tSd1mqCQPg2J qZV9WHiV0NyljmBgBhsdNQR6PU9dmy5IiTFyoersmJ3KpV5TdiKfaUzAU34m6JReM2W9QcNOfthf n/1tHutwT7JKPcu+/ud3ZFJuKIOguGxwop4HI0Yhflq9w2gma4a2GomRxsOzugknXDUtEfymLQkE Wke/3qtnGvgYnLDredOGXkKtYBJP9jGAnGnlBhFEDoYVtZHyp7sMPe+c20S1z56/enDoETYOAD1a xS+cN0G8b/S26E/O3bu7AntUuP+973FR2fX2c2C4qtlq5ycdrlYrfuKlDjcMxh6VZV29nY/PxpGt jFuzGvS4mrZ+qBVkb6r7wbftW3LRmPg9WTQcGVVwo96bB1vT8ZbergifolTLDRZ6dR19S6wsyYE1 MDbjRdZvsRRyniSPqVlwV536NgqQExx9t5+HDJUnrgT5oMsACNMTXcVXzTVm3tpTe513accwO8f9 5vWbxowI8dxOUENxLuF3xWs3HscX6mPfHpK7VLjDcDCA0pNgYM00L6JLnuucN5++Turlku8BPMRP KX1IWJrEU2Q/XPfHZ8Xb87BZeKMWowQkCe+dWfJM+GXSR4P9ZLzf+mnf/iq0JnmbdUwOO+OhQ3Fu ZRruWtq86D8j7JHuyLaqnjja0XCe+DqiAuHHp54+M+2o3TL7mTwaXWNFEQ0/NXDi5k4gSkpSFeMr fROXn4S02vOS9IrRgilnB/01LmhdLtyXRGs0HPCccAP7b0DwrDUgOHQJRGs1jCHS4tnV7DylJKQV T572NR2/BSNe0Uvp6Oq4atcrdmkxzczN//waz/oIIzE90dvrBep7c348dDMfe+3TX/n019WvkDLn PNOU0B6PaTYmRXFPv+G8BV30TYI3n7RVoqttaE8c7b5n/x2TQFye3J829D/U3I9/2sSE5iicTDAX p5fnwXuUzNP3ncY+ax9epw0MiJPoIUX104PRF7gN40On++RPpzNPFvQermzuhJP2wPmoK4Dw9X02 nzEyYrVRJY0wRWF6ABiT1asG/OuyA/gxIeq4Q13vboQdkcHarQYv0N0gBjeutB8YDYbKs4DPodbM v+czFSRqNyUg63Uz1ifbWfaARaZQ27+r2CBz2toO3qZPuktPoUeayvi7Unx6Ths1ev7MonzjMGa8 8p54F8VUmIwt1xU6R46TNmSGMbWvGzeCXCyMySxkYBvssXGKJtXwxJ/iJzsO+OFN9jnMICB+Yaag 3shHW6s/6FCvBHXQb+Xkecg23RMM1KcNw7X/qZmmKXrTJLoZ7iocaNDA8EiOTIS+IMx/5l4Uez37 hDLuo0p4ObFpHPkK5WBM7ReHvr+HvTxC8uWH+tgcjhCjRPDleWd/dA5nCM4maSOHkwfYciMdzate Scf05mESTi/A14anKnhk20oQ5JiCUu4pi0hk/EPwSF6WZ2x20jtIhtonDJ6rDI9als0ZlvkX2g9h CtRTdwTFcp20KXCBGdX+1E1x0vyrqTwP98BFuW0lpiu1FMNT5bUsKyNNjiQUiJPetFf/ghGAS+s3 pqcJmSsVY698q8WZxU2GZx5zsNagamwtntyRpDWmvIrIxcHlzd3iGnNzo5/uYFEot6B0iicUPrmk vEFYlmLtlpL8TaPjUEU/y08eq4P84qYf05bpp7DtsQ8JZ5cqmw7v8onvsSz/PdDI1dqW0qRbZHLl S12JMpiHoyMPVvkhseyj0c//x4//K6fRClK8/7z48T/+DzaZFqTQko+HKy46cpm28Ai6J0Jlv2sN bZlm37377i3tam58Yv7Gm5gtBsKKtgSjf0CPLkhLnxPedgfQo4C6JiMmFoewYbkDQt/D+uLDKClm MDM5evdJEJcfy3jfmK0CGFsQWGYY47ze7fKsksOAut+q2QiUKVaGziRBpg0+5a5KIREIsOGm6A7T y2OOHtpF0iWj2GVobDHdvJR5oWheutDBaHNjqbsUnRQ0/CuEcF1NqVuAxJJeMBWS2Tt/+uHrs7/N fQQBGdlcDbPEJYT1AkeRmgmQL3aZ8YH9qFovNvU98g6JQuaEmAma65bNrgDtzspMX/g77X1TYQqT S8h+tDvNpMJ8gCbXEt8+CxbB8W4ffwOYtuDbGszklB6/QVygXg8CnuOFTDIDICRn/xn7NkFqJ6Y1 H2udqeqEhGA9/dEElvZXSH1Aq+jo4gFM2BJ+hbMn85aoHfajXMxxyqUd881rx3w/oR2I0jl0auW2 7Xqtlgwfq7sIT+9bOu/t5ms8nhMqNc3kL25D2RXUllCzw97BcPiN+Iic/YKU7eyxA7CnZJduwNb2 5kMJFqFakGeBPgQPVUe0yPZrkJjmDlRX5t9Ax4zLZP71f6ZdgBNyomYmmDEjZa8IvVNJ23Z2eEBT OwbDsDwDTIyWwQMdKUWcTZv7KcvBBce/ZWhN8pFPtufhGo7soQwemMknOor+w4kO8p5ahCcBdXgE fDAn/smcOrBxnjeAxB79fPnjfzDX5oIM1iV5+P5c/fh//Z+ffAIXmtwyqAOgnC0dOEo1Z9fCzEId rLx9lCNizg5xaiKj7G4QZNvevLfr+kG+OFus/GAGaq9kzm5qpH93Rz/Lvvr2m9xmv6SxZxgwfVUv K8D8bowUBh/sBb58XK4hErs9YGoZxw2YM2G/yjTctu0HYIGsJQ88x9Dtg7LymZ2ICKVmMohhkIqL 7fpwc/NouQbzrdn8sdpUNxDC+19Ms+bJ+o8YGUDfoRv6Phrd8nOzmH7RyZjaN+KqHdo8qK7KmAni OUH98GE7ejZy6TJptd7hCGEXHXb1xNKAY/rC2L2kh3yEFZJ6xTg200HF8KcRsVt3hlHB0DAO8Nri zHbazVjxX4Y32HO2ouoaQkk5owBrCJvNmXAIOEu7w4ZZL0hFhsqmmU1y450Am3ZGl+exuCr0g0MK axHg77Bvz3b1DaSGBw3+6rDTIPI6lIexb5UrSFLqie53Or1m7iCSCHD56YcJmaV4mFFwaXJHAOpK ZM3sczfhS93eZCnl4UCg/4u6jLdVSpNj8UfIgBEnYLB6nbfv33/7fsbRE8C9rNtqJTDO2YTg1Xqb kZjUAX/xpHcmTXdJE31Hp56yZi5AM4GMVZ//JdeF413S4V0Ywo9uzrj36fmc/oTuvxtIDto7HsPP dGZJF0Zc5QAO4Th5B/wJNN50YfnLDgsI2mxwO0ioQt26i8GV513wsk3daexM+1uhRfyCMyCzoDow G/6qAfg8yrAIMXFYFyaAOY9meVcbtnQ1gd+sstm9QETJMDkZvlqzEap4QMME/vSRjSaY8AiODZw+ 9u0RdpAPDng00quMIdSKRiWKaKAhGyA0xDRvV1fAde6xO85wn3UfGoJHZtXzeH+3XTVmhtvNh/oR lUvgkQg3HlzO+/rKdADYaXyuNy2mqWDlDeASdkuAxrHt/Qt0+XC35uRy6/bGiEtLHoPZhyyY7cYS x1a49NDuJbt6PwlevQiLldVqJRcOtMdUGiYQThqXEvhLRhSDcyhTTEBv/EU0d+CUzSSrcMoj+9NM WG6pF/F/tkFQP70qGEXBSGRd/fMBvG5AJ4EEGRcPJczlrkbgcyPu1t2tDyXmnWQzNd/hC3u3Op8k S3q/pMF6NakIHCa8uZtNFsyvUrZ5tIPYCC41gcqeqECduomicos7GdnMuzu+vUIY3Cozsq2HcCSx ZLPt4wzP0+zS5wfLxHtfTgldV0Bn+U1ovddmTlePSHRBNYE/UmSbAOxySA3I9hDOBvDXN5QCiJpF iEWzUC04UWAyYWSO+MI0xVs5zOaTOXt4kXf0wDT97qu3/sXJM6a3k0+n3QYOLs5+hgP0sWCeimJt JPDFkEeIfLeRn/Xax1Lme1m78xdRK+dgfEXTmGokCIyjhiYc4IaA/3GoQVQ+zkxEsus/gRnLS+HN WYgIMoDy6UInM8lLhO0pQi8TAGw+kxqHWGOPil6M5HFL3acxG9RcZ9ExkvPGnBiQ/lSRGN6aik21 0ntxVXU1zUCPYjK48I1UAFSWj6N5cW71KZGgfpPCNkYNSZSFVzrFQ6D4lUBh0hXn3jeyx87dujGz 8DszG/aSdYM/yms4nBC5tVPU1PsWErCP9Q75jE6TKpK4Sp84Yd701Ur8sIFyNtecgVxoEAL1zog4 vUBahakL+B4MlZ8Z+dBcXn73zz+8/f6HxXd/+NPv331zeZnVm4+pHNCXl7wC3KApSblfXH5Ts0Mh j7HbnIYiwhCIbP4dD+zyUgnYphUZKMkPJOGdHbZ/501VJL9puzrivycm3yHBc0WRKKcgz64JnWDO Py6irIkyzICVUO6SzyhXHCQ3hEzLsEiU8lWqereIaxnI4xsoc9euOh9V2u8aC5pCfWWWhz0wXIGH LT3ftHYUc51Vx7kirFYLkb67SagqKEJnOz6xvirNEJsWgg8+Njsj2kH+q5z301dvf/en34eWD9KL OTY78M61WlUxIKGCM5cHgOt72F/r8IZe0YV10yjdrQ5bUO5Qa9LYPFauKqKQIAguNKzrRmkMtnLX tnsw7VIw8sQKEqkkdxs4MxiyQnKUdr3HRXCpP0GL1u4o5sCHf7GfyxJCssxFDxtxNsvelH/rlvtP 5hIECgOiRprA+JvhEtkpw/KkofRYhWXmF0LPMZXFfPzuzbjX5eu6W7NYMhdLNMQLd2QeQ3EbYnEo ++jrot/XDLJ/NSviYPrKsMPTfAxqM/8i8V5S3hE4xvExZ7Wxm1y3PkVGslsZkQ6YoQlPUzrzt3/4 wjUeqWSd5p5biCJt0W73si/kZt/4Gdytqgxbx4wI1fq+euwyonfmBZAhZaqnaVkLxpjqY9usOC8S 3h+t+Xu1fswo7XO1ontBdLE6vSCnWegOdfbs9av//Jsi5NhgqJ6LpyW9syF31GeM7Ei5ZQzbvW93 zRJlj8YQW5StGRQC2HDo6aqW9988mpcfJTAxxv59hu73fQNkL9dF30id4x1uCEXBvFVy5iCzjDZz ycDNlVr9dItAiKHRXkAdDSoyGRuaiQZqcGYynyFaAz5KBnjoEb7DX0yCBDJxTAqhR+3JQl5jYgin ueCBRqcA6qa2Oayq3ubB0Yj2+9On0vXw5AyJ6cGkFiFegGhrHGlMbddTzoyai7+McW1JaTKeRQvi PR5w7B3LUUu1YZ8Vfx1e2oXhcpvrR5x6XlP4SP9Sc09i5nRzUUN6KcaLxZ15w4ZcODBE2ZUsGdot lLE66wOcuqlUfeG6/QVLX42vx4Pe0Op6lJ4Gy59yC3o34fMdvnmG9iN1k3kTdPwSxD0hAjPKySiZ Bee77xZUQb6KlfTvsRBlBdIHn3C2A3EycSxNQ4kABi1Ysq7JGTRKnBbZ5n204sM9SpW42tTEXAYh UiiHhwaHxPzx0MREJ2aDLb073UwBGuDU4pkymFyNDYQipEwwRhcTtxUZWQ6TDIjTr002LnE7DMYc 9aHBYObsCHGcFRPIWsB3cnOjC6fL1KwmoMev2nY9SQ5KM0Is/1spnAbH9gM9V5idpr0n9xo3NlHD gD0czoHcqhO5C8uyLPxkyzbdFTo8SrmXfGGCbYEw0bpQa2C4OyNyovs0YyNxwYAQ2Ht4hi1lFZ1T GBbiqJIC0SoZu8Py1r2Wf17HvAJ31fLW9Lh7JG0w5pdqUU8MNmR6ATCKVDvD05kPzN/Vmon9BW8B E/L/1ktAX/AOlODTfwV37SD1YR4iCgahY+tiOQKtGf/K2FoE5/MXb6Q5ej/Osvzd6yANTc6VzUNp xn/uyL0pEhPxnMh79CyQ/zXtWrc3TGYDosXUif7w5DwbSXg+Zxr+4rt3Al0Xqy5sckZVl0BgzVFl y65VV3SKYqC1K8AqRaMlV3IdgWzeMcEAFzvKX76CKEtuZuyDs33RhZXBpwvUY2ZHNbusvd8k/TyC ZBsgL6ATmDWCZ5P87Ozu8cyUR1kD1C95AZSAQp7BUQ1+91kGTGJHMBkfAWQ1+wL8/EjZig4lv9mt MMfGoyXSuKuhbz/lXV1vWFkGTM19/RGvuBZfpt3Ia1Btygy5uQYS3x5g9W5YHyj/gf9IWoCXJNYR 9M6QiokrUWCYXZrSlUGQbbI+p+OYU+iEYSMJ6KyEOsvVdD+rBB+kOOu8grBRgNc2fShz8GGzMgf+ Fj2bSEfmadsxgefGtThLglpFwWR0wPjagON8ZkTqDjOn++w9u4xwMNZsNk6EoycCslTn8McLy0Jz hbySt2bkvwJr9DqRGaqB40sVixldf6TORaEbnaPI/2OUDORbGBq9gL1riYE0lsiNpmcds6EHegJV IsG1Jbri99TkPy7EQVn8isH2grwjXJDksi4a/7NsXQP4idkmcCTJKIJ74wWYZM3G6vSLUHVyl5iY h/Mw+6LNXsslwQJlyhnhHJpMyXem1YeBBo++0UMAPB4+7wP2Ck9gMm+Gwl8azFHva7/P4duJSekb yqJcNh2qcxNvv0SPpXn/DGB9M3eILVacAnlH/KS5WAxZWoEaDW4Dc93sKrTo3lcbNNkCGWa2CZTA msq4luAywDzMUHyHdnu4atDIuyZzMH1BpF9qBm4ODXCrIU2NKAD3fO3pMnf1z4cGTSmQOBoNRYR0 SgS2d87OL5JZDKl7NOrA3ME91k2K3mi66OLANC3Bj5zJmJoeyDkIDv3N5pBGhtU2EiSEjtKNlYVp XPQNVTcwsKeU7sfuLPJjcORHtVT0vw2mN2fXkDtQViRoW+JwAB2HqqkTRQ/cod6BBAVC2ILb8NB7 gpPNh+LYefGD+WEaIMcsMCeGS2MtVojVkrTJ8JjvQH+klGApxdcJzvjJDUIGfyEfoWQbrpsTIe3q zU4kYqGF7lz/cCI92364sSnI1VbcPvKDOIGj1OjNnSjmas63tugeO1qgid+FKQNeAAnYo9TC0dYP BklzOXmq+YxWKO21q3uYBrksk6clNNGiG9dduyoGyqZXDETB1k+8y9dE+Ob29ggXR8o3yYtu1kNd 4U3RDJyuVmKW7wGCi10CkVUp4nkkkFI+k3T1/Fs/fWOnNlhr9K7Bg9oNkcPOI2Zpk+hkTAJN5lMW crTBioma1uPEntSoB0dLfKlWhNkrc3tCzmRyUGRZll0NdAVHHJybC0ug6Sh+zOy73b+emn/ewCz9 a7Nl/yP4F3yj4kBFqIA2p7NtApjJf2fnZQM9FKkB2hJ2hD6/Zn7wTAabdhayk5zI05Q8/83sIl4C EO+vjFT4wZD4tF3iCfa8ZKu2MATTez3EjBhW9p0H4aUTc9ND22nXJbhaqzr2S7I62v+xXGB+wcWi mA3s2YDecs+Jodabj5Eri+IuRCNNFuLAy2Lsee18Py5SHfBIrB3tpI68izm0kXJe3/hK9dvgqC3w IvFn3PwSnQ2deNI8T7nx4YgpRgT+sAfeeDqO3fN5OOKXGvfYs51UPfV2gb+qTGSknkc8ltas90Ye GwJ1zSy+qIKYU5qibj5zzsYa9GUs/tdojh6zp/W4BHfTVmn5K0x7b2MvbDiX4u+fZXLD48RYs7m5 +0kBbviq7O7QobGcXlR8A3QyhmcSC8T+A06jxBeGVpvSu9MSRkdNKfdlDvvN1TEilUxsY6EEFkkf SHoV3i5jcWsCKsMtDNAZr25YPGKNFrL5FxNXMQpHIRYnwf6lspw5zikRsOKFh6XosRhpqcQ0y8FD Py8SmSdAGKCJgSJlGGTQP8zAujfGGACzb/iGfb4TICC3GeoSwX+G6DvLVobh40Ny7ib0IgV5xUQb iZRspuM0mYQu8daEO37ngiroO56VdIgUZUuXSEE0i9iwqeZjtSPETWRXZ2g4AGn8BvIgwqmrdtVd dvY5w/EYsrBqDBmrHiXVqdtmoLfNMW0vxXm4GMTIf1PHb4mSty/eDYNExPmbmjQMRpTXAte22rSb x7sWg1+/xY3x+1172BrB2tCL9k400eMpOW6wjTNUqUGVMOMDcbi2exeFbL4EpQ4Mt3Xw8Kv45to0 OMMJv0gAAECPoLhjt0BBqkQ3Bgd424YHwmo3XOkUowcxbqtISZZ6+Ql34dmBcdY8qd00hmEx4B8w HnMEYLhusIPBPDGB7YsRIAVERpgGVjyoDJewdGLUDJ7OiBOkqAkpeUMlbUE1AsoIrMeEJ+bsDOJ6 GB9C1cSxuj4oCgKbn1KsBLLTO3NGYXsHrdhmfsDEV5xwHGsLospthQfl8tIIfjT4y0vxtLG26M5L Zd/cbKo9RwSCUyQYJmeXtI9L24wt/1kYOhIU/PwSL1IBd4D0Ueifr+/QXY34I5A6mUZPzxWchnhX lzwHl5dpyw0iyEgT+phFO5HWUJzdcKn7FDJY1D6k5v1zH23EnoPfeFlpGOn3ZrdN4PzyuIvEwN2w afscAZ7XzQHUi2FKJg1kBMGfIscLelvtbesd+xfgvWT+vICbtIuSLdLFY45WwsCozxa0MpPzhPRo KjFClCIGDa4Qg0KkVJ8Z6HiGu1b5WbLBErYN7vYFj7owG97a1lXwE/93KaHqZqBXu8pP8v3Z7X6/ nb18uWqXXUmRfmW7u3n55iUXfim1y9v93frzy4WuDT6iWxs5jIZZjE32ZgZqN+41yR/1Y9Ws0Y20 pXPADCaHfyksITjiH5uKYwbM6eOJ/uaLP7417005xS8v+athJg/dAUJHwVHftnP1iD7bGCttCgNt NoXtzE4Jg/GhAn8FW0lRlMn47IyzCEPd+Ri6M1/AX6TvnAbXqCMXk2B/BS6QPToHLyTfPITg0nW9 t5hpYOxSPweoE9s9HVat6KVfNPi+38TEr5p2YraP2bsS8yFhfNdDocxb5teLwPLE3Qfi79H3RGu/ /LjTPqD2Df/4SITrO9fDNLz9C5/YKQ04ff00Ow8W8CJNgQdpL2/5mHwBHQU/UCylb1JpuvTkDhWE JrTZTTxQAmECafgTaLFIahtbSRp5bISoIaJ+4Lgh/ZqkLRuVK4Y7uq8YD94b8OTFBk9C4QuttxQg CQADvNbCZoCNNZuQ1hGxp17mRbwL/D6+fveHt4tv3y++evceOCrwh8lf5EVpt9G8Z1c5b1ZqNvRW NjTGuzlICRixjeTNwlM/F7gIOOt+0vsEYqeuWi4WwPEuFmmNcCeQa3w9JwE8XdAoiYmq+Wmm5imK P/iwMVyNztgcEChD+rAgyUjUTcf8J7pfCDFHngxb03LVHnOOuBkDTJI0XdXUxxvaZrU4bNQwcYDn ry563iQs/t/+raaZBuSl1K13hE6mXp0HIVMw9OqnkXEdZBsR4d6tXUbLHGStJldATywBNnWK2DYs VHIUQEoycXzTxknQMdMUCyRQWOILXTnodIZdSzkpY5ksw1BX+1uwjl5eQpQjvI+59c10XF4CY0JP PBkHRz+zAeB8CkGzEo6Z3WWQ8TeL9vPBiC82LlwEFqrfXnvv0Mn4zAqYOh+NPAP8TUW+jXsHOe0k E+Z8MONxQ7r4SCj5Upf5vIcnYX0dThsEgdCqjWWeIN4DZgnTJPIMRYFNLHdTxlkAkHC7wG6Aokcg F2sRG2VZDfMFn4VetAv8+x6UUCtyq7FVXNA/ZCtCoZelvmZjZr8xki8Dsm5QE9RBIpenqEwA7iMm 6ASrLZjYEa+FUHcr9guLJPwevC/RLdj6SdMzx+dkFm47m/i1pnZwQ9o2TUThDcKlsFNPPxPieHPX LDtCDKtBf2GkA7OPb6uPDXgftteWmJTEf9mlW5jNsbirgG1xLrS5IXP5DJxdnPY7p5h087P5EPq9 Qj5TijxDGQOd0m7AwAhQSE270tHxFH1J98kP//zd28Wfv3j/jR8Em1jsFyylJSU/0J2jMHOHhtrt rvkIzsfmWGN2Y3K032Sa8UiIA9AuGN3gb/AMhcIFB/BECjMQP/oersglEhulCFz4JY/173YqTnDV QD0MN3qew7c8mcgmf86HHhFAoVyamRTUsxK1xr1G5ZwlwQ25SHUWaK3MxtLT2OWszfsbypa31eaG YrLHzwX/pTCHJu+Pmfn6AIqhP9NY+4sZorP8sDbEez3/TdL9Ie3uEQUPRzNvToqbdKCp+ameJLrZ VDJgZC7IiZkcMCrILF4LRNJ9vV4b+t1u8r31aFsifg8c/gGLnRnkE7AlIFYEXnGe5cvbtlnW+bAf Wc+O/QUbC/cE3nwW8IMQFUSLAleIxQV5vivz4aayr8k1rqsBME0y5kn4JPKL97f1BuN21oY3yI61 5/IwV3ibHh3ARIQ3cxMUOVwFuBZIxI4k6zhxmw9vdeXVKBqm+mGL+HD0BoRfuK8+IHghiPY99eFO 0bwcxqiYXYzBI2lhUp8QyKdkPkz4R9pYXX5hmP/iaZkA/vvbc//d7ppwBYX1KIVbODd/LxJOr2g0 YJd8AoEBK9LZ5+qHBRN7cxdqcd73TYJl6SO1/RtF1zV/+in5MwVLjcJCzWwq2vzxDZhnXyTsX+pu J1nEjlRu219yLzCjUSObsWCgZYrkKJJpnGMrljWBWYakZ46YKQkKmyN5/mZ2AVl/1uAblp8BpMci P8UPO8mmpPtzvBR0+Hp2kciDS6Z5yJLbc1M7X0VfQulnOTY1gEOwVn8nan48bzlHqjrmk1RqadTf iCP8NJxIJZijzi3K43rYrjA4bvOoTQhm7VEbHu84YU1lg6GmG/m53ELrhZsg3h7Eg7KYZ8v4Ki4o g6wyWjmOc6KKdT6Hfy9UBD1rbfb73S/yHvZOh93aipHG9w/4mMpus37mGMpUbpdbHtlsdsWKBtv+ WVjLLNMNVYFPUfnEIKCB9GYikcOP3tNUwJq8A7mHYgzWj6SaFxFP4V0gS8mIG04wrDrLE8EkExvu LFEViHCEURmop2FnxGSFEw6ZB5C7/U2fU/EJB3VsNQMkpNrLd9YT/j4WDykjA69riPrd37cgXBjZ E4TMjFJ3PocG5ZD7xEwP3nC+b5JsMcwgFAF8fPQTpfSe8MvrCwgB83Pt/mIiZd9fU6fjs+DNhLBp 7e4uO3uYZpMHpDOAD7MC5T1MTiFT0i9ERVOVEoaFmMDsnXBJeDM5e8NzqSbzzb/LZCpD7lPmEj1n SWF1dgZmSAgNIvxImcxfNY32uvBm8ZQM2Oa14DKQeZjkMZl0axQpl6D2p6a6LmN4z08xk+ckrA45 w4DMjU5lMnQPrkjYgX0Sta/q4xUW1MQrKzEmca4jUkk8Y9E7MlJR+y3Dbye0LLdFf+NWVx2OnG6W RBdU+fzMcF8ofpvHiFLM0FC4getNe7i5BUqNOpjJ2C7/OCtSQ5lLs7OzNxep6S3yBOqFeWg1jsrH pBenPe0Exe4nKe81dm33bKiystbUOtctpnS4KVWbtb+EBsGUE8mQOhGD1SuJ6MYph+vyJvDQAnU3 UeoaPJ84kQoQ4MqjOSAJEiIkiBbkjOTcH2rUQuzqTkSn2xo5u1INOz87M/fafbtbdbA38NsZfdXm Q0AM6kTTh75OaIXVxc29vn6comnEtQkcm2O1yHHEDMbMzWb14gWOCKy9d4CHjaxns6nkzdh4VUpb fcYxWlW7ZxNLEKpj5e0XVp0ltlCc8wPAXknCJ7c7n7TW/37jIpT3xLBcLe3HmHinCFDXlYgDlR1v hrboPurv3CCZkzEinuJkyqaDK243Gbx+NV4vFgf/WBqdnE2zFevdx3o1jsWSrfLrTZze0vf1FANN igKoa5OMOEy1AhcTq6OWNabfhzJPwPOp8hcO6RgviHIoDuQb3481DCH1qZQyDafGWSb9hHmyyAnX Zz8QutCcf9pGU05Mu68Zx2z+1a7dfo9Ea/cHQ6T+iyn6tRTRnh7qLVARJi7TE99XuvCcpa/FP3qk w6oZAZ/02QClzRm77sBqA0Gipq+DuZSgMxiJJbqI2L0b8BJ2X0JPgsBvgI3g1jcgYQan0G8UpzFz GmTWQNgQ0hmLXdKz2Upg2UfPdSS01GvIlSAQ7GN8lkF9SFT1Y/L0Ys4QCFXf3bhTPOvPvAo3ZX7Y AMr4zab513rl3gX0jKhmzLOcYrOh16K4SLYGg/swzT6icyvGo0yCFRHnl+JIjlU5unnGxlIcBLRd FP1aJNw/k/ynDY+V0g77FUT3QNOunWZKzKqzojcMGR9K+MsEZOiEOHLiHxxrlGV+gK7g68CNlHPK NdfXKGGvMbwApy+7fdze1htWApyZU7FeV1tDV1+8gAbMLew1AX6a4jst+hTyk9RtUVMCxFmRE6rT fN5VW8uH4xM4AIZXOeyQHUFXmNWKDwDPmH4baR/eeAm+Fnz6cXT4diCMW9dSuGY2Ip/esXad5FyG kzmjvBHMyYD7KY+ZHXmU3gIcMmAni9j/Jts3dwx36qFSc/oXamjhMnAIbVgG7gOt2Qn7HcVeJha6 PLFBD3SSmsQJwI9wbP+Gji1m2jMz5WxTcjZTPgFUXXN8St1GPYPGVkj+Kh5lzjGCvvTRJT0Qdgo+ 1nHdNAZWOwI36rXFuhQoS/oUfO2J+hkMP/QEDof6/TX/XkS6erfFYI/nZ7dT9sPPMZnf2Vl1tUS+ uPINLPT25dB82Bc6abrh10UMyMGcHXlRxOsRnDMz0r/8NUQllfpJ6ACvfc1QIJuHR9L73XcmTbqR ekvl1oO+n5NqxlwKJ2A6KIaI2U8VcmzWJi9OUwjmirSoc4AKGMjMB4qiWXb+vLvITwKGfS7WtCKl +Ht4sLy/vHNgiAA0nwd5I9Kxw7nl4Hu3JAmduBUJ564J36iSJ3PUuorci1pgszhJ1C5YRVfs3DZx AbpYeCgj6EMjStVVA1eMHLh9qBFBcA9iol03SIthkZhrg+egpKCULVV36wFRi1x5X2cf6npL3peo qW7F0ZojjlCtrb12jmxxhg341ZtcnfRQykhGlJ2z4sbNDlooepa+eEKHrjJqhea5TntyEnmDasQv qU5iBuh4WyPJutQLYuLHXnv2olW99gJIuejFaNBIiiYgySR4tyK5DhNEG3ZAZdy6bdcrm9/LcRyd sq6VvbkqQNJnCMYw0FJ8usleNxGgxhNUtOgP+Jkbc/Z897lNCSrtTm1GsW/afScYuCe1/M23P3z/ 9ofPx6PRBqtikok9JcBQXC+sv4LWy3VaxuYmnkgClkf/IkZypW1E4bTTAKsVcU0YhxKQu8thf00/ SZWyh868fqPArWAhdb2JQ9wtMGRReebe2ACAIY9cGybIGF0pVQPk2XK7z52dBdgE1Wz3SfqsifBz PzP2s5gPs3Pethd4x/E/ZVleoCPpopqa7gIfEBUnHAavuoKFN8/BCnrpx5wqJkiMFGdE8lFkrPDr pXNQOTcQE4OmPvRZRjDaZH14Evsqk4SQ0KsAHAv7GcTJWIyQsMHQnMh3E9PfJfvHRwMTUwZI2QwZ kX5Nh4y8irAs4aisWjD6mt1lKENxKq4A1RA4AajZD0Kr0Dw9DFrp2GdKo+pWf5mGsCWAbRdzKpu/ 8IMUZCF4xuCcBpr3L0Dz7iImKZcpC3voskcx9pjSi6VCUF4j89Fej9zpqrOJRBua4s1m2WBIkk6u oZJGFWXsD8xjlfsYB6tom5k4H+1a51JzGQjD1R/aFh7YZrQEtujAEnDaTsY0d4NNpMnqcXFXI5r1 wHT1bOPkoHWPenDDtdyrLtS7Pvrn9/4WQj68tZqFiUqtN4gsJmRqjNKZ6vQ+CpeaMvpasGmVByAZ 3b/B8GmzeyXLAPCoqK+g3MigUjHnJw5EfQpWNK5ykIV3BUhIaqjzJLC1n8aAP051toLChzpYCNjN gvMlDbhD+YRRQclYxBzDz6BGbVyUi/19DBzvJY5L8AtR+Nez7P3br1/LUYMawIFHufHMPppmqQbL MLdtb+ifelHlIdbuIc+FSytMXXBmYbHrJCwHwtNsxMulvD6s13hZBgdu/7iGm26MPixD8FtSEKxy H+uxdj4ENtJlt4aVQYM0Z8whPGh/n4DZEPGmu/lNELWYu2dGqiAz1TQeyhz/TXEgOwdnqTe9YJ2T gpdHPee/06elgeE3nUeJwFlHobzhq82jkYm6BO6vZJGGGCEehuSwHf+0SeKnRbmJ333zw9v333zx B8xR/LnkKIaWi6Ha1+tDd6sJ0vJ+tcAMdmZpF3RaxfSOX7wjweD0gkBFtTIFWUuIhhBNe9j7JUw/ 0WXghD+QHkBnSQA/hH0bzJvZxQK5rQoxIDkN1ce4w9+kuN9VeQVhCjU2OJGWoxNJLdBU/QMKNoQt YucO9AdAMdESs1zb+F+Uv1IBpYjOtt8dALgXmAiMacJMuocrZq4BQ95Da+/NL+qelg61kE1GyE51 Yr4OSochxSx+qrH7TpsYQurXTWJvpROGx7iFD9FMS+pfy1AomBxrxw5gGAUOzDwJ3GXxlx73IZ+Z t5GMUAV+GKU8c9C5zznmCG1Ne0hrJC4l401tjSQ64r6/vHzi6ErajTp9CSTEUGnf1a2HCOh9aRow B8giyqCSklTS2R50A6UzSS6UMVIBBUJ1G0McnAwQD3RAtmWrUvHJyVhvt6HQt4e4AgzSB/waAIZp QE9B3kTmu1JamA2j2wszXxKZmQoVwWbct+U1HM1dUjJXhsvznNtBL13d8PGa3KeryT/4NQNSeiy3 g4NKgEXJmV6ALo9MfKkEGvAUZig/0piZefZVghrmW3OHchJBk9eSxlYcmvLCO/cR+qqjZrjHZ7HM jhvLX7tGvLKC448grbOLIJtzTxLTL7766tvvfvietapmn6AZt6c5xjiEoYy563FUh4UFwPDntw9X po94avpe9EeeJNpAIoAHAfOPG1nN1EKkgU5QWF+/Hg8BFybACLEfwgCE1J/ZeImhSED8MM2L6y/D /ljLYAOXa51fe+jFASY1KJkiNeDxN0w2YlIhXEiqPZ2ThG1mDsueD2B8+dlsKf7h05UKQJCOAF5O Gsc8heOf3gG+yJe8BDT1Rpl52ofcQlmzPcwvq38Jd00S2TtwX2KsRwfuff46Mo0ZEk1gcDv4yGcl lZ7hvg4CV7eATb/ZswX35dmZ+E2aZ/ft7kOija7N/gU8stf1XmIWSPe8awAxwArcnLSq3qx6XK7p QARHIcx41GWT512B3HpWl3HSgLRvO+cat4TSoyGhriWp0SOyrC4Rc3cRufMIdmS+p6f+iKgheiKC Sxng8d49UikBdFpwH4bh7KkBnWGlz7KPKeA3Mutye38CFcRQrMfzbvZ8NZNbp5Pk6c87dKIAfzD7 Sw6mk37HIJ4rYW8Jnl49gEuyvfbmsSeakkpME3NSnIYF9owecr4ssUg5RBnOH9J0vhKzTKkOA8dz utqnWTwRY0AtQTcS6lx1i/A9hH+8ITQGtv1wx5Geut01N8zixTdjoBEmo89JiRj1f3FSRp2L0b9o ioiXSV+0lAdG5V+Esc0GlKmib5LmNKF1RDVC7kncXw5oisiwEhIi7QOUCK6lexCBWwxpM5/jvAVY YEjwDkfHTE5u02LlSXT4eCgaoMj0GlhK9KYIgIdUDkIdFIC6joRjPTGtEHIWww0hNg+ryDAKB1PA gZuBMpcYUR/YVETIthFujzWGP4EtFEBGON90R35y2ONVbbjmuvMwGF1Eu+h8GnNK8YV8Mf8hmF4f 0zgG236A99eG9gcxJOC0ICr5CkICCLUFzVorrGIGAUU8XayP7hTBNykZ3bPYsgPFJpvt6uvZpWmF UoV9xsxO9/llmb3zUSldqAIK8IYIwe2Njh4K0nx/u8NwFMgI2LS7BDCSJ3Rkn/XBtCIiklOAAM6S NdzQ6FltayhfpXzPMW8pwg756zScF0YMiOfO+eBolHaqptkMFGJjob7iPaE6x6AaDbDYu57R8D1U Vw/IKaRGPvrTae8We/QL5FliN804LQie7mJAyKG95zEyTxkUJGvhV+wFoFeTy2VHMZRJ3Z+Jh+vm +ZFcadIQZqQXKK5ghba9AkXAlRQ92WnWcX4vUKCx/pMcwZwwTG738SuthcCstuLvs3ZJBVE2T27O 9ciLhrWvi2hj6bMUjaanCQtUlk5JR/6clMym2k7W1d3VqsoeZoZWQpzmdlIwRqLWvRe4JhcD9hAP Sa3zs1X6h/JQpzPuLWSph/JzRdse4e7NpMMt3fX4FMQZwFTbJ55ZGr73WqYhSbTmbUTzu0uLkth9 wc7jXQcvQFnE6F2SOlR113G5qd950s2N2p7LJ+veNn45DqqXXb0tBlrgV7ZbnUZgt/ooeTS4XKTf Xnu3rRdAJgGOhJ5I3laGyfvQbKNALe8yjt2YaCsrQEWI5OhDeS+z7J/bA6XOhYyWnCrQR2RAzsZc yOYqurw8O/v2ux8ARFHcIm3OQczkDKrqsYa8Lv2BDCIsimPmNYUfbCjsAFAWg1ZgXmZQCbOPewIh PFIG0FVbdxxGBe34Ds87go4nvQ7PWyqwkINJfaMBCs2sSfZu5NRFFeBVlBqhNeKbobynbYK37fNu 9uAthnmDJyBjxJfjRvkOnn49pofe72uE/mZuISFrlWEHZDExJWyKN0gzGW5HUQoE5CsyW1mfRVz8 iAynPDCULyC5AioHwKIXptYVCrIRSt/tDt/3V44A6QXdwScOhWkMB5LCiDgLMN3pzc2m3dXzt6QW t270Kd9b7gOpJaWnLbTbLbUUFWc4Rp4Kw8mweGvYGslcJIoPERoffEBbG7iKYLdeJrKzMceYJYVR aS8wkVANP0TOrxXdf5iGTN9uMHSuyslSOVVmaLyQCup1UTpUb5+ArDEDgMd0KamySXd/Wc++7IGG fxTbsnkr+7V8t2nYf3fbmz2VoRpzHjPX7OrlAKS4WnwYt9nnU1f3XFpMxwYi36fnChlmohfm53F/ j88o7oxAaIwAX99t948nj49dPRVPNFX/juz+XVCS9gXwK6Cpmii93TNWlO3q7B5ut3s8uAxlimr4 dNIEkVO5EQbroeB6xhH2diOr3DqBdKTFCwaGjtzM2fVudaDfFORYOEiayNzhx+lshw8HZtz1R5IU nuLhbocydl1nW856GVSk7Jcw9ODBiSFHuOGCqpK4OJV6emDYA4BytxV5Om5LaiB6i3QYD9YalF3T Y6Kao1PXI/FSCaMyzhSMJJytpoN85sVQe2EVX4JQvK4qxIcuNPJb07w6eUQzfFvdCWRPTHX9jJ21 /Dv6xdRofKoSQlrw5CzJ+j3vpymjeDupCR2uprqYZnbC7FD4HvbGeS7NXEyzc01xp9l43z7IR1yD 0tQeX/ixn/xCybOO4qAU2NjXOH5x+o1z1m8aAqT8Lvnm67n4/PxBAyY3uxh26+no1b55NC8FycVw k5IHvaHL5D7PuzJighPJH0zxONWDj76LZbHh0KeIEupZ90ronpr3jXtic2tX/Yosybvorluy4Cdz lFC/oBjpyj9iJNYPgM2aTNEnfolhxFYiFTM3XS4WYApapLPVd/HbRmmDzTNpxIejj6MeUNkSKZ/i zLRRp0Gdk7t9BqLr1b+AEyRNdBim7ASkU17BywTpjYx2JgHmRz7Y4tH8gpjxIHLNSBZfYj0jOv/A Nf+MFR0Yv/Lgr5bLdodhEewhqgP7m0SsRZm9NWf+EX3O2cRizbdRj1SFBATDOqFAb8O8qiCIg6Fy D2ivMZtdIkBKL6J/f8+XQlv6nU3C+XB3qPaKXLZroMLzLH+sOxX3ub8vzfDuqt0HDBKycRgDDWza /vouLoJp0f5+9PPVj//hk08+kTi03WGzqXc/L38c/+6TT0B2NBxts0TYB0Q6gIwmhw0ndm0h084a 6BKhLlcUUgizwrTqanUlH82ZHaHhBAARbAYq83k0soRt5JM4LG6mdQHrWuLicgGZ5fdGsKV9GYYT CfnjN1U5BK6rZp3bLT/L4LtOJwDJT9Vj+K4e0wBI+M7NY/1dFTM3yV63At/psSHxz0bPxJdNhyl6 L+LworYaF0hSObFtxWZ+tPEMGQU0NJh4bKy/UALIMQWErNnAbrMrOUSvFRtXOg15T1G3c8poMOYE LpCHwcvfAqEe++pjZbr5RiUoRtCROUCQ3GffZIjlhIEn5t59ibNgu8wm38xfkXxh5JByXEy9SbFU pzsYuWf3OAmjOAQ9ybZnbpWgSOmfHFtUDparG91tKrswQnGETVPfPg4Dqa63bEDNAKHCnJOupMjV SeCbbEqSghsrRDKLeF6Y5+BYzCNNIRmsdMj2TjTWzHCv/MbVa1E1ANGZfKgf59ryIb0VqiCzWhO/ dZlAbZKg6APDcputOkfGj3eBv/7jFJs6UPt5FzZgWAz7xV1usij493xmS3CiJzX1wdzYYADzuKQv zjYwm5n1m8F4zL9FPF70PBg/f/WmfHPdZc/P/rYjN0ZvtWB17OROsR8IKLRhFIV3AjhaC3VWE/7C yy+BXCTXwC4D7ut7+PI9fDGrFDd0bZjP7vZ4S+W+rnYr9DNcgwBn48NX9TsLNJaIrZaArtD9du2A ANY2jl8Njy+ZhVwyE+BpzZzUD3v4JByx+Vg22n9G6q3bG5qjYCXnWIU+u9HRrzb4bOSig7i9nmHM 7Xj0XYPXNL5MurYZG8U3uXaU0tacceBdKGJYDjxVHC/4ydgeOFUa7mY0gMG7SEklA+DPsDj8yArL cJ+gsxS4yBMtkw5xA4xxyLY0JNgG+mY+Wl0p7FqCbNZkBYsKEerpAX7mDrwejlST7UhV3VUTr0wh ujRUm2G+LK5Lt67z5OF4Xi6PfqESj8ap3GiiEePN8Io3hl28rx7jpQgn3a2nH5mKT20XSqS3QEc4 FcmDwcqL4CykTi65ktVUNtkWvLduylNbYLtc0lfQ26xb2s3we0x5ROH3MlGEYLdtu/0d3JN3hlBc HW4M3+PSYJEHCUum+6vI1dcVhGf7q3J/tYAlxi7BgPcC2PMX2fXOw281bUCUy8IlX0g8FLcQMrzH deFdrqrlB+zYQw4xgzH9/77eZ7sGLZoNXfIgKVhOdBS44iYWQHbkAJUbpMn1g+HPwsp+T7iVFuhH bOoeQE0CvziFF33HuwfzvNmz786ar1HgCsA+hzHZz8Rral/ftLtHRhFdY2aNKfjoXrVdjcivyXxl GG8JPb/FfyBQcex7cnDfwHRv656sZ/wQ2QX45/t/fPfdd2+/Gh9PcQZIwfS/ETHr7zwJhwXhJGGi q9tReBD8ViIGoxcZ01pZeqBBXl2uQXcBgVC4a05RSLgdEhffXfWhViOaU9PQ5Rz+sReHGaJ7954b lNuhP3PeMFYABYsdhchWmKRcxRxDT9PM22FhN7awbQKDMcPxSite7x555NV42mhEQ2yelByRa+/P 2FVYsd2mCbMv7qvuAfb9uMjaOFWMbhXAIZXqDfZk6bIVPrG2kabL362u/rdDsxe28KS9NLObyVfJ 2Yrj7FOsQWvLu07UgG73TW0b3jp8acYATCA7Ss2oBb39eBw0rDn8YzlIqeywft4jyuJLO0t0jSjw DRey5lwsn83I+8Ew8rYiNOv5sctKq5s2wbJCPzRSHwuIAWEpN6eMYCbYkY5cEkeja2puZXxX37Ws TgnwFpD0zt1C2AeE+D9HbcnkWBAXg1TO8T0mKd+tq9aM5h0cld1hu080YYT8bdydu8L8JhMNuIne PqLepvQWJQzM8vs7CjYl8VfcSwg6ALcb7HFLACR4rBNfGjldx9W0tjGa1Zl4hKiZnhYJfC3e1LTf n+/MAD539ehsUtuFtQR3a8OHwrBQagRaOOAzAY8NKyBV0AN4dIKnDkiyWNdWHfmhOePnXYn/j4L0 eS5xJlA0vzif/ebCE6jCMQDfBq0gSpQRzs/Osu8e97eYfFRC+Hwn1fO8WeUXU/hgOC4jWO8B6g1+ wYAX83P9UC8Pe4h4zy9i8AuhI7+ruvo93VcWPWwIV+04ppraiftWVD0SVX7Q9xqEjDOgBQu39H0g WwNMXqi3MY1iSNAk2g2UoAC2RJFqU/qD/BJ2pGHrUqhULwOvMbD9k5mV7CilwWQSpT+BfXNVv93g v+lESral8WeHDcbMIayBtPv5OMB9ES8RQU3Z1dfNQyK4f0qkekNQlUhgkv4lDeXT0g5AUZvy32NT r1fcpW2fhsepiuagEN/Wu/2j5zBsXhKiO9hRG0qy8E588ynVqCRXY672lHrCAEvsv1RwMBQdGs0H 8HNY48VuzqDlwuToCREm4DuJheNW+WJDzsbebqLykgdwCZzxJ7MeWOZD/UiJIOZorZycTx6mr1V6 cmRNpNBFEVzympNivdYyyNEhHgiqpIJclrm0K5c68ZaV8M9P7I1sIXiSd2JMC6RvXv7kYXYQOr58 lOYflZ9kGabMTnQs+8fnABRqz4Jhe5a7qotiB9wIJ3Dx7ijSwPDheOY3LXxiQKghGnRkIpprt61w 0yP3lQhCcMMhhQZwFtcUZjyJMHnsUDDfgONDyWYBTKZwdEc7WuieFttHuw2eBB9E+EXYoG++2F/h o8KpsYm7MIfCI4N2LKAFiMmh/CJat8n4y2q7R2OsXNwTbBKbL2zTha/4NLvrvaMBVs2a0K4moi/5 GE9lyaeZu9fwpXoqytinmTNRMFOgBuT4AwUr+js0bqIFgYVqNvtO0Lcds4Yiyg4uOwiIVncI+ww8 SUfs8P6IBL0oY6T3IC9RoHqeJl48ftFgJuw7zyEURV57/gpYG8Th8CWXDYDnrjHFAkse6OKM9tQA +M/aOzSGkQXpnGBw3mNn1pO8feUor9q7yrwmHKLMTNUadH+GYleYsEJH8SGmKgZRWwsA5iXCNYB9 kp2BEo3CJ69qzkkAm5hsx35T/DY1IfjX5U1JyY8IbonSAN3WYItZSdCea5AcSMoT7BLeHKAILVlG 8FoCYHB0PjAMTEMB/+u1u7sqFfZvWgBrPGQANPuzXTYYE4zgjzIHTrgN0CvcXSgfvZFhbXt0OEOX CKd8f00tEZ068h704wguf/J6ESG7ypikYSKxuhPdWDSdlhpaplg3x+PL8YABXgocK/gr5ywH/THv pdq5HtyCM3O/9Ky7QMsf5IcxZ4ZjZqp9VXBKCp3ahRxHIB8ruIIEa9bdmpEBfxqIro6l4LisJZse vbVBlweAmWg/wAuZ9yDkCExirUMaKOOYY43k42hYWqFDPzodp9lRRoiWEDGVV3xOoNCBqKbowzTT gqzaNYry0voh699Hgnvudl5JpzXpNy4KVYzJXu/261u+CIG3Z4oV7ws874JpkKiB+auNeGCdr9WR 2eflQmmCAr0Q3aopJvOXMKw+U4V0kN19xJ1m0yqtDtAFpz2FqZl8T6RiCrhEUBaRNINyfqrfIzpQ Ve8X8J9qDkPuSvc7pUDPcVFaJvX/CxYVrRkiktiRewyoHnUxBAxn20IvWpHjU8CPutcvqVc5i6qZ Xp7dllA2Ym7mfbDRLU2I+TbbuuiSSRWfk+ZMQGOs3bdUBhKMXKhrmbGFKYgok4EBYOSQ4/XgIlIz wIkl2E3W7I16eU3ku3qITshCHbldn0awrHZXchHtIsLVfyWdfIXEqoK1ziYUXyikoSJ9ggS6qJ+e cjN5CwmX07re0MvOn3fDN1R0S2ESEjdtRc9lFZ0P7V7Yv4HuupuBC8c8PVV/aBVhXhuwDVcSZ0cD Vc48UYoEju4gvx8WWpD9Rie7CvOWoORiWe0Odo89xgo+NHrX8DVNJ2gOj+7Ma3hHI2hgVnjwZleA LPaZ2FnkO0iTa2XvtqAse9MNMMa2pPgDM4oR1Sr9WCH8TXz3pmSLh8ymjPGi2rqtHN/lpe5isC4M K/bcntLBvhzXL11bPxx35fGjKclGETyLwv5dMpc5seNUWEJBR1a7iauBeGSGshw2DXnVdQxwRsIr FZq97F0wQzf27Mvpxnt+UViceTcgBbvYbtEGbh0Ygt0iQ52rkQZY5zQOO8+IQcB9EcWRzaFBzMws uZFbWPRwE3m7MXpfGIZ9UT/AwVzFYYQNobq76ilI96Dx4rgynUDeE/rzhG+NDyn1LcBqEUKQ01Dh PkewIXM8rh4xS+U00QDu+FWNYDZw17KX+1XNapB6VaYDQ5f9AR9u3no8d6gBv6La+eZeQOvixNyq XkKDga3Rt/AMl+nvEruPEhYUuw+Szi5qJ1ufm4kfvxueyUXfTgnPcGdF6vSxDpJrYbhdL11xF44m W8GZVPkJsIsUqlB0rv23/VBjhkiLRKJft0i1N7CGpq2iP0GFazfxcuT2RJsg6TlFHoH1ql4t3D0H nBkXI1rNX0p4neVtBUcyxVe5l9i39+ZTN4maTm5bKc1cZ1Tn1JURszdfvvO4qfOZZXiwUHERH9M4 iK13xR2uIHsQ9h03ZD9IMy6RxJiJjeJ0eHQZTq3c4AigqFDRXUii0rECJGfTHjpDpbzmvaQoqfWV w6pW9JeuJRFMdC/iRKIZeAVGilQIIyLcL8A1Q/EpJBD+ye517jclIVkmTzpIyikH/yTlNFVLXbFI DSHeNsGumV0kfULg6han3HZ9wuUGoyE31adeceF79F8qCd/KUGKMVDLi4OQkWOdb1/jpXrAAOZLb 0nPXnhKOvYqDiqGwPgu9IP9amQzYB3GNdqwJ61XwkJzk8KadZk5xvrMj6/HAK2Lp+5mhRL/iP1Mf VJHZtySSvXVqJ4zNq9db4N5w90IAIZsTDM8vIlFYcRIaNoE4hYWwcQBU7A5X1IxcqZ1TNmu9Pev2 2RXtClNKis+9ogQsWHZHrUBGOOSAKbMi4F8cRivboZYJodOnZeYXJW46XOxHyYHGn053rDJtpfHV xIHKG4SV3J+7adQ5BXGCzZ5eYHAeZheEaouFaQ6DcmU4Vsolvd8kXDULiwH8760hR013CyaE7Dcf ABvj2hw6uF7WkDiEo0SZRHZcseEcnlAM3f65K8VCox8KbDPKOrp7uWmWHNm1WJDJCAedS9M2d+HX qPvrGzVicNH9IOCX9cN23Swb0uYiBDXZ50ErOHFwPEe6ffvQ7CeRV1+iV2Ad7+7qFdicwHnkZlfd YVxil5nTn1k39+4lRdc1dVcc2cIWldGcza71eOaerRkNNLm/R2B237YwbCIBbNHrLODQfuK0L/CS 8BMeSVg6TgICeCZmS0ddZveQsHvX3NwAZGipJtrOwa2RjnC+bcgtgUW9lZ5HI+jReVGYovCMo/cB mAnnZ6wVNBCmgMsO/mxIyWwuWqfUYH1zmUHezHpmqFTeZRrQ5Qq96GG7HBhElrcNGBbRtwNC89HI CIUYlVbMi4hl4zkSHTZwIMweRwJnCB1lVu/MOTLn6a7p7irDQ+G0snNeJ27Lqxq4gXqzbCD5TPZ9 rceD9oEt1cMYV9iAq9r0sg7o4wnzLiQBJhWn3/dhgTg3KkELgCeIFiBJYWnH0Omr12S6h6VZHnZg Gl4/ng0v0h95kYikIsAc94IYc9cQ5YPF4QBYAykh6kLWIGs8VebHhEBNmiRoGjwoXRyKiPm+sP6E 6WRSxbPppoj/FiMYnze9VIMxAHTMs4A0TDOHYq7D2RT2IFUzW47oGaJS7Cn+HjD0gaseu0bGeHwZ gE8BnruUq2bLvUMUQFcJ5GkHFAzTXeFGH7GOD8HI7dEXhp7HA9hIIHle1XaoT5hZyF3VuGTDkPsD sqJ8BE9Mc/VAJis4SIaRNazEAwoIXezfa6ghdm3ooYd+ESfXmHkGO509gI16BIorw2ErCyFt9GY8 trD9MpmpAGiLs/ERMgvudypWANEvcrVaecC/+q3HOESRIEEYAB9uDI/QtYcdcmgMEoAo59Ka2Szb jwO5SAKRBqfsviYuoHIpZqQ5IFbPdxYyS03rOD6ogBvoDxEuc4S8l/YYhKtMLIlgOPJkKo3Q9uOE f4Wk6eabm70i9T68j58TSqU+M8/RmsDv2HSCmBy/it293LE+1r6zF2yC0c+rH//nTz75BDAa1u2N vct/rn/8r58QfoT5GQL9si++e5dNcnMzrw7mrulyJG45pGs53OF383FDvjwfm8q6uBAbNPr5+sf/ hftB10nb0c2PJXfEVNKwRlvixl8iYATnv4Q1gCFAaz/f4qAXyh0S7qmfmx/Xn1Jb3WGLa41mFPP4 JUb72AgUEk7YkafUeBdtp+EuBORCiEY/0sWvQX44CuiwO2xw/LmnCvYQHQxhOwCsA8CUzsdSYezQ HTBw1atPmA7gyULGBsiewgT1ETHrcH5WGQdKea8Y5l51UYi+d6MMRJnK1iuXGgSfRSntgvy4EpQU YtuM5RVNk+okUg7N7SQNZGO1L5AA3gVC+KzIj3xZ9qHq2J5NRdYy8dijtAVj3mQqnmhMLN7EcmoF YZQo9gRZFhcuZRhm06SqoGgYB7Z0iKNF4LicZCB7Cx/o5NziXHbIBrFkpZpgsnOzbq8oXQ2ESZWG H64gbJJGZwYM8R2l8JCgv/xpfN9sfvPmp3HujQiKd1ZJCMO/r3FDtdQzVrLMaIleAqr67X6/nb18 yVuk3d28NCXNx5dyzsvb/d16rGL8nzL5uHRuKqcs+bAwb/Yrx30in9UxI4RHgd5I3squjho5MEIo FRIZtDxivH4EQqxXSzVD+eDRtsPgzHjBwTAJapQECAsNI6A+dMahO9XYY3tgMyKeb0mWROxx4n0w bQNyWcyGLXVrKittgUsqLzvNoCO4adFdD1Q8iIOCszgldc216g2ECN0wCPbm6S4Dr0cwBkQ8coZT BmROJtabNJBdnrZzTkEdwqAF3DJz/Nca8plETJTEX/4KjcGDUhnguOgH3pueFPogsk4g4VgvZ3fJ BUIPtVY+QcyQt6SaxeghEiv+H+bercltY1sT3DGPfJiZh4mOiZmICRjVagAWC6oq3/Zmb3qPtiwd q9sXhSWfoxPlOhSLBKtgsQgKIOtiH5/n+QXzl+ZnzM+Y18l1ycyViQTIkuw+vbuPxQISeV25cuW6 fEuzSp6Wb9U+YbajJbaA5oFNPW6CCkptQLZm+MfzyaG4VwSf6/BwuVTnQH8yaSfaBMG8Td2Og8t5 VS07HVzgZcppf6BBrQxbVatfirpihRhVIbN/N2paOMNuFggHbGVlQrOBrUAJcfA92QlMSmhZE241 kUwmTehR0koWRM9DGsJQv9wIGM0ZZdcgsW0r7/uOfCn0TSu6tcOmoKM+++0ILkqi/ub0+GwYvcRL m0SydoRmVHOdxlEcfRzJD/NqsYDEPw+jT8F1Mv6XeHgW+lrLKrFoZ6TXjG+M8T7Z3qgnZmPmpF0Q +n5gzenHpoujk7NsEIBSR/YRU0KbguUAxSnUzUKxoJqgKH5axZ0xLDH8B1NLdxd50HS/fGC31lCv HnhEQaYNgu0ELVDWHUSjNRqcyNjJpkGCSuNTHAiWvyZVk4yUGA9Jxe/gZwPnSUIiAvxpGAE9+s1a 2BTfNLlloEB1/nNP+hztdgefqesM92kyye4Duu/WAv/RFbXU83OZUze449pBquymmXVvRCrRMiAQ a/P6KrMS6SXIghZu+jwPZwJz3SBdQB1rsI2pjthGkkzxdCFMgJr/+qqYVTWcNf8ZZZZAPeabt0UB UmkN+jeIWFHnr7qJKfrcgIGqhACiWaHOyTkh0gaqggydKN0YBVbIx8ZJAU2DAI0Kf5t0QNPqqsfO BOqv2s7BQebhVnSa+msxdCrne1GbnzE6uCpORRgmvA1oJz+A7d3GEw+uPRYd4xedBV1WTrxDWswB p51UMtmoNxDPEBolQpugJO4zgWFELcyzzrq6Z1x0OWYzCp2bK56/0c5IQbKIsVyvSB1tw+TKKIyT iLW5qyo6QFDsBz8BkDH1JYKlyZevfnj+3T8oDv/TnhGMMcZzbBGaHuQadTtH04w1NeTxzqrkueRY H3sXDYUtWJusj1IY26G3SpfrGDl3R3G8c415HVmowodJCFL5val9B1fuwZHvHhXXJ3PQSMd9/1zV 0vAwIq2hRAXtEKcdPoKT43zqVg43n+kq6IIOr7xsOdhTOc90vTGCbXgNWLyF+kZ9QRhGwl7XSdaZ 3yaO94EK57JmL4wiwOIRSCWSdrk0dHAwGPyfvCfAsQMgeFMlZKBDKPuM7wMaB+wMlUdj9+7FMfwJ qW4So77X5XMtgPtQd6JC/XPg7WHUVZuKvLVlTZytjO6rHd0jtSZrcdAhBp+oyxQMOYB4t75DIQkB 7+i3mIxADaKMxJlqtzKS0VmBOO22JlMOzhuu4zKrHwamXBKtKUYUvgXy7kDAd5QG8el337/64cfv zpDwnGq8dWkTHPy4qeHuUnfTXB8whI2GQXwN4U7FbzDQjJiOxh4U0yYRqkBIMu+crS1IMvQBAjnL 8gfoQr9BrQiefaDUxLwuoGnUURVKBpxsV1p/1WwRQXzgCXG6nVbBJGNEyXUncgGmKNdnsJI7Vw1o oyhRMwApcwRfgQgrTXTrqKSxYgYpI/gi4HjEXMAeTfH57X5lTg0dgW2UU2cfGseM6DAUUiGis1kB 4de2nhYEW0/koCTcIIBF37CdeklrKh1TvPE6sYcEqWEITwd4wCfaiwKe2c1j1DW0zD+1N32IgS46 wjrbnEAqc9rjCp5Jnau564Dqnha/nJj5bj7i4pTsxO4IdxxICgm+FUV3/76YxaU8gNYobXaoXGNA EEXEZoN+BJ+g+73cuvqT87tIuOX8Z/CBXl1w6meBf4B+IaSVFpWAfrcqSeEOJUqCTgXIZrI9oMr7 BjStWuE9LwFC605W4jWlJrumDuB4ReyIdWBmM4+XbQ+wH2wCbW35YM/VVrSiW1qfcbonoHhytp4I nAu3Az5hHKGlJtVHXid/NvD5MmaN+6Gf9kA8hkBPe4FHby3Gwm1szH1BANMQeKqpxoI2vFb/SePX Lx6/fKl+/ZrcFYCom4zwhP8t8+YGrSTe/Gge+oicsd4HVL8b8p5lkA1GNavHispl2MuBBuaCO62e HbNF+E89WrmLnKoJNt+m0DzKvKIB6PWvn3/3aoR+cslhnejcjnCnLQoGgIjblWg7JE2H7/PbCEXs QTiqgpXhFMSvOtK46QBgejgXQHC+EFx1iuk8FAF5mmx19E94ClsLRTum8Xmsrut1sC6a9/vUBau4 eBaqrMFUIF11DSn3RjFX4lb87PHzbwBYqKuB5mWwAfYDvOfIn75XZ9FHK9EIxLazgJ4LRZwMBZPN TS7yE1yi4weKkIKMYjcgAzkjxlGtfHsK10hAe+VKp9rcq+OwU4YRqf55kxiwuVY2DLut4JcZoM+Y RIaEEM9aV32pNmY3gJKsxFcIU6DY7NTmU/AwCGAMJuYUxxA9SFX9w0zOwa4tQN273Wfchl+bwd/2 jP72jx2+c6jqM6h7guLXeh9BMDzPUku9hUJwG6nMqSgyige21jqzvYNJ8GwbJMTe2XZQEGG2/cQB crb9d//Osw0nsEVEg/mO3OmSamJfOezoCGy0FxWiyyh+njgB1OTUZF5SXH0XLmyr+Ck0fjZwAYA9 S9KBcFkzzzAOIvryS7CXNpu54oUggmCdh1dlo10II1dDBX+h251F/tV+sTQLVxBmFEP3BC/s6LWq 5Jbl91RX7CjZedC37Ja8AIXiHM+IJuWTQqM32GlDa8O1Rgf15TiIbB3T+7ZMy9GpEC4HUatwtHyi ZgVLI46bcCOT4fSInCdC6fEDxvhxRQMsia/RbDJvp/IzKeNT6AYVzRCYx7Rvc8fbI2PHublLwrOo o44klvDzBIenybs1qQdWilNkr6Qw+6EvxLkCXFvQih9YyRGlsaGxTxxyoNhVxY71MtOOqQBjHZk2 PEHO82FYkCPaOExXUlqjkl4KBDdr0UQgrjlygWfWR1F5ezWMNJaKQSIiVgXnb6A1h9U7Ga05LmIU xR2WLsED4cfpX0ZnO44KSKQQnT6YA8Lz6MF8FEhqZJIb9YxFTf+7n18P2K13ui7Xby/evX39//4H 9MEd0AOCXa+rJYFy3LIzl3G4IvRA9v1VD95SWEYj3bnWZU4F0KcL/n5ElQ8G6SwDx58LdUN6Wxdv i+UwOjk6+kt0GH37/JXq76xYNcWg08GXMAkhbaX2DrfZKwcD6YA9jpLj/JN8XlwntC0n67vJ9JwA eBEiZ+SEGmjFo/Yfh2FSaQacnPKNf1mABzu8aMhN7Geai5+nNYVhF069kPgYEvEKEkkmqi/ofwVv JpNEI2cLXmIadrVE/LZqKLuvMx4OFVmVGzXTqfo/urbREqpXDZmKxugjlwkPNVRvYNA/O57xshoE SK5DqEIEdo3aq60YB+RV3IOsdR7IjKf4MUYwgBaiHb6wEFIKOGqJRVxwzaf2YzjBFr6GQbRhoySk G8qp8wbqoE9y8bin0mU1Vad1oE7zwqlSP+2p0ZKFUx8/htpOHWomgGaU30wzVNgEmajP59VMfa1N 3ZYsUM0WWBAqz+vhdYXeOePCRwPHSQYDKbrGGevYa8knbW0OVNZcxtI8Xpe06cM0Dnc1gg0fm/dE 94znLUJxuIBOZStjrc5/hrARYqPwufB+ZPfrsRc7JKG46L9ippyEfbq+UJyPqnmghQolh1HPtoyC iVwY0hxzBRonPI8tHjHidGNBp3qqSy8zPRhGt16AOTzVvqF2ni2PdbC51NC0FXpvP0L46D4OVw7p GqyXydV0PZl0WndNobcFjtbUkLm9b4wN3Vfj2846aaq4HokFr6dhaKrMOtMgEDESzcB54xArkQxS qrfjuDMUzK2dar2XJt/yrQBrNw3hrQ8SFquZANG/BnAJMD8BafpV4dxadi3e2N5iAftnxPpGKaPB SNpZxE2CY/Q9UkXaArcVEelKFLMFMB66MyGyJXfmmJbzrsplgdQFcpbknIU75vo5yaUMZPfGnmzP 2Rc6wTQficlK4o6j7ZmiRCaf4XFlXTTUn7ebPwZmR1XvNWtUdB9XWEwGT2Shp5DYUzJKslCacGCY FF+1Ifyuo8AkMKfT5fCwwl+nR2dAdnEcksu5digDOZrzJCyK204IWn6oHw9CNYf59++z4u6qL8tp 46879yz86f0WW3PX3IgE3UO6D3H0O99JHnOqexg4aXdjZyxdOMS2M22HuOfc6WMdQG3s9NxB82k4 AYxpggXPrvoTFKETr3L6yK15GTw0k7+azR9RVqMQNcUR+2gvs5auxq0h9Lkz1+bMtMvs4k4tp7+U yzsMvoZ4JAJlN/YmUCRiJIp7psMAGbnCgZIyLF43G+bxVraY1uqo9ZECSUbwz7V+acHUJIsgEwpU 5Wl4jYD4MdWS9aUIa5G21+apjQXv1RnyQLnfvtUcKw6f76GDVdEGJIl0irLjNsZnQwgF9LfpkrAu WswgkLbMI4LULRZKBsl+kX0i+GAXT2Lk2d1oWZBPtGcldq6G9bc5oGDOuphtFde4Lg61xqLccDzn NJpX2/NlcQiNQtQdBXiGtjz7krK8yRPNUUp6m8gdSzclnzsewJ6cFZR+F1HhKDNJ5QAwIDhJhDfS OaHA6/qAwupiao8NeDwvmhloLO19wNzU8KqDv4RACQ84kxB+muN4dGfl/sWSQXwCjHx2uS6griZZ ULQUmx4l4vaKBUnBOZmYAYaP6D2uLMGQZRGfqG8SNM/uVQKfZaxelxKABf3wd4S8LZDkcHrmePKq h57XE8yyeup2+za88dpe0yzb03R3LZmuUTOK264tDNd9Pixvs8B9GNNfoc2CLqViTpxrqRNP3iUz 6F5pAa9jWKGhPByrQxakBF2o47i2/YMDm1At6NQ1S3ib+b3lWUKKcm6L2R754TyWrFc8xJZ3oXSI 6vCE9brZaGbk36taLnBNsDO6rF/vHKyHXr1ehVykNTqpvnAkZsJGwULZ4N3y9X8QABRkVgIPyu2m XL67ej3IUQX+o/qr3JQFmTVMKZs9W+il1yi5SIAJszgo89k4EKOqfglZydW1cdC1DLoAA8kPBn+n 8JnHuickTI1lZI2GJ8vdQoOtW2wCiOi3G3BceqX4P+4PkOEQqUqTng74h1kxmEENZWViP6dVcWMn ZnBAHqbq4kTJaCI0RYJAYievLtAqw9hYG0j2hBDhDFJ1M21UNXwEYdi56oNOFYxNUtJ41D0jPBn0 uME7IJ9m6vuvYIWe674UdT5wRsgCo7ZacoimdUwUv61e/BX0kgprnABdiMjuO8zyxIjOxdV5MYcx qBkiFyQMt29mU8jjAQ7ExTVioGP/2e1wc1mjX5TGYBxFP61+Har//EZurKt/yyNcL8Kd3txUWCtM +mrOgBezCupVDW4QVs/0sSH3aYN7gKtiVloWtFZaApBoojS/LpXwMnmCIOxq2+Jf5tBLs4z7hcis IISWthaUIzA9lG3DJPmJmrWayisl4ZSQtIodaDCRlE1USD6ViJ9fLhYeeJmsVclEsM+m66aYIAaY s5KOO9gEdRGdqz5wBNAJ0wh+nApPJ+Y02zT5aZVkdOnSAiebmXo6ZEjrCZeBwUxXDTIJRcsUW0ms oKJdAjFza/S6VQt4B5AVaBHHkopWyLmUcCTGUZ7ninRoms6X1eytN3VUehwdDSz4MTg0ClUjJz7W JUXvc7X/1IVZt6zbjIdU2BHn+PNxdHjssnHXbW+ptsTS9Adlprq4nszchk+xU2eO6q4cRqiuK1YA ZkTZNLwPRmdt1R1X/1B9DF5qahihzIXYK3XeH3tKr1AFv3VWcOhXIIQvLBGWGttw0WZOZn13J7pw OWdAGm9X59MlaCoV/4bobONEIqdLejBBEoYxU8HDqBRA2UwPAqIV4eXtpMOnh9ExKdzU7hh5kofc tc5qjWh9IRjGX8OHx5+NVL2HqtaHfcF4Xj8eHo+8KHvqPyzJFwMvsMuwdNq+/WzC7OAfqIKpyXYG KLbX5RwT7SHLYdie1qnxyuTHqP066EPsARzFahZ/BUg7RWWM3qUOhIS29GPFDAiAxZw3GoCFzxxi +EqyZt/XS+K2cHbqpH6A2V2rDsNyoe/mdAbB1S7TqKc3E81E5VyArkfxwUSdBazmBZbouuCab5UU b31uloQ0o18dS/hr0IRhz5egu1XlThOcg9/gP/8G//ky8dCyHV+JZZ+CgdpDagIahVE/jJaOCw+U 0KQQOATM+j8jR0mMEvBWvr3Mas5mFAKgB0PL+W9y1oEAqm0N8G+lnirVBMY+qTm/2IJF3iDE0KUx SoiwFeOHeqFS+Em185bBByD7DaPN9C3UNkNsJyRZnUVQ4MffTO8YZrNF49wjRVs05y6d6MOTZnl0 TAtuMtccib9nq4141PLMbZOEeup4UPyatJm7rhkWOGCHUQ0qcoWZiaJkH3sGf0Ez7H3hgLODhxML AYFS3KP2gaLf6mqOsoA2TL9UHYkeJuB1Br9Udz7GZgk//vAYXjRAzGqiTh3uh8dWa/5+8+cvlCjG 6WT7FXXwFEvACHGIugM9u1A79UFJvcf1zm63HZ47Il0gNjMJQTr5NzVl0ANZ7tCrqz3RML3cgj+l wiORqxvrvnn6O3UreVFXijEUkQU/iCjK57JafWLvi+L1WPyhr4nfqTusuCQ6pRvQBSK3oo6h2oNv PcbTtVpDYq6FYgA1qHhbhxi7PmEkkrwXEBojBIIBr4Ew4OYR/lrNGyNSlnO0n/35COb1M/UfmJpq DdN8AmpI9QyjLSS3GUbHETmTTetqC3mfKGYZOjnhoCR1dy2rvJlC8OK6Tqn/V9PbpvylGKsLUIot PzrRGJkwso5v8Z39GD88hG6a9jJWJFD0Vl0cYpAnrlfD6RvIxQaX7iQyTqoHxJFX1epw2szKUvLz FK5fZdNsi+jPX3xhXQ+K2TZt9nCYUKXUpthuFod/TjC+Ho+RpIVXAwqwgC5H+0LQyHRQBLI09KdW /19tDhAFVX/sTBC5wDM7pXp61GCEhgJhHqPbUZQKi/jtMErhuOAMOUOj08j6oRcCObxUVQI1hB1o GjjJnNY7v+APWAnd9QGa7c3o+kqq9YQoj7r6BXwUN5mDqIWSFKQRq85/7ltbKIdlQmtFEwAjdIvs tdDi8nhd1OcV3s7Y0fui2Gh0Un6XZIHLtLGqOd1WfLVao1Q/HicBbwjsLxAQxd7yA8lqui8CE7jg T0wNzKGGegT7HNPYB02XTj/Mw66+BNUJV5QD5d3EqbO/ZzZIG2jI68Tmvdvf3K9pdOyUbeOD92vc 1LW79dKhf9m+ebirD17jTmW7O9C+jPbbJQKjzxUFYqCAehRuoB9PyJ1IxAtxFoc3EDla/O6bSFVb rnbtom7APre2U6c1dVqkGibZqHRJdTvyMpHDDYHTDXDIWq4kKa/viZKJztXa3oFGlbJLMbgqRm7c GdNNniUe2tw21REuZgyY4DnL2EIk4GR4OC0HS2vV4AenfDB66gd9BexnTwx258tT3rUfJQd4BpUB aNRNgZDBt4gBeg6TS136cbUEO/zhoebfWvduU2piCPmymM41jOymVjMNwiLhqRjhg1Kro7IYxK5y NkX4UgBVs32Bq+bVdMnXvecLvs6uQdmovsSuEby0yXOoZCr0/gCI8g1DZQD4sHMVRAMItLAsz03G a/g7cOacGhdlcdrSZEsrB3RFOv+oAijLGOEwUzK6uipg6mmQk9Ia9BGoPbFoOqIJXsmeNrCEbYT2 4j6tABHyEopTFPScIDBiGnpI/DHFa8kCqaBm34smAkxSkKEvhHkSNZ6kNFldFABKn2rxNaOcu9S5 rH0phjKn5Rn4hmAZ9XtXijqYp+jL6NMTrzJUnx0FsND0NQevCoxG3aP8O1U85aVOVQIpjAyBasJO +tHJEkHnELOlCGuIMeeH12hhuKxuULIt3esk0wzNiBdzo9ea52jk+JWZuQYebme77dwq1sh8kwUl FuzEoVyXw9DChBXCHQvkL9IeC+MvzsO+1dGsZtfyfMga+es0OgwUcBfLFPEHwsqAulwL1WQIClHr npBF4aqRRpMUfz2Yp4FuOV8yVmO3snlfmcc5aLo4jD7R1AL+aCYanMVMEhwYX8KdOojmd6vpVTnT DJqAB4v5di1xSPglM/NB+3aAN0ehqhyzZTxf00PaBc60uBy292PaaeGv21zlmR7kSI+yW+g5wIRm I7VHis3m7kWNhmzTbmYVNdEJo5+jXVN0ljJ6Y2DYbApoS3A+YrQcmEzLgoC39NnMMDX8PqqMXvUG 08ig/SbHjE6kMjj44vjPufjyMchIN1X9llQmQ3dVQVTgxBtkqyf0R9JmqMMr43woIKMVkOMboW30 H5xsD8zm3cvKXcfqbjMbZYDr27ekXR/S2u6znFG6UDOJmZgwqw/OKg4M5tGMJxPL3pLsBTfInF3P pJ3b3S+6P2wNyM3J0r+ne2+Qzp4OykTvc+zvc+QHOP7jDernboHj4wYC5yVVwYM66dfbPIjScqib HJoGPZRae4Y5x+mXwdM00L1v4EhgKm043hh239Ak5AZkGXg0QrVWN8x1SK94antxNtQUtHR6+te9 eurfnH7Ag+oe/faCekN6zFPTKdPXNi0Cw3goby8hntx9rnnAPEGenAXpffOepI49FQd/dEhV2JfO oY9q5sVmYLxH+evg0gjN/lMz38Y+i62pjive4UYH6dTggco7GvCWC1lS5vQRO/8enaRB7+ylV/29 u7kXU+vUDO1eZVXLFf5tlGQ5HrsNOcqlVlfGoZrkLo8tpm+Zzbw9I/79Fi9RVKPmem/R+4D2yVuB jwD1aA1zS24K8Jvvr0o6vRwBmLduW4rt3EhoJgIXRMFUGsfBNND4Ex4TtGZOtEBZb1tiO21JCc9P mvG3ffP2UWDe8CTo6+pXqkBRG2HI6a1py60lVJNHkb8qsYy79RsYNhOMbOj3AIkCdejx/GakArWx NJexetrDyNKdgd01RXft1q6jydmpAXnEWz3X2bWb4G3HMnexMzFEzSvtuHiQVlYzY9yLJXUeZL/L KA3d+cNkXhAYZzenErpQAFYZsutD8CKFEs+YFFjo3QZfUAOXxXTOr05HWJBoaEMQl/gcHz+EPY7f jTSTq2vIQs6GKqzoIX4n96M4m+UHXnepL6vihr86JeNd2RiRnRxiR3iX9rYADV9bPT89ydreFu7W DBjQhTIg8VUZ0IVytS12fH8Yve+XD9tf8lR4xnptpT9xHR98hb33MaG8SfMbvR+8W73+XxgkhRMb 52/L5RJ+v6te/1//w5/+1MoqCLhUgE8yAAbvZV2jpGsxqPkMygJYdjHEDXSHSUbGgU0yCljfqIEZ gp7szEwKW2BeQW/TdTn3c+jd5Xo8s6s5pKNK4820eQvFo0fPokcvnn8VPZgj0FY5126B7jz2NvDi h++fPH35cvLq6Q/fPv/u8aunke+3calOYYROoPHkamrmy2X+tqhXxfKTk/x7tTIvqI9pJ7tvNcPo +MNo7eONdTTziiCXNoVui/o1jA6P9/r+yVJtzq/xG/40G9h56pyjiggJZzc6/owRW7yCgMiCK6KT aqvbfCmSZouaB+/WTmJN+qeo3717/f/835RYM52XDaiVUCmggf6ddJsmhzfBW2N8Nf0kM4+bb/Ni 1ptvswXaA/aamfmrLswnkBtDbyPeLITus1hh/mtN+PynaXV7zvPSnduTMtgaxb5JXwtH0WRArycm h7ct8JLSLA2jp6+fv5p8/18H+2QJPejOE6qXA5Co9G8Kvj1EJK2M8VE1zCVX4KQSXTbVYu80olB4 dwrRFHOIPvuKoPUxYzt8CKfK9FodU0AusfZuCPVJfU7DSWxbcbnidZFJTalY7PRhdlmVqpzqhvwk tgur/sq6es2UqQpDAkW6H2EyVNJ3TVdRYmpNgpmDFcUntq0kSlnLd3gVAS1knPg+Nhfc/gyqB+To aZIeMSqwCXAAOlc76HtMgz19S16gePknXRvn8GRynIBCz2JOOXmqQyXCHmKh4oDU44NG0Q7Q4eh5 TdqxuJrFQqgLVOQ/Msaw+D+ChRbi9GBFFTuKs4GXZ/YCIWa2qiwSqwRexBw64L71jXrzbP5NMX37 hJ6lmQvViw9z5Atq1Seaf6RtMQOaJDZ2peTEiwIAgC/AuF6nXA0sM4UWtpsl+7TAvIHo1UodUThl rXxmEKShg7vhdJ3AEEXf7ZemGKXUhnIT9fV6u0nVP60wSPuhCPy1LXjdUCcDrbbq7Rog8VvYYgE5 ADnA4bPF6ig6XJMQQKepbbDdV4rWgx67AkLZQI9JwAr6KrX8NBecnyGN58Wy2ADiPINSkM/6qo1f kVwVV4lfKoo3t5vWt1Eyu5k7ZUUIorMqOnTWF5TVGDXW0k+rOIQJ0zVigmYvlvOGXaONt/xRQE+5 mCMeOxQ/PTpzHGl9nHdb8DhcENDTuKwz14+6cprZmTCQl4v50FSSZYN9CLO9LXcBRHXT43XccoJL 26Vz5H3D6MdVCeIG5JibF6HUkQcRf6E6ecchM+2PwKbwT0rgq24aEHLgmuvVgj6fgKyvGDwFYWwu IUBwBTnXLv02ARaxGT16dF5uzreKr2wYFRF46OG8uFY/H6HNp3n0+efdnn19uAlYDLNJca7VHXlj hpGXukgvnpdKBu74IgesdMCA2/ixyF4q+aJdNJtlxgdQgSyPSipa3xmoFcLrdod2Mcs5kFZUim2f dLY9EPe9yWLesCLkdAPe5ijxmkCDkzOtGQm9PRa3yaU6Foq55RMbvyYE52B/dm7YcyKwFXjaMA7q PT1rPzY4NR/D/0AdqeQ2qAqCQSiatkBeTVYB24TnbkuVsVLmFIKjF6RtWZAJz354lvX3Ivp7ob4r RvG9GvCnM1z144U6mN+j5pO+mvEPtTC7GjeBsoCxCoFyTQQT62TR6EndavKkYs3ZsJUQdUBJA2fV utQJpoEVrYpNguqcBV/hFEGaYFklUF4V9UUxH6gb6Pruagr3jF+xEwn7oudfJKOoTp6MfnpBD774 ibFXVe18czBlP/fKft5Z9pP82C37yXFP2ROv7ElP2U+8sp/0lP3UK/tpT9nPvLKfuWV/I2keM9JA Hm70tSBQAkTAHv/6WzbqhvlGkGwLENMJDGMrpzgElI/xqMgVy0MlowvLgIpY/U070xge9OMoJpDZ QLBp+17c0owDdwQmaIrkL1Bawc1kG1c0G6PvIXDj+CxsHtyuSigxXU503CEfKARZPpaNPH/xtC3h KElqCLsPpgd6AXDlV6rWGQTxZl0Bs/ABgL2d5J8Z6U496/IoFmvgIEWJWqGq/CS+X0V8msNhvr1o 8p8tyDEe4Mdf/MWGMguSQZdgXVU7uaB5YxK+LcrbDVw1MeFtMz4VG3god/5QbivSMtC+ibuNuwkc uvTl+u4TQCbF8KHVHX2c1uC00GiRniVNfphjhwatuWnvKmFlMOXUPdl1yO5Wlvr2ItGW5oQiM00Q o6ZrV/XvUrkfBkEnc/06xwtk2gny7S+ud2pgUsZ4ValtWVJPHkDA1XaFxzkNzDd2WEI5IMfgKUSi AQTD+R3Xe3g7L43qzqcnjYMNz7x1Bl2hifcEhUtRsw9xBSY+cD66AMVI9baGFM5qr6NQybi8qDLh 8tRb+OBrVeAHLm3yIXEpaIJYlTrmAHPJIoY0nPuHVSkI/+GHmmJHX+BAHtcXZiz6Km/ejLqgWN3R G/wnfmwp3kFScoZP9eAk2EpkCVWJnAGcL3Xjv8qCTYKKbQFpAMpfuKyuB0xT6loxob9NZJOYCFl6 YM65yXp7vixnaGZo0qVdaFRGaZsHIgqjNIIeiBuMz4YLDkJOGJdcRZeKClQTRe6tgkScXSLQLEjB H6mtPInPjHLlBSgP5oAnMupHx+Us120oXgcQmkt5hZhZITrTTvxImx5d161EsztxBAFUG4Bdo5nm zJ/z+K92SNGDOv344wd19iXYTmxfMHeGngFJCyJiAB4ggAzB3DDRI54cI+RozZWMK1d3uSaSADn4 ofEXcb8EamfSIdaNPn9T9OgHWR6DyacX0412GVwhsA1Vyc3ConctnKNga62c8xbYrfzbLUtjcLUw 0B51EzcFzyv+hKttE6AYtz4t5NvlkhXxxx4k1XSBYXqU6pBb27NhRH3zpkBtnmqC9292cnU0kmrj T6Ba6O3kqlIzW4FLRUqjHlJnhCLOZwc+YQfaTN3czjgvYtc1rgOhiJLAtyDc+aoUjUSO/7JKq8WX TpHIMAMb/NDYfEyqnIxyonH7sCoBXUcHwkR7HXB/i9WmLp0eTybG/nRZzgki28msXToQM1wBY2yl uj7zHupBUaDhnAaAzrZQYk+RHmf5YkLvBDIKoOhwLe05GpK6GqFTsEgI6BgducCnV0+ThbWxEwZR CeFgAjGN43EPii8ZwNL4u8ffPv328asnX8ea6WKG4M64OkytBKMYiskZcrMas7A7Nk43++Trp0/+ 69MfdMvoo4DV4sXjy7ivG/3Rd2Zg3/e30dtE0DHBja14OIZlih4GgH3CkRpu59rzHsNBG+xVB8S2 1DjM0HEcLkNwrQSHXSI1RvgR1CdDlRX5YTLuINLezq2ksZd66LStHN+HPg0YK9P6WRcuIbx3NYFw YPiTMaNTeag6ORLy9Jn7pdEqxRFndIMbsfRRt10S+qOw3ocAYtqMNjzTS6G+JHbsqgUEzsSSMCaG ekmXLT67NCCZB0aNpQTJzZ0x8HP608bpHT+jDoYoGjnyOPaUwktI/Crs7RPW0NLDOGtHpNxy2k1v Xp2hN9mZZ0PgHOasfoYygPk3jsXd9r06iIBlKz/JAlyADCATfMVV3FxCJOa8Qtgb7UkAdlDso6I+ iWftYZKLvHp6wHrOqef+4duJ8clqEAxBcfKYf6SzOJvHoQR+IgBFDXH9aFNM63l1s0JphWMpoFvo Vw36yPJiVWHW4qoJM8Mgp9wTHNcBxrWIcSsnEY3q0RDhjVY6BQ2MFf5uVxjsDE+ZIZwID1n9B0RV mByF2rQ3GoVydhkwd/VB5sPoLkMwbP8IFm6GYPMYk9iMxlKmGNUo5Kvg+C2sKmcjw9VfLftHyNzM sIYepjxxjy+j4x29bLUdoyYiOol0eje7Ixq335SY0fYgCmDQW/7EnIdTb/ewHt7ayb22dhLgPbD/ du3DjBNNc3bodl+LuYBz9eVtmXRGji0Jd9FWDvIn3zFalZrMnoKd2JyAksfohKv78R1nruNQD6Ou KQ+Yvfv4Tblw93IMezfWe7kj+7w7/ODGM470IlN8ALyLXuyuIZRd1s5r8HuTog36ONRNDfkTu75q 6686F1jTJ+zRlsThUEbWuhPxK339xn6Mj0xP4Cf1ZXzktDhd6j7Db9Nv+MOQUaB9XyjRtMnB0Kba VkFDsLZkK5sjF9Xt25L0RGyX2VKdWsHLLsmMozNWHQTVniCeQRSLp/fkZfhGvX0Cbz2vL5Cm1CV/ MoEC3+KJX3fXwAU6egAP5qX5fBhtrtbq78liOlM3/ju3ulc7Cqs26uJ2wouE+kqT+DVOf5o/zKL0 9Kebw7OHWZyxBuqH7eoHBCcTEMeFxu2rFuBRt0IvOgwPUYcx637Med4wzPpIdXIU0cfYW3TpIh3t SHWJ0murKZGwlrPpGqaCTZ9qdOBTQ58Udd33SWM+UQX5E/p+FI3WdyMc3eiNWIE3UAcVoXidN2+4 QRDwszdvok01MNtCiQ/q8Xa24U8ixuugIJnlHeradXFTEzumMjwk1ElqcNtB1dt6Vw/tiObbmjBL oq/4F7ED1bu51MJ1KrQ36IqlEZV5SoeRrret6iY198Z9rKsAFzL+6RbQNYNKg3+6BXgSx3JLpLqu rFWWbIGyrK7WK6sHAhFh/FNca0G718VrHeMG6CvgflTfEeImfYLR0YdfqvssERvUJ0O3gR50ot6I 3N8o9JtegMmF3bXVv/PtTB0d8mIgfclqAAKH5N7OfLcP14TXPtF+DqOQMRV7jwtpuAHGssDN00Y4 eFXr78KH79xN/uZrqjDD7Gy6Yb+4noqwslNVFDgzYPapT7M+c9m8pf1zlnT/sw5WnE8Ws0qUthic L8y0MTyuQVVVvGYNUt61vUqoLp8jmt+R2t9TcDkGNIQ5xPtXs9m2zrTOnQB9iDKQhKYssG/dnEfm kHVJtueUnVMed07jPoyO+g5aLsxPgqXtWcuF6QGVNfYKPoHsWVHA5Re2DQ5LvSrwKOLZq6plQ2hA zeYRuWrnWLDc4GiF9UL9f4Dpm+t0A2/e0OGmWCifl5E6bWAjAXoJWBJpEdR+FeZGg3FUzrkLJpDB aVjjKhGXVcwYPh+9mV1CiwZiCfRFpl6IvoBTA0pjGkPdQTWDFOO1rWtABwU8BoKp58noPDGpAjo0 xYng2J7fWCMpp+nZ6DkfmJg5t6ERx2iMoscGpZcfwWLAIHBu7LiR6sgz+o30q7UljN/+GzV3zyk3 MHiv89KBo+PVenNH7alB6hp0u5De6LyIppgNASgCkaeVMEQpAyCiBtGHCT6jgoLiONalFRMAyVvT iGNiVsNCXColE1Rqzy4ouQQ8GAg+xVhkexiw+iWyHuOw1auAa1ddXFXXhTqc1suS/MWYMLFWbZO3 doamUG8gmNBpNS9WzRaSWChpNGaZUbjEeQ4ZWt1nMqZ1gUYdHx3to2jivo519/KrtyCGYqsPUT1a ZsGcMoqSyafu6dPXz1++2lNJ46rMcZZND+iH+1LTmHsvRoNXM70umruGYxQQhDRF7xLIlziMzN+K kqaYHTnLAjVQ1pO3xZ12GxVJFb3yyEHSTC3+dHkzVR/ggz2M+/hG/2krZRIfu1+2EDxjEYATO+oe XYG6WtvQmoBZdGK+n3htmufmexfGULQg4nXerwkZybXLVm9s7nwoQU6l2GQyJEIZuiZSnNyAIPhE 3SJX0XatI28Uw90ADvGmhP2nuQX87yVcrPSZoEigXFAKHP6wtNlmdCUrguoTnu5gaATIGmwUOeh2 DVxVsbeqIIxK5hpBdi9OWZ1ARnG8cqN57LKq3pIbEBqJrTCqptn6pEwbthkXczE8KZPofaLu0MPI 2SR0q27tsL6cmNVyrrqdhAzy/E5vHU++x8gPyo8+n/Cek5brcIH2En+F5TiBESM0YVrDcwBe5FRD 6gpBd128p9tpQQlFHXjg/U9wiHaZEXwIYhM5N9LsElhro9H8nMuCTZ9U63yAxTwPzr6bvM5lOfkc IRYQRSjEpVoRDiXghMDJ+ku1LgheYwGZP6AngP4Ig0Y8OKRZ7+PUpHq6KTGfUA1ptwpSWzdZ0DsV LBBuW3GHeU+kpyVPWmHveVugD8TEc6/qci2BjayODth0mJJKiFTSz+YNJfKKXmA137LDhZx7Folh I2o6dtocRjGinM4Eq/UDyuA1Hsn8w/H6ckewx+lA1ex2+qJyQj2GeyrA8MCbiMUww2BagqQUzueY VXS7qa6mCHwCGpA1qiNAOlXiIAocYU6iNrjmF8SWW3udDSf35xqgkViKGyKmaoSYBe0ZAsAJ4JET 8MwhYZNdPuitzu/t9AxeeD2otvWsCCZTo1gwsv6281tP12n7E+pgBogFXfW58pFiKzJp7G6xz4xW 7Ucg7VRdkFNdzZCH45pofC9pJ0/7FtkSgX24jk7eOuM0oBE7VzsyVeMZq//LOicTkXxf4oOU0wK6 HEOxhTs9M6DRYkj+cYyQ+HHYF0bOatkgpGvadDinNOFVlW3pH1mXO0ITGN9kSzFlEWaIYveAUzsY VMs4KiH6LkdF0Fm2N/25zWUtjA1KkcGVM/ZdjkMqUj2LiBQG3XSPAvs5/9LhwVmo+DrHHH8plwVj z3mcta1Fm7YPuEuH6zaX27jHhL/hP6Yd//HHrT3vnxHwpVXWoBwpmJiqjG7n6BMCIRAcqq0+ai7R iLsFiIlyNVtu59pTcl5tcjmUp5DIDiOfRdXIVKLHyyX+MljKG+wcpEpkcEZKbg/UUswpoH3gopeQ 00oUCbW9rgzmfwMm9EYvWMN34oEXO8rfU7ruhR2krslRzWzkLRcq0EFSzIhoHiBPIiluApOhp9os XpJvbgE6IIHhHOsfJ0kW2ymjxRxFT8FVVck5N+AlW5JEpns+xX4P2QMP3hC7Yi2R4YW9cyRmYL++ q2M5GbJ5aJyc0o+zn1aEkNCMD+sGwGbj8PEobcX2/GqfXC7N6+gwpnvm4Q6l/xPsP7TcrHQcGa+q ug4n9EUiR553dQsaXN9hv3S7Y27R7ZWaiT06tKluYc4+pDfOzKv62t1Rt2P1dra46OmQAGfXKBJk 0CdtLVI795Xu3EQUsmPmyDPD5460A+yhO3Rzf74qn+CvdJ2dsk9A4sm+PN/U+V6O9vJSXSRmW3Kl srOT0dROI1h4w8Hy3aSX5BgM1EN8arP+bp1Tdd2zd8QqOrrHl1EWdLSFYHMZ8O16UZM6cSqu1IDg xxdfA2SCXLOl9w0IyeBf3RKT3Vt4+LYHQgroqIInIWuvhFzVuqMLuQ7UcZ4m6wB4AAYGVN70ZOpI 2WIvyY5h7CIYclCLGm6mfHro2EK4LjJaNFYw45OLsAIGXmA8B6FFN8CUt3A7Vny5hLANA2YFoXHi Qw4UqJqmPF/eTewHE/pgQh+kDhrFztLeVehAdoSKoONZgcoUJat/8gmlTDyvrsWWbmfwoTHQP4CJ 7SlCO5NrO25vbf9eoUkxdQ9Bk2eGR50OCr76g7xVXE4a6XKD/qi+sJQ22/PMXhK7tirL/lZJ7LS2 vtu7PUbhWU9nENru7zciOLAE2X5VG217MhaJN2+0Yl9xtTdvBlLsAcUZkjxqZGbVxQrznWHqkc7G w8xfDNYKwKS1T2PRg7h9MHByXwKaUhXyL3mQgUsiz5lO4KbYXudZZh3TIvjSCkZiGCMM2+TqHI8E DYPFZ9UTtgtpOxSmkJbU1m1HCr9SUyJ9LfBiQstOfacyvkKB+6uGDXat/c1l3rAdDac/5RrGydcE JaORQYoB/gpz79CAGy7qvOZZxEA/reWm1hB/JeU/xvyvJA8yN+DjfF3UEA6r3fIoTnudnQ0B4h1v 4gwqoBNo9rdNmiS/cbg+lRtQAm6bMQOeBXRMrsc4DFzQJ549H0KY+jBdlm8LQUC8C96gGRiMfYNe +mMik5SVmjfzTBuETSVE5YZ62oQH4/rdKI+FSWn0t1hiOIP3INJbQSYLPN3zc/TMXRKkl1PdH0WO t//+lEiNGza5xD9dUvwHTodAYZLkEABKQPbN8MjTJ0p1RGzrBnX7rDv16Zn87XWsMxvfLTfh2EzR sIVshVOrXO3kVHpcanLzRhwUvESUbddz++VvCON5GVDbcbZTjnzRa2xmlD/KQguAaU31GtTblUAH Cl64tsQIYuNJGUfPAU1FTnVh0jnQTOl9leKUoyMK2fwN+HBLLUEmuiy62jbGaUStyJs36Pe8Xa2K WrjncXWk0vEHOY2ovG5TSRb1duX4eG0qNUVsVgAVjYjsh/kYEi8rQH0A7AOGbY9Zqj1n12pd25sO SuAgfyRY7peN7iGTjNO2CCmipfFupwd2IHpmIbXxTYHZvjjyGFszNwA9negchV2wgrGqB6sxa+bp qPVzO8k0hnH7U7lSLcKj50iVIuPmCpRGYGamUTp0qO6ns6s5FGjfUYEq2TNLm+hWxnePUCTfvBHg oEA6Leag6kCFZxPF1GJMfGIqLCwodCKTUH0037fqjhDqfcijJZNklzXLrraecp1ajnd16ySj3pFi kzXJMz6MDS3QNATERTuFI8w3T9kq2DeYwfXqi+2VVjYqapW10IhG3bY5/xBtDaJT96L1JR6BL7WF R65+9DA6XZ8Fby+WiNKPl23i8o6Zj8PE5K7oaXJ4yCcFuA4nZ7DE5epQg+LYwYGohEcHJsrVc8Df QqwZHhp4I3XEn96pDFAqcUzLi0Rv31h9rlo+oGo4tsQpZlzpVo3mAo6vK7nYIcsLiGh2esGT7Gt2 YNh4buPoU2YmwbGhiyNXzMa9ZsG9uM40EYmVj82CHcKKxXqhW7bD01s0GYoERsXMxjDqWBooYhYx zlqEx0kkHNOt6M0eWrY20bk05vISOUP/LtSRc2PGe1adqu1zdzeToCP5orwuKAGBAGzYkEMr8Y/G 6HPN4b3S/jKosju/MxFsVuhCn/VH7I6OFQQdIkN3VOaO3XwRFD/eJTg84YGbCGdaTdkGgiSaRZQi hlE+9Aw1vrUnRCQ8mdaiFeLYjz9wiwmZlASNJ7QhRi0Lbwtc+VZrPbKQiXCm47HMSeB5jYQgfyW4 h/UfZCcA8qymp3EGkR+i8xoAnRt9opEofeu5nGY8f3DTau+VZsz/7unv5AVwqrFRALgvxxu3kxli SvRlPqBVoE92xOOy+4mNDpHi492aNcA3wMMpjFRR5nk1refkKVVv12IHRmqXLeeON9qB2oezKTgm lxBorE5woMJaGhRNRZxUWDMWuWHZnKzm5cRk9pFLuqom3MHJbFMvZ77WVEPN8HBbbFyPamI607Zn Ux1ThhtoTg+Pz9S9agY4pjl6Oave/Veu57muJkDWOI2tgulOj5+Au+Y+54cOhWkHfrFdTB4ldAGg o6Qpr8rltBZSKDt8AZO7Ad2q6+KZZsaHP/dNIHKtHDtFHPIA8iwZ1hm6uoHrRHlV5PAf8YZDx0hf V1b5y838CT1Ke3T7QZdos9NaMqM3yyG36JcIIPz0Vp170yYK+D30b03LY4oc2pB6FtFKIL+lHRID euQERKK+CMAs7tuLT4ROfQWcwC0swB15AXJIEL7xWgRTFkfRkd+IA3ouSkB0HJVQvxz4adi7Jp4x tUyrG/fQg/DGfjoPOr8U9HWoKM7Rk/nuf716K7sz9tqmNt8BER0hGMBGNK7TQw6TwNSeKxO1qOUQ AXKOzNTxHRcaLFcAM/PapZhANxaDdI+GjwnGC0DMgrsVHLuu7xTe3kEC3t6rlmbMmybuyKkP2wLP Xb2YedwyutG3DkL64aFuNgSVfoAbKUpj9JSBUqDAbDaNBkPAQWXZjjTb7VMaOaKGJLZ9GDM0jbC3 qf9DfW9i++k2Z/pIUTi6WFcPNRWox15IJQlUPTdgTT9kxKMLgadgJ3EAJPeVpk4tJDctY8DqunpL oqyp7ryqNmqVGD4N9RdqMV3TleXpxg7Q8gy2Xyi+5LgEO5FQbD83fiIT1iZQAgRC27OtqDZC1/Md hjUx7OcL4W/AkuIbdNpHd3Ul2m3ZB/uyuNOC+3nhhxNpb3e6JmmXJ53topjbIEfXGfq9d7ifoapj PYz5w5uRieKWkFKSCYwYgYzxkXrLG7y6JUrEgxP/xom7xaHOKz0+RUOX0+XiEIFuIq8zBxGl9OBQ jW0DNSP6KIwQLqdKIAHfDms+QnDEolYyLzCQ1Z2oC3z+oxQTANyACEdHHtEoLJKSWGkVphhSOkRG VNxOr9YSXLbbE1zPFM+/6FVr5/I4Q3sXRJ77bV8x+G5TGVtJtP2jc6sFyV/AcDmGP2lUHqL1b7ps Kha05e3WvzfirryvAS71FD16vueVuJD+wQtldPW4QkZ/DboB8DAYC+NJp6XV2JjYLIF/Gw9xb8lY b72xCmHUW7MLhKO01gSRNGKKjEaOxQ26RQDREweS2ienc85xTF/iVILNQeuZMFdJrxKbdfbs09wq qudt1PJxdSYF+0Cc0tOZgIGKLEnnWk3ZGTWlFYPS6NK0lNIyS2/AHldSJGyu4fHMCLo8zp25ZKeF o2EUP+BmEGoK0ZsAARana/TT6kHzEymztQgQkHZ109aMQmbVFrU2LrmGWYprdbV6baMbaNkd/pvT p9tHyQf2MdSq+sAUaNefGlDPuvxCuSBbFU6pgjN3fkUlLksgzgEca5yq2wt1rdw4GU3bvEFHqnnG ayDKN2+o6rZ9i9fAFqA1wMknE5ll2dYcY81TdLqS/tUV5dz1ce1ecieG+rvTYLXD2MVTAaIb1d7l IeVbvPZR5gadUtoN6FUbRf90WVDmoIrOuBv2l/Z82HDSZWNeJNfyznVopSMIJBk0q/S7tL0F7cmv /YFFIz9Wh2lbx5P8Ngj5rgojHVzuHKWmmYO2nkd8pmcBgmgOYj/0Wh/pO51rwBRsFlUqjuaF2Lno 06S97VwnGo2TrkpIZC8koMn5Hc4Sb1XazyFXxx63KBP86fFFUbC1PUGsbIppDegXfTtcerm4QzcQ fhjQjDez8NlLYwKTQLidHg9BycwCWyF8TGPvwNyEM9ZBt56jC/Uxn1wVV5XJFtVGoaUP8n4cWiOm YWEHNrfQ1jl1H+TrCiNMkaaK9Bjuwj/H62wr9UrLvxUFXL8U3EwwXHdbs7+kCzsSiBLnEJkX//zq 6++/e/H41deipX+utnCZOZ+egwJ/quphhBDH0kVCejHtEnqK1TVlF1Q/yrpa+aj56vFpYttPzmzm yaZYUyyc2uCArw7u78Po1GUDmB0Z9fE38zQDNd3qGtXEslJMmnwmFBhvb04TVRBbU/+2Dl4/9Y1e wn7QTWMYHLsrPXYW3NHv6asWNxDyPdEKOvJd1meL9AzAYq5PSos2mum13r8MuCVVGBpZzPE2oJva fRR9vvYuNeMSmrreUfOTkJKOXwlz23EopDSm4cn465OucmrMshwjb7N5YxQrsokSKq172i7Npg0o jX63jrtvJj5YHOMBBPmNc+IOUPwYkMZvYi9e9c+iW4uT0HcnO79rGSe6rR84Hp32CU9Gh+o1VS+O DUUvToYBo0DVFJDIbpw6aXo+Mml6PK0jW0ORw91MnYwAQXPB4jjHNryeL05aj3vmun7Pua7vNdeE aKc6XCvWmGZkOGDoPz+xHBQ86S34gbNB+3G+vVoz+iDxJmNV6SmJbMtaV1pyjrSpEKAgGkqGbSOI ZQCieuIDjDy4WPdl/ZTxz4T+GIC7NyHPvDuhIGUkHS/WrdygnMvz6crk8vQicKAShmQGbSIpydUp +KAxVmklh2iqQISZxXooQd0hGQQpn2AntWOMKJwI7uBQWYwbxyZuGjYzJTRvsjhgDke0KMo6ikwd S8KBjr6kU32Fgtr8RfNbaWVoHkKY96p6N/VtUZDwiz0nqWeB84qv3twhPo6cBsG0KXBS7nPs7Dp1 8HDxRsddDYxlMjMu4XjGtoejs33PopjLxMNdRrD79C0+nMW2+ZCt3p7k+zp76cszxirZz0mAIOE9 JEbABVb7uzhgbAFzA7qv470CS5o6aLUJpO9wra6jjpcTWRVz1dR8Tl7Jyzvh6WpNWG8s0N4aJZU7 z1GW3Ci0HFuKiA80eBL+XzEXkq4itUV5q+0aNtn8YUyRXoW6GFfi0kNq7WU521hLCOc5otrn2tiq k30ChxLezr3d/WBJqxVZRN5NeuATCDmjIY/lWN1DG/B9xiRV11UFketjISZlvnVHGjrHD5oEUn4P I3CYRUOgYVEd9tMDjVMKDpSrhdoCAOCi46ZuM69k2wJ64JpAD1q+SAdeZ20z4zwZtjoqwOFuPUBt /crNbnRLmY2cPL0aULFlmaU+rBPj1gU5Zf0uOHYz96holfVZycd+dPN6erOaOA4DhBMBATMAUzqB 4xjkuOOj/KibbdAeXtM3/s0TqKzhGybdBlFpWl5cbizfUbTeoF1s7SjpAmhCZvM0XpQHN88OYcZ0 1Klb13TpSfoUexlzbRL+ji7aSjKNGHAFAHjUfA3DiyEkVyUVw3dKBnC2A2eESanmoemRXoWwdhcX DQTt1iK5f/rrbFULe66uvUd2r2/vtAe5EBc3Lo1k261qylapp10dc5/kRy74oJPYO2kl9k4yJKPk 80+RQ+i7hOJyoIcqfH2NkyQTKjv8/NPovCSgrma7Jjg1twetVKLqsqMkqjhY8y1l79EDNmh8oFoB 1LMStSTqEKBK/vZRd1vSdSRe1EVx3szj7MNaNdVYS2l1gfr34M0XKCjHSzLdclz4HVr8sSERQaNc 65j/3cfYyUXpUuI1kjPNYsJbScQtMyiUNpkq1fVMCexzdAPruTHwt+DIRV8YEKOOi8BXRcdFQONJ Pv/u1dMfvnv8DSzCIVwBD6likuUgJGmGrhe049GMhjwhnLMCHQ2bKcD1rRHxPBva9I86w0BH+ksf a5ZaLCvjwPiquN08/15G83v58do3sJMeQGxOWo+BX8bclVLQDHiYm6TteWjiTLwjWUgIDx6NjmG+ sjOv2PXUGNL0yEHphwEiaRaemlyvj0yn55ZoiuKtfEtDUi1dQz5u6/vnk6dEo6dvMg/vnyfYWV7+ wiBmP1sWtyVcj4y2HZTcasY8MGxE7VFSfAkoj+yKyUja0VIdV4QtzlHScDwzyjiHYvA50JhacUkp owGYzfCEtytGi6UzvKrqyhqcRMul1ihroKlhVOZFDujc0GWpxzAWwz5Q5ciHtefMIivOvbiSnpHN JgRdKMwm6m6jZIxICdsXJUU/qj4FLmYWcM02513fe/eJKyDS61D+S94/LSQ7TRf99bkfdVVNPwxw m5tqQadWwjIC+VZS6aRWdFFd9fCEJ5gxkBYFnRg1QBqRmCdN6FsmEa1HUJTWGWBWFe0iND7XNRA6 tDXok8iRKqKQpIgwvvA+CVE6zI0QZRehveazaT1vOsREM1dGyHO3Z6ey6aStjJLpd4LqqJLGCrLF Lfji8lzDNQIh/fqzblK+uPko0nkp8Ztsz0yS4XyQ7XRj2MEHtesFQhMPJxdlhJD+BkwplPGWCGWx 8objenVobg8Yua4JUc+wTofgkY8o1F5pu9BdFr9yaBrw8k52JNCgcWBOIfae1ivGasRVx7JJgR7r Pi0fHo9EKN99p51b6timPfvzJVl5TX4JmAdzmhAc4PtuUayGo1dWQuFT+AuCLqqsUMEB6i+dRJhK ZGgcD1p1x6Au6USJFKazOjR/1wW5PuAOQcxBLx6vY9PjgXFZ3YDT6DH6hJ+0xG1fcWyLsvo4pAPf l5sYMUJQiCCPlVopojwXV1XISk6M3F5ZV/u416rCOdXzOI7QJ8gpQiCJ1PE2wYses9QXyFLssUD9 TQe2KqxPXNxOZ0wvo/diewZ5Xu9c3Wovy6XG+ZN9GqYPYJqUWGQ+0G3ds7ddmYoZ+NhdrO7EOdQn Lr3PIIKU4NBRcMiwL/cZsqVeHaNgCt83c3FdXCGUx3ZlDsUHqKgp2ByJlyxcZtWRd/Xr//FPf/qT dimmm++75vX//j//6U9wrWF1AO4SG67WVk4xFr/jCArcDVgL+7DXxUD/pNbsXwP0z9GduKpWb4u7 NTJCLiIeiRw62NlnlNnDXgzob87OG+qnOkEKmYQMtU9YtoXcDSwW31olHEc7Cz9uR48v1fKswt8p zbeCckN+WF4iD2Bq5h39SQF/tISxOA9FzhNX0wm63mPvHpvOMdQKbuaZPqtDukh0SIMd7cb4GUmE 2gCzCp6vfAcC3/kN5WhAm8XWsWrgxi82nA1A60sTGlFiHYzNOYyHrmeF1HmNNG7ddlW+2xaH66I+ RLU+qBzZBmFG4+qjV6jMu9hOlYS/Kci0o1YcqwtLUAfqTFxWF/lkui5vpvUqjb88zo9BlYeDoKQr re7HXT6sGxMNkmnoO7lkaG4QSIBiZS0WuTZujIFJdWADNttzu6DsI2b2gr/gIqCtFOibSnx580Y3 9ubNUDtJIoCzdJ2idQCAgOmcY17pM+EkAiaY6AK7Bxt0SncZvDtREF6R76XQdqbQB8fXnW0jrutv WBOuJ7Mv+PsepiWzNi3+jaalI2tXstpwVeVbo6tG4NUAG1DXH6QBRW/rLlREvpA4EX/hBN1dBOBG GXfpD0m40834qsO+5NX+GjJnYx7aqpEX1ATftQMCbX2um5F+ERTADAnM4PKedshAphTllwnE/Hqk tM8pDsWBAloUBRdJ/TLQFEb4j/G6CT/T4LjgTVfacuBRyAwOxYZdGU9o7BMg3q4VLzzcrjtqadN9 hleVcMAzUTrCVVELpFdiCOfDanFINlPod3YPObBd8aCjiOasdAjuTT7d+1v3Pdnt+NjzP80D+N8s kLFDdG0juRYlC95cpoGPmFFAJJkur9jFJgvt4Y2T64lABdtKdK6RSsQ6ta+lQiOQSf9s9rFFkqVz SklpwNc4ozV96tpuBuypICtg/1gUAlIQbQ+Oj46PstxJ5MqyI0JrsuHbYVs8XH6fm+YHgmOlAnF4 CDgS+KudPQvvooODCO6ZNwDYAfmClZRxrsSezd2AZdWvIToXd6srvLp5ka2TvSMYypPb/ZygmzYb 0PWVm8hgKqL8SEGZnlYc4zSu1ksG+TUnrDblkzaDLWlQ2SX3HEUhrGp6rUQ6clDatEMG4cyiIEMl jSGqiQ2uBZY5Z6UzS3868MJJ1mfQGp38B3p1kf7FvYDXbdOaXAfnU0cTYtKw7VpDNZ6q7QOg42pL cHIgzhSinjecaF2HMCQT6iZPCcDmD1FrBb6OFDDkf0rToz61ojh8JrIRtmpopblOm1m1LsYJT0qS Ud5rZ8a87NkyBtWjmBbIHYP2E2KlM9EGbMHJmedOQldWbiyzIym3asdYvjpvGkTFA9a2zC6FRAmB OUD5bhCiFfOJHc9sQhA866Idku/A8f03eUHIwK8jnVEP6MHXUrYg0Wl3Nr0UkwiPCs/cl7nqYRqf /vRPZ3CJmMQc94KFvn38+h8ffwN4IUcDAWWEBaIv+fXIz2kJ/5yO6CVpx27b2TH5LhG6QUhSuB28 27z+P4TagIyfQDnqgDHOiu+2r99+hmqEwbNyxRhGV8W8BB5WgPlxM+V8J4QtBrYLzrkL+dM4LOyy rrYXlxHrHKPHL1/lA+RjzFHqYr2Ey3C1nJumMVODuoZu8IKZD/D2rRH37xr9c9psBl1aCDMmfY5s N+Wyo4g6ek3Tuvjfqb+PdRk8ONQ+6XNw+FkxVe3dcBC9VOfa5WazHj16dL69aPKf0b0yr+qLR2XT bIvjT//yBRadKEZdow9V/PeqWn4PR3v893JFP36EdNz085vp1fl8Cr+eL57e4qOvSvA58SSWGFLF g0EdSjDWb1XzF/9cFktw7IyhwLQu8Kea5nYtPxRrcASPv9tewT8vN/iXuQTgs+05eZxiOUV34b7A 21eAYsh35kmzudrQiJ/xjv+qWGBPQDfEv4n54SgRDgxbVxzuYtVu5fH2Qr+K4heg4oMfzyrs8j+B gpemDf9Ui4X1g6miXdWr+o4wg7DX9d0zckjn1gGGCWpCKrG/ninCalf19LaY4RpgWkz4pRYBu/RC DROXGRSltBqUAlbPENDEBNiLTrZ6wYfRFDgxcQuZHJGISEzvvT7G9cisgqtsJqoo1plCPW2JCTnf ZIK6vMnE9IBabVUE9e9fke3+wF4V9uyXsChTDN4U/cLXdXafTgVrgfLqZDdC6OSl2vs1qpLhNf81 6LksH0QvyMf6JI8UkSPQSzTfXl3dsWsDZDC1TWfsdkwpdJXohcIFHUhUXnchpbMqG5GTqNaxPlMy HsgeBgPLntnYK7bHkQHEsECQJIFN9+k81Ywupyvk/+M4buk+0Wt/zK7wM/Ry811VRA3kEqX/Ymna dCc1wA81BeDjuTEBdbkT4H1V6ZXAWFcn0PxazSo4fIzVtCtm/Nw65KdYa9a+XvAnOf6bqsqdiwXP rC2+oAetQZ8enwVuLFw65X8zLQmIsbVoMo1Te6hRWnoS0W8gnBxyeU0xoSoAe8Lmjlv32BhtHwZG UJ/l6EkELi2QuZ7gAqF6JTS93F5cALhgBVnUA/XBJWQLNxo69mGbscx/XqgukBqRX1YIZhgdHtLf Y7Xe5SqDm6cOD6wWC4LrmrANGlZG5isCW1eNLMvPD0SPrcfJsxpDj9VKgKUS36bHmSMFWfoKtpuZ C7FeK90Ll3BBrMhBEpgiW9Jv0kISOBMhQvoCXB3uD00ZjLNFeR5HriHV3RnslpVAEjW33OnRWfQQ HHyjv/5VO+dihUPp/yf7DZWQ0ob9gEiHdbshf9+RrkV39ujMhL07u9+QLnlCCaQwV3QamSQi0o2R 2oN/To8/ZzOxsVrcKukO8IVAeJlcTeHC+CvdXdUe/3u5+b6OFFX+Kx+7/PB1hU//xX36GJKwRPF/ Ek+/eXlZLjbw9K9/FY9/MI+//FI8fjzHCh6KR0r2gUeH4tG3ABqpnn0snn1VXsOjR+LRs2VV1fq5 fPFtha08EI+evoMn47F49F21oacfyaff0FicJ0/xkSz1DzQ05wmW+lKWelHd4DDkOJ438KhsnEeq K/QUuIZ8s8LHK7fX9JQSyMSD3waDLci2raXlSqHcA6e51TUQkHr1b87zH/VKuE/1kqmn0BYfiS3+ Ty3Oi38kfm9PSFMIDsOIpCl1Wb1YFtMrYGWL7VKdjKq2C+KoxAQw6Kfv5CTu4h2Ymn/hv04yj6Iu ZxM6gzhZlCuwHIBQsAS9FZ0DBg4MfVmmoPadlZCSHZC14Eo2tUZN3rl9UpV7sD41DJ7KeVlVjXcI nAsAVGFOzR0gopyvw05FDvfLdFZl90T0JO8jLfb4X0v+J9pC6z51IqhQFR8Oda4PxwGjT6B0J/Bb BH1IT6HQ2T7Tp24GEEIX7zGNcvbUJ5PfefqEpnTo+e601PlUj3sApPFsSnQJKidGWkLh2okh1WN3 c1aomSjGMRBF3BbWzSdcOP6ruPzrTYzLp/geViUaxK01AcK2km1AQYyTS9sQCuScldmrhpfXQJ6I ekAiA/pgUI78vJrfBVBeeKfTTcOt/DuLpuKhqAQI1JpSJQdxzaGkoigXNnMspJtCK4nlTjrFMmJo reh1gx5tKChe4M1WPUBhAXFSyvlQ4sa1qNoHgGoRM7axgx300/KB8eRTlLC9YswfRX3BdhxiBnUc PmcZE+RWDKyxnVG7fVNvixTLZUE7qp4In130cBRvtVk7Y2N2ZcD4slhQ+umrdQ6/nRcTp3Z84tIE 0QK8cJ2Aq/UQPdcm1RqW+pdynWIL1bqhHuRoFUF5zHcpxe+chvFJqGFuwuUu1XrS3F2dI2aYlPlO q7VVDpz18PMYo9K01NqeB9PA/uY9f0wdycfjCZ6cIABMcGFUN8QjjBfETtku7OT8/h55n7NzGHkd GwtauIeR0x/LWKzshx0wnXMbHCr7fwQ2IvdltK+/OHVzX/j5wLejwe5Wdm3F3h0zkPwIr5gTkFJo /xWa+bZz5BL4d+sDQXqyF06TgZT0AT9/d9PV7aCLPVgbKbm1y5P6o5K8TS0qKmqEHozK5MCfQIj6 vg5eapt2xjfkJORwznWQrmPUxUj845M4FlfTKU4ar89OgqbpxIrHNMJdJMR2H5oNGEMMJxH/B//u uNjHaRw9pAMIr/eynxBnHWfxe6wZWyF40fDeJtZsPQWvP1SH6BvdKf7Kw+ybJ9Tn0PQwtAK6Mm8d 3JHrXiCrbTfQK5SIbyU/L1Bdn2V9jlP7MWD4MXaHuK80swfTvMfmA7uS3nvlqvLFij2lB/w0d2UI PB3c7+lRdwX4XiiGgyIAFQ1Tkk/7WgrIOsSA+8kArRFlg/c//ltn//vIxn/wed866+UC/rvQK5gm tRCsfsob1XY1cxcXnrhUBp8gbqcD8DHpPjXw71/lmlJyzhFW/pushXFPW4eOeoUQbtB0O6uC1zzG 3QQ3iJM9uR0uqV4PjfknIPpAtXyGyNGAgratyF81p7o8oATaLoWqZTAdnYzhYxa5dQWh7A7+nAc/ dnj1Ph6XHUM0V4BVqk68YfZ7jlZ/t/8QvefujYszlxly4b/fl2T4c62c8IhHv4XU4b/bXHKlE6En aMYP+DPRYrZ7br2q3pOkwrX8XrT19mbexPtsig/bFXtuC/jfYD/KlvcJ7QwAJDeMEmAJwKcSUutl 70l8SMC6rmzwXrxov515fx70ofynZ/YImOz3mLtQpqy9yfC9Z+79p26PuYMB0TvE0BhDfDdDEPj1 dgn1ip+kWpxrn/huAy0UL6c5GvkOCQ6aMO1RKqA/Tl77+GN33B8oVNlbWAwpDX59AFMAv36TN771 HsaPznuVKo3RkAET8L5iHRhL2BlQAoR7Km05FlLAcjQ8aZ/hAmyfa6V03F5b0Xejk+UfH7qw1i7w XjpqroDCkT2h1/gO6dReGwdkgzVhUhpUBfLZ5pYUJN9U03nW3V3XJoB1exPn3ZnoWVBIhXY9caO1 f3NmFKG6sYJQF7x9iUYXzXD0Nx+4Nz9IoYr3eWdmgrrQvpApslR8O707Z0cZXZaUP6uimDccvHg1 XV0si/nfupSiZkocf9TJhNK22reKc4t3HTE4LaWnuyr6APRXx9zOwceeXUUIjbwtMe2p8jaObvoQ /MBFQWMsTeUExoBEBuoy0cjDyM5Xzyx00KasPSAu32PcvwchfvCR0trL9ljJ6WTBjR0+Tu4bSPV7 VbMfmzmICOCH7Z9IDiWn552uRFqvLlNoxz5A6p+Xsw1S/6+/hU4lcTn5nXgZdHtiokL+QKLxG/KN p+57YUQN2G2csq0Da72nl8Y+Ys8fLdTwsY1uB/rMbpragewrGk8XiU+Cpyp8iviinTuRnemY67Tq bkVNB2ZfNJ/tczAitwiHRfzuRsDQnIv+Bia+vFjZiVd/iCGhfOJOPT3qmHv19Q6ZJs9zpDHrZ9kx +3xsoY8ZyLpt24IR2NIeRgcumqtqLPuW07Pub2bVclItFk2xcb+zz0U3i5sJFeLO8oTyh4ALW2ya Icd8ur3Z1Y/u/oR6EnCVMn0762WRQWepFiUHnKTajFFSxx+s9JZNDd5dv/6f/vSnP63v8glGpDXX q229fHfz+pe/UBwW5xmaQ+gA5x3fnjOUrIxZw2C4uU7zBkGS9Wq6HGhU3ERVnOQMcsy5UaflFQqb CLeKUaWqUHScf4J3rcvy4rKoB+BtfoX4xwhOhc5VgGJ0UyyXHIo6rZdlUUfcqcaN3aoaTLAw5PjS uvCjt9Z3Ov6KElQxnLt+SfOiixD8S/id6vzNDKIF1Y9QuXw2nV0WYCiXAV/zWdVsHs+gySfwfhg9 BudO/D0YfPX07z/+w5gvbORN+vJ69YQm9QVEbpvGcvUCnvx9asITAKNB91B4YhLkKLig12oRsGlY hnRdKZoHxFvAKNgUmVhp9pJWJUpGWLcOp5NlUxfXODi1Q0JjUiLqrWocvhsfn/w505+tKvGhHbZT /OjoaKgE6FvMJDZvxp8D/LL0dIXNqvbUshnyAqo6GXV9ut1cjj0lGexGsPZRoKX4vAskkiqFAr60 cE1n+qWSE65dBdYWU6/hO/jtyw7mZbPBxNG2c2YxEUzifDqfXU7rJnVzoMkaaoKjTB4lbdBVUc4H Er5GT4pr9zF32+mxuMTLSQfJqA2VC2EFpv5xdHgcVAgkxGPSB3WW6ETa/kQE/Dv9j4cRV5DKGoam B5JIYGsqVqGeSmDvQALeiJJHQFJLZEbMvhQpoQoyUuJrVN2sItUFhreBIxxSuctEpGIaWmEjLeQT 6BskG0xFn3ZkJQcDYHIIceS6nTN1hwR0wbStz93dmDtP+Pr3myUHHhQ7Dl8QVIeq/6yVPD5RInVs CGNSNLPpukgh/VvmJG91k1UtdVy+OwFLrTv2a8WcNHOgpEzezxblrUbmQg1fYfLBUCaZRPFNk2Aa Y74ERiLCVwnI+6XDUpCVBxPgwGzCp5xY3oOzJ/xus3xqzqA8bNK0A/keAL6dNXW+0Su715JGCeSS UYvlZHBGhH7Lq9Sk0WRhUgX1trUTkLN0epBBfQ/HkAxMfW7KI2yKekVwPjJdk0PRPDYgaMenmx+H htuRTUondHNq9CQxCNx3i+UBLVt/SB5PDIRr1TVgRyjqfAbRkE8BU6NJMsjodXgcVXWvgNv6fLqE HFcMfmWqybouQ2ooBXQ9f/r09fOXr4iXD7q1cl3EhfnF3oO0RJ6fdbkmWAkYAOYz2qh//vulOZO+ TVKcl5Ky7c8PaRdDHwpe5J2nTqPMCOVhJ2tBWWoyL5YgOd1xP7CQrY8PeDs9lEqka/AaacdLXybl ttw0SKncoD2Su2SEhZgZjKpI6iSMJKYoBMpCWmqgaJMZiAAC4dvcP2nhoTbKpJhFLq5/jIdZ6Kok IYLxO7bn2AwWqE/lABEzawwwgVHGiPGFiLXHkMQL6Xm64f4LDEHsvzkq3l80sLsr0W3pkywd3EPH GSSfYZRlu0Wuvr4c1uB79l49UlMw7OmbpJ95ic/2SdBlQjkdMEG6py4cQCh8Bue0yK8VMeYsgggS 0WExkc8rBCYokyWQXI9Bs/SoWDtiAPi1LLPor9GnIQq1TPn5d//4+BsecYxAM8zL1PW9lJlIMByM a1VC96fda4hCiT97e66/uiYZdMNxkmQdlTHkgNpC5eIOs7wXm8tq3kQpXfOuts0GjEvlCoeBmKEC lxKgf/ZZZILmif5TeLVpUU1CV7FomC18GiVXzUViPKEMNigg1hUbA/NablTvmwbzdYdWncpMVF1q +amblBkXaleLhsMB9Mr1nZLNzwW+kEwGgyORubrtxIZKCRE+wQbA3HV4lQxFd/x8k97RICrTGytr HXS2kEyzvdYHC6nnFDtvLsaJel6q+Q6N1OfzUAVtKcDvwkponZCxQpwazThUnHucXhs/dNuJGpV2 gukJTwjuK11HrC9whH9eXl1R5kA/w7kvRRMDhMEcXiH7s/9RjDBVvd+hnWwxvsxjhtRDmRgruJhU TC6kzXFYCF8HuWAxvZl30KbPT1GhvAHF3b4LF3WsHHXlQ9aN+eGHrBpgyZlVOzxUYuescFevf+Vg bX+35cOHgV3YWdhZX0QSpSlRvG98zPuRXuy3Iams4okksNSCjaaYst7+vakpdBObygjJeY9tK+Wd /8ZLXV8521PvzMDq3XedLFL2LUiOepNVnsBNtx/U9UJgKId5Wq5qbqT4oYYng1mi7C/ruqwQQRG8 9UgxUTZDK236WRYsqJwxJgePLm7Px7nl/nerZNIA3QdsSB3lufqhm+FxN314Ki9mJKjjO/OzOHYT A68DaZ5Sk3kcD9ph+wCkzvqQ6HtJJwbPegrJGrF/hyyT4LTTBT1K1f5UNU/BHjht3BHjdsxywMq+ q7aEqLC4U89bQksC0K+At5f4sOokFpH+HxLEKD6ngcmnnmwcFnD+fTg3Hy490hCh9UqJi+SgI9fT HRMI8fkIIPJNqhov6qbwAc55rLfdCM5unFwX+IAd8nffP/3ulRUyLqc0V3CrQLkXjWVeDsNbkN7p k1bX4GPdPY3n3qXXgdmBe73szauvnv+Q3uKFXqzLS3oakvlvBatgYVt3Tu275aaS3+l7ARTh0t4N aBgdZ6dHZ06qUlpFDyn57dxDYG970NGnGotZNyhw7n01zxiNBtrmFpLXOi6uMW9k1su6rIya7TCg u2ULkRzSIMR3fHnrFetSVXfyOkdr2XmeidVbENZgeJZbaOWaOyIp6Ose6vwX7VufUI7V1Rp2atDx ti4aqeHWlpqEP0oklKkDL9ucjg6Pz0ANA0YwmzKCU+YN3PbRPtLSsHU3DeV90CsKQO4GxcJkxzpF nOVCBJh1PDprAbNZjeYL1SQAVwK8pkxBJYQN1CV34/Crs+a5KhFRrkGgXG1UP+QkF/M2ZpC9GqNW hCfDiDqOWwmFUBTv0KgIxfMJTBLgwerX4otzg3mjqdlhz+TYAd/ADMnq2+wPmctY1diZHAy+HfSz YxafLVG0+t49tQ2A74J3WUW9OcR+20OUzdXwGg3Mfn4s8D6fW4zzXe7AQZpcNnjXv06CXr97mCX2 M03wnEvzAqQJQ6EFM5mx/4A+ybWhocezN7gUQ2oiCyeYEs3HT0+O1P/+Mor/6JbIjmKSxv3hI0ug KRBNgG6m1r/iLsk+Gv+R7f64Qhh2yAy5LlZ/XGvL6gaInlulU4EkIchWWMzv0/LjJ0+evuxv2f8E Nf2BsrtYeYDfnZ61ElQuGycJXDhBZdOdkw1ZyBhZtvXpSemLrCtlGXyUk9e4os0kT0YRmyGO88+A Ccy3ig3AC+BOTbcWSo5PG8lTWztx5qx7TvIG7r1ZFxKRLva72Z720yRIi4V1S4JLQlUjD047vEXY aHXvRBzM2Pc2ozjGs+5uvV9nRHfMKceHnEYCLJfsGwXL5/tGwYGHOSpF7rJqBVwfnKu0d5iqA5It qdurNc2pZxit3kqLZb5q0MDWedEUDleqrlCKX2hizA54+bPvdD5o9bhTSOEp7xZRBBC+/gyNKB5L EqLK2GlD3mk8WcURfChDGGyutwBrr14ncMFPAsE50nnaXvj2MePzNc+14wM5oVRqb9MWizsVO90X whwdzUJiAzvV3lohl55RaXXBOPN1MooAUATHckSA7dxT8E7IaMvqwig4rzF6d8P0C38rngVKT3Wp P6/UtV4iM/uiscm9+k118RSuQEZB1nBCC9Zv5wPTEqY9uYQkiOoPuFcYb6+U9TaokqNEJAvFbTeQ byyjGgrKCYeeRNNm0/nt108ff6U+UdPGw4CvQEExtDqcQJ/RGfbtqrrh5BZATk00u5yuLmCXyd3V tl9n0QHwW4Coa9A1tDZJPcAVQyyKnolx5MwKBlggIhB0HxGCzHvna5iFcSTmo+NL9daJFxctj3VR 9rejOlt7FN6o0wP8r+JeZmyKoe16xB71pkFDWZY2eWH4O71MOIjDa4JHsk3eXi3RnWUcdRrOFVFH h4eqIOHGaC3Entw+5SEMZb+GkWs8H8jYGehTPlf/6tSY5apUfwodSwH95ccMZc7jkDuUIxc87BE1 moKJk4+GlHYoVJvjtngCecMV7an/AuxtIDe0rgSzm7y6W1OaaP3w6TdPv1Vi5+S777962hU+qWUY e6HWuybV9WQhFQKGdhwcHZ988ulnn3/x57/s8evzLwYHqo6Tk88+p9ou1291xceff6Zo/Do6+TQ6 /mL02WcGijdf36mvXr9+HTXrarMh88w/bEvIIPTyH78Dt/f8KAJN4bwEz2y4ak2X5cUKkziiArJh 0/S8+Oijj7ALx58cn0Q/V5er1Z2YkOPPT76AGM/o6LPo+NPRJycUxzIvZhUBKWJf2J3cFT91zgDM onn0t4RuJ5xK66qcA4xq2VCw2rzkpJiKq95cFuDrgsXUpFKsGWegPsCchIAcD2m3cAdcFsu1ko1J Zb1sbDhVXeQ6uMKuVfIv0cfp3178VRH+lz/NH2bRQ/gL9lNVf5k//Bs8OPoblWnKXwoslP0tcjXi Cb4Hl4Mvf7p5GD38af7ryW/Rw9Of5qMzXSdw0S/zj7P/mGRdWMpenuMDOjkwrc/mbl2C6QWvBbjx aLs3OidLnue2TwcTXKtjtVb4v5+3V/rVUfRftku1uNHxZ6OTP6vFVzz/8pENWME8tzrdtZ693OZS F6ry6WYKWxte5Rd1tV1DmGDasnaR9hZKn5Jk0jbRYKFT0LeB+PIoGYW0jCJklsqDgq5dkKQgtF0k PczaKYvdsrOH79R2QdUeiCJLTpKN3XuReNkhKJfThDzfweuWxgoGjTNvNuC4nhB1mTmhPxNPpgFi M0Xgj+SMJT1dPz3E28yR++0VxKOQIk2xcPhjApqeyVXZQFKvyV0xrbkSoNlWL/lzUdfHEQRLqP9J R/3inaFc9Ebr8i7k8FGYPCxnnihh7GDyHv9TDOYA93lh89g271kVZrrrmyd4bG8MIPdNV9Pl3S8U 5I6zg4yMIm0j+JDTrwPzinmXqsN8wLYzvFFX2816u8HUguD4DSm68R00ickrG842TK0TyU2vzsuL atsEEwuCw+pqPiXHXsg3cwM2E/V5foFrmPLFbYP2Kn7XQIg9aik4S5y6kl3q7+DExy/pE94Dwyh5 cJ4Y1d5cnQU7y89V+RMqjwLrOHKKKE6H41aUfKnY+0hJC9tN0c5hothFPIpRK6Jq2eGFaWka6/b7 uMTcQcmDf04c6xG0T/LKFu1SRzJLiq195HwwtOXDjXw9evCtaueT0WdnrV7BSkEPrMhkAzlTKDSk VRnCVA+d9obR0RD/n3PrNN9/SZW784TNHioRd/BBbWlXLiY6ZBkXV6nF1mMRAKLGUFIadR16a6AE P4GAiDDCHN1C1AMpDhciJ+tVmvz46tnhn/0YpelMR0ZjBRfFxqKQJPQyyTqrMI7eXIti+49DpxK4 aWHYt9NbtzFd5hDK9LQp23Xq7cDGN2XswdPbPJxH4F7y7hbDMnXauNl0Dfacd3ev/79PKSxTJycH V3nFpx6pf4q6jqggmeDgMlg2V/kAb4OUhm6y2EJFkPSKOBLyUpM7L5TxruJQSDAJopMQP3+l8x6C 0lzmxDO/oH8DEwNZVvbL283z7wfbVQmTTEZghufJKQULpudUfYAjCMARj0aAGTYvV8lQ3fvwtxq0 +uOE/lBDT35zU6JO56xMTPHk0GcDykD62K1hGfBJGiNCDWD922K5qMQsb3J4yKuhmifSG8eNkqpl Wje+4o/jxTwGelFyCrpRQDBqPN+u4wylHXXy3DXis6tiM72e1uOYNOXxUF3oq1Jd98dKKpuD9UeV h39WVXJmP4NTdhwbipA0ANWMoorOucX8X9X3/7qq8j1G2fjDg1StmFYP/x3Hq0r9Vpc59ZMnJPa7 pE7MejPbbvCeaOZtTB2w+T8vq+otqCFS+HFTw0Wu5hSSYkGX1XSOXKmcLjFtLDxtUoj+vZvoTKu0 rATSxSuO8JqyVA5qk9UEcbxARlUCNLtJUS5bdQ+aXmDKXecr5yXlQ5uu1Z+q3BMa2Lf0Ll01esNm 7WrzurgASxqgucHniiC4MBeIrRc16GisK5FbDK4cIPoWNQbsguOyKoPGfCWpbNUGuaGoXWcQaql1 IltuP8dvJ4ZomkDz6gKNCWdMkmU6yAsdlt5A0xj2vZqbI6RRbGE1Kyb88WS6meh+pW7MaMxFUGoA 4yQHiHu83L44NV+c5diVp7YnY4a36h16T9/M8NkvQkk35QXMtya5CAgRZoPyoAFHtDsuxTSbf/kk EwSS41FqJ5ilHsXA1FUX2N8dpMfUz4YR8PGx/rbZNqDW4LVPTeor/hrsuGRCD5lEYMqIVebkMq5+ Zf5bsNPRW7STaaHApelOyYBYjC8aTNjUN+b34kaiOK4eTEcNENTDn48j4KBBcwrkvSq5kzCuMelM 1Rj4F78bP/vqidyMxkIp2gAu/GGNvLxrdraiGOZ+jSABUyv8s1xNZJ7oPic0GeO0XSGrC5wID2rQ evLUSwcTl1I9hwjWJAOh6RON3frsRy3HXNu4Vgx4JKCppfNDAhizf6eOE7TLvfwuz6YG00ffaPFC I3vMHo2SAOGz7tjB6RrqmKi1Ums02VSTSvEIzxYKhdS5ue7s9lZJaGIWWlvIDp8Khyvy+AMthyUX r9J5AUf6tZL2EHUSjkDRbZor1+XzQ+Yp6N1Ck0YMLod4T3rgzV7QKc1MK41ZTAgMWP1f0BpN9dsZ a88A33Hu4AHGmTvkw8VQTNUlArTExTomSVfSR1NcJic7RBry4nO6Y/8QkXJFeHhdQ+rYGL/fYGbL qjFqjT0EPj0QFvpABlEH+HJZzODaKnzt+WHlgVQKO7IpMeTacripZIEborsbMz82vHVMi3f6uKYb ceiwdtHF9Lmtdhlfw9PW7VKVCVk5FOEXMwcQN4352JjzNVAtGBzxrRpVH9+nRvVZjAPsDROleXnP Ba63K/xXcfGtzhHh7cHeJXIXJbAKE6gN4SMUM8NW4uxDOzuzCQLu01ejrXD3J1bRMaCDbraNMSEQ KQ33607K2zUjUMmHT8hGSdoo2P/RC6gb6uyyOnNQDxXu71vOvzQpdQImk4EPxehApwtPdH+fZrE1 daCho8b7tdg+62le7IQPMRmnqG9v7oQnGlyPiMFOmCmkUB9sGsla7vGR5R6DAY4chqVE7cUc/wIT /Gy6ghME8FXoHZpP4PiY6ytlg9GH5VURC43BoryFMaB6gD5Ma/DQbTbWBFCgj2MjhF+wU8JFB9Gu 7N3okb0IYfOo2df3N+KFbAmYXk/LJXpOXpfT6M0batqRYt680SI/7Cyqhjw0jCfKmzepXhoorjjS svCsBQtUCqDyCIzUOLLc7P2R5+isC+BfRGOB+dY6YSoLGlpfnrCajGc0v6l/rdEa5c6VWMzvvRCo U5wXzawu12Ccjo5xFU7uvxaL+R+2FHBD3LUW91gFdvKSasFkvl3L4Eye3+ZtuU6JGCK9VITSXDU5 ahLfY1m9K7FdVffuz8U77/68JPiNz8fkO5JVzZ8SPgYl3Z7rD8hdOy/h5rqzt8Okvra3uhq+gxZ9 N1CScO957SzufZmiupzb0wffQc1e8Xrfizxv5iR4edsDg9ypTN/OkIE000UxAQvARFE28IWUEWOG WqNO0VBqIOP4x1fP/hwLi6/Z1OBsRWneKaaZ4ClBhZqAl4aqegmeK6QSZ8BK08FnXx0ui+tiCevB vqseR9A9EFdluCfrx87COhO5AH3YIodOrbQTajfAJzCe89ikIRAtwYQAzE1MOQk0E3E6kfnJaW8K 8L65AobLWbpxhpqNWsUrSLoGk/MzoHPAYVxuQiu2GLQvAKviBsdF3ChdzLOOEUCvWymqC8BgUoXs HFFVizlCBmHlmgKOMhjHqorOt+AfpUYpmddTipJ7xkRjFgki2j3SsTpO+RGRCc8bsmrM5gGhXLNN DE0bV2bgvzq8/hP0x2K972effdbpN0S9tj3zGR69V03SD/eloDn90+5jidinRtF5H1bvII0iGt08 +lCvCBNTGz6dVjFsd72czlpR99RXrVxWbXu9wsAI4TgFTriiafZOSjgU25RwG6HaoayD+8lbwkxw K6gQ6UJvHIP3yQ+QOZlvYxpInOlQQ00h7tkjSYQw44gZqwNIw5J3LX/XueWqkT1/fIz3mATOAWpQ 98t1LWhpD/AL6q7+4tj5oqUdoNXHoekvTuQ9xDsMO1BAO7ue+wou/UVn1zu/6Oy6+cLexdqnZSDe T5UyCFHNSklul4p9wSXBWtfJ9Xex3DYIhgI1MR9t3JBK/wIWPDD7VoxIv6ovXMNN35LZT5yoJ6sL xR617pTeaoZVyHssE9V2v4UKfQMEbgKEegip9a0VldR7fo1poGCj+fr33TTcPVSq4V4jDX3i21Fk r+OsY9itimhYy8DI5a51BMEA7UMJcUsjf3swLNtnTOd+9I47imSCnyU7Mfhupo1BrYTG18W8ZT6i HvD67b88c8VJ77U4HR900x5/sIc4LeOINUvRzi8Ixo5hw2E/Ho+lcDWp3XGqwjSTEyKvEOxlEg/D 3km4/dwKoPFABcZX7LuKTwQanj7lgMVxoAjMC/xJFEhRlltUoC+nV+fzKYGnjPi4pFrNhdSK8/wg ev69YrKP2HGTgs2qhmV0EKWt5kBAkgcOYEIsAHFyQ35MIWDwXJcyaBeL+Q5gf11s0oBYbQRh513r evT9y8C9iJ3qaBZprkZuDKS149EcBwu1FfTgb2jGNY6OAqknrWGXZ2dolHMIiceuX4QnAI5Y7fxK usyY4D5hHorr1RYyFsZ1nIUpsLlr7EXfapvS9syFh6aHp13TQpCa8m7hOK2l4ShbHORi1KlLsAPt vK+O45vzh4Exy5WgiDnj5jbqBhLZNUmGpEOx2E2xb81ma4eOUzto/tVZZEK7h/6wt92d4PHM2uK/ GmYAsVHVcr6Yjx80X9qsT3bY7Q3oS6khVvwSt5jQRq7somwb8pK4UlLdLwCXxMNw0bNa+NHqxgo+ lGmoQ97WT13VyFDzgp2HJdQ291ieBQQFbKErcEIUwOHIiU5Sb3G8afNNRYYi2hI0HhXehC60cOuT BeD+FG/l3YRwLUgMdk/a2vf1KjCp9k71ihSI1RcYemHvu6pWde0GNWrWBbIhHE/VpQB2Mn2lagte emlgmxqUqxvn4hUeshtq5pN6kgjDPUgTO2UyzAIFzphaEDMg2nALQd8/vZ+RiYu1Ld4S+hdCTIC/ 9C9FXXl07R1lAfWlUyRAa877TkpTpUlr2rFVfEr0ZDNJb66DgbjRBLXKkrpbVwd3v/QOxLtH7Gqr Ja/vuzVdbQrc6kiYQWWISyhYQt9HkRI8w0oLlVMSP3ik3lLQkrdZWEcD/2jlULzdLP4cQ0QIhDOC vtCq2xa2fSJROWarqfLnl7U7OsWNOeM6bQ89ghwHocnD9XQx98PR1cEinZ3uGh9limCPqS4HvGiX vCFAAGKSlUY9wtJX1Wrzg+KIz5SE+3y13vr+IOET3H5PzvQdu0Mc1/3nYiPnwYx86FT2vieB5vtq rvG2I/oa5qWho8Pw0F6O2TsMWHIRGWmuy5Xvf3B/1rKz1Z0M417T388NTLOO5rT9FjVYqd11LUo0 lzEjNSvi2Z5T5tI8ip7PC/SQBpM/p2wodUIpCPfVdhWhPiCAU0g+q9YTjLkL1X8UuI12XVVJTEdb fLGOpooWU8joSDjd6Bkwq4tipfqBScVs1eTvva3BOAydqLYXl3QS6lwukD1mu6muICQUY6MjRYUN wCGois4LCKdF0NV6Ciq+yyk50gO2AoQ9Yya0TbG8s3Yh3zDkqoJR4BHAoZlvwH/+Pct4Ov8F+fTg jJKHORu9y8bMijH8TucYxzjGn86zRj6cgL9IjTd1fGZ6xxK6L4235E/VJqLCqCl7qdd63RTbeUX3 RQK51NVlsXQrBu3QXYfA72WjDppTAbd98O6X1/+biIma6nyQuT4a3v36+vh/pfAozuiAgSdrUCGt EG9jrvYZCNASBg9xCxg40NTJSeRaQU0QF0WRVNyLq2r1trjDs8bAK9hHbllTuy4JueA+LGppXpxv L4jgnZgeW09yeEjtJmHreFcIk6tahCgfqoasj8FiOlgJaAVZDybjKND7aQ2/lTitTsNh1tUKB02Z r4PFTJDUt99/9bSjDIUfxTGgF9XV0q5rhBN2Qdgr1RK4WIK9SnpdB9ZFDfSCBB6oC2rR4+yvSJdS tN8YYBYdfaeeLDYEonCHJOllpmgJAVXEuI6iU5BNUvFfImyL9dhbUcIznkQpZlKghcgifqx72luH GAXARQBT1XkeLcFvqv5pdkbTNRTguJ20vqruQe6YlDbup8YexxLaFquKGuwlxa+evvjh6ZPHr55+ FRXvtuU1hOTiQaZ355j2Rs+4rqYX5QwRIGGQ/NcfPsb7dl8LEyZb70ugCyNJ4F8GbMhSLYXI5X0K XB3id+WarwkAgeJI4R9PlKunmDKaY8Dwz7yuKgzATWPTAey54MNahgAvcvjFDXI7XJsRaCVrNA5e rUKGUBAOIvAa11Qafbg55pu6Yno6jgyf7HHc4X0H8fzoPPFu6uujnmOJgDpaN24YeI+G+SD6e6Vk uP9yp6StFephnryg3yf55whrc11Ej1++ihTDbCiaEaMLpecN1WNJgkYHnBq8bFX5pYaRyFup1MAL U03SBpgE6a0aECrT5Gd1VCRZVyo1+IwTnCIY6unoE0Q3SU+G0efgcRJQHIWnRS/LR2a17JcUucrM ELNLidzDSLVGXpDBOEQfOmRRO+hf5dvVvBIV5PruIK7z/C94FbpZs4MMQ5xJuVs8c4gGl0FkX+8n RS7NL2zFP+hl/VoVSLMWWWKYpxoSpcxVg4D05kdDrI+GfTOtV5PpuRKJDQiIoRoxvXoC6R0eT5Bl 1uFLqcNUuj7LeSzwT2cZZC1pbBgH5x/CGUITSsVBd05+MWA5sKAyIpZb6+qIY3eFotJchw5h+HDl zmQgltZMMoN82xkORMwS1Xk8EuNrYNYbOqYzCx+lOqU79/+39607biRZevPPAGHDXsPwPwPZKdSS KZEplXpmZ0yIGvdFagurabUl9Y4WpRqaVUxW0WIxKSapKk6v2l7f7afzPz+BH8Bv4PjOOREZt0xS UvfaBmYwaLEyI0/cT5w4l++US3Wrk2AFuio6wgHSAAglEXdu0WVPscjiZgJwOu1BRhBUE4ROa7Bj qJu4MYOb6bzayOc99vI10cpC3qk3s5e0ND9vHfLIcLtzhp04FlJmRNwhc6NdrDAJHI14xhh8cheg VpCxBJhYGChqDH3wUpVbFtdm54q1nrWAemyv5+oujQsvLho52V00pTk78803OhuFWp/khr9VUsNV wk79YL7wrtZsur1h5iYO2Za6gusq0ZNVhbLzSvF2LQDQtcjxrmQ/8sXibL5EBb1yBefEGWD5kATc VXp+BV3B/hFjIFL1eLIuNEIZwb5pUtRs1fvKQnIUzBWGvri0CBEqI2cGqJwDbFYC1FiNWd3G28mz dxSgr0EDrUTsvPSna3J7UEwAEzZ49y6BU4RqiwWVejt5dHVWTOHHIsj2/C3nFyCtPgGq0SyznDy2 KnIUiuqQVBdIi/STmQyJWTqk1kQLkkJXezRAHmolV1LG8DWKk2nEvp/wbWSDjUaVKFbHbcEyyu3B 1hOAhLpQ2Egxdqls7ASK1QoBteQ3O06gS+RjsLKYsho7hwJW5rRQG5eLmweC2cGIPtQHRbka6SU5 stbliFenC3BfXFMPwLuspoTKYikXtWz3qu1VDxi1K4ZsXRFOq3yBjAJZ8jD5zb3bv2m8WJFVrO5C zneKXK/IB8n9rMFCfFlej68mN2rsju9FS2jl7XSs1U0L9tql1mXJwNCIfm66oUsNTwEvGTHKNXau +3VMo2PalfSOpgnMopJKoflyri5WYH+p2oEphQepJiEziNfFLMTKN9Osmo4yueyNXvp6CaXHa/UP z52GC9dfnB5ulVS0fkwl6aIZ39h6sWc6fj9pkNfCZgAd3fTlCF05Oor4NHj2zfCoGdkMPX4emvhB 60iMEWK9qk1BzlmoZKtLTw75qU93VkU4rYjI9uZAfzr541yxfnMFqy82C1qbsKWZZGkXi/JsstBs uG8L5R2D49qoSLRKOwJ1u4i+jyafCJoed3i/8D0MIx9En2MBs0iUiHPb8NS94U2zvTfEsihPFkA4 F0C8sy74lYR+YR1pedIWQ9NWxVRKkhTyll4Avt1NvxqgVrqNSLVymfCKlAS7E+lKDQv1FF4NnWZU lvT3Xzz/9sm33wyTFKmqbeJ3mhudGmNHRMsoYyB5uadtnU8F5l3J/xBk0A+52ZsVp476NgI9VIck Zuxbs+KvB89+m71mtcut5NHNCkcRY3CTJqhbJQRMjQYzTzcA1e3CcfPrEXOU8E3n7d+8+mdRw4K1 rd6+f/W3f+8Xvwjh0Va7BiV/jur0ZvqS+bm74DvbKLMPdWhsgYnSyBot5L6pKfp5Hv3I3nFukCNf sNR08CK4n/8FIouQrw0nP308Gt3HZA31wlN3995Nf5c10/g1ySiKqbwrQG2yuJ7sKpcoAX77IU06 v+/JvVO12jk9YsGV2aGcHtg/03uYRNKObEoSKNWsODkFW8zwzgd+NoAo/gnrKyln8LYn30cT+kRi wqI04qnLHpycrcs36qai3e1O4U032SRH926mD+P79SjRDVLLgpbgeNxP5lPTzFYYiBkvZjrVHq8p 86xiZYi3mdFfxx4sRXx0GDka7gJEaLZdLPhZTNgxONMNMZOtVQVV8g9ITYZX9mY5hLZl2a/PbyvE P/C2FJWq4pU3DfmXgloDB9/9rptuq+E2wC2fFrBOq1ZnmU5BFs0U5SbzaZmEaNtEu4O7GyUhKM/P t+tkygZ+i2MS2+6LxucyRue8HJO1GM4yrDeA5J0+UFLhwzTYu9yq1s1g1S5j0k8UU2PXgDHO4cjk xcfZopo+ODdpWac47q5Yjjf3DW872Rk8Qu5ZA4FwVtOerqmvzkJ009NJK07V+xy6aCYTsG8WYMiu n2q9b9pASTTbZH9oUpmnUJlrI0TDyeYonuSEszRRlSO91uPbQK1cTA+n9vbHV39mndV8pV6UF2// 7av/8Q/I9k/pFa4m55dqlgZkMOdcVwSWKjK8KAU8L4BJQqr7jokdZieA0AugrD7JaM9LiKR90bKx oVy6IiJQIrmQmm2C5gu2CvKfA/67yaxvrOfQ/KYmrpqTqviIosDLhdylRxOOIzSYMn6qKkLy3G84 qztnFNuihzBvRHm7QpJWdaQiiIA5iv5STVK1gCEJIAeVOuenJlaUfYilHIQJG11Bq2669PUcnk12 aNJ0vhYvv7LiXKTypKf/npxVlAzRVJE5EhLq0kXnFXItCYEs8BKH0QtpuUyJOntkeWFHT5iqVLOv AXoLb0vSH3CkqqV509dae4if0++n5YXpvNAP7EtN2KQ+UXeWt8sD5ln7VprxH9sLtvbitidv6KUb wQqTpht3PNuDL2hne/+2S9NDv2eE/zs/J4uIrYY4v1QsQasPEZ1MD6QZFwIpfUIPlfxHfnssBc4q eWne8RPzkuJ86jsxqQxJ+7qUT46Hp26gvaZIKB8WtVqRqIuMpPpA2cgVh0fSBa90NjJ2h91QwIk0 uf0IdUnm3Tbh0S1716veVO0EAWrfXAyG76BLuSfUtUCNZbd30o1VBn/2uhqnAe7WrIddj2/HceJn rdwFp06Xq1u9AZ2g8Ra3Br1BfRwVem24ppepwjAN/Yv4p+IPE3hSuvzC9R4F9O24zm3fp/ORc88t yAHynEAXFuXyAvcHB5jGXFjpVjDupZTGiGyb9reaYkZp5wRsJeBDtmJU18bpDhg8wGOikdqlbhSP 1mQnExsL/p5JKoYDeG+XdU8spqa/7GL5zafdCJyL+SrqJW7RZFr+hq6xD6y52jNLnSaANkXBQU/k P9yAZ2kGCeyfjQQaTuyK9AbKqmIaA3OJ5VMWBmwbXAQqjBRhahi3lQzjSJpjMe8pe7RWdnZacqph /V/3xtvTegjkRiQtrgfGAeU1VF41U+l23W9axsD6ysk9Vn/Fznyf0GJ5CzSo1YcROrkf5LextoFe xvvWkZjQ964hAgdvHqn2EbFmPn0cqigOHbDmE0k0Uu5gNjbhRWsTUuSOA5IyMR+vMWFw5McMegNs oMecyEJCnuo1d5JSfXh2ytuAQ4UMjQvCT5fvBgFHa+ZmQiw9v55KRj3FqOlIXZSKj/SydrbGLK37 WZcSf+rmKzH77b979U/UdU8RG+sE18bb+29f9X7BN77L+cWlhIRX27OB9g65VLyLNO+4xb3996/+ sVAizZK5f779D6/+599v0Ox2okpTV2urL92e71SnE7FdqfOZAu03/URbFMQx5mxXr06+7dLJaPlM lCu5dY4j1nHrd22AIrcGLkwp26xCvNa+xbuFxFwUbT4G8L+6VgNMOnggoKwl9c8lcgfWiQCGyevl D331n/d0cLxe/pizxZ+dKjbXJVFFDwmdgvcb6KoKYYqwHSQ4YZz2+mMlsQ6edQoa+Vk8htTlMEe2 zc0YHiI9JYDwX3XGlSyTdlGqI8zMvKZCJyCBH9R1COgeLMMrNZRXwAVaSQ4pBIzmFzl9x3t4rgSY CRlLkMzPywW1nlwbe7k9cdDKdLtZkJH6lkxCPTGcoZxTaGPlqBHn8f6R0zcJ8RNTkxKFT033yCGh fuXcMqAjdxwofyDvSe/h+9jDH328DyKvRepFm/TPDUFquTvq4H2tep7cSRYd60YJEZcKDUUeUDWf w7irde709zmp4vUjR7KMdxXmeq+3wYGlKaN9EVUeRAUMfeKlG2xQK6L4NW0htzjVYgbLaAA8nbnd FozVcfStJhMEItt5MtUQY5S7lBgRFdLX2eA4g5UR468GhxxMXEkkGLP3/pgJH4sVjHTZvYY53Qhf cRdOqATGgAZBN7RlgTU16cdu+xCpsamHJhgTTbUuYaxU+nKoljJfD03Krf+3bXv7TFY4ncXU1WRb MNZMdZQWNw1pqyPf7tHBt9uzkqO4HUza6tmzdA/+ZM76kznrT+as/w/MWV6YggTvp/jHnyJqbA0O TT6Tu89T3wxl7gG1+xKo7TE/Uaz4XtNab49tLWtvhxLzPsCoZrt+jYK2dt7+x1f/yLKXadPT2//0 6n//K748hdYouNWTI/QW7tXqM/LbketXp/PSJDy+KMup3l6cCrx8Q2G0DN3+Tt1cym1lEYYySEJr 3Sha6Nilz49ePXk5fvaXff7x8tGLly8ef/Hk6aOv5cmTb18+ev78++9e4slrGgN6/v2LL755pN48 ey4Fv31GH3/17OnTR1+p0l5iwmhsr45TnF8VpoBMpLED6kaPYVu42JEbF/3q/CxWwfoPig4d7ctU 2B28Y3ugePhaxkC18ZeROEWOY5Tilk0QUTdkCJwvkT+5KsSNfb7Z5akE8Uaqf8vVv93Oi82hlVPh WNXT4kOqdgKcPBOo1MQDCnf2yjd/1sZRed3xwiApA3Bxs1lPxJy8vboCKgKxALUMxDmPL2VEI+nN MtJ09QMfubT3KCsYAqpXZaKMgq9UNpMveq8yVqIlvetM4lzgfwlYwKQ3ydTdNm9eBQueBrSZdDBV 49hIiKgMUP2BNT5+hKg1HlyWHCoRAnWmBGHVOnUFBv+lkdDxxC2NHfC0HDp9zTOnKEYmrjdVMmNB ftzs5z1YZy2N2Zx1LZLVZreIRNDG27c5k+KmgcgdXoaBd3VmT36fdKEIpByflzQSlOUTj9XxTH+p 4+1dYef9dLpoBp+DIthTtgfad0H4LlG9C2J3mdLdZdk6I+D+RJTXEf4cyN+dAwKO9wQXy+4ukVgb GUIny527fvhrnDNA4ti2r57zcoHgRmsD48GhcyaFD5+xXVHV80OFm2aFSNdHrMB49BQBNfx38Wl2 oAdFPHpj4LtTECMVwQA7hSDFX0r9z+WRMcnXSVCcwL8GpwBNUXVa90g/6vphz9Icgkiwwp3lMc00 PxraSXOTqx2phte9zeSictK4GgcWFmKTlO/VVwAi2uiMr0HGLWqcVjertd9LT6y6T8mlWlEM3CKs QHElx4vsAxQUnqShQG70TYONF4HYSFRHfc8IeVzVZiL1F+O/hk4xKGxyfUqxVhtsHaI/FA6XAAmv mABkJ9EMVpyKcm9rsNXUeJ676NRB7Vq5pkaGpDr2VaJCorxM+2kWuydw+ZH+Fb3WGfRdKQwULT4c G6NVzMgim0CVRlAwPYI3fMQeRvAmtSaQT/X4fNG7jmPnokdDx9iNR5xKJlJAbyKUkTAFqzWUHAmv PoPSsRtN6Wa1HEU7wTgQgdF+AqrE7FF18+q623HCfHQBN5CnwbIrq6DZfspmbGyJXNJrtJk769JV WNo3KdaFH6d77dyeQtp8OkvD3udiyNNG+L73PN8iY1rPOIP8nmU25r4tjiBTEmSqSnHdfsJ+BSLe zCpIWXR2xVCLzzUshQ9/IdQoDy/98tDtqA7xoZl7KGh1ndBfmT+MBtM/VPZ6uMSw+rwrVczJpdUD xtwKPK8D95j0gBmV1Hqp+GJhgPlrKuoefy8sbTyADioNcYtvzepWEH7jfzJebq9MAHwCih0fEZp2 4w/vOyFS9HQu1siorXXO6F5xk63GMDYigNeszbVuPJ9w6i93mnLczDYAQOaFMJajW+b70FxM+/7n ugvxJHOCBjMtjmJPUi3YzDp2KrvlLyeVusm92dZZmzbX9cPaMq8elSZpIMjbOZ+IsSY/dOV06Q7h pgKBntkY/q667wl5BmWFgI+Hps8Hvx++Axf3XicRlRwotI8JJdZGZnSWr0weZBu1eiSklL7Th/dw mGaOgl/8BhWNz0aRGYjAmPsz5Pk2ha3Sqzk/K4AbuiA3TC4SS+6gZofEuYZ3HDknNdyBtJh1Ggph qPyh5ej+MVzp5jc6PTD90efr/yhVot/t22+uPQFVo+i73VeDxl8PP6wn/iAykbYecwk3UwjaO2z7 iEpY3dnfkMH9esRkrMQ23ZRHY996+ZBhcMEV7exHgHtTJdEX3rgBKqbpdFg0cJDU3emLa2GEqOjG I0i6+CRiD3ddR0zJvmScGjUlWvJGObKa6bnXUBuC0h6nxv5IE2GEoQ40jV76ep2KObRlBKtCZ/RV v/rJZr4RAaB5gvb3k4lqctHaK4NKQ46tXE59M0pHsm1j6yIkrMpZzqP1coB1o5EMlatLfKRTl+27 4C8YXVqza4TRRraUfeklnfm3Xzwl9fjDRM9dcPYcB81dlBeicnTE1FoeDERWqy1GWTmyRBlcqEXT ggwwXELNy4l74FhA7nZlFNfpddeRVNkvDx5olszqNUgVc2TyHjo18ns2surdK8zIIIx8+V3GJBgS 7WMgf4frhHUwY618KTSCLD+Psdj9GhZLf/Ld0++/efJtUpPXnow9rqDvx+sC6psspRyegzD2S+qD tpUSptFdjeTAJhSXBPWfovC3sDZutssJYHQ1pG2VlNu1VpHBRabx84vJmjLKWuXVKFwXpPjwFn/r xiDVjz/y00IVI2ncyq4cJDgN1nK3/q5LqzlXmxVTzJ+3uWbXkNy1CKeXnlXvLTlsGUCPguHFIZOU QFC2F7Ny7cLq3UqOK4G+KmfJRAAPGAW8Au7xUmdStBeTf4+JnmTM83RDaUB162+b5jeNvytj8UmS pp6zkXcD87e9dXf1ZNemWl2hGRS41o/2m1cPjAf/T+AFbykiJ5tav3BdriWT0p5FSF9h7Ql7cUjK GYV6x+vJMpJUC8KM6D50FB2q9uP/V+vyjCJMxDzlbv22+AA9p/V9+EGQkMhLjrzGmUxhFt2szgnX tCha51uRys3+om4e7DtRyz7+h9F8S9bphQGMn1vE0OituXviz8NSHqEvMRd7w+c1yR+6F8BJ7w4x 2e/julEQa/LI94itcZHdQyoaphChtSvgwxoj18xh7Dm8jT/inKZlEbUumBhb4jmqBc3A9cdbIW3l W5ZYo+xrAz4e1J+YxH5yVMHcQaEKnCb8Qp2+15NdPp9m+9b8vhHwK4tImAdfKGPokv6d0jgk1Xob wxnihrKHIx/ww8otm+rKlBiT53mipNGzcjEV76qPjYVpiXRpkIbpTpD6DNyJjNobDdRAWptQWomT pAIP6hu6gNzU5odcR8w7rO2mr9PUP0HA7GmbYvMOg8OJMOSfB2YevaOmjZWjWZoTdB91I5KGnLTS CDdZo/NGcspAi9mY9bQJPu9eNCCunjCdSprchOvJgRawWzAoL+bEOqZ5qho+0cpE7yNS9armRwW1 tJ6GdI8bvlWaImdc1cAdcdAMpjcjLRtNburlqS19+5amlCZ3k6OpFAFn4l/OwEfj3dzv9cpWBPyI rj2rKz5mbhWvvUyHsq5EFKDjwWIVLaBg3s2DmWMz04Mj5Hy2oxGNppfyVrDFqv6F7EnInADR6m3W O4S5WG0MAfTsK4iLolfvZ7sornfILqT+yfGfXhblz7WtpTVs1BodqGFIT5M6iB18X0mjo/0O2eDJ 1mKcLhllbCw+mlbj5PqrC8KJfDDQkGZyA7bdN/uaejxrL/L1dFe71W5su4P6Z3LdwDT3/RaoMp8A gMg9ZwY0HCvyBIUHR5X6/ym1Vog3Ufr81O08aGi2rWjgJ/9DLowDGQJ/R2iXR0N73CfXVedvomA/ y1rk/ofJPYKhCVmr8Rl5bbfCZOoKPsAMABb6bL7UQY7D6NBhpglDj2cuZ/w7uKnFwxONhsCJU9p/ s+MFH8WStb7sJ9rmMXIsIF51OfBQ1g7wha0cnC2AnLvsMTrpx/Act9G2ydY+BJdzsRe6OeRkEOS1 x17NN57JyTbxuATCoT5J5Svop/qapiirei5h81pJIrWrDKmzZPtF/ZsA6qHVbYCUQVmXndU0hp3m ELfgFEn5u0qr1sDUePfr6hArILul6tW12EBropmlmtrOC4OAGufgcSlGvgdCe8woQ2olc8brs4jR VD1BzlEe1dKKWEKzlls1MfzPMDZ1byj7DVSCEbxZrH5oXbSJ9KDaRFWTA2GRrdU93YBGRNvjWBrP e59yzN1C2+eMjDFZk+NUoaSoYj3RaRE18r5rVrwVVerT+UgXKBOH3pvfOTbkMzvpbnwqY9rNW4zk DR9SyiZOdwIBPp+v4bcO/a9eOZa8dgsa2A3SepwT0Hqp5FfANYHKE7kyKEpvJom1u24ZnFIGDde7 gcKEL0pO1ERYkOv5VAITruAtqm6uHyui7ys+OI7hEmyXvhuGvSIxTJhPGq74+hO8GgIScpSW3eGQ IJ58vaVb9wlBCxETw5+04jlL4D1I38fRZnEB+oI2DDx1pj2hwKsg26dA4NV2BDZGUnbPIpodot04 dHy0N5I1Qu0FZRQNSPVw2MuGQ7ASqIEP6JVvnYmJpjrQ2MIhobA09yzc00dEjxfTcb1rIohSCCxF 8gv4RCY40qh/DhlOBkhNiioFpbGjsL6TYR2mehof/7N1MXkT8umGKF1GJ1gwnrlfWV3XMBYzbcc6 q68iGjUSLRa5yaPayyK+mrdEsFIn9jYSUKlnyYpuTgZAUrutpMAIZHGw4EUWZkJY8Ius6YqFH9dr dGndes1yTuniZi4WAGsLig+havduXliZSbVvodr2WgfS5AVgm1EkRGWMuijQjIL0nL5/UMCVH2oV UvLDrjxvFN1lYkdB42K6LF2ItAMxBxFdQgsNbWW0/TXqaBJK9Ma3Tb7v+Y7vJLs3dVGtXH8EY2KW SOBvit1ZOVkzGOZ6u/IzAdcZa4OSY2Ss70Q7bFkzs3gJEqB64cVA1zKuG2TcFUhK9fUD8Wap9SYf 5OyHt+4B0gMiToOC1UYXDHW/5u5Nbek21NrNPnCka1GpsZDXFvHDMGaKPbPCmgf5KDdwO3nUM9fS hUA0dm6hagzSv5S6nui6UuwnVewQScdE9oQsVTdvr5wcP+nD3kUJ1WPtmHZcAzjre9lZCRHr0xJR opkXL/JGXSR7geOJb0LSDqvX0zFlX5i/K8b8UVQEmM+kNpJ7CTVCHVUcwxs0w6uPICKGA5w5UjQU 6pArhF9qs/VJRFxZAMBwRP8YEaebw6FUyYuUOI3Dp+Rdot6Ru9BkPbmqmlWaJ3IHXcTEnsRxmbil xXxRvgOOSB0gnBMJngFTcchA7t9Jkt5NB0uCFJr/sZjS1aQT+pD6NyQcSM40uvJcSgZ6sjrj5lGZ GlzPHnMjizgDwAGT67Zys7wG4buxMBU0idRFD0RddLB/argpuHvpiV7np2kkpzl7qFq7AiATfJZd Sirn2swUZ4ZsD9S1dAMHqdhWYr+FPHCSshrHBVv7R+UcXW3K3kK/dTtE7KCxKwGkhRAWoDcDrFZz lsxPZGnAnSJQFVHEjIYqspPhr7yL2AE12IMhU3lLZ7Ojc3ZeVBI0ZQmCVjknekzfzT0U4YV7DzE2 Ok8Pwvezk9Os1a/iBofnanoG3cUypjNZaBH9JtRGWc6WvmDV4AEsnvPptb/l4k6ClJ7VeAdGbfv6 bdNENOlCawuDG1Otu5KGF51rjHJzfZ74/XvCQ9XWhGsKz9nnQXid216O11oqsHU4gZjb5GvtOgJy QDJFOi3LdBiJkDRDb60/o0uLjbwU+viBx/3i++ePXkSGWlR7jVW09xJ3RUxCQ2Sf41biMCXHUWq/ Ev1wdBvBTdI1+nz9kHpp3Ma+GBguQHVFVOTMVYVIB6tHrlE/69phs/bPs3To2tmycGoeciLtiGgg PmZSoh5FCCJs0jcb6allXXB3EtvizhHJzc5VFLdIUbHwukuH+6lPNuyhB/Xp4eS1O9+BNRjH35ZK Dl7TB6xn/21Mqtir8ecD+VwrNCkkRLhPLlEEVUO0CnVgkPb198FqF3InA6j1MKCvY0OpKx2Z8sPB 8WlLgIwUi+xsvscHvgIkboyn27X2kLds9sjQGDXtm+/Fx4FwDDL1MSIRpmOnyjpShvddYGw/ImXP UX6fQjNKdZNirHCi7DfQ+to4ClLtQ/JWVXsOHgBd/ut9p83CHHiWxhiKhGr4nm0hOTWFg+PhPnfy eEBKqIsJ+a/tP+4yMu9e6wqB+N+bePTrm2IX+JOqit60iHrp4A2LLW8874N4DehpcePhHSNNX2sV V5IJ+yrYM4vhXp5Bh8DRVLLp1WMGoBlJsB0/+h1fqhN7tE+zfg0oscgy1/tP3MXWY/Yp0S4l7+xQ ZtX0d2GU7TsJr7X9McLkiPrWcFTl9H/27UBH3tm5Ensvdyu+ePSTvwLUgg0R6V1n3kmzjXOARhzT F4bFsCHURl0KejBJaIflLER92NluBzeRs4/01smu5dbIJW64kc0chZgJf6mWMimuUxZLjeO5uMpZ y8DR62ugh+RGPjCXDXa11DFUma5kvFlPltVCs8ofuvoDBO96EExdtgRul2+W6tyD+k+tUByeXlIP 9YL2M91r0JGeu/HxXrAe8Da4tKmHQ1wj3fgaLX5dwsQKcOerlWJSqmxfklSSpTSYHNSgd6L6HR69 ke6YKIHVhAW+k1O/c27D300WFEWoL3LUqgBN/J3veYcqxUjqTUVNJWgztcnwFsUYTCYKtUcni6xv yIqtUns5GmcMoiDcGnxYbj5mzgiXmUVJ88yK+iaEn1FCjvE1JkW9cBw6/uhG6IhTvEWK125r5ezi H8mZGpC14Sycw11ntN3jmsKkF+4qkJgxAF/TOrYdZmpx+IISw1dsCIdmVeh/5qd06f4AQvlqXSJ3 CjXl/YCfySfvu5IjHEBjm1GdCYpreruFdrJcEgTkOZj2cl4sgZ95Ri4Nak0UK2RvJ15A0Fh+9hgH t1F2vq+60BlokGzm1xYAMXlCTIvz+ZSzs7M3hWQ+XU3O3wCTA1/ZzhNqu+4IhpR29BXv4AkDkfN4 +k3UXMN3+g3T2Bi1zdv//Oqf2ij4Durk2//y6l/fI1DIzuM5sobDuHBVTOcT4K0D30cgNtn+SFJd mF12c7kutxeXicSsJl+8eJkzZiQDlxp9tYO8ma92HFm4BSC9m3jNAmacVJuOn3k1hPQ3sCIhUn6/ IRWrASttwe3kGAMf+vMBIX/+qm/yqN9KXhRFcrnZrIZ3755tL6r839DM5+X64u68qrbF8S//+a+p KFq25oPty7JcPFuBK305X/KP75fqROSfTydXZ9MJfj2ZPbqhR1/Pz0M4xfSp2glflVdU4hsCityU a/nir3Hs4sdXnJSAfgL8JqDyXMk7ePvt9gr/vNjQX0b/Sc+2Z9X5er7aUDm10uJtwduXECXkxq4O +KsN9/ixAPt/XcyoJUCVkd/Pab1SL9W5zhWqCVMHW1jLF9sL/SpJv8NOIw0TBVKkv4fDBA8b/Tmn xBbpc2BQh6RernecdZVavd49xrVxsZPaC8IdTJ9cCQKh/Hqs1mBI6tFNcU5zQHm9SXFxw2P6neom TTPcLXg22INBjxDWxHgppnp16ve06+sEchltauPbgy3Ii8ga3g/6mOajdlcYzyu1L2nLrMkgE0qY FDxkALVNC7jWgBDoH06obr4FcXtguywxdkmh3Kp8jvLZhzQqSgXla+z2x6wu6pkMvXXKDc4PMiu3 y6k46xg8Xih3wAvT1Db1uFBJFqMapWkA80R+cnynULeCseeoykFkVj6JkZvxg473CKL0mrQfNqq0 HQJzVcLTCoNAiLXyGddKWTVIvPgaPttP6ozgPaKahbcd+YTTcyBhfGZfcmRkLRwEfhB02k4LJRNX 6/F68q/BJLT6Fsx3L+3V54ZGXoWUQIqwOcwMQDAerLecgzyNuPmC6TAQnnVgEh4eXJY3SiziWFqQ z5PkxfbiguWTahijh6QvSHEiZyuWsERB1PHd+iVkSqD9DZblgB9lGk9StbhXzmZKElBtG0t6NEyL d3OlZ+HtlR8fBoKv945ZXNF6a4xEf6KGsgjstRtLcyPl7VUuK1FgFHUB2ip6kZBj3LpHZTywk8rd JE7iuSAwGo9bUpzYblc664oYkh/oWwm1oW/bLu0uQ0UoWghy5+ftg2y0jGuhqbi9pPQG4OcIwghG hhLR3WwcccaVfUym9tRJeUe14p+T478Q2VamWZLUlyuWLsZXE9LSSU6MTf7lfPNsnail/TdyLsrD VyU9/YP79AvFKtXTP7eePn1xOZ9t8PTBA+vxc/P44UPr8RdTInDHeqSEEzwaWI9+h/BF9ey29ezr +Ts8ums9erwoy7V+br/4XUm1HFmPHr3Fk9HIevRtueGnn9lPn3JfnCeP6JFd6hvumvOESj20S31X XlM37H48qfBoXjmPVFP4KRav/WZJj5duq/kpXyjSzvtOZwvhM5haIYpyR0510IvRqx+d59/rmXCf 6ilTT1GXnKvBIcI1Tou/4kOjPmZNIZyokg8YbuKLYnIFfjjbLhIKI7pgtmxyG+RJ2/HLXMo7dTUf pH87lq2e88XyQVa7Ljme9OogXRAmMx0muBSSxw7rbBgufLLAbWVBlyduos132sQe93R+ZE4JLudF HxlzFw4XdcjVR+8eHwnJvlQPRY6bYO+8jCbjMCJRQ94XIzv5X9ts0KqL3AV17pyIr4Vzs+Nybqh0 m8TnDuDvCBild4JCp4cMnxLdEUGWZgdm0JHRU5+Mf+Lhk8FgaC0HDDHisUN0vPRD6fmE1+VyqkRW DiUh6deJIdF9lxgjkR8BND5KsSjSUJo2n0jh9IF1SXfydjxMmZRVISdtw8KuxeOYxpvsNLQNUSDn c94nI9MrCF7l1APbwvogF8pymp+V01g4lOx0vgq4xL+dmJSynstOZIHWFnObg7g2RNYhzDkPh84o Q/CeNXsweW3SozVnzwUQfy/TCYQu6OqpHpigjXw+7dtQ18GqtoX76GKmOvawg/a1fIu53wYJE6ot OgaQd7X6ovW4uaa1IIaXUXcx3UmfFbRwC28mRTVi4iCvHHi8YsaW2qtVjt/OC1fLRE/c+eZ5xgvX AF2u1KpRItW4JAeGP85XPaqhXFXcgpyzQELW8kM86TunYnoSq1iqcDlHuRpXu6uzcsGJ5408d1Ku 6pv5aQuvTh1fp3AcTAWH48H6ffI89c2qH9OpiMN9TBOjmmE9Ws8vLjfUqLoJe7m6v/4/5lzsJ17D RtZa+ABUXL8vI2tmP+3waBzbaFeN4w4qPjRySJoUuKl/Sjq4sJZ92651d9SuA5Sk1brp2olbHUAX PIv599ILa53ZzXDqzMJsyFXMi97eYTbo1+F8jNXJwsbO1B+l4zlcjUltYym7uEwOZgRp6Nk6ekmt Qg9UYhtkLZB6+AD2+tVyDjJ7EjKNcqG5ZjeuXh5OIjziHu5bQzoik0YDfUihT5H/0N9NF/UeXJzo tKHrut1OgkLJ0o+YM9H3y6TRBcyasxUs7mvUbq5mJ/Qrj/NqGVCfHfPD2AxoYt48uD3XrSC+GlbQ Kl1Y39rMuyDFeJa1OYMfxm3xY+R28VCx5AAO+QGbDxYcvffmy9KXIQ4UFejT3BUY6Chwv+dHzQTo vaUmjp73XDS+kvy1r4/8rOHM/7ADP+hR1vn4sz446D9GyP2ZD/fgYLcn8P/KeqUs2SLxqp/21Wi7 PHcnF0/cVYZPcjyuq56sL8bNpwb9/YM9p/g6TYZE/L1NZcs25eDQEfQEqjpMSulVT8mBohsEKAnB l3Iq2O2zfEoUg/fkyGV1oj9DvFZdl0+ZO6PPMf1N1tZ0p3R0lsUJhxBC9YjI3x87KvK5vkj/3YyP VDq2brXV6EgI6xbF5ssdVY+M+lbX3c8OG+k4BeeQc0wDNOLQrn/COnRoHDTiKJz+FMswvS1j/KHj 5Hy4Z3g4s8CnDE4sN0HD0Ly5nlY/0dB8/NgcMDjoEL+bLwnur3ZJ8+k2GoyOqp4+h0NW7VbgVuxX xz3fc/SiClMfqPycB+3t226/P/E0rMVnNWivlz8cYQjw633qgTnvUz83CsQUEkL/+ejzGOpqcZyi BRdXKtp9MXnCjLqPbi71c60WTMO5tdpuNGfy41MnttbMfpSWUAiw+s+TVowbkgwO3FtCeFjraosC +fnmhm+2T8uJHypuN9fVyhJtb+A8YZefRaUL1OsdosH+zTXoYIQ2EYg1wduXpPbWDEd/83ckBNOd yxmEn3DTBqNVb9yc9y4NXXzDfmgGqp+KzGETeSv56rI4f6N1/HgJxT15NE6WiV68zep+7djlzQWi esfT+flmPO72kx/ex/a9Jdr8RKsFzR7rNv+ci8avyEewd94HAYsHGhcPOSt+7pNAeB1ZyzSjqyoH Y5rAUhwiAugYYUX4NMdrRzjzKTheIsR8Ve/p32Qk/q+vg+0QEDFYGZHUNH5h8jFxH50c/2o4uN+o fhBnFWF3wRgEbjvWmBwCCkBMKe4j/JPr3GPrwGpuZDHML5b1YlB/ZE7QxdZjO/yoYT2or/ccToBC HzmeSw0jLUI4uWtAaAm1e+bk7bXwU4anGNltywWyovGb83IxLmezqti439XPrWYW12MuJI2VAZUP gZlYbKq+gOa5rdnXjub2xFoS8TowbTtt5cRRv4NgJUf8DUL+a6+On1ntZFfVeftfX/1DOwaBz4G3 /+3V//rNL35B599Y3TSQEQhOwezJf6Fd2asOO/2fzRGfq1/zX6xOi0QNqPNgpd6rzVW+KZbzPxZ+ CMFmtyoqTYynBOF2nfPVTo+82H3Vr07HjLeOM0BYgj6d6C/95rvdV4/Hz759+tdjOCpNqgT/jh8/ /eKbjgw0O5FbiCKmRKKzixJBnfdOfKVe0KD1yjNEyNSOUclE1XzFoMYJv0wuywU8MeFwxOc+pYtV q+MCd756Sa9Ktf6Q1WVaMOQd+U5tck2b2yKDQOiPlBT0XpM31W0KrIrmSaT1qf0vDdTvqQXthBgw +oqRXXWTlEjjYn+vGS7RLc0Pg7IUqTRZbwQlaVNF8VHwJuTmeBppaBhBiYJ9mZ6snQ5+8yiEWZoD ij0KyARbUmf4HsInNzkPAZ/AddwnCp0eUJmd0PBsUgHyCEnKDuiOIJq+XnajCArcrLgVmf3lDcVh I68FIrMudTI4PtVpxIet3DkObxl0JAJ1GQf3sLuOc4M3JI+fXq6jaZFFZhj4Ynsoago98zCLeB5L hjGrjLUZi7dmK5bqirE+BG7J2pcj/spr/gFQSO6CIiLAOl9nrRBMFBBvaj1AGTCGGzowVE0vERva FNjMgbHLTban3yeq4Gl7bidVQq04dZkQBUuP/e6OsyYZ8ImayZva0Y5Qoxfzc7iAMp9IIC2DPyuq adbYQOoxfam6zK2g1cY/SwcdY7woljIwoceciYUPF41Vg7j5cR1qmVl0lLRiLpNyEmXhy9zBy+fh JXJDRS2I3zCfWbgJtK+9PuCUqz/RZ5qcdTSQGzXsCzurHSk9geRXTOgkPFOSyRs5d9bFVfmumOY2 fRv8VzqPg65vBs7K56gRedWx8oAK6sRpfqcb2BR/emdkATgzTdB6KK8jNNXrRtaHTwc2xebJsmfq BEAlh02WP1MrJXKsEfWkrd4UqDLqqjN4MgNMKn4JT+wm3eR28sv4lE6UdLLaCdB3ZHKdfna5mi6N T5cq6iYMw6vmgdpjBBh/aiWUxgwJ/20pyWcs3shr+jM7bAOYY1hjB+tkWE7mhnqcT1u2DjdL/ryT 6H+5eR5vbt5IcpYI4PtPPQ2TxUIaxqQZjAMfXszfIYiKng5YiIjPxgcylBMZ2DuHDWvzwIDd6dBl KzkyQBKNo3KQEcoaJ+HfhobgYQKkZ6LOHicTJ/7HA0JVbK/O1AJjLHY1YnR1uJcdwIc03JapdD1Z XjAwmdPuLOYobe/p6CgwsY8Yip51UjB6iAxGtZrwSCRX6n5wNVn4/E+GDrloy6U7goT/bxYStyc+ RCK99+4hoyQXVAzZMOwsdo+1D2b5BMkK1KqnUbCOYoqedWYhGDPc0swkuIeEEXP09/XQGzlPBDVW HXhJbJyNGR56mgbvOyaRO919MpPHOswPg7pMLrZFVbG2earDT3RBrEdXXaamYTZXArwa5+WgPkIp oPGsKt5uMYm8QzUqLMJcPL/u62Idq+56rpjIGe6mq3lByBBn6v2VGni/ETtKDcHO44SucMaXBkzb 1VbdWVg0ji4STmN8Ndmdca5g9EnrBNaM1ACvqMVOh0IYgm4ujoR5WZUUm/N8tfrtR/ExPm6dBcAv 9DLIDuHsFYXl4r4vS8jcPejyG11EeENRkdxUJBDWRPrJZbFdIwsOzO47D4Dc1gtgrUl6wfhgB5cM rXRBXWv/RhHoQWp/NbVUbsbnsJbQibwgLITkZmiiSwBlOqmQE68LdVe3NRGbT46bk1dbdZdw4MR0 d4dx/3OTCM/MYNZar/9di/rulmt3uYPrdD9Jb9J4yJHbJfujQK23xyHbdcb+ABNtS7xRveTse4Ya hcbrSR0GG72kuGFIyPe01EHNEo3EqyBU1s4Wk4tRrUrMhdJ6jBdh8ak6g8bzpbqOzjcjJf2ry9Ey CKD2tpaQnLKSjRl0zpkGuZ2aA3upsiipuuLEipHNZ3MKCzRfMDedqq2+mOwCfigr6y4JQCtg1TFb pXfYxGqVsyq47dw0lUFHtssJLJs8B3r6TZbTAqO/R/dCbGEzOmEoufF8NEU4nt8OJGcEHGmwa/Jb 9uVwHtUU8hkrj8/LsW5g33nLnziEoMmCXePB0XSAj1VpyojraNhFsRlBYNSOsX5R9/IWGdNIRhw9 2iNu1J2ke1QNj6YPu+TJs9Si10HZdSK01olNzoxPjHBtVo7tOlB7LcBSUVZFJgpLTV7DSpharwhG A1ssYEcviHNFmH5x0wr5wAcxUBkKRL1i7zAT1OlWGRhIcXacVQK8JGe2nxowoqQYFjdi8Ak0veoN H85RUFkXDyBJb5viGMg/dLNO6wc9YhoAnDBsxKRapx4pVkS578gDy2xMLyLsmgbPGlpSx0raSaky i3ykWzqqOxkpZLai+R0pJOgB8isieVOxdjUbFkzy57U5pFF7eF6GmlG6I94gEsNVgMduhxoiwgN2 AnrDw1HyeSzvEKTI1e7zbqVNS7nRAGNWellCvJIR3yfYAdtFEaEDvcUkWRWrz+/dh86uRAq58ZiS UPvR4s1ENnzYyJoZUGrWqgQBZGaCWDtDVjYlsmH9hOtWDVZt8+ql49UO9ITceFUV22k55uojaSpW UD5Ocz0QXK4622EgTvQaPdX2q4avMfjy5QnKoXwIXniVW2PkM12hhMk9n6jhz+m/Tgt6x30JkhY5 O76F6nXVudW5lay2Z4v5efLFd08YKe5cXRFngl1VqRIdSygZB/wvIpfQ0q5GrmKgSSrxpBDL1KcN k/X9WHg5YmvVPru2ZZBausGaQ1aHDec34TDspZI3aLxE2JgALLDinHy2eLaew53H0wuxPVGtdDrA 6zqdKifLnSJwvlUb7F2h+Nn5uphsXDmpck2NkCnIlMrhzHRtpUCzWquvB3tM1vwXLx3wBWxSgZzT aprtim4gakcJGtNvg4D1A4+yyp0YQd/6IPmmqu+Itn8VG/31Kug1VF7LouaXA8WDxWvQdipm1LAW W+vnua3KTXTygaRn5wrJzLzyChOBtiNKBXsRsGHjDMCHjLhdTGuMJXVzGRxnzvQ6ogStgjoC8yv1 H2qtDQ5lAHBb7FgzuHb0PJbk8maQTTxvnignw8jpDwLJJdIY+wZD/a1vk5I+Z4T2YQl7EvYSDXL5 ozlmB8f7UuhE/ZjG/ZrETN1PK+MvEI0dfvKsIacJsEcjsKKmQzRdlOknaDm9Io2RJSeI95a1h7XK DMY5ewW7SWuYFV8WixWuMz739Xo4DBcYvxW2b5rozXhsoGSAbIu42trFjXVrNZdmP3LZweWQiYyr h3z9NinWxIbv6bfrjjigTJpZ6eHSel3TncARQz2zthzyN0yuz52N547gZl2tEfoVbKtgsJ7U+j1v WRki6ev0S6QL18K5SF7Q+1ZzdcAn29XFmqx1fc1akASWK3wtLCRcTEyfzc326Gg+K6/NSPA4GQ2O o37zYNJcBeowmo27ASJMnFwAW6Z2/2ZyFqQf1CUWMuWBcBruTCOtLyT9d0ZJx6psT9BzKGwbSve8 vo4cBH2TIUz03FKTEuU9xxhGTOdcGmMj2AQpyvcMHIOEc9oy9xLK9lFolGJfdAXjeL6h4PmGZnTC BY72KLap/t+rGLVunKnfRf2bMCq1vjgXksWYnlQ91ksOKd6/Nw+cdDCL1JuHZsaqrCFCXQkLj5aU 7ni+XG1hGoFsNm2jp6ehPTNddcLfDJLj0+blKOSdFWlS4Z0MeXWc5vNKsWiwsNZkO/SN3JmR3/Zr 2WydEPfj2rkOW+nq7SmaU4IOtlLx1NAMZbF72td0gdLbW+eKhezHS7acRT4yOn+e6irpzfMitx6L IiE7qAfVyfzUYY49nzvWbon5S/zwgf3NEXwrAW4aBGmxshRAlkQPq0I18FF+QZpGgMFrlS2jV+KA Eg8H00RxHeImugvo1GGd+nktT46N4YvCEEHnvjnGLYwtC7OZmy9ZA8hgbCFGY2XJ4LDZZY17tbrF QOJnugNwHT0IL16qizfNBBtRK/GSwCzfkKfjRu6GHkz5DSNWb/LryeKNjwYWJEIYG+RXSGeRd6wY /5fc5KwBhNtoTJB6OFjMGoY3nQFqGMBT0PGXazDpSLYYBtbXkR832lXZhda3OhRA7NerfIP7lxj1 COX4LtfKtjS1auZArL9e1hMV3+S6n6oqIFHWna07vMiRd1x4jBpFdWaPaa6gsrQ8d3sLVz3Js4oM mM5H4F36oHJePJSz0IbfIlutkazds49futRdmcoy2HaihnLX6CsimGcuJ+d3LDZPoJCnoURR5wQi W5EXexNRVTEG+a8zXzXLZO6wbrf50qQbYjycdZIhtRS5dmN46ifH9+7/ktJx4getYbUf/dtRnaAk 4uzUbEEvF9PmwWyBvLPmKVZLK7+SzmfCXCyl2Xm5XsO8jj2iPtHg7gN8MtC6ZTodSV9LvMyUgRMj HB7UssadmLNz1O46KHKt35OCb1Ggo7UHDd2Iz9QF8U2VTEwj9NopSA/irRtZzxACretEndnC9ii7 kxzbupIrKAgrIC0btSPcNtT5Mpupjiw3i120aRaJs12yrbS/xpd4iyQCqktyadtS/hXSLoU3iAyv iecUi/pMpjrGMyZTXzws4j07oE518Vr74rFH5bJuNIsKEKaIqhBV05zympimpGCJ1p1LERM65/j1 ge0ZUajeppR6PqqDDkiQO05bdB10MOWbT5E+gy7RZ1DBrXu31e9AwdHTo60E0WczGvJ+cLGL+B2O 3GoW0ODd4Uk50LBM8o7sEln2slGqDbxEViWyaZCSU7Ydzud6h/XNzp1zlcaf0sV+9meTvCYhFweX MC0L29Fxt1ISCzQw9B4HzPDSVV/KtGcPM6L+IadOK6N0nLQ+zUHrU5yz2NCjtmDtZcWGUcVnUKnT I0p8clYwcr6rBmZF7uaSADAv5ufge+VysWOGgoQqpEG4n/+SBMmzYlFey4fHOWmGWE25ER8h+cOS aci0BqYGAEaWWbU6HwtsImyXYUIlfsT1uRsck37TESbNfMTTkod8xLNukmhWQg9f31fg+USW5a0S 2ChUEGj155c0hMTyzieehQcJhKrtquDkRVQ7ecuC0XqPdPyOeXyIQ/ti/gbq/Ima1TMykIfJeiVk MzWIBLrGlMg5z+MZEpEew2aPxmYbslKekjvHp046oPn5G3XMqv+Qj1cBZD9jHvZPCdfB9Za/FtRZ 1eNtILZmtQRT3mIp3AehvoIKpMqCFucsafbu9ZHtb5bc3Nyoy3PXKWj0g93Xy0Sstvr7zPNCM//7 Q0LHj2vfi9jq3Y6Y2kLmb1mP+8kzJWvO1Dpsyz7nzJTVzPvWFixYpRFuQL27CoYRtPfWneO+JdFk d/woC3vE+EfMa12HO+vCue021xaX4siVvPhtw3qquJm6+MynWq3LzExcz2kxHU0Tk+1SsQoAKnfe /vdt/n8AWrvG1w== """ import sys import base64 import zlib class DictImporter(object): def __init__(self, sources): self.sources = sources def find_module(self, fullname, path=None): if fullname == "argparse" and sys.version_info >= (2,7): # we were generated with = (3, 0): exec("def do_exec(co, loc): exec(co, loc)\n") import pickle sources = sources.encode("ascii") # ensure bytes sources = pickle.loads(zlib.decompress(base64.decodebytes(sources))) else: import cPickle as pickle exec("def do_exec(co, loc): exec co in loc\n") sources = pickle.loads(zlib.decompress(base64.decodestring(sources))) importer = DictImporter(sources) sys.meta_path.insert(0, importer) entry = "import pytest; raise SystemExit(pytest.cmdline.main())" do_exec(entry, locals()) # noqa rebulk-0.9.0/pylintrc0000664000175000017500000003052213113544037015372 0ustar toilaltoilal00000000000000[MASTER] # Specify a configuration file. #rcfile= # Python code to execute, usually for sys.path manipulation such as # pygtk.require(). #init-hook= # Add files or directories to the blacklist. They should be base names, not # paths. ignore=CVS # Pickle collected data for later comparisons. persistent=yes # List of plugins (as comma separated values of python modules names) to load, # usually to register additional checkers. load-plugins= # Use multiple processes to speed up Pylint. jobs=1 # Allow loading of arbitrary C extensions. Extensions are imported into the # active Python interpreter and may run arbitrary code. unsafe-load-any-extension=no # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may # run arbitrary code extension-pkg-whitelist= # Allow optimization of some AST trees. This will activate a peephole AST # optimizer, which will apply various small optimizations. For instance, it can # be used to obtain the result of joining multiple strings with the addition # operator. Joining a lot of strings can lead to a maximum recursion error in # Pylint and this flag can prevent that. It has one side effect, the resulting # AST will be different than the one from reality. optimize-ast=no [MESSAGES CONTROL] # Only show warnings with the listed confidence levels. Leave empty to show # all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED confidence= # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option # multiple time. See also the "--disable" option for examples. #enable= # Disable the message, report, category or checker with the given id(s). You # can either give multiple identifiers separated by comma (,) or put this # option multiple times (only on the command line, not in the configuration # file where it should appear only once).You can also use "--disable=all" to # disable everything first and then reenable specific checks. For example, if # you want to run only the similarities checker, you can use "--disable=all # --enable=similarities". If you want to run only the classes checker, but have # no Warning level messages displayed, use"--disable=all --enable=classes # --disable=W" disable=basestring-builtin,range-builtin-not-iterating,unichr-builtin,buffer-builtin,dict-iter-method,hex-method, setslice-method,long-suffix,parameter-unpacking,oct-method,old-raise-syntax,backtick,import-star-module-level, no-absolute-import,suppressed-message,nonzero-method,raw_input-builtin,reload-builtin,apply-builtin,using-cmp-argument, next-method-called,raising-string,execfile-builtin,file-builtin,cmp-builtin,useless-suppression,getslice-method, metaclass-assignment,cmp-method,round-builtin,dict-view-method,input-builtin,print-statement,indexing-exception, unpacking-in-except,delslice-method,standarderror-builtin,coerce-builtin,filter-builtin-not-iterating, map-builtin-not-iterating,old-ne-operator,long-builtin,intern-builtin,zip-builtin-not-iterating,reduce-builtin, unicode-builtin,old-division,xrange-builtin,old-octal-literal,coerce-method, too-few-public-methods,too-many-arguments,too-many-instance-attributes,bad-builtin,too-many-ancestors, too-few-format-args,fixme,duplicate-code,deprecated-lambda,cyclic-import, I [REPORTS] # Set the output format. Available formats are text, parseable, colorized, msvs # (visual studio) and html. You can also give a reporter class, eg # mypackage.mymodule.MyReporterClass. output-format=colorized # Put messages in a separate file for each module / package specified on the # command line instead of printing them on stdout. Reports (if any) will be # written in a file name "pylint_global.[txt|html]". files-output=no # Tells whether to display a full report or only the messages reports=no # Python expression which should return a note less than 10 (10 is the highest # note). You have access to the variables errors warning, statement which # respectively contain the number of errors / warnings messages and the total # number of statements analyzed. This is used by the global evaluation report # (RP0004). evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) # Template used to display messages. This is a python new-style format string # used to format the message information. See doc for all details #msg-template= [FORMAT] # Maximum number of characters on a single line. max-line-length=120 # Regexp for a line that is allowed to be longer than the limit. ignore-long-lines=^\s*(# )??$ # Allow the body of an if to be on the same line as the test if there is no # else. single-line-if-stmt=no # List of optional constructs for which whitespace checking is disabled. `dict- # separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. # `trailing-comma` allows a space between comma and closing bracket: (a, ). # `empty-line` allows space-only lines. no-space-check=trailing-comma,dict-separator # Maximum number of lines in a module max-module-lines=1000 # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 # tab). indent-string=' ' # Number of spaces of indent required inside a hanging or continued line. indent-after-paren=4 # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. expected-line-ending-format= [TYPECHECK] # Tells whether missing members accessed in mixin class should be ignored. A # mixin class is detected if its name ends with "mixin" (case insensitive). ignore-mixin-members=yes # List of module names for which member attributes should not be checked # (useful for modules/projects where namespaces are manipulated during runtime # and thus existing member attributes cannot be deduced by static analysis. It # supports qualified module names, as well as Unix pattern matching. ignored-modules= # List of classes names for which member attributes should not be checked # (useful for classes with attributes dynamically set). This supports can work # with qualified names. ignored-classes= # List of members which are set dynamically and missed by pylint inference # system, and so shouldn't trigger E1101 when accessed. Python regular # expressions are accepted. generated-members= [BASIC] # List of builtins function names that should not be used, separated by a comma bad-functions=map,filter # Good variable names which should always be accepted, separated by a comma good-names=i,j,k,ex,Run,_ # Bad variable names which should always be refused, separated by a comma bad-names=foo,bar,baz,toto,tutu,tata # Colon-delimited sets of names that determine each other's naming style when # the name regexes allow several styles. name-group= # Include a hint for the correct naming format with invalid-name include-naming-hint=no # Regular expression matching correct constant names const-rgx=(([a-z_][a-z0-9_]*)|([A-Z_][A-Z0-9_]*)|(__.*__))$ # Naming hint for constant names const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ # Regular expression matching correct class names class-rgx=[A-Z_][a-zA-Z0-9]+$ # Naming hint for class names class-name-hint=[A-Z_][a-zA-Z0-9]+$ # Regular expression matching correct class attribute names class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ # Naming hint for class attribute names class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ # Regular expression matching correct argument names argument-rgx=[a-z_][a-z0-9_]{2,30}$ # Naming hint for argument names argument-name-hint=[a-z_][a-z0-9_]{2,30}$ # Regular expression matching correct function names function-rgx=[a-z_][a-z0-9_]{2,30}$ # Naming hint for function names function-name-hint=[a-z_][a-z0-9_]{2,30}$ # Regular expression matching correct variable names variable-rgx=[a-z_][a-z0-9_]{2,30}$ # Naming hint for variable names variable-name-hint=[a-z_][a-z0-9_]{2,30}$ # Regular expression matching correct method names method-rgx=[a-z_][a-z0-9_]{2,30}$ # Naming hint for method names method-name-hint=[a-z_][a-z0-9_]{2,30}$ # Regular expression matching correct attribute names attr-rgx=[a-z_][a-z0-9_]{2,30}$ # Naming hint for attribute names attr-name-hint=[a-z_][a-z0-9_]{2,30}$ # Regular expression matching correct inline iteration names inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ # Naming hint for inline iteration names inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ # Regular expression matching correct module names module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ # Naming hint for module names module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ # Regular expression which should only match function or class names that do # not require a docstring. no-docstring-rgx=^_ # Minimum line length for functions/classes that require docstrings, shorter # ones are exempt. docstring-min-length=-1 [ELIF] # Maximum number of nested blocks for function / method body max-nested-blocks=5 [SPELLING] # Spelling dictionary name. Available dictionaries: none. To make it working # install python-enchant package. spelling-dict= # List of comma separated words that should not be checked. spelling-ignore-words= # A path to a file that contains private dictionary; one word per line. spelling-private-dict-file= # Tells whether to store unknown words to indicated private dictionary in # --spelling-private-dict-file option instead of raising a message. spelling-store-unknown-words=no [VARIABLES] # Tells whether we should check for unused import in __init__ files. init-import=no # A regular expression matching the name of dummy variables (i.e. expectedly # not used). dummy-variables-rgx=_$|dummy # List of additional names supposed to be defined in builtins. Remember that # you should avoid to define new builtins when possible. additional-builtins= # List of strings which can identify a callback function by name. A callback # name must start or end with one of those strings. callbacks=cb_,_cb [LOGGING] # Logging modules to check that the string format arguments are in logging # function parameter format logging-modules=logging [SIMILARITIES] # Minimum lines number of a similarity. min-similarity-lines=4 # Ignore comments when computing similarities. ignore-comments=yes # Ignore docstrings when computing similarities. ignore-docstrings=yes # Ignore imports when computing similarities. ignore-imports=no [MISCELLANEOUS] # List of note tags to take in consideration, separated by a comma. notes=FIXME,XXX,TODO [DESIGN] # Maximum number of arguments for function / method max-args=5 # Argument names that match this expression will be ignored. Default to name # with leading underscore ignored-argument-names=_.* # Maximum number of locals for function / method body max-locals=15 # Maximum number of return / yield for function / method body max-returns=6 # Maximum number of branch for function / method body max-branches=12 # Maximum number of statements in function / method body max-statements=50 # Maximum number of parents for a class (see R0901). max-parents=7 # Maximum number of attributes for a class (see R0902). max-attributes=7 # Minimum number of public methods for a class (see R0903). min-public-methods=2 # Maximum number of public methods for a class (see R0904). max-public-methods=20 # Maximum number of boolean expressions in a if statement max-bool-expr=5 [IMPORTS] # Deprecated modules which should not be used, separated by a comma deprecated-modules=optparse # Create a graph of every (i.e. internal and external) dependencies in the # given file (report RP0402 must not be disabled) import-graph= # Create a graph of external dependencies in the given file (report RP0402 must # not be disabled) ext-import-graph= # Create a graph of internal dependencies in the given file (report RP0402 must # not be disabled) int-import-graph= [CLASSES] # List of method names used to declare (i.e. assign) instance attributes. defining-attr-methods=__init__,__new__,setUp # List of valid names for the first argument in a class method. valid-classmethod-first-arg=cls # List of valid names for the first argument in a metaclass class method. valid-metaclass-classmethod-first-arg=mcs # List of member names, which should be excluded from the protected access # warning. exclude-protected=_asdict,_fields,_replace,_source,_make [EXCEPTIONS] # Exceptions that will emit a warning when being caught. Defaults to # "Exception" overgeneral-exceptions=Exception rebulk-0.9.0/dev-requirements.txt0000664000175000017500000000001713113544037017637 0ustar toilaltoilal00000000000000-e .[dev,test] rebulk-0.9.0/MANIFEST.in0000664000175000017500000000013613113544037015337 0ustar toilaltoilal00000000000000include *.py include *.txt include *.ini include .coveragerc include LICENSE include pylintrc rebulk-0.9.0/pytest.ini0000664000175000017500000000014213113544037015627 0ustar toilaltoilal00000000000000[pytest] addopts = --ignore=setup.py --ignore=build --doctest-modules --doctest-glob='README.rst' rebulk-0.9.0/rebulk.egg-info/0000775000175000017500000000000013113544041016552 5ustar toilaltoilal00000000000000rebulk-0.9.0/rebulk.egg-info/zip-safe0000664000175000017500000000000113113544041020202 0ustar toilaltoilal00000000000000 rebulk-0.9.0/rebulk.egg-info/PKG-INFO0000664000175000017500000005711613113544041017661 0ustar toilaltoilal00000000000000Metadata-Version: 1.1 Name: rebulk Version: 0.9.0 Summary: Rebulk - Define simple search patterns in bulk to perform advanced matching on any string. Home-page: https://github.com/Toilal/rebulk/ Author: Rémi Alvergnat Author-email: toilal.dev@gmail.com License: MIT Download-URL: https://pypi.python.org/packages/source/r/rebulk/rebulk-0.9.0.tar.gz Description: ReBulk ======= .. image:: http://img.shields.io/pypi/v/rebulk.svg :target: https://pypi.python.org/pypi/rebulk :alt: Latest Version .. image:: http://img.shields.io/badge/license-MIT-blue.svg :target: https://pypi.python.org/pypi/rebulk :alt: MIT License .. image:: http://img.shields.io/travis/Toilal/rebulk.svg :target: http://travis-ci.org/Toilal/rebulk?branch=master :alt: Build Status .. image:: http://img.shields.io/coveralls/Toilal/rebulk.svg :target: https://coveralls.io/r/Toilal/rebulk?branch=master :alt: Coveralls ReBulk is a python library that performs advanced searches in strings that would be hard to implement using `re module`_ or `String methods`_ only. It includes some features like ``Patterns``, ``Match``, ``Rule`` that allows developers to build a custom and complex string matcher using a readable and extendable API. This project is hosted on GitHub: ``_ Install ------- .. code-block:: sh $ pip install rebulk Usage ------ Regular expression, string and function based patterns are declared in a ``Rebulk`` object. It use a fluent API to chain ``string``, ``regex``, and ``functional`` methods to define various patterns types. .. code-block:: python >>> from rebulk import Rebulk >>> bulk = Rebulk().string('brown').regex(r'qu\w+').functional(lambda s: (20, 25)) When ``Rebulk`` object is fully configured, you can call ``matches`` method with an input string to retrieve all ``Match`` objects found by registered pattern. .. code-block:: python >>> bulk.matches("The quick brown fox jumps over the lazy dog") [, , ] If multiple ``Match`` objects are found at the same position, only the longer one is kept. .. code-block:: python >>> bulk = Rebulk().string('lakers').string('la') >>> bulk.matches("the lakers are from la") [, ] String Patterns --------------- String patterns are based on `str.find`_ method to find matches, but returns all matches in the string. ``ignore_case`` can be enabled to ignore case. .. code-block:: python >>> Rebulk().string('la').matches("lalalilala") [, , , ] >>> Rebulk().string('la').matches("LalAlilAla") [] >>> Rebulk().string('la', ignore_case=True).matches("LalAlilAla") [, , , ] You can define several patterns with a single ``string`` method call. .. code-block:: python >>> Rebulk().string('Winter', 'coming').matches("Winter is coming...") [, ] Regular Expression Patterns --------------------------- Regular Expression patterns are based on a compiled regular expression. `re.finditer`_ method is used to find matches. If `regex module`_ is available, it will be used by rebulk instead of default `re module`_. .. code-block:: python >>> Rebulk().regex(r'l\w').matches("lolita") [, ] You can define several patterns with a single ``regex`` method call. .. code-block:: python >>> Rebulk().regex(r'Wint\wr', 'com\w{3}').matches("Winter is coming...") [, ] All keyword arguments from `re.compile`_ are supported. .. code-block:: python >>> import re # import required for flags constant >>> Rebulk().regex('L[A-Z]KERS', flags=re.IGNORECASE) \ ... .matches("The LaKeRs are from La") [] >>> Rebulk().regex('L[A-Z]', 'L[A-Z]KERS', flags=re.IGNORECASE) \ ... .matches("The LaKeRs are from La") [, ] >>> Rebulk().regex(('L[A-Z]', re.IGNORECASE), ('L[a-z]KeRs')) \ ... .matches("The LaKeRs are from La") [, ] If `regex module`_ is available, it automatically supports repeated captures. .. code-block:: python >>> # If regex module is available, repeated_captures is True by default. >>> matches = Rebulk().regex(r'(\d+)(?:-(\d+))+').matches("01-02-03-04") >>> matches[0].children # doctest:+SKIP [<01:(0, 2)>, <02:(3, 5)>, <03:(6, 8)>, <04:(9, 11)>] >>> # If regex module is not available, or if repeated_captures is forced to False. >>> matches = Rebulk().regex(r'(\d+)(?:-(\d+))+', repeated_captures=False) \ ... .matches("01-02-03-04") >>> matches[0].children [<01:(0, 2)+initiator=01-02-03-04>, <04:(9, 11)+initiator=01-02-03-04>] - ``abbreviations`` Defined as a list of 2-tuple, each tuple is an abbreviation. It simply replace ``tuple[0]`` with ``tuple[1]`` in the expression. >>> Rebulk().regex(r'Custom-separators', abbreviations=[("-", "[\W_]+")])\ ... .matches("Custom_separators using-abbreviations") [] Functional Patterns ------------------- Functional Patterns are based on the evaluation of a function. The function should have the same parameters as ``Rebulk.matches`` method, that is the input string, and must return at least start index and end index of the ``Match`` object. .. code-block:: python >>> def func(string): ... index = string.find('?') ... if index > -1: ... return 0, index - 11 >>> Rebulk().functional(func).matches("Why do simple ? Forget about it ...") [] You can also return a dict of keywords arguments for ``Match`` object. You can define several patterns with a single ``functional`` method call, and function used can return multiple matches. Chain Patterns -------------- Chain Patterns are ordered composition of string, functional and regex patterns. Repeater can be set to define repetition on chain part. .. code-block:: python >>> r = Rebulk().chain(children=True, formatter={'episode': int, 'version': int}, flags=re.IGNORECASE)\ ... .regex(r'e(?P\d{1,4})').repeater(1)\ ... .regex(r'v(?P\d+)').repeater('?')\ ... .regex(r'[ex-](?P\d{1,4})').repeater('*')\ ... .close() # .repeater(1) could be omitted as it's the default behavior >>> r.matches("This is E14v2-15-16-17").to_dict() # converts matches to dict MatchesDict([('episode', [14, 15, 16, 17]), ('version', 2)]) Patterns parameters ------------------- All patterns have options that can be given as keyword arguments. - ``validator`` Function to validate ``Match`` value given by the pattern. Can also be a ``dict``, to use ``validator`` with pattern named with key. .. code-block:: python >>> def check_leap_year(match): ... return int(match.value) in [1980, 1984, 1988] >>> matches = Rebulk().regex(r'\d{4}', validator=check_leap_year) \ ... .matches("In year 1982 ...") >>> len(matches) 0 >>> matches = Rebulk().regex(r'\d{4}', validator=check_leap_year) \ ... .matches("In year 1984 ...") >>> len(matches) 1 Some base validator functions are available in ``rebulk.validators`` module. Most of those functions have to be configured using ``functools.partial`` to map them to function accepting a single ``match`` argument. - ``formatter`` Function to convert ``Match`` value given by the pattern. Can also be a ``dict``, to use ``formatter`` with matches named with key. .. code-block:: python >>> def year_formatter(value): ... return int(value) >>> matches = Rebulk().regex(r'\d{4}', formatter=year_formatter) \ ... .matches("In year 1982 ...") >>> isinstance(matches[0].value, int) True - ``post_processor`` Function to change the default output of the pattern. Function parameters are Matches list and Pattern object. - ``name`` The name of the pattern. It is automatically passed to ``Match`` objects generated by this pattern. - ``tags`` A list of string that qualifies this pattern. - ``value`` Override value property for generated ``Match`` objects. Can also be a ``dict``, to use ``value`` with pattern named with key. - ``validate_all`` By default, validator is called for returned ``Match`` objects only. Enable this option to validate them all, parent and children included. - ``format_all`` By default, formatter is called for returned ``Match`` values only. Enable this option to format them all, parent and children included. - ``disabled`` A ``function(context)`` to disable the pattern if returning ``True``. - ``children`` If ``True``, all children ``Match`` objects will be retrieved instead of a single parent ``Match`` object. - ``private`` If ``True``, ``Match`` objects generated from this pattern are available internally only. They will be removed at the end of ``Rebulk.matches`` method call. - ``private_parent`` Force parent matches to be returned and flag them as private. - ``private_children`` Force children matches to be returned and flag them as private. - ``private_names`` Matches names that will be declared as private - ``ignore_names`` Matches names that will be ignored from the pattern output, after validation. - ``marker`` If ``true``, ``Match`` objects generated from this pattern will be markers matches instead of standard matches. They won't be included in ``Matches`` sequence, but will be available in ``Matches.markers`` sequence (see ``Markers`` section). Match ----- A ``Match`` object is the result created by a registered pattern. It has a ``value`` property defined, and position indices are available through ``start``, ``end`` and ``span`` properties. In some case, it contains children ``Match`` objects in ``children`` property, and each child ``Match`` object reference its parent in ``parent`` property. Also, a ``name`` property can be defined for the match. If groups are defined in a Regular Expression pattern, each group match will be converted to a single ``Match`` object. If a group has a name defined (``(?Pgroup)``), it is set as ``name`` property in a child ``Match`` object. The whole regexp match (``re.group(0)``) will be converted to the main ``Match`` object, and all subgroups (1, 2, ... n) will be converted to ``children`` matches of the main ``Match`` object. .. code-block:: python >>> matches = Rebulk() \ ... .regex(r"One, (?P\w+), Two, (?P\w+), Three, (?P\w+)") \ ... .matches("Zero, 0, One, 1, Two, 2, Three, 3, Four, 4") >>> matches [] >>> for child in matches[0].children: ... '%s = %s' % (child.name, child.value) 'one = 1' 'two = 2' 'three = 3' It's possible to retrieve only children by using ``children`` parameters. You can also customize the way structure is generated with ``every``, ``private_parent`` and ``private_children`` parameters. .. code-block:: python >>> matches = Rebulk() \ ... .regex(r"One, (?P\w+), Two, (?P\w+), Three, (?P\w+)", children=True) \ ... .matches("Zero, 0, One, 1, Two, 2, Three, 3, Four, 4") >>> matches [<1:(14, 15)+name=one+initiator=One, 1, Two, 2, Three, 3>, <2:(22, 23)+name=two+initiator=One, 1, Two, 2, Three, 3>, <3:(32, 33)+name=three+initiator=One, 1, Two, 2, Three, 3>] Match object has the following properties that can be given to Pattern objects - ``formatter`` Function to convert ``Match`` value given by the pattern. Can also be a ``dict``, to use ``formatter`` with matches named with key. .. code-block:: python >>> def year_formatter(value): ... return int(value) >>> matches = Rebulk().regex(r'\d{4}', formatter=year_formatter) \ ... .matches("In year 1982 ...") >>> isinstance(matches[0].value, int) True - ``format_all`` By default, formatter is called for returned ``Match`` values only. Enable this option to format them all, parent and children included. - ``conflict_solver`` A ``function(match, conflicting_match)`` used to solve conflict. Returned object will be removed from matches by ``ConflictSolver`` default rule. If ``__default__`` string is returned, it will fallback to default behavior keeping longer match. Matches ------- A ``Matches`` object holds the result of ``Rebulk.matches`` method call. It's a sequence of ``Match`` objects and it behaves like a list. All methods accepts a ``predicate`` function to filter ``Match`` objects using a callable, and an ``index`` int to retrieve a single element from default returned matches. It has the following additional methods and properties on it. - ``starting(index, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that starts at given index. - ``ending(index, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that ends at given index. - ``previous(match, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that are previous and nearest to match. - ``next(match, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that are next and nearest to match. - ``tagged(tag, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that have the given tag defined. - ``named(name, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that have the given name. - ``range(start=0, end=None, predicate=None, index=None)`` Retrieves a list of ``Match`` objects for given range, sorted from start to end. - ``holes(start=0, end=None, formatter=None, ignore=None, predicate=None, index=None)`` Retrieves a list of *hole* ``Match`` objects for given range. A hole match is created for each range where no match is available. - ``conflicting(match, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that conflicts with given match. - ``chain_before(self, position, seps, start=0, predicate=None, index=None)``: Retrieves a list of chained matches, before position, matching predicate and separated by characters from seps only. - ``chain_after(self, position, seps, end=None, predicate=None, index=None)``: Retrieves a list of chained matches, after position, matching predicate and separated by characters from seps only. - ``at_match(match, predicate=None, index=None)`` Retrieves a list of ``Match`` objects at the same position as match. - ``at_span(span, predicate=None, index=None)`` Retrieves a list of ``Match`` objects from given (start, end) tuple. - ``at_index(pos, predicate=None, index=None)`` Retrieves a list of ``Match`` objects from given position. - ``names`` Retrieves a sequence of all ``Match.name`` properties. - ``tags`` Retrieves a sequence of all ``Match.tags`` properties. - ``to_dict(details=False, first_value=False, enforce_list=False)`` Convert to an ordered dict, with ``Match.name`` as key and ``Match.value`` as value. It's a subclass of `OrderedDict`_, that contains a ``matches`` property which is a dict with ``Match.name`` as key and list of ``Match`` objects as value. If ``first_value`` is ``True`` and distinct values are found for the same name, value will be wrapped to a list. If ``False``, first value only will be kept and values lists can be retrieved with ``values_list`` which is a dict with ``Match.name`` as key and list of ``Match.value`` as value. if ``enforce_list`` is ``True``, all values will be wrapped to a list, even if a single value is found. If ``details`` is True, ``Match.value`` objects are replaced with complete ``Match`` object. - ``markers`` A custom ``Matches`` sequences specialized for ``markers`` matches (see below) Markers ------- If you have defined some patterns with ``markers`` property, then ``Matches.markers`` points to a special ``Matches`` sequence that contains only ``markers`` matches. This sequence supports all methods from ``Matches``. Markers matches are not intended to be used in final result, but can be used to implement a ``Rule``. Rules ----- Rules are a convenient and readable way to implement advanced conditional logic involving several ``Match`` objects. When a rule is triggered, it can perform an action on ``Matches`` object, like filtering out, adding additional tags or renaming. Rules are implemented by extending the abstract ``Rule`` class. They are registered using ``Rebulk.rule`` method by giving either a ``Rule`` instance, a ``Rule`` class or a module containing ``Rule classes`` only. For a rule to be triggered, ``Rule.when`` method must return ``True``, or a non empty list of ``Match`` objects, or any other truthy object. When triggered, ``Rule.then`` method is called to perform the action with ``when_response`` parameter defined as the response of ``Rule.when`` call. Instead of implementing ``Rule.then`` method, you can define ``consequence`` class property with a Consequence classe or instance, like ``RemoveMatch``, ``RenameMatch`` or ``AppendMatch``. You can also use a list of consequence when required : ``when_response`` must then be iterable, and elements of this iterable will be given to each consequence in the same order. When many rules are registered, it can be useful to set ``priority`` class variable to define a priority integer between all rule executions (higher priorities will be executed first). You can also define ``dependency`` to declare another Rule class as dependency for the current rule, meaning that it will be executed before. For all rules with the same ``priority`` value, ``when`` is called before, and ``then`` is called after all. .. code-block:: python >>> from rebulk import Rule, RemoveMatch >>> class FirstOnlyRule(Rule): ... consequence = RemoveMatch ... ... def when(self, matches, context): ... grabbed = matches.named("grabbed", 0) ... if grabbed and matches.previous(grabbed): ... return grabbed >>> rebulk = Rebulk() >>> rebulk.regex("This match(.*?)grabbed", name="grabbed") <...Rebulk object ...> >>> rebulk.regex("if it's(.*?)first match", private=True) <...Rebulk object at ...> >>> rebulk.rules(FirstOnlyRule) <...Rebulk object at ...> >>> rebulk.matches("This match is grabbed only if it's the first match") [] >>> rebulk.matches("if it's NOT the first match, This match is NOT grabbed") [] .. _re module: https://docs.python.org/3/library/re.html .. _regex module: https://pypi.python.org/pypi/regex .. _String methods: https://docs.python.org/3/library/stdtypes.html#str .. _str.find: https://docs.python.org/3/library/stdtypes.html#str.find .. _re.finditer: https://docs.python.org/3/library/re.html#re.finditer .. _re.compile: https://docs.python.org/3/library/re.html#re.compile .. _OrderedDict: https://docs.python.org/2/library/collections.html#collections.OrderedDict Keywords: re regexp regular expression search pattern string match Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Topic :: Software Development :: Libraries :: Python Modules rebulk-0.9.0/rebulk.egg-info/SOURCES.txt0000664000175000017500000000202113113544041020431 0ustar toilaltoilal00000000000000.coveragerc LICENSE MANIFEST.in README.rst dev-requirements.txt pylintrc pytest.ini requirements.txt runtests.py setup.cfg setup.py tox.ini rebulk/__init__.py rebulk/__version__.py rebulk/chain.py rebulk/debug.py rebulk/formatters.py rebulk/introspector.py rebulk/loose.py rebulk/match.py rebulk/pattern.py rebulk/processors.py rebulk/rebulk.py rebulk/remodule.py rebulk/rules.py rebulk/toposort.py rebulk/utils.py rebulk/validators.py rebulk.egg-info/PKG-INFO rebulk.egg-info/SOURCES.txt rebulk.egg-info/dependency_links.txt rebulk.egg-info/requires.txt rebulk.egg-info/top_level.txt rebulk.egg-info/zip-safe rebulk/test/__init__.py rebulk/test/default_rules_module.py rebulk/test/rebulk_rules_module.py rebulk/test/rules_module.py rebulk/test/test_chain.py rebulk/test/test_debug.py rebulk/test/test_introspector.py rebulk/test/test_loose.py rebulk/test/test_match.py rebulk/test/test_pattern.py rebulk/test/test_processors.py rebulk/test/test_rebulk.py rebulk/test/test_rules.py rebulk/test/test_toposort.py rebulk/test/test_validators.pyrebulk-0.9.0/rebulk.egg-info/requires.txt0000664000175000017500000000016013113544041021147 0ustar toilaltoilal00000000000000six [dev] pytest>=2.7.3 pytest-capturelog zest.releaser[recommended] pylint tox [native] regex [test] pytest rebulk-0.9.0/rebulk.egg-info/dependency_links.txt0000664000175000017500000000000113113544041022620 0ustar toilaltoilal00000000000000 rebulk-0.9.0/rebulk.egg-info/top_level.txt0000664000175000017500000000000713113544041021301 0ustar toilaltoilal00000000000000rebulk rebulk-0.9.0/setup.cfg0000664000175000017500000000022613113544041015415 0ustar toilaltoilal00000000000000[zest.releaser] python-file-with-version = rebulk/__version__.py [aliases] test = pytest [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 rebulk-0.9.0/tox.ini0000664000175000017500000000054413113544037015117 0ustar toilaltoilal00000000000000[tox] envlist = py26,py27,py33,py34,py35,pypy [testenv:py26] commands = {envbindir}/pip install -e .[dev] {envpython} setup.py test [testenv:py35] commands = {envbindir}/pip install -e .[dev] {envpython} setup.py test [testenv] commands = {envbindir}/pip install -e .[dev] {envbindir}/pylint rebulk {envpython} setup.py test rebulk-0.9.0/README.rst0000664000175000017500000004505413113544037015300 0ustar toilaltoilal00000000000000ReBulk ======= .. image:: http://img.shields.io/pypi/v/rebulk.svg :target: https://pypi.python.org/pypi/rebulk :alt: Latest Version .. image:: http://img.shields.io/badge/license-MIT-blue.svg :target: https://pypi.python.org/pypi/rebulk :alt: MIT License .. image:: http://img.shields.io/travis/Toilal/rebulk.svg :target: http://travis-ci.org/Toilal/rebulk?branch=master :alt: Build Status .. image:: http://img.shields.io/coveralls/Toilal/rebulk.svg :target: https://coveralls.io/r/Toilal/rebulk?branch=master :alt: Coveralls ReBulk is a python library that performs advanced searches in strings that would be hard to implement using `re module`_ or `String methods`_ only. It includes some features like ``Patterns``, ``Match``, ``Rule`` that allows developers to build a custom and complex string matcher using a readable and extendable API. This project is hosted on GitHub: ``_ Install ------- .. code-block:: sh $ pip install rebulk Usage ------ Regular expression, string and function based patterns are declared in a ``Rebulk`` object. It use a fluent API to chain ``string``, ``regex``, and ``functional`` methods to define various patterns types. .. code-block:: python >>> from rebulk import Rebulk >>> bulk = Rebulk().string('brown').regex(r'qu\w+').functional(lambda s: (20, 25)) When ``Rebulk`` object is fully configured, you can call ``matches`` method with an input string to retrieve all ``Match`` objects found by registered pattern. .. code-block:: python >>> bulk.matches("The quick brown fox jumps over the lazy dog") [, , ] If multiple ``Match`` objects are found at the same position, only the longer one is kept. .. code-block:: python >>> bulk = Rebulk().string('lakers').string('la') >>> bulk.matches("the lakers are from la") [, ] String Patterns --------------- String patterns are based on `str.find`_ method to find matches, but returns all matches in the string. ``ignore_case`` can be enabled to ignore case. .. code-block:: python >>> Rebulk().string('la').matches("lalalilala") [, , , ] >>> Rebulk().string('la').matches("LalAlilAla") [] >>> Rebulk().string('la', ignore_case=True).matches("LalAlilAla") [, , , ] You can define several patterns with a single ``string`` method call. .. code-block:: python >>> Rebulk().string('Winter', 'coming').matches("Winter is coming...") [, ] Regular Expression Patterns --------------------------- Regular Expression patterns are based on a compiled regular expression. `re.finditer`_ method is used to find matches. If `regex module`_ is available, it will be used by rebulk instead of default `re module`_. .. code-block:: python >>> Rebulk().regex(r'l\w').matches("lolita") [, ] You can define several patterns with a single ``regex`` method call. .. code-block:: python >>> Rebulk().regex(r'Wint\wr', 'com\w{3}').matches("Winter is coming...") [, ] All keyword arguments from `re.compile`_ are supported. .. code-block:: python >>> import re # import required for flags constant >>> Rebulk().regex('L[A-Z]KERS', flags=re.IGNORECASE) \ ... .matches("The LaKeRs are from La") [] >>> Rebulk().regex('L[A-Z]', 'L[A-Z]KERS', flags=re.IGNORECASE) \ ... .matches("The LaKeRs are from La") [, ] >>> Rebulk().regex(('L[A-Z]', re.IGNORECASE), ('L[a-z]KeRs')) \ ... .matches("The LaKeRs are from La") [, ] If `regex module`_ is available, it automatically supports repeated captures. .. code-block:: python >>> # If regex module is available, repeated_captures is True by default. >>> matches = Rebulk().regex(r'(\d+)(?:-(\d+))+').matches("01-02-03-04") >>> matches[0].children # doctest:+SKIP [<01:(0, 2)>, <02:(3, 5)>, <03:(6, 8)>, <04:(9, 11)>] >>> # If regex module is not available, or if repeated_captures is forced to False. >>> matches = Rebulk().regex(r'(\d+)(?:-(\d+))+', repeated_captures=False) \ ... .matches("01-02-03-04") >>> matches[0].children [<01:(0, 2)+initiator=01-02-03-04>, <04:(9, 11)+initiator=01-02-03-04>] - ``abbreviations`` Defined as a list of 2-tuple, each tuple is an abbreviation. It simply replace ``tuple[0]`` with ``tuple[1]`` in the expression. >>> Rebulk().regex(r'Custom-separators', abbreviations=[("-", "[\W_]+")])\ ... .matches("Custom_separators using-abbreviations") [] Functional Patterns ------------------- Functional Patterns are based on the evaluation of a function. The function should have the same parameters as ``Rebulk.matches`` method, that is the input string, and must return at least start index and end index of the ``Match`` object. .. code-block:: python >>> def func(string): ... index = string.find('?') ... if index > -1: ... return 0, index - 11 >>> Rebulk().functional(func).matches("Why do simple ? Forget about it ...") [] You can also return a dict of keywords arguments for ``Match`` object. You can define several patterns with a single ``functional`` method call, and function used can return multiple matches. Chain Patterns -------------- Chain Patterns are ordered composition of string, functional and regex patterns. Repeater can be set to define repetition on chain part. .. code-block:: python >>> r = Rebulk().chain(children=True, formatter={'episode': int, 'version': int}, flags=re.IGNORECASE)\ ... .regex(r'e(?P\d{1,4})').repeater(1)\ ... .regex(r'v(?P\d+)').repeater('?')\ ... .regex(r'[ex-](?P\d{1,4})').repeater('*')\ ... .close() # .repeater(1) could be omitted as it's the default behavior >>> r.matches("This is E14v2-15-16-17").to_dict() # converts matches to dict MatchesDict([('episode', [14, 15, 16, 17]), ('version', 2)]) Patterns parameters ------------------- All patterns have options that can be given as keyword arguments. - ``validator`` Function to validate ``Match`` value given by the pattern. Can also be a ``dict``, to use ``validator`` with pattern named with key. .. code-block:: python >>> def check_leap_year(match): ... return int(match.value) in [1980, 1984, 1988] >>> matches = Rebulk().regex(r'\d{4}', validator=check_leap_year) \ ... .matches("In year 1982 ...") >>> len(matches) 0 >>> matches = Rebulk().regex(r'\d{4}', validator=check_leap_year) \ ... .matches("In year 1984 ...") >>> len(matches) 1 Some base validator functions are available in ``rebulk.validators`` module. Most of those functions have to be configured using ``functools.partial`` to map them to function accepting a single ``match`` argument. - ``formatter`` Function to convert ``Match`` value given by the pattern. Can also be a ``dict``, to use ``formatter`` with matches named with key. .. code-block:: python >>> def year_formatter(value): ... return int(value) >>> matches = Rebulk().regex(r'\d{4}', formatter=year_formatter) \ ... .matches("In year 1982 ...") >>> isinstance(matches[0].value, int) True - ``post_processor`` Function to change the default output of the pattern. Function parameters are Matches list and Pattern object. - ``name`` The name of the pattern. It is automatically passed to ``Match`` objects generated by this pattern. - ``tags`` A list of string that qualifies this pattern. - ``value`` Override value property for generated ``Match`` objects. Can also be a ``dict``, to use ``value`` with pattern named with key. - ``validate_all`` By default, validator is called for returned ``Match`` objects only. Enable this option to validate them all, parent and children included. - ``format_all`` By default, formatter is called for returned ``Match`` values only. Enable this option to format them all, parent and children included. - ``disabled`` A ``function(context)`` to disable the pattern if returning ``True``. - ``children`` If ``True``, all children ``Match`` objects will be retrieved instead of a single parent ``Match`` object. - ``private`` If ``True``, ``Match`` objects generated from this pattern are available internally only. They will be removed at the end of ``Rebulk.matches`` method call. - ``private_parent`` Force parent matches to be returned and flag them as private. - ``private_children`` Force children matches to be returned and flag them as private. - ``private_names`` Matches names that will be declared as private - ``ignore_names`` Matches names that will be ignored from the pattern output, after validation. - ``marker`` If ``true``, ``Match`` objects generated from this pattern will be markers matches instead of standard matches. They won't be included in ``Matches`` sequence, but will be available in ``Matches.markers`` sequence (see ``Markers`` section). Match ----- A ``Match`` object is the result created by a registered pattern. It has a ``value`` property defined, and position indices are available through ``start``, ``end`` and ``span`` properties. In some case, it contains children ``Match`` objects in ``children`` property, and each child ``Match`` object reference its parent in ``parent`` property. Also, a ``name`` property can be defined for the match. If groups are defined in a Regular Expression pattern, each group match will be converted to a single ``Match`` object. If a group has a name defined (``(?Pgroup)``), it is set as ``name`` property in a child ``Match`` object. The whole regexp match (``re.group(0)``) will be converted to the main ``Match`` object, and all subgroups (1, 2, ... n) will be converted to ``children`` matches of the main ``Match`` object. .. code-block:: python >>> matches = Rebulk() \ ... .regex(r"One, (?P\w+), Two, (?P\w+), Three, (?P\w+)") \ ... .matches("Zero, 0, One, 1, Two, 2, Three, 3, Four, 4") >>> matches [] >>> for child in matches[0].children: ... '%s = %s' % (child.name, child.value) 'one = 1' 'two = 2' 'three = 3' It's possible to retrieve only children by using ``children`` parameters. You can also customize the way structure is generated with ``every``, ``private_parent`` and ``private_children`` parameters. .. code-block:: python >>> matches = Rebulk() \ ... .regex(r"One, (?P\w+), Two, (?P\w+), Three, (?P\w+)", children=True) \ ... .matches("Zero, 0, One, 1, Two, 2, Three, 3, Four, 4") >>> matches [<1:(14, 15)+name=one+initiator=One, 1, Two, 2, Three, 3>, <2:(22, 23)+name=two+initiator=One, 1, Two, 2, Three, 3>, <3:(32, 33)+name=three+initiator=One, 1, Two, 2, Three, 3>] Match object has the following properties that can be given to Pattern objects - ``formatter`` Function to convert ``Match`` value given by the pattern. Can also be a ``dict``, to use ``formatter`` with matches named with key. .. code-block:: python >>> def year_formatter(value): ... return int(value) >>> matches = Rebulk().regex(r'\d{4}', formatter=year_formatter) \ ... .matches("In year 1982 ...") >>> isinstance(matches[0].value, int) True - ``format_all`` By default, formatter is called for returned ``Match`` values only. Enable this option to format them all, parent and children included. - ``conflict_solver`` A ``function(match, conflicting_match)`` used to solve conflict. Returned object will be removed from matches by ``ConflictSolver`` default rule. If ``__default__`` string is returned, it will fallback to default behavior keeping longer match. Matches ------- A ``Matches`` object holds the result of ``Rebulk.matches`` method call. It's a sequence of ``Match`` objects and it behaves like a list. All methods accepts a ``predicate`` function to filter ``Match`` objects using a callable, and an ``index`` int to retrieve a single element from default returned matches. It has the following additional methods and properties on it. - ``starting(index, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that starts at given index. - ``ending(index, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that ends at given index. - ``previous(match, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that are previous and nearest to match. - ``next(match, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that are next and nearest to match. - ``tagged(tag, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that have the given tag defined. - ``named(name, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that have the given name. - ``range(start=0, end=None, predicate=None, index=None)`` Retrieves a list of ``Match`` objects for given range, sorted from start to end. - ``holes(start=0, end=None, formatter=None, ignore=None, predicate=None, index=None)`` Retrieves a list of *hole* ``Match`` objects for given range. A hole match is created for each range where no match is available. - ``conflicting(match, predicate=None, index=None)`` Retrieves a list of ``Match`` objects that conflicts with given match. - ``chain_before(self, position, seps, start=0, predicate=None, index=None)``: Retrieves a list of chained matches, before position, matching predicate and separated by characters from seps only. - ``chain_after(self, position, seps, end=None, predicate=None, index=None)``: Retrieves a list of chained matches, after position, matching predicate and separated by characters from seps only. - ``at_match(match, predicate=None, index=None)`` Retrieves a list of ``Match`` objects at the same position as match. - ``at_span(span, predicate=None, index=None)`` Retrieves a list of ``Match`` objects from given (start, end) tuple. - ``at_index(pos, predicate=None, index=None)`` Retrieves a list of ``Match`` objects from given position. - ``names`` Retrieves a sequence of all ``Match.name`` properties. - ``tags`` Retrieves a sequence of all ``Match.tags`` properties. - ``to_dict(details=False, first_value=False, enforce_list=False)`` Convert to an ordered dict, with ``Match.name`` as key and ``Match.value`` as value. It's a subclass of `OrderedDict`_, that contains a ``matches`` property which is a dict with ``Match.name`` as key and list of ``Match`` objects as value. If ``first_value`` is ``True`` and distinct values are found for the same name, value will be wrapped to a list. If ``False``, first value only will be kept and values lists can be retrieved with ``values_list`` which is a dict with ``Match.name`` as key and list of ``Match.value`` as value. if ``enforce_list`` is ``True``, all values will be wrapped to a list, even if a single value is found. If ``details`` is True, ``Match.value`` objects are replaced with complete ``Match`` object. - ``markers`` A custom ``Matches`` sequences specialized for ``markers`` matches (see below) Markers ------- If you have defined some patterns with ``markers`` property, then ``Matches.markers`` points to a special ``Matches`` sequence that contains only ``markers`` matches. This sequence supports all methods from ``Matches``. Markers matches are not intended to be used in final result, but can be used to implement a ``Rule``. Rules ----- Rules are a convenient and readable way to implement advanced conditional logic involving several ``Match`` objects. When a rule is triggered, it can perform an action on ``Matches`` object, like filtering out, adding additional tags or renaming. Rules are implemented by extending the abstract ``Rule`` class. They are registered using ``Rebulk.rule`` method by giving either a ``Rule`` instance, a ``Rule`` class or a module containing ``Rule classes`` only. For a rule to be triggered, ``Rule.when`` method must return ``True``, or a non empty list of ``Match`` objects, or any other truthy object. When triggered, ``Rule.then`` method is called to perform the action with ``when_response`` parameter defined as the response of ``Rule.when`` call. Instead of implementing ``Rule.then`` method, you can define ``consequence`` class property with a Consequence classe or instance, like ``RemoveMatch``, ``RenameMatch`` or ``AppendMatch``. You can also use a list of consequence when required : ``when_response`` must then be iterable, and elements of this iterable will be given to each consequence in the same order. When many rules are registered, it can be useful to set ``priority`` class variable to define a priority integer between all rule executions (higher priorities will be executed first). You can also define ``dependency`` to declare another Rule class as dependency for the current rule, meaning that it will be executed before. For all rules with the same ``priority`` value, ``when`` is called before, and ``then`` is called after all. .. code-block:: python >>> from rebulk import Rule, RemoveMatch >>> class FirstOnlyRule(Rule): ... consequence = RemoveMatch ... ... def when(self, matches, context): ... grabbed = matches.named("grabbed", 0) ... if grabbed and matches.previous(grabbed): ... return grabbed >>> rebulk = Rebulk() >>> rebulk.regex("This match(.*?)grabbed", name="grabbed") <...Rebulk object ...> >>> rebulk.regex("if it's(.*?)first match", private=True) <...Rebulk object at ...> >>> rebulk.rules(FirstOnlyRule) <...Rebulk object at ...> >>> rebulk.matches("This match is grabbed only if it's the first match") [] >>> rebulk.matches("if it's NOT the first match, This match is NOT grabbed") [] .. _re module: https://docs.python.org/3/library/re.html .. _regex module: https://pypi.python.org/pypi/regex .. _String methods: https://docs.python.org/3/library/stdtypes.html#str .. _str.find: https://docs.python.org/3/library/stdtypes.html#str.find .. _re.finditer: https://docs.python.org/3/library/re.html#re.finditer .. _re.compile: https://docs.python.org/3/library/re.html#re.compile .. _OrderedDict: https://docs.python.org/2/library/collections.html#collections.OrderedDict rebulk-0.9.0/LICENSE0000664000175000017500000000207313113544037014610 0ustar toilaltoilal00000000000000The MIT License (MIT) Copyright (c) 2015 Rémi Alvergnat Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rebulk-0.9.0/rebulk/0000775000175000017500000000000013113544041015060 5ustar toilaltoilal00000000000000rebulk-0.9.0/rebulk/validators.py0000664000175000017500000000306513113544037017613 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Validator functions to use in patterns. All those function have last argument as match, so it's possible to use functools.partial to bind previous arguments. """ def chars_before(chars, match): """ Validate the match if left character is in a given sequence. :param chars: :type chars: :param match: :type match: :return: :rtype: """ if match.start <= 0: return True return match.input_string[match.start - 1] in chars def chars_after(chars, match): """ Validate the match if right character is in a given sequence. :param chars: :type chars: :param match: :type match: :return: :rtype: """ if match.end >= len(match.input_string): return True return match.input_string[match.end] in chars def chars_surround(chars, match): """ Validate the match if surrounding characters are in a given sequence. :param chars: :type chars: :param match: :type match: :return: :rtype: """ return chars_before(chars, match) and chars_after(chars, match) def validators(*chained_validators): """ Creates a validator chain from several validator functions. :param chained_validators: :type chained_validators: :return: :rtype: """ def validator_chain(match): # pylint:disable=missing-docstring for chained_validator in chained_validators: if not chained_validator(match): return False return True return validator_chain rebulk-0.9.0/rebulk/chain.py0000664000175000017500000003577113113544037016536 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Chain patterns and handle repetiting capture group """ # pylint: disable=super-init-not-called import itertools from .loose import call, set_defaults from .match import Match, Matches from .pattern import Pattern, filter_match_kwargs from .remodule import re class _InvalidChainException(Exception): """ Internal exception raised when a chain is not valid """ pass class Chain(Pattern): """ Definition of a pattern chain to search for. """ def __init__(self, rebulk, chain_breaker=None, **kwargs): call(super(Chain, self).__init__, **kwargs) self._kwargs = kwargs self._match_kwargs = filter_match_kwargs(kwargs) self._defaults = {} self._regex_defaults = {} self._string_defaults = {} self._functional_defaults = {} if callable(chain_breaker): self.chain_breaker = chain_breaker else: self.chain_breaker = None self.rebulk = rebulk self.parts = [] def defaults(self, **kwargs): """ Define default keyword arguments for all patterns :param kwargs: :type kwargs: :return: :rtype: """ self._defaults = kwargs return self def regex_defaults(self, **kwargs): """ Define default keyword arguments for functional patterns. :param kwargs: :type kwargs: :return: :rtype: """ self._regex_defaults = kwargs return self def string_defaults(self, **kwargs): """ Define default keyword arguments for string patterns. :param kwargs: :type kwargs: :return: :rtype: """ self._string_defaults = kwargs return self def functional_defaults(self, **kwargs): """ Define default keyword arguments for functional patterns. :param kwargs: :type kwargs: :return: :rtype: """ self._functional_defaults = kwargs return self def chain(self): """ Add patterns chain, using configuration from this chain :return: :rtype: """ # pylint: disable=protected-access chain = self.rebulk.chain(**self._kwargs) chain._defaults = dict(self._defaults) chain._regex_defaults = dict(self._regex_defaults) chain._functional_defaults = dict(self._functional_defaults) chain._string_defaults = dict(self._string_defaults) return chain def regex(self, *pattern, **kwargs): """ Add re pattern :param pattern: :type pattern: :param kwargs: :type kwargs: :return: :rtype: """ set_defaults(self._kwargs, kwargs) set_defaults(self._regex_defaults, kwargs) set_defaults(self._defaults, kwargs) pattern = self.rebulk.build_re(*pattern, **kwargs) part = ChainPart(self, pattern) self.parts.append(part) return part def functional(self, *pattern, **kwargs): """ Add functional pattern :param pattern: :type pattern: :param kwargs: :type kwargs: :return: :rtype: """ set_defaults(self._kwargs, kwargs) set_defaults(self._functional_defaults, kwargs) set_defaults(self._defaults, kwargs) pattern = self.rebulk.build_functional(*pattern, **kwargs) part = ChainPart(self, pattern) self.parts.append(part) return part def string(self, *pattern, **kwargs): """ Add string pattern :param pattern: :type pattern: :param kwargs: :type kwargs: :return: :rtype: """ set_defaults(self._kwargs, kwargs) set_defaults(self._functional_defaults, kwargs) set_defaults(self._defaults, kwargs) pattern = self.rebulk.build_string(*pattern, **kwargs) part = ChainPart(self, pattern) self.parts.append(part) return part def close(self): """ Close chain builder to continue registering other pattern :return: :rtype: """ return self.rebulk def _match(self, pattern, input_string, context=None): # pylint: disable=too-many-locals,too-many-nested-blocks chain_matches = [] chain_input_string = input_string offset = 0 while offset < len(input_string): chain_found = False current_chain_matches = [] valid_chain = True is_chain_start = True for chain_part in self.parts: try: chain_part_matches, raw_chain_part_matches = Chain._match_chain_part(is_chain_start, chain_part, chain_input_string, context) Chain._fix_matches_offset(chain_part_matches, input_string, offset) Chain._fix_matches_offset(raw_chain_part_matches, input_string, offset) if raw_chain_part_matches: grouped_matches_dict = dict() for match_index, match in itertools.groupby(chain_part_matches, lambda m: m.match_index): grouped_matches_dict[match_index] = list(match) grouped_raw_matches_dict = dict() for match_index, raw_match in itertools.groupby(raw_chain_part_matches, lambda m: m.match_index): grouped_raw_matches_dict[match_index] = list(raw_match) for match_index, grouped_raw_matches in grouped_raw_matches_dict.items(): chain_found = True offset = grouped_raw_matches[-1].raw_end chain_input_string = input_string[offset:] if not chain_part.is_hidden: grouped_matches = grouped_matches_dict.get(match_index, []) if self._chain_breaker_eval(current_chain_matches + grouped_matches): current_chain_matches.extend(grouped_matches) except _InvalidChainException: valid_chain = False if current_chain_matches: offset = current_chain_matches[0].raw_end break is_chain_start = False if not chain_found: break if current_chain_matches and valid_chain: match = self._build_chain_match(current_chain_matches, input_string) chain_matches.append(match) return chain_matches def _match_parent(self, match, yield_parent): """ Handle a parent match :param match: :type match: :param yield_parent: :type yield_parent: :return: :rtype: """ ret = super(Chain, self)._match_parent(match, yield_parent) original_children = Matches(match.children) original_end = match.end while not ret and match.children: last_pattern = match.children[-1].pattern last_pattern_children = [child for child in match.children if child.pattern == last_pattern] last_pattern_groups_iter = itertools.groupby(last_pattern_children, lambda child: child.match_index) last_pattern_groups = {} for index, matches in last_pattern_groups_iter: last_pattern_groups[index] = list(matches) for index in reversed(list(last_pattern_groups)): last_matches = list(last_pattern_groups[index]) for last_match in last_matches: match.children.remove(last_match) match.end = match.children[-1].end if match.children else match.start ret = super(Chain, self)._match_parent(match, yield_parent) if ret: return True match.children = original_children match.end = original_end return ret def _build_chain_match(self, current_chain_matches, input_string): start = None end = None for match in current_chain_matches: if start is None or start > match.start: start = match.start if end is None or end < match.end: end = match.end match = call(Match, start, end, pattern=self, input_string=input_string, **self._match_kwargs) for chain_match in current_chain_matches: if chain_match.children: for child in chain_match.children: match.children.append(child) if chain_match not in match.children: match.children.append(chain_match) chain_match.parent = match return match def _chain_breaker_eval(self, matches): return not self.chain_breaker or not self.chain_breaker(Matches(matches)) @staticmethod def _fix_matches_offset(chain_part_matches, input_string, offset): for chain_part_match in chain_part_matches: if chain_part_match.input_string != input_string: chain_part_match.input_string = input_string chain_part_match.end += offset chain_part_match.start += offset if chain_part_match.children: Chain._fix_matches_offset(chain_part_match.children, input_string, offset) @staticmethod def _match_chain_part(is_chain_start, chain_part, chain_input_string, context): chain_part_matches, raw_chain_part_matches = chain_part.pattern.matches(chain_input_string, context, with_raw_matches=True) chain_part_matches = Chain._truncate_chain_part_matches(is_chain_start, chain_part_matches, chain_part, chain_input_string) raw_chain_part_matches = Chain._truncate_chain_part_matches(is_chain_start, raw_chain_part_matches, chain_part, chain_input_string) Chain._validate_chain_part_matches(raw_chain_part_matches, chain_part) return chain_part_matches, raw_chain_part_matches @staticmethod def _truncate_chain_part_matches(is_chain_start, chain_part_matches, chain_part, chain_input_string): if not chain_part_matches: return chain_part_matches if not is_chain_start: separator = chain_input_string[0:chain_part_matches[0].initiator.raw_start] if separator: return [] j = 1 for i in range(0, len(chain_part_matches) - 1): separator = chain_input_string[chain_part_matches[i].initiator.raw_end: chain_part_matches[i + 1].initiator.raw_start] if separator: break j += 1 truncated = chain_part_matches[:j] if chain_part.repeater_end is not None: truncated = [m for m in truncated if m.match_index < chain_part.repeater_end] return truncated @staticmethod def _validate_chain_part_matches(chain_part_matches, chain_part): max_match_index = -1 if chain_part_matches: max_match_index = max([m.match_index for m in chain_part_matches]) if max_match_index + 1 < chain_part.repeater_start: raise _InvalidChainException @property def match_options(self): return {} @property def patterns(self): return [self] def __repr__(self): defined = "" if self.defined_at: defined = "@%s" % (self.defined_at,) return "<%s%s:%s>" % (self.__class__.__name__, defined, self.parts) class ChainPart(object): """ Part of a pattern chain. """ def __init__(self, chain, pattern): self._chain = chain self.pattern = pattern self.repeater_start = 1 self.repeater_end = 1 self._hidden = False def chain(self): """ Add patterns chain, using configuration from this chain :return: :rtype: """ return self._chain.chain() def hidden(self, hidden=True): """ Hide chain part results from global chain result :param hidden: :type hidden: :return: :rtype: """ self._hidden = hidden return self @property def is_hidden(self): """ Check if the chain part is hidden :return: :rtype: """ return self._hidden def regex(self, *pattern, **kwargs): """ Add re pattern :param pattern: :type pattern: :param kwargs: :type kwargs: :return: :rtype: """ return self._chain.regex(*pattern, **kwargs) def functional(self, *pattern, **kwargs): """ Add functional pattern :param pattern: :type pattern: :param kwargs: :type kwargs: :return: :rtype: """ return self._chain.functional(*pattern, **kwargs) def string(self, *pattern, **kwargs): """ Add string pattern :param pattern: :type pattern: :param kwargs: :type kwargs: :return: :rtype: """ return self._chain.string(*pattern, **kwargs) def close(self): """ Close the chain builder to continue registering other patterns :return: :rtype: """ return self._chain.close() def repeater(self, value): """ Define the repeater of the current chain part. :param value: :type value: :return: :rtype: """ try: value = int(value) self.repeater_start = value self.repeater_end = value return self except ValueError: pass if value == '+': self.repeater_start = 1 self.repeater_end = None if value == '*': self.repeater_start = 0 self.repeater_end = None elif value == '?': self.repeater_start = 0 self.repeater_end = 1 else: match = re.match(r'\{\s*(\d*)\s*,?\s*(\d*)\s*\}', value) if match: start = match.group(1) end = match.group(2) if start or end: self.repeater_start = int(start) if start else 0 self.repeater_end = int(end) if end else None return self def __repr__(self): return "%s({%s,%s})" % (self.pattern, self.repeater_start, self.repeater_end) rebulk-0.9.0/rebulk/rules.py0000664000175000017500000002613113113544037016574 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Abstract rule class definition and rule engine implementation """ from abc import ABCMeta, abstractmethod import inspect from itertools import groupby from logging import getLogger import six from .utils import is_iterable from .toposort import toposort from . import debug log = getLogger(__name__).log @six.add_metaclass(ABCMeta) class Consequence(object): """ Definition of a consequence to apply. """ @abstractmethod def then(self, matches, when_response, context): # pragma: no cover """ Action implementation. :param matches: :type matches: rebulk.match.Matches :param context: :type context: :param when_response: return object from when call. :type when_response: object :return: True if the action was runned, False if it wasn't. :rtype: bool """ pass @six.add_metaclass(ABCMeta) class Condition(object): """ Definition of a condition to check. """ @abstractmethod def when(self, matches, context): # pragma: no cover """ Condition implementation. :param matches: :type matches: rebulk.match.Matches :param context: :type context: :return: truthy if rule should be triggered and execute then action, falsy if it should not. :rtype: object """ pass @six.add_metaclass(ABCMeta) class CustomRule(Condition, Consequence): """ Definition of a rule to apply """ # pylint: disable=no-self-use, unused-argument, abstract-method priority = 0 name = None dependency = None properties = {} def __init__(self, log_level=None): self.defined_at = debug.defined_at() if log_level is None and not hasattr(self, 'log_level'): self.log_level = debug.LOG_LEVEL def enabled(self, context): """ Disable rule. :param context: :type context: :return: True if rule is enabled, False if disabled :rtype: bool """ return True def __lt__(self, other): return self.priority > other.priority def __repr__(self): defined = "" if self.defined_at: defined = "@%s" % (self.defined_at,) return "<%s%s>" % (self.name if self.name else self.__class__.__name__, defined) def __eq__(self, other): return self.__class__ == other.__class__ def __hash__(self): return hash(self.__class__) class Rule(CustomRule): """ Definition of a rule to apply """ # pylint:disable=abstract-method consequence = None def then(self, matches, when_response, context): assert self.consequence if is_iterable(self.consequence): if not is_iterable(when_response): when_response = [when_response] iterator = iter(when_response) for cons in self.consequence: #pylint: disable=not-an-iterable if inspect.isclass(cons): cons = cons() cons.then(matches, next(iterator), context) else: cons = self.consequence if inspect.isclass(cons): cons = cons() # pylint:disable=not-callable cons.then(matches, when_response, context) class RemoveMatch(Consequence): # pylint: disable=abstract-method """ Remove matches returned by then """ def then(self, matches, when_response, context): if is_iterable(when_response): ret = [] when_response = list(when_response) for match in when_response: if match in matches: matches.remove(match) ret.append(match) return ret else: if when_response in matches: matches.remove(when_response) return when_response class AppendMatch(Consequence): # pylint: disable=abstract-method """ Append matches returned by then """ def __init__(self, match_name=None): self.match_name = match_name def then(self, matches, when_response, context): if is_iterable(when_response): ret = [] when_response = list(when_response) for match in when_response: if match not in matches: if self.match_name: match.name = self.match_name matches.append(match) ret.append(match) return ret else: if self.match_name: when_response.name = self.match_name if when_response not in matches: matches.append(when_response) return when_response class RenameMatch(Consequence): # pylint: disable=abstract-method """ Rename matches returned by then """ def __init__(self, match_name): self.match_name = match_name self.remove = RemoveMatch() self.append = AppendMatch() def then(self, matches, when_response, context): removed = self.remove.then(matches, when_response, context) if is_iterable(removed): removed = list(removed) for match in removed: match.name = self.match_name elif removed: removed.name = self.match_name if removed: self.append.then(matches, removed, context) class AppendTags(Consequence): # pylint: disable=abstract-method """ Add tags to returned matches """ def __init__(self, tags): self.tags = tags self.remove = RemoveMatch() self.append = AppendMatch() def then(self, matches, when_response, context): removed = self.remove.then(matches, when_response, context) if is_iterable(removed): removed = list(removed) for match in removed: match.tags.extend(self.tags) elif removed: removed.tags.extend(self.tags) # pylint: disable=no-member if removed: self.append.then(matches, removed, context) class RemoveTags(Consequence): # pylint: disable=abstract-method """ Remove tags from returned matches """ def __init__(self, tags): self.tags = tags self.remove = RemoveMatch() self.append = AppendMatch() def then(self, matches, when_response, context): removed = self.remove.then(matches, when_response, context) if is_iterable(removed): removed = list(removed) for match in removed: for tag in self.tags: if tag in match.tags: match.tags.remove(tag) elif removed: for tag in self.tags: if tag in removed.tags: # pylint: disable=no-member removed.tags.remove(tag) # pylint: disable=no-member if removed: self.append.then(matches, removed, context) class Rules(list): """ list of rules ready to execute. """ def __init__(self, *rules): super(Rules, self).__init__() self.load(*rules) def load(self, *rules): """ Load rules from a Rule module, class or instance :param rules: :type rules: :return: :rtype: """ for rule in rules: if inspect.ismodule(rule): self.load_module(rule) elif inspect.isclass(rule): self.load_class(rule) else: self.append(rule) def load_module(self, module): """ Load a rules module :param module: :type module: :return: :rtype: """ # pylint: disable=unused-variable for name, obj in inspect.getmembers(module, lambda member: hasattr(member, '__module__') and member.__module__ == module.__name__ and inspect.isclass): self.load_class(obj) def load_class(self, class_): """ Load a Rule class. :param class_: :type class_: :return: :rtype: """ self.append(class_()) def execute_all_rules(self, matches, context): """ Execute all rules from this rules list. All when condition with same priority will be performed before calling then actions. :param matches: :type matches: :param context: :type context: :return: :rtype: """ ret = [] for priority, priority_rules in groupby(sorted(self), lambda rule: rule.priority): sorted_rules = toposort_rules(list(priority_rules)) # Group by dependency graph toposort for rules_group in sorted_rules: rules_group = list(sorted(rules_group, key=self.index)) # Sort rules group based on initial ordering. group_log_level = None for rule in rules_group: if group_log_level is None or group_log_level < rule.log_level: group_log_level = rule.log_level log(group_log_level, "%s independent rule(s) at priority %s.", len(rules_group), priority) for rule in rules_group: when_response = execute_rule(rule, matches, context) if when_response is not None: ret.append((rule, when_response)) return ret def execute_rule(rule, matches, context): """ Execute the given rule. :param rule: :type rule: :param matches: :type matches: :param context: :type context: :return: :rtype: """ if rule.enabled(context): log(rule.log_level, "Checking rule condition: %s", rule) when_response = rule.when(matches, context) if when_response: log(rule.log_level, "Rule was triggered: %s", when_response) log(rule.log_level, "Running rule consequence: %s %s", rule, when_response) rule.then(matches, when_response, context) return when_response else: log(rule.log_level, "Rule is disabled: %s", rule) def toposort_rules(rules): """ Sort given rules using toposort with dependency parameter. :param rules: :type rules: :return: :rtype: """ graph = {} class_dict = {} for rule in rules: if rule.__class__ in class_dict: raise ValueError("Duplicate class rules are not allowed: %s" % rule.__class__) class_dict[rule.__class__] = rule for rule in rules: if not is_iterable(rule.dependency) and rule.dependency: rule_dependencies = [rule.dependency] else: rule_dependencies = rule.dependency dependencies = set() if rule_dependencies: for dependency in rule_dependencies: if inspect.isclass(dependency): dependency = class_dict.get(dependency) if dependency: dependencies.add(dependency) graph[rule] = dependencies return toposort(graph) rebulk-0.9.0/rebulk/match.py0000664000175000017500000006564613113544037016554 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Classes and functions related to matches """ import copy import itertools from collections import defaultdict, MutableSequence try: from collections import OrderedDict # pylint:disable=ungrouped-imports except ImportError: # pragma: no cover from ordereddict import OrderedDict # pylint:disable=import-error import six from .loose import ensure_list, filter_index from .utils import is_iterable from .debug import defined_at class MatchesDict(OrderedDict): """ A custom dict with matches property. """ def __init__(self): super(MatchesDict, self).__init__() self.matches = defaultdict(list) self.values_list = defaultdict(list) class _BaseMatches(MutableSequence): """ A custom list[Match] that automatically maintains name, tag, start and end lookup structures. """ _base = list _base_add = _base.append _base_remove = _base.remove _base_extend = _base.extend def __init__(self, matches=None, input_string=None): # pylint: disable=super-init-not-called self.input_string = input_string self._max_end = 0 self._delegate = [] self.__name_dict = None self.__tag_dict = None self.__start_dict = None self.__end_dict = None self.__index_dict = None if matches: self.extend(matches) @property def _name_dict(self): if self.__name_dict is None: self.__name_dict = defaultdict(_BaseMatches._base) for name, values in itertools.groupby([m for m in self._delegate if m.name], lambda item: item.name): _BaseMatches._base_extend(self.__name_dict[name], values) return self.__name_dict @property def _start_dict(self): if self.__start_dict is None: self.__start_dict = defaultdict(_BaseMatches._base) for start, values in itertools.groupby([m for m in self._delegate], lambda item: item.start): _BaseMatches._base_extend(self.__start_dict[start], values) return self.__start_dict @property def _end_dict(self): if self.__end_dict is None: self.__end_dict = defaultdict(_BaseMatches._base) for start, values in itertools.groupby([m for m in self._delegate], lambda item: item.end): _BaseMatches._base_extend(self.__end_dict[start], values) return self.__end_dict @property def _tag_dict(self): if self.__tag_dict is None: self.__tag_dict = defaultdict(_BaseMatches._base) for match in self._delegate: for tag in match.tags: _BaseMatches._base_add(self.__tag_dict[tag], match) return self.__tag_dict @property def _index_dict(self): if self.__index_dict is None: self.__index_dict = defaultdict(_BaseMatches._base) for match in self._delegate: for index in range(*match.span): _BaseMatches._base_add(self.__index_dict[index], match) return self.__index_dict def _add_match(self, match): """ Add a match :param match: :type match: Match """ if self.__name_dict is not None: if match.name: _BaseMatches._base_add(self._name_dict[match.name], (match)) if self.__tag_dict is not None: for tag in match.tags: _BaseMatches._base_add(self._tag_dict[tag], match) if self.__start_dict is not None: _BaseMatches._base_add(self._start_dict[match.start], match) if self.__end_dict is not None: _BaseMatches._base_add(self._end_dict[match.end], match) if self.__index_dict is not None: for index in range(*match.span): _BaseMatches._base_add(self._index_dict[index], match) if match.end > self._max_end: self._max_end = match.end def _remove_match(self, match): """ Remove a match :param match: :type match: Match """ if self.__name_dict is not None: if match.name: _BaseMatches._base_remove(self._name_dict[match.name], match) if self.__tag_dict is not None: for tag in match.tags: _BaseMatches._base_remove(self._tag_dict[tag], match) if self.__start_dict is not None: _BaseMatches._base_remove(self._start_dict[match.start], match) if self.__end_dict is not None: _BaseMatches._base_remove(self._end_dict[match.end], match) if self.__index_dict is not None: for index in range(*match.span): _BaseMatches._base_remove(self._index_dict[index], match) if match.end >= self._max_end and not self._end_dict[match.end]: self._max_end = max(self._end_dict.keys()) def previous(self, match, predicate=None, index=None): """ Retrieves the nearest previous matches. :param match: :type match: :param predicate: :type predicate: :param index: :type index: int :return: :rtype: """ current = match.start while current > -1: previous_matches = self.ending(current) if previous_matches: return filter_index(previous_matches, predicate, index) current -= 1 return filter_index(_BaseMatches._base(), predicate, index) def next(self, match, predicate=None, index=None): """ Retrieves the nearest next matches. :param match: :type match: :param predicate: :type predicate: :param index: :type index: int :return: :rtype: """ current = match.start + 1 while current <= self._max_end: next_matches = self.starting(current) if next_matches: return filter_index(next_matches, predicate, index) current += 1 return filter_index(_BaseMatches._base(), predicate, index) def named(self, name, predicate=None, index=None): """ Retrieves a set of Match objects that have the given name. :param name: :type name: str :param predicate: :type predicate: :param index: :type index: int :return: set of matches :rtype: set[Match] """ return filter_index(_BaseMatches._base(self._name_dict[name]), predicate, index) def tagged(self, tag, predicate=None, index=None): """ Retrieves a set of Match objects that have the given tag defined. :param tag: :type tag: str :param predicate: :type predicate: :param index: :type index: int :return: set of matches :rtype: set[Match] """ return filter_index(_BaseMatches._base(self._tag_dict[tag]), predicate, index) def starting(self, start, predicate=None, index=None): """ Retrieves a set of Match objects that starts at given index. :param start: the starting index :type start: int :param predicate: :type predicate: :param index: :type index: int :return: set of matches :rtype: set[Match] """ return filter_index(_BaseMatches._base(self._start_dict[start]), predicate, index) def ending(self, end, predicate=None, index=None): """ Retrieves a set of Match objects that ends at given index. :param end: the ending index :type end: int :param predicate: :type predicate: :return: set of matches :rtype: set[Match] """ return filter_index(_BaseMatches._base(self._end_dict[end]), predicate, index) def range(self, start=0, end=None, predicate=None, index=None): """ Retrieves a set of Match objects that are available in given range, sorted from start to end. :param start: the starting index :type start: int :param end: the ending index :type end: int :param predicate: :type predicate: :param index: :type index: int :return: set of matches :rtype: set[Match] """ if end is None: end = self.max_end else: end = min(self.max_end, end) ret = _BaseMatches._base() for match in sorted(self): if match.start < end and match.end > start: ret.append(match) return filter_index(ret, predicate, index) def chain_before(self, position, seps, start=0, predicate=None, index=None): """ Retrieves a list of chained matches, before position, matching predicate and separated by characters from seps only. :param position: :type position: :param seps: :type seps: :param start: :type start: :param predicate: :type predicate: :param index: :type index: :return: :rtype: """ if hasattr(position, 'start'): position = position.start chain = _BaseMatches._base() position = min(self.max_end, position) for i in reversed(range(start, position)): index_matches = self.at_index(i) filtered_matches = [index_match for index_match in index_matches if not predicate or predicate(index_match)] if filtered_matches: for chain_match in filtered_matches: if chain_match not in chain: chain.append(chain_match) elif self.input_string[i] not in seps: break return filter_index(chain, predicate, index) def chain_after(self, position, seps, end=None, predicate=None, index=None): """ Retrieves a list of chained matches, after position, matching predicate and separated by characters from seps only. :param position: :type position: :param seps: :type seps: :param end: :type end: :param predicate: :type predicate: :param index: :type index: :return: :rtype: """ if hasattr(position, 'end'): position = position.end chain = _BaseMatches._base() if end is None: end = self.max_end else: end = min(self.max_end, end) for i in range(position, end): index_matches = self.at_index(i) filtered_matches = [index_match for index_match in index_matches if not predicate or predicate(index_match)] if filtered_matches: for chain_match in filtered_matches: if chain_match not in chain: chain.append(chain_match) elif self.input_string[i] not in seps: break return filter_index(chain, predicate, index) @property def max_end(self): """ Retrieves the maximum index. :return: """ return max(len(self.input_string), self._max_end) if self.input_string else self._max_end def _hole_start(self, position, ignore=None): """ Retrieves the start of hole index from position. :param position: :type position: :param ignore: :type ignore: :return: :rtype: """ for lindex in reversed(range(0, position)): for starting in self.starting(lindex): if not ignore or not ignore(starting): return lindex return 0 def _hole_end(self, position, ignore=None): """ Retrieves the end of hole index from position. :param position: :type position: :param ignore: :type ignore: :return: :rtype: """ for rindex in range(position, self.max_end): for starting in self.starting(rindex): if not ignore or not ignore(starting): return rindex return self.max_end def holes(self, start=0, end=None, formatter=None, ignore=None, seps=None, predicate=None, index=None): # pylint: disable=too-many-branches,too-many-locals """ Retrieves a set of Match objects that are not defined in given range. :param start: :type start: :param end: :type end: :param formatter: :type formatter: :param ignore: :type ignore: :param seps: :type seps: :param predicate: :type predicate: :param index: :type index: :return: :rtype: """ assert self.input_string if seps else True, "input_string must be defined when using seps parameter" if end is None: end = self.max_end else: end = min(self.max_end, end) ret = _BaseMatches._base() hole = False rindex = start loop_start = self._hole_start(start, ignore) for rindex in range(loop_start, end): current = [] for at_index in self.at_index(rindex): if not ignore or not ignore(at_index): current.append(at_index) if seps and hole and self.input_string and self.input_string[rindex] in seps: hole = False ret[-1].end = rindex else: if not current and not hole: # Open a new hole match hole = True ret.append(Match(max(rindex, start), None, input_string=self.input_string, formatter=formatter)) elif current and hole: # Close current hole match hole = False ret[-1].end = rindex if ret and hole: # go the the next starting element ... ret[-1].end = min(self._hole_end(rindex, ignore), end) return filter_index(ret, predicate, index) def conflicting(self, match, predicate=None, index=None): """ Retrieves a list of ``Match`` objects that conflicts with given match. :param match: :type match: :param predicate: :type predicate: :param index: :type index: :return: :rtype: """ ret = _BaseMatches._base() for i in range(*match.span): for at_match in self.at_index(i): if at_match not in ret: ret.append(at_match) ret.remove(match) return filter_index(ret, predicate, index) def at_match(self, match, predicate=None, index=None): """ Retrieves a list of matches from given match. """ return self.at_span(match.span, predicate, index) def at_span(self, span, predicate=None, index=None): """ Retrieves a list of matches from given (start, end) tuple. """ starting = self._index_dict[span[0]] ending = self._index_dict[span[1] - 1] merged = list(starting) for marker in ending: if marker not in merged: merged.append(marker) return filter_index(merged, predicate, index) def at_index(self, pos, predicate=None, index=None): """ Retrieves a list of matches from given position """ return filter_index(self._index_dict[pos], predicate, index) @property def names(self): """ Retrieve all names. :return: """ return self._name_dict.keys() @property def tags(self): """ Retrieve all tags. :return: """ return self._tag_dict.keys() def to_dict(self, details=False, first_value=False, enforce_list=False): """ Converts matches to a dict object. :param details if True, values will be complete Match object, else it will be only string Match.value property :type details: bool :param first_value if True, only the first value will be kept. Else, multiple values will be set as a list in the dict. :type first_value: bool :param enforce_list: if True, value is wrapped in a list even when a single value is found. Else, list values are available under `values_list` property of the returned dict object. :type enforce_list: bool :return: :rtype: dict """ ret = MatchesDict() for match in sorted(self): value = match if details else match.value ret.matches[match.name].append(match) if not enforce_list and value not in ret.values_list[match.name]: ret.values_list[match.name].append(value) if match.name in ret.keys(): if not first_value: if not isinstance(ret[match.name], list): if ret[match.name] == value: continue ret[match.name] = [ret[match.name]] else: if value in ret[match.name]: continue ret[match.name].append(value) else: if enforce_list and not isinstance(value, list): ret[match.name] = [value] else: ret[match.name] = value return ret if six.PY2: # pragma: no cover def clear(self): """ Python 3 backport """ del self[:] def __len__(self): return len(self._delegate) def __getitem__(self, index): ret = self._delegate[index] if isinstance(ret, list): return Matches(ret) return ret def __setitem__(self, index, match): self._delegate[index] = match if isinstance(index, slice): for match_item in match: self._add_match(match_item) return self._add_match(match) def __delitem__(self, index): match = self._delegate[index] del self._delegate[index] if isinstance(match, list): # if index is a slice, we has a match list for match_item in match: self._remove_match(match_item) else: self._remove_match(match) def __repr__(self): return self._delegate.__repr__() def insert(self, index, value): self._delegate.insert(index, value) self._add_match(value) class Matches(_BaseMatches): """ A custom list[Match] contains matches list. """ def __init__(self, matches=None, input_string=None): self.markers = Markers(input_string=input_string) super(Matches, self).__init__(matches=matches, input_string=input_string) def _add_match(self, match): assert not match.marker, "A marker match should not be added to object" super(Matches, self)._add_match(match) class Markers(_BaseMatches): """ A custom list[Match] containing markers list. """ def __init__(self, matches=None, input_string=None): super(Markers, self).__init__(matches=None, input_string=input_string) def _add_match(self, match): assert match.marker, "A non-marker match should not be added to object" super(Markers, self)._add_match(match) class Match(object): """ Object storing values related to a single match """ def __init__(self, start, end, value=None, name=None, tags=None, marker=None, parent=None, private=None, pattern=None, input_string=None, formatter=None, conflict_solver=None, **kwargs): # pylint: disable=unused-argument self.start = start self.end = end self.name = name self._value = value self.tags = ensure_list(tags) self.marker = marker self.parent = parent self.input_string = input_string self.formatter = formatter self.pattern = pattern self.private = private self.conflict_solver = conflict_solver self._children = None self._raw_start = None self._raw_end = None self.defined_at = pattern.defined_at if pattern else defined_at() @property def span(self): """ 2-tuple with start and end indices of the match """ return self.start, self.end @property def children(self): """ Children matches. """ if self._children is None: self._children = Matches(None, self.input_string) return self._children @children.setter def children(self, value): self._children = value @property def value(self): """ Get the value of the match, using formatter if defined. :return: :rtype: """ if self._value: return self._value if self.formatter: return self.formatter(self.raw) return self.raw @value.setter def value(self, value): """ Set the value (hardcode) :param value: :type value: :return: :rtype: """ self._value = value # pylint: disable=attribute-defined-outside-init @property def names(self): """ Get all names of children :return: :rtype: """ if not self.children: return set([self.name]) ret = set() for child in self.children: for name in child.names: ret.add(name) return ret @property def raw_start(self): """ start index of raw value :return: :rtype: """ if self._raw_start is None: return self.start return self._raw_start @raw_start.setter def raw_start(self, value): """ Set start index of raw value :return: :rtype: """ self._raw_start = value @property def raw_end(self): """ end index of raw value :return: :rtype: """ if self._raw_end is None: return self.end return self._raw_end @raw_end.setter def raw_end(self, value): """ Set end index of raw value :return: :rtype: """ self._raw_end = value @property def raw(self): """ Get the raw value of the match, without using hardcoded value nor formatter. :return: :rtype: """ if self.input_string: return self.input_string[self.raw_start:self.raw_end] return None @property def initiator(self): """ Retrieve the initiator parent of a match :param match: :type match: :return: :rtype: """ match = self while match.parent: match = match.parent return match def crop(self, crops, predicate=None, index=None): """ crop the match with given Match objects or spans tuples :param crops: :type crops: list or object :return: a list of Match objects :rtype: list[Match] """ if not is_iterable(crops) or len(crops) == 2 and isinstance(crops[0], int): crops = [crops] initial = copy.deepcopy(self) ret = [initial] for crop in crops: if hasattr(crop, 'span'): start, end = crop.span else: start, end = crop for current in list(ret): if start <= current.start and end >= current.end: # self is included in crop, remove current ... ret.remove(current) elif start >= current.start and end <= current.end: # crop is included in self, split current ... right = copy.deepcopy(current) current.end = start if not current: ret.remove(current) right.start = end if right: ret.append(right) elif end <= current.end and end > current.start: current.start = end elif start >= current.start and start < current.end: current.end = start return filter_index(ret, predicate, index) def split(self, seps, predicate=None, index=None): """ Split this match in multiple matches using given separators. :param seps: :type seps: string containing separator characters :return: list of new Match objects :rtype: list """ split_match = copy.deepcopy(self) current_match = split_match ret = [] for i in range(0, len(self.raw)): if self.raw[i] in seps: if not split_match: split_match = copy.deepcopy(current_match) current_match.end = self.start + i else: if split_match: split_match.start = self.start + i current_match = split_match ret.append(split_match) split_match = None return filter_index(ret, predicate, index) def __len__(self): return self.end - self.start def __hash__(self): return hash(Match) + hash(self.start) + hash(self.end) + hash(self.value) def __eq__(self, other): if isinstance(other, Match): return self.span == other.span and self.value == other.value and self.name == other.name and \ self.parent == other.parent return NotImplemented def __ne__(self, other): if isinstance(other, Match): return self.span != other.span or self.value != other.value or self.name != other.name or \ self.parent != other.parent return NotImplemented def __lt__(self, other): if isinstance(other, Match): return self.span < other.span return NotImplemented def __gt__(self, other): if isinstance(other, Match): return self.span > other.span return NotImplemented def __le__(self, other): if isinstance(other, Match): return self.span <= other.span return NotImplemented def __ge__(self, other): if isinstance(other, Match): return self.span >= other.span return NotImplemented def __repr__(self): flags = "" name = "" tags = "" defined = "" initiator = "" if self.initiator.value != self.value: initiator = "+initiator=" + self.initiator.value if self.private: flags += '+private' if self.name: name = "+name=%s" % (self.name,) if self.tags: tags = "+tags=%s" % (self.tags,) if self.defined_at: defined += "@%s" % (self.defined_at,) return "<%s:%s%s%s%s%s%s>" % (self.value, self.span, flags, name, tags, initiator, defined) rebulk-0.9.0/rebulk/formatters.py0000664000175000017500000000107413113544037017627 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Formatter functions to use in patterns. All those function have last argument as match.value (str). """ def formatters(*chained_formatters): """ Chain formatter functions. :param chained_formatters: :type chained_formatters: :return: :rtype: """ def formatters_chain(input_string): # pylint:disable=missing-docstring for chained_formatter in chained_formatters: input_string = chained_formatter(input_string) return input_string return formatters_chain rebulk-0.9.0/rebulk/__init__.py0000664000175000017500000000063313113544037017200 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Define simple search patterns in bulk to perform advanced matching on any string. """ # pylint:disable=import-self from .rebulk import Rebulk from .rules import Rule, CustomRule, AppendMatch, RemoveMatch, RenameMatch, AppendTags, RemoveTags from .processors import ConflictSolver, PrivateRemover, POST_PROCESS, PRE_PROCESS from .pattern import REGEX_AVAILABLE rebulk-0.9.0/rebulk/introspector.py0000664000175000017500000000746013113544037020201 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Introspect rebulk object to retrieve capabilities. """ from abc import ABCMeta, abstractproperty from collections import defaultdict import six from .pattern import StringPattern, RePattern, FunctionalPattern from .utils import extend_safe @six.add_metaclass(ABCMeta) class Description(object): """ Abstract class for a description. """ @abstractproperty def properties(self): # pragma: no cover """ Properties of described object. :return: all properties that described object can generate grouped by name. :rtype: dict """ pass class PatternDescription(Description): """ Description of a pattern. """ def __init__(self, pattern): # pylint:disable=too-many-branches self.pattern = pattern self._properties = defaultdict(list) if pattern.properties: for key, values in pattern.properties.items(): extend_safe(self._properties[key], values) elif 'value' in pattern.match_options: self._properties[pattern.name].append(pattern.match_options['value']) elif isinstance(pattern, StringPattern): extend_safe(self._properties[pattern.name], pattern.patterns) elif isinstance(pattern, RePattern): if pattern.name and pattern.name not in pattern.private_names: extend_safe(self._properties[pattern.name], [None]) if not pattern.private_children: for regex_pattern in pattern.patterns: for group_name, values in regex_pattern.groupindex.items(): if group_name not in pattern.private_names: extend_safe(self._properties[group_name], [None]) elif isinstance(pattern, FunctionalPattern): if pattern.name and pattern.name not in pattern.private_names: extend_safe(self._properties[pattern.name], [None]) @property def properties(self): """ Properties for this rule. :return: :rtype: dict """ return self._properties class RuleDescription(Description): """ Description of a rule. """ def __init__(self, rule): self.rule = rule self._properties = defaultdict(list) if rule.properties: for key, values in rule.properties.items(): extend_safe(self._properties[key], values) @property def properties(self): """ Properties for this rule. :return: :rtype: dict """ return self._properties class Introspection(Description): """ Introspection results. """ def __init__(self, rebulk, context=None): self.patterns = [PatternDescription(pattern) for pattern in rebulk.effective_patterns(context) if not pattern.private and not pattern.marker] self.rules = [RuleDescription(rule) for rule in rebulk.effective_rules(context)] @property def properties(self): """ Properties for Introspection results. :return: :rtype: """ properties = defaultdict(list) for pattern in self.patterns: for key, values in pattern.properties.items(): extend_safe(properties[key], values) for rule in self.rules: for key, values in rule.properties.items(): extend_safe(properties[key], values) return properties def introspect(rebulk, context=None): """ Introspect a Rebulk instance to grab defined objects and properties that can be generated. :param rebulk: :type rebulk: Rebulk :param context: :type context: :return: Introspection instance :rtype: Introspection """ return Introspection(rebulk, context) rebulk-0.9.0/rebulk/utils.py0000664000175000017500000000743313113544037016606 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Various utilities functions """ from collections import MutableSet from types import GeneratorType def find_all(string, sub, start=None, end=None, ignore_case=False, **kwargs): """ Return all indices in string s where substring sub is found, such that sub is contained in the slice s[start:end]. >>> list(find_all('The quick brown fox jumps over the lazy dog', 'fox')) [16] >>> list(find_all('The quick brown fox jumps over the lazy dog', 'mountain')) [] >>> list(find_all('The quick brown fox jumps over the lazy dog', 'The')) [0] >>> list(find_all( ... 'Carved symbols in a mountain hollow on the bank of an inlet irritated an eccentric person', ... 'an')) [44, 51, 70] >>> list(find_all( ... 'Carved symbols in a mountain hollow on the bank of an inlet irritated an eccentric person', ... 'an', ... 50, ... 60)) [51] :param string: the input string :type string: str :param sub: the substring :type sub: str :return: all indices in the input string :rtype: __generator[str] """ #pylint: disable=unused-argument if ignore_case: sub = sub.lower() string = string.lower() while True: start = string.find(sub, start, end) if start == -1: return yield start start += len(sub) def get_first_defined(data, keys, default_value=None): """ Get the first defined key in data. :param data: :type data: :param keys: :type keys: :param default_value: :type default_value: :return: :rtype: """ for key in keys: if key in data: return data[key] return default_value def is_iterable(obj): """ Are we being asked to look up a list of things, instead of a single thing? We check for the `__iter__` attribute so that this can cover types that don't have to be known by this module, such as NumPy arrays. Strings, however, should be considered as atomic values to look up, not iterables. We don't need to check for the Python 2 `unicode` type, because it doesn't have an `__iter__` attribute anyway. """ # pylint: disable=consider-using-ternary return hasattr(obj, '__iter__') and not isinstance(obj, str) or isinstance(obj, GeneratorType) def extend_safe(target, source): """ Extends source list to target list only if elements doesn't exists in target list. :param target: :type target: list :param source: :type source: list """ for elt in source: if elt not in target: target.append(elt) class _Ref(object): """ Reference for IdentitySet """ def __init__(self, value): self.value = value def __eq__(self, other): return self.value is other.value def __hash__(self): return id(self.value) class IdentitySet(MutableSet): # pragma: no cover """ Set based on identity """ def __init__(self, items=None): # pylint: disable=super-init-not-called if items is None: items = [] self.refs = set(map(_Ref, items)) def __contains__(self, elem): return _Ref(elem) in self.refs def __iter__(self): return (ref.value for ref in self.refs) def __len__(self): return len(self.refs) def add(self, value): self.refs.add(_Ref(value)) def discard(self, value): self.refs.discard(_Ref(value)) def update(self, iterable): """ Update set with iterable :param iterable: :type iterable: :return: :rtype: """ for elem in iterable: self.add(elem) def __repr__(self): # pragma: no cover return "%s(%s)" % (type(self).__name__, list(self)) rebulk-0.9.0/rebulk/pattern.py0000664000175000017500000004374513113544037017131 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Abstract pattern class definition along with various implementations (regexp, string, functional) """ # pylint: disable=super-init-not-called,wrong-import-position from abc import ABCMeta, abstractmethod, abstractproperty import six from . import debug from .loose import call, ensure_list, ensure_dict from .match import Match from .remodule import re, REGEX_AVAILABLE from .utils import find_all, is_iterable, get_first_defined @six.add_metaclass(ABCMeta) class Pattern(object): """ Definition of a particular pattern to search for. """ def __init__(self, name=None, tags=None, formatter=None, value=None, validator=None, children=False, every=False, private_parent=False, private_children=False, private=False, private_names=None, ignore_names=None, marker=False, format_all=False, validate_all=False, disabled=lambda context: False, log_level=None, properties=None, post_processor=None, **kwargs): """ :param name: Name of this pattern :type name: str :param tags: List of tags related to this pattern :type tags: list[str] :param formatter: dict (name, func) of formatter to use with this pattern. name is the match name to support, and func a function(input_string) that returns the formatted string. A single formatter function can also be passed as a shortcut for {None: formatter}. The returned formatted string with be set in Match.value property. :type formatter: dict[str, func] || func :param value: dict (name, value) of value to use with this pattern. name is the match name to support, and value an object for the match value. A single object value can also be passed as a shortcut for {None: value}. The value with be set in Match.value property. :type value: dict[str, object] || object :param validator: dict (name, func) of validator to use with this pattern. name is the match name to support, and func a function(match) that returns the a boolean. A single validator function can also be passed as a shortcut for {None: validator}. If return value is False, match will be ignored. :param children: generates children instead of parent :type children: bool :param every: generates both parent and children. :type every: bool :param private: flag this pattern as beeing private. :type private: bool :param private_parent: force return of parent and flag parent matches as private. :type private_parent: bool :param private_children: force return of children and flag children matches as private. :type private_children: bool :param private_names: force return of named matches as private. :type private_names: bool :param ignore_names: drop some named matches after validation. :type ignore_names: bool :param marker: flag this pattern as beeing a marker. :type private: bool :param format_all if True, pattern will format every match in the hierarchy (even match not yield). :type format_all: bool :param validate_all if True, pattern will validate every match in the hierarchy (even match not yield). :type validate_all: bool :param disabled: if True, this pattern is disabled. Can also be a function(context). :type disabled: bool|function :param log_lvl: Log level associated to this pattern :type log_lvl: int :param post_process: Post processing function :type post_processor: func """ # pylint:disable=too-many-locals,unused-argument self.name = name self.tags = ensure_list(tags) self.formatters, self._default_formatter = ensure_dict(formatter, lambda x: x) self.values, self._default_value = ensure_dict(value, None) self.validators, self._default_validator = ensure_dict(validator, lambda match: True) self.every = every self.children = children self.private = private self.private_names = private_names if private_names else [] self.ignore_names = ignore_names if ignore_names else [] self.private_parent = private_parent self.private_children = private_children self.marker = marker self.format_all = format_all self.validate_all = validate_all if not callable(disabled): self.disabled = lambda context: disabled else: self.disabled = disabled self._log_level = log_level self._properties = properties self.defined_at = debug.defined_at() if not callable(post_processor): self.post_processor = None else: self.post_processor = post_processor @property def log_level(self): """ Log level for this pattern. :return: :rtype: """ return self._log_level if self._log_level is not None else debug.LOG_LEVEL def _yield_children(self, match): """ Does this match has children :param match: :type match: :return: :rtype: """ return match.children and (self.children or self.every) def _yield_parent(self): """ Does this mat :param match: :type match: :return: :rtype: """ return not self.children or self.every def _match_parent(self, match, yield_parent): """ Handle a parent match :param match: :type match: :param yield_parent: :type yield_parent: :return: :rtype: """ if not match or match.value == "": return False pattern_value = get_first_defined(self.values, [match.name, '__parent__', None], self._default_value) if pattern_value: match.value = pattern_value if yield_parent or self.format_all: match.formatter = get_first_defined(self.formatters, [match.name, '__parent__', None], self._default_formatter) if yield_parent or self.validate_all: validator = get_first_defined(self.validators, [match.name, '__parent__', None], self._default_validator) if validator and not validator(match): return False return True def _match_child(self, child, yield_children): """ Handle a children match :param child: :type child: :param yield_children: :type yield_children: :return: :rtype: """ if not child or child.value == "": return False pattern_value = get_first_defined(self.values, [child.name, '__children__', None], self._default_value) if pattern_value: child.value = pattern_value if yield_children or self.format_all: child.formatter = get_first_defined(self.formatters, [child.name, '__children__', None], self._default_formatter) if yield_children or self.validate_all: validator = get_first_defined(self.validators, [child.name, '__children__', None], self._default_validator) if validator and not validator(child): return False return True def matches(self, input_string, context=None, with_raw_matches=False): """ Computes all matches for a given input :param input_string: the string to parse :type input_string: str :param context: the context :type context: dict :param with_raw_matches: should return details :type with_raw_matches: dict :return: matches based on input_string for this pattern :rtype: iterator[Match] """ # pylint: disable=too-many-branches matches = [] raw_matches = [] for pattern in self.patterns: yield_parent = self._yield_parent() match_index = -1 for match in self._match(pattern, input_string, context): match_index += 1 match.match_index = match_index raw_matches.append(match) yield_children = self._yield_children(match) if not self._match_parent(match, yield_parent): continue validated = True for child in match.children: if not self._match_child(child, yield_children): validated = False break if validated: if self.private_parent: match.private = True if self.private_children: for child in match.children: child.private = True if yield_parent or self.private_parent: matches.append(match) if yield_children or self.private_children: for child in match.children: child.match_index = match_index matches.append(child) matches = self._matches_post_process(matches) self._matches_privatize(matches) self._matches_ignore(matches) if with_raw_matches: return matches, raw_matches return matches def _matches_post_process(self, matches): """ Post process matches with user defined function :param matches: :type matches: :return: :rtype: """ if self.post_processor: return self.post_processor(matches, self) return matches def _matches_privatize(self, matches): """ Mark matches included in private_names with private flag. :param matches: :type matches: :return: :rtype: """ if self.private_names: for match in matches: if match.name in self.private_names: match.private = True def _matches_ignore(self, matches): """ Ignore matches included in ignore_names. :param matches: :type matches: :return: :rtype: """ if self.ignore_names: for match in list(matches): if match.name in self.ignore_names: matches.remove(match) @abstractproperty def patterns(self): # pragma: no cover """ List of base patterns defined :return: A list of base patterns :rtype: list """ pass @property def properties(self): """ Properties names and values that can ben retrieved by this pattern. :return: :rtype: """ if self._properties: return self._properties return {} @abstractproperty def match_options(self): # pragma: no cover """ dict of default options for generated Match objects :return: **options to pass to Match constructor :rtype: dict """ pass @abstractmethod def _match(self, pattern, input_string, context=None): # pragma: no cover """ Computes all matches for a given pattern and input :param pattern: the pattern to use :param input_string: the string to parse :type input_string: str :param context: the context :type context: dict :return: matches based on input_string for this pattern :rtype: iterator[Match] """ pass def __repr__(self): defined = "" if self.defined_at: defined = "@%s" % (self.defined_at,) return "<%s%s:%s>" % (self.__class__.__name__, defined, self.__repr__patterns__) @property def __repr__patterns__(self): return self.patterns class StringPattern(Pattern): """ Definition of one or many strings to search for. """ def __init__(self, *patterns, **kwargs): super(StringPattern, self).__init__(**kwargs) self._patterns = patterns self._kwargs = kwargs self._match_kwargs = filter_match_kwargs(kwargs) @property def patterns(self): return self._patterns @property def match_options(self): return self._match_kwargs def _match(self, pattern, input_string, context=None): for index in find_all(input_string, pattern, **self._kwargs): yield Match(index, index + len(pattern), pattern=self, input_string=input_string, **self._match_kwargs) class RePattern(Pattern): """ Definition of one or many regular expression pattern to search for. """ def __init__(self, *patterns, **kwargs): super(RePattern, self).__init__(**kwargs) self.repeated_captures = REGEX_AVAILABLE if 'repeated_captures' in kwargs: self.repeated_captures = kwargs.get('repeated_captures') if self.repeated_captures and not REGEX_AVAILABLE: # pragma: no cover raise NotImplementedError("repeated_capture is available only with regex module.") self.abbreviations = kwargs.get('abbreviations', []) self._kwargs = kwargs self._match_kwargs = filter_match_kwargs(kwargs) self._children_match_kwargs = filter_match_kwargs(kwargs, children=True) self._patterns = [] for pattern in patterns: if isinstance(pattern, six.string_types): if self.abbreviations and pattern: for key, replacement in self.abbreviations: pattern = pattern.replace(key, replacement) pattern = call(re.compile, pattern, **self._kwargs) elif isinstance(pattern, dict): if self.abbreviations and 'pattern' in pattern: for key, replacement in self.abbreviations: pattern['pattern'] = pattern['pattern'].replace(key, replacement) pattern = re.compile(**pattern) elif hasattr(pattern, '__iter__'): pattern = re.compile(*pattern) self._patterns.append(pattern) @property def patterns(self): return self._patterns @property def __repr__patterns__(self): return [pattern.pattern for pattern in self.patterns] @property def match_options(self): return self._match_kwargs def _match(self, pattern, input_string, context=None): names = dict((v, k) for k, v in pattern.groupindex.items()) for match_object in pattern.finditer(input_string): start = match_object.start() end = match_object.end() main_match = Match(start, end, pattern=self, input_string=input_string, **self._match_kwargs) if pattern.groups: for i in range(1, pattern.groups + 1): name = names.get(i, main_match.name) if self.repeated_captures: for start, end in match_object.spans(i): child_match = Match(start, end, name=name, parent=main_match, pattern=self, input_string=input_string, **self._children_match_kwargs) main_match.children.append(child_match) else: start, end = match_object.span(i) if start > -1 and end > -1: child_match = Match(start, end, name=name, parent=main_match, pattern=self, input_string=input_string, **self._children_match_kwargs) main_match.children.append(child_match) yield main_match class FunctionalPattern(Pattern): """ Definition of one or many functional pattern to search for. """ def __init__(self, *patterns, **kwargs): super(FunctionalPattern, self).__init__(**kwargs) self._patterns = patterns self._kwargs = kwargs self._match_kwargs = filter_match_kwargs(kwargs) @property def patterns(self): return self._patterns @property def match_options(self): return self._match_kwargs def _match(self, pattern, input_string, context=None): ret = call(pattern, input_string, context, **self._kwargs) if ret: if not is_iterable(ret) or isinstance(ret, dict) \ or (is_iterable(ret) and hasattr(ret, '__getitem__') and isinstance(ret[0], int)): args_iterable = [ret] else: args_iterable = ret for args in args_iterable: if isinstance(args, dict): options = args options.pop('input_string', None) options.pop('pattern', None) if self._match_kwargs: options = self._match_kwargs.copy() options.update(args) yield Match(pattern=self, input_string=input_string, **options) else: kwargs = self._match_kwargs if isinstance(args[-1], dict): kwargs = dict(kwargs) kwargs.update(args[-1]) args = args[:-1] yield Match(*args, pattern=self, input_string=input_string, **kwargs) def filter_match_kwargs(kwargs, children=False): """ Filters out kwargs for Match construction :param kwargs: :type kwargs: dict :param children: :type children: Flag to filter children matches :return: A filtered dict :rtype: dict """ kwargs = kwargs.copy() for key in ('pattern', 'start', 'end', 'parent', 'formatter', 'value'): if key in kwargs: del kwargs[key] if children: for key in ('name',): if key in kwargs: del kwargs[key] return kwargs rebulk-0.9.0/rebulk/__version__.py0000664000175000017500000000015613113544037017722 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Version module """ # pragma: no cover __version__ = '0.9.0' rebulk-0.9.0/rebulk/debug.py0000664000175000017500000000257613113544037016537 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Debug tools. Can be configured by changing values of those variable. DEBUG = False Enable this variable to activate debug features (like defined_at parameters). It can slow down Rebulk LOG_LEVEL = 0 Default log level of generated rebulk logs. """ import inspect import logging import os from collections import namedtuple DEBUG = False LOG_LEVEL = logging.DEBUG class Frame(namedtuple('Frame', ['lineno', 'package', 'name', 'filename'])): """ Stack frame representation. """ __slots__ = () def __repr__(self): return "%s#L%s" % (os.path.basename(self.filename), self.lineno) def defined_at(): """ Get definition location of a pattern or a match (outside of rebulk package). :return: :rtype: """ if DEBUG: frame = inspect.currentframe() while frame: try: if frame.f_globals['__package__'] != __package__: break except KeyError: # pragma:no cover # If package is missing, consider we are in. Workaround for python 3.3. break frame = frame.f_back ret = Frame(frame.f_lineno, frame.f_globals.get('__package__'), frame.f_globals.get('__name__'), frame.f_code.co_filename) del frame return ret rebulk-0.9.0/rebulk/remodule.py0000664000175000017500000000050513113544037017253 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Uniform re module """ # pylint: disable-all import os REGEX_AVAILABLE = False if os.environ.get('REGEX_DISABLED') in ["1", "true", "True", "Y"]: import re else: try: import regex as re REGEX_AVAILABLE = True except ImportError: import re rebulk-0.9.0/rebulk/test/0000775000175000017500000000000013113544041016037 5ustar toilaltoilal00000000000000rebulk-0.9.0/rebulk/test/rules_module.py0000664000175000017500000000225313113544037021117 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # pylint: disable=no-self-use, pointless-statement, missing-docstring, invalid-name, len-as-condition from ..match import Match from ..rules import Rule class Rule3(Rule): def when(self, matches, context): return context.get('when') def then(self, matches, when_response, context): assert when_response in [True, False] matches.append(Match(3, 4)) class Rule2(Rule): dependency = Rule3 def when(self, matches, context): return True def then(self, matches, when_response, context): assert when_response matches.append(Match(3, 4)) class Rule1(Rule): dependency = Rule2 def when(self, matches, context): return True def then(self, matches, when_response, context): assert when_response matches.clear() class Rule0(Rule): dependency = Rule1 def when(self, matches, context): return True def then(self, matches, when_response, context): assert when_response matches.append(Match(3, 4)) class Rule1Disabled(Rule1): name = "Disabled Rule1" def enabled(self, context): return False rebulk-0.9.0/rebulk/test/test_toposort.py0000664000175000017500000000771213113544037021355 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright 2014 True Blade Systems, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Original: # - https://bitbucket.org/ericvsmith/toposort (1.4) # Modifications: # - port to pytest # pylint: skip-file import pytest from ..toposort import toposort, toposort_flatten, CyclicDependency class TestCase(object): def test_simple(self): results = list(toposort({2: set([11]), 9: set([11, 8]), 10: set([11, 3]), 11: set([7, 5]), 8: set([7, 3])})) expected = [set([3, 5, 7]), set([8, 11]), set([2, 9, 10])] assert results == expected # make sure self dependencies are ignored results = list(toposort({2: set([2, 11]), 9: set([11, 8]), 10: set([10, 11, 3]), 11: set([7, 5]), 8: set([7, 3])})) expected = [set([3, 5, 7]), set([8, 11]), set([2, 9, 10])] assert results == expected assert list(toposort({1: set()})) == [set([1])] assert list(toposort({1: set([1])})) == [set([1])] def test_no_dependencies(self): assert list(toposort({1: set([2]), 3: set([4]), 5: set([6])})) == [set([2, 4, 6]), set([1, 3, 5])] assert list(toposort({1: set(), 3: set(), 5: set()})) == [set([1, 3, 5])] def test_empty(self): assert list(toposort({})) == [] def test_strings(self): results = list(toposort({'2': set(['11']), '9': set(['11', '8']), '10': set(['11', '3']), '11': set(['7', '5']), '8': set(['7', '3'])})) expected = [set(['3', '5', '7']), set(['8', '11']), set(['2', '9', '10'])] assert results == expected def test_objects(self): o2 = object() o3 = object() o5 = object() o7 = object() o8 = object() o9 = object() o10 = object() o11 = object() results = list(toposort({o2: set([o11]), o9: set([o11, o8]), o10: set([o11, o3]), o11: set([o7, o5]), o8: set([o7, o3, o8])})) expected = [set([o3, o5, o7]), set([o8, o11]), set([o2, o9, o10])] assert results == expected def test_cycle(self): # a simple, 2 element cycle with pytest.raises(CyclicDependency): list(toposort({1: set([2]), 2: set([1])})) # an indirect cycle with pytest.raises(CyclicDependency): list(toposort({1: set([2]), 2: set([3]), 3: set([1])})) def test_input_not_modified(self): data = {2: set([11]), 9: set([11, 8]), 10: set([11, 3]), 11: set([7, 5]), 8: set([7, 3, 8]), # includes something self-referential } orig = data.copy() results = list(toposort(data)) assert data == orig def test_input_not_modified_when_cycle_error(self): data = {1: set([2]), 2: set([1]), 3: set([4]), } orig = data.copy() with pytest.raises(CyclicDependency): list(toposort(data)) assert data == orig class TestCaseAll(object): def test_sort_flatten(self): data = {2: set([11]), 9: set([11, 8]), 10: set([11, 3]), 11: set([7, 5]), 8: set([7, 3, 8]), # includes something self-referential } expected = [set([3, 5, 7]), set([8, 11]), set([2, 9, 10])] assert list(toposort(data)) == expected # now check the sorted results results = [] for item in expected: results.extend(sorted(item)) assert toposort_flatten(data) == results # and the unsorted results. break the results up into groups to compare them actual = toposort_flatten(data, False) results = [set([i for i in actual[0:3]]), set([i for i in actual[3:5]]), set([i for i in actual[5:8]])] assert results == expected rebulk-0.9.0/rebulk/test/test_introspector.py0000664000175000017500000001175513113544037022221 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Introspector tests """ # pylint: disable=no-self-use,pointless-statement,missing-docstring,protected-access,invalid-name,len-as-condition from ..rebulk import Rebulk from .. import introspector from .default_rules_module import RuleAppend2, RuleAppend3 def test_string_introspector(): rebulk = Rebulk().string('One', 'Two', 'Three', name='first').string('1', '2', '3', name='second') introspected = introspector.introspect(rebulk, None) assert len(introspected.patterns) == 2 first_properties = introspected.patterns[0].properties assert len(first_properties) == 1 first_properties['first'] == ['One', 'Two', 'Three'] second_properties = introspected.patterns[1].properties assert len(second_properties) == 1 second_properties['second'] == ['1', '2', '3'] properties = introspected.properties assert len(properties) == 2 assert properties['first'] == first_properties['first'] assert properties['second'] == second_properties['second'] def test_string_properties(): rebulk = Rebulk()\ .string('One', 'Two', 'Three', name='first', properties={'custom': ['One']})\ .string('1', '2', '3', name='second', properties={'custom': [1]}) introspected = introspector.introspect(rebulk, None) assert len(introspected.patterns) == 2 assert len(introspected.rules) == 2 first_properties = introspected.patterns[0].properties assert len(first_properties) == 1 first_properties['custom'] == ['One'] second_properties = introspected.patterns[1].properties assert len(second_properties) == 1 second_properties['custom'] == [1] properties = introspected.properties assert len(properties) == 1 assert properties['custom'] == ['One', 1] def test_various_pattern(): rebulk = Rebulk()\ .regex('One', 'Two', 'Three', name='first', value="string") \ .string('1', '2', '3', name='second', value="digit") \ .string('4', '5', '6', name='third') \ .string('private', private=True) \ .functional(lambda string: (0, 5), name='func', value='test') \ .regex('One', 'Two', 'Three', name='regex_name') \ .regex('(?POne)(?PTwo)(?PThree)') \ .functional(lambda string: (6, 10), name='func2') \ .string('7', name='third') introspected = introspector.introspect(rebulk, None) assert len(introspected.patterns) == 8 assert len(introspected.rules) == 2 first_properties = introspected.patterns[0].properties assert len(first_properties) == 1 first_properties['first'] == ['string'] second_properties = introspected.patterns[1].properties assert len(second_properties) == 1 second_properties['second'] == ['digit'] third_properties = introspected.patterns[2].properties assert len(third_properties) == 1 third_properties['third'] == ['4', '5', '6'] func_properties = introspected.patterns[3].properties assert len(func_properties) == 1 func_properties['func'] == ['test'] regex_name_properties = introspected.patterns[4].properties assert len(regex_name_properties) == 1 regex_name_properties['regex_name'] == [None] regex_groups_properties = introspected.patterns[5].properties assert len(regex_groups_properties) == 3 regex_groups_properties['one'] == [None] regex_groups_properties['two'] == [None] regex_groups_properties['three'] == [None] func2_properties = introspected.patterns[6].properties assert len(func2_properties) == 1 func2_properties['func2'] == [None] append_third_properties = introspected.patterns[7].properties assert len(append_third_properties) == 1 append_third_properties['third'] == [None] properties = introspected.properties assert len(properties) == 9 assert properties['first'] == first_properties['first'] assert properties['second'] == second_properties['second'] assert properties['third'] == third_properties['third'] + append_third_properties['third'] assert properties['func'] == func_properties['func'] assert properties['regex_name'] == regex_name_properties['regex_name'] assert properties['one'] == regex_groups_properties['one'] assert properties['two'] == regex_groups_properties['two'] assert properties['three'] == regex_groups_properties['three'] assert properties['func2'] == func2_properties['func2'] def test_rule_properties(): rebulk = Rebulk(default_rules=False).rules(RuleAppend2, RuleAppend3) introspected = introspector.introspect(rebulk, None) assert len(introspected.rules) == 2 assert len(introspected.patterns) == 0 rule_properties = introspected.rules[0].properties assert len(rule_properties) == 1 assert rule_properties['renamed'] == [None] rule_properties = introspected.rules[1].properties assert len(rule_properties) == 1 assert rule_properties['renamed'] == [None] properties = introspected.properties assert len(properties) == 1 assert properties['renamed'] == [None] rebulk-0.9.0/rebulk/test/test_validators.py0000664000175000017500000000417213113544037021631 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # pylint: disable=no-self-use, pointless-statement, missing-docstring, invalid-name,len-as-condition from functools import partial from rebulk.pattern import StringPattern from ..validators import chars_before, chars_after, chars_surround, validators chars = ' _.' left = partial(chars_before, chars) right = partial(chars_after, chars) surrounding = partial(chars_surround, chars) def test_left_chars(): matches = list(StringPattern("word", validator=left).matches("xxxwordxxx")) assert len(matches) == 0 matches = list(StringPattern("word", validator=left).matches("xxx_wordxxx")) assert len(matches) == 1 matches = list(StringPattern("word", validator=left).matches("wordxxx")) assert len(matches) == 1 def test_right_chars(): matches = list(StringPattern("word", validator=right).matches("xxxwordxxx")) assert len(matches) == 0 matches = list(StringPattern("word", validator=right).matches("xxxword.xxx")) assert len(matches) == 1 matches = list(StringPattern("word", validator=right).matches("xxxword")) assert len(matches) == 1 def test_surrounding_chars(): matches = list(StringPattern("word", validator=surrounding).matches("xxxword xxx")) assert len(matches) == 0 matches = list(StringPattern("word", validator=surrounding).matches("xxx.wordxxx")) assert len(matches) == 0 matches = list(StringPattern("word", validator=surrounding).matches("xxx word_xxx")) assert len(matches) == 1 matches = list(StringPattern("word", validator=surrounding).matches("word")) assert len(matches) == 1 def test_chain(): matches = list(StringPattern("word", validator=validators(left, right)).matches("xxxword xxx")) assert len(matches) == 0 matches = list(StringPattern("word", validator=validators(left, right)).matches("xxx.wordxxx")) assert len(matches) == 0 matches = list(StringPattern("word", validator=validators(left, right)).matches("xxx word_xxx")) assert len(matches) == 1 matches = list(StringPattern("word", validator=validators(left, right)).matches("word")) assert len(matches) == 1 rebulk-0.9.0/rebulk/test/test_rebulk.py0000664000175000017500000003152213113544037020744 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # pylint: disable=no-self-use, pointless-statement, missing-docstring, no-member, len-as-condition from ..rebulk import Rebulk from ..rules import Rule from . import rebulk_rules_module as rm def test_rebulk_simple(): rebulk = Rebulk() rebulk.string("quick") rebulk.regex("f.x") def func(input_string): i = input_string.find("over") if i > -1: return i, i + len("over") rebulk.functional(func) input_string = "The quick brown fox jumps over the lazy dog" matches = rebulk.matches(input_string) assert len(matches) == 3 assert matches[0].value == "quick" assert matches[1].value == "fox" assert matches[2].value == "over" def test_rebulk_composition(): rebulk = Rebulk() rebulk.string("quick") rebulk.rebulk(Rebulk().regex("f.x")) rebulk.rebulk(Rebulk(disabled=lambda context: True).functional(lambda string: None)) input_string = "The quick brown fox jumps over the lazy dog" matches = rebulk.matches(input_string) assert len(matches) == 2 assert matches[0].value == "quick" assert matches[1].value == "fox" def test_rebulk_context(): rebulk = Rebulk() context = {'nostring': True, 'word': 'lazy'} rebulk.string("quick", disabled=lambda context: context.get('nostring', False)) rebulk.regex("f.x", disabled=lambda context: context.get('noregex', False)) def func(input_string, context): word = context.get('word', 'over') i = input_string.find(word) if i > -1: return i, i + len(word) rebulk.functional(func) input_string = "The quick brown fox jumps over the lazy dog" matches = rebulk.matches(input_string, context) assert len(matches) == 2 assert matches[0].value == "fox" assert matches[1].value == "lazy" def test_rebulk_prefer_longer(): input_string = "The quick brown fox jumps over the lazy dog" matches = Rebulk().string("quick").string("own").regex("br.{2}n").matches(input_string) assert len(matches) == 2 assert matches[0].value == "quick" assert matches[1].value == "brown" def test_rebulk_defaults(): input_string = "The quick brown fox jumps over the lazy dog" def func(input_string): i = input_string.find("fox") if i > -1: return i, i + len("fox") matches = Rebulk()\ .string_defaults(name="string", tags=["a", "b"])\ .regex_defaults(name="regex") \ .functional_defaults(name="functional") \ .string("quick", tags=["c"])\ .functional(func)\ .regex("br.{2}n") \ .matches(input_string) assert matches[0].name == "string" assert matches[0].tags == ["a", "b", "c"] assert matches[1].name == "functional" assert matches[2].name == "regex" matches = Rebulk() \ .defaults(name="default", tags=["0"])\ .string_defaults(name="string", tags=["a", "b"]) \ .functional_defaults(name="functional", tags=["1"]) \ .string("quick", tags=["c"]) \ .functional(func) \ .regex("br.{2}n") \ .matches(input_string) assert matches[0].name == "string" assert matches[0].tags == ["0", "a", "b", "c"] assert matches[1].name == "functional" assert matches[1].tags == ["0", "1"] assert matches[2].name == "default" assert matches[2].tags == ["0"] def test_rebulk_rebulk(): input_string = "The quick brown fox jumps over the lazy dog" base = Rebulk().string("quick") child = Rebulk().string("own").regex("br.{2}n") matches = base.rebulk(child).matches(input_string) assert len(matches) == 2 assert matches[0].value == "quick" assert matches[1].value == "brown" def test_rebulk_no_default(): input_string = "The quick brown fox jumps over the lazy dog" matches = Rebulk(default_rules=False).string("quick").string("own").regex("br.{2}n").matches(input_string) assert len(matches) == 3 assert matches[0].value == "quick" assert matches[1].value == "own" assert matches[2].value == "brown" def test_rebulk_empty_match(): input_string = "The quick brown fox jumps over the lazy dog" matches = Rebulk(default_rules=False).string("quick").string("own").regex("br(.*?)own", children=True)\ .matches(input_string) assert len(matches) == 2 assert matches[0].value == "quick" assert matches[1].value == "own" def test_rebulk_tags_names(): rebulk = Rebulk() rebulk.string("quick", name="str", tags=["first", "other"]) rebulk.regex("f.x", tags="other") def func(input_string): i = input_string.find("over") if i > -1: return i, i + len("over"), {'tags': ['custom']} rebulk.functional(func, name="fn") def func2(input_string): i = input_string.find("lazy") if i > -1: return {'start': i, 'end': i + len("lazy"), 'tags': ['custom']} rebulk.functional(func2, name="fn") input_string = "The quick brown fox jumps over the lazy dog" matches = rebulk.matches(input_string) assert len(matches) == 4 assert len(matches.named("str")) == 1 assert len(matches.named("fn")) == 2 assert len(matches.named("false")) == 0 assert len(matches.tagged("false")) == 0 assert len(matches.tagged("first")) == 1 assert len(matches.tagged("other")) == 2 assert len(matches.tagged("custom")) == 2 def test_rebulk_rules_1(): rebulk = Rebulk() rebulk.regex(r'\d{4}', name="year") rebulk.rules(rm.RemoveAllButLastYear) matches = rebulk.matches("1984 keep only last 1968 entry 1982 case") assert len(matches) == 1 assert matches[0].value == "1982" def test_rebulk_rules_2(): rebulk = Rebulk() rebulk.regex(r'\d{4}', name="year") rebulk.string(r'year', name="yearPrefix", private=True) rebulk.string(r'keep', name="yearSuffix", private=True) rebulk.rules(rm.PrefixedSuffixedYear) matches = rebulk.matches("Keep suffix 1984 keep prefixed year 1968 and remove the rest 1982") assert len(matches) == 2 assert matches[0].value == "1984" assert matches[1].value == "1968" def test_rebulk_rules_3(): rebulk = Rebulk() rebulk.regex(r'\d{4}', name="year") rebulk.string(r'year', name="yearPrefix", private=True) rebulk.string(r'keep', name="yearSuffix", private=True) rebulk.rules(rm.PrefixedSuffixedYearNoLambda) matches = rebulk.matches("Keep suffix 1984 keep prefixed year 1968 and remove the rest 1982") assert len(matches) == 2 assert matches[0].value == "1984" assert matches[1].value == "1968" def test_rebulk_rules_4(): class FirstOnlyRule(Rule): def when(self, matches, context): grabbed = matches.named("grabbed", 0) if grabbed and matches.previous(grabbed): return grabbed def then(self, matches, when_response, context): matches.remove(when_response) rebulk = Rebulk() rebulk.regex("This match (.*?)grabbed", name="grabbed") rebulk.regex("if it's (.*?)first match", private=True) rebulk.rules(FirstOnlyRule) matches = rebulk.matches("This match is grabbed only if it's the first match") assert len(matches) == 1 assert matches[0].value == "This match is grabbed" matches = rebulk.matches("if it's NOT the first match, This match is NOT grabbed") assert len(matches) == 0 class TestMarkers(object): def test_one_marker(self): class MarkerRule(Rule): def when(self, matches, context): word_match = matches.named("word", 0) marker = matches.markers.at_match(word_match, lambda marker: marker.name == "mark1", 0) if not marker: return word_match def then(self, matches, when_response, context): matches.remove(when_response) rebulk = Rebulk().regex(r'\(.*?\)', marker=True, name="mark1") \ .regex(r'\[.*?\]', marker=True, name="mark2") \ .string("word", name="word") \ .rules(MarkerRule) matches = rebulk.matches("grab (word) only if it's in parenthesis") assert len(matches) == 1 assert matches[0].value == "word" matches = rebulk.matches("don't grab [word] if it's in braket") assert len(matches) == 0 matches = rebulk.matches("don't grab word at all") assert len(matches) == 0 def test_multiple_marker(self): class MarkerRule(Rule): def when(self, matches, context): word_match = matches.named("word", 0) marker = matches.markers.at_match(word_match, lambda marker: marker.name == "mark1" or marker.name == "mark2") if len(marker) < 2: return word_match def then(self, matches, when_response, context): matches.remove(when_response) rebulk = Rebulk().regex(r'\(.*?\)', marker=True, name="mark1") \ .regex(r'\[.*?\]', marker=True, name="mark2") \ .regex("w.*?d", name="word") \ .rules(MarkerRule) matches = rebulk.matches("[grab (word) only] if it's in parenthesis and brakets") assert len(matches) == 1 assert matches[0].value == "word" matches = rebulk.matches("[don't grab](word)[if brakets are outside]") assert len(matches) == 0 matches = rebulk.matches("(grab w[or)d even] if it's partially in parenthesis and brakets") assert len(matches) == 1 assert matches[0].value == "w[or)d" def test_at_index_marker(self): class MarkerRule(Rule): def when(self, matches, context): word_match = matches.named("word", 0) marker = matches.markers.at_index(word_match.start, lambda marker: marker.name == "mark1", 0) if not marker: return word_match def then(self, matches, when_response, context): matches.remove(when_response) rebulk = Rebulk().regex(r'\(.*?\)', marker=True, name="mark1") \ .regex("w.*?d", name="word") \ .rules(MarkerRule) matches = rebulk.matches("gr(ab wo)rd only if starting of match is inside parenthesis") assert len(matches) == 1 assert matches[0].value == "wo)rd" matches = rebulk.matches("don't grab wo(rd if starting of match is not inside parenthesis") assert len(matches) == 0 def test_remove_marker(self): class MarkerRule(Rule): def when(self, matches, context): marker = matches.markers.named("mark1", 0) if marker: return marker def then(self, matches, when_response, context): matches.markers.remove(when_response) rebulk = Rebulk().regex(r'\(.*?\)', marker=True, name="mark1") \ .regex("w.*?d", name="word") \ .rules(MarkerRule) matches = rebulk.matches("grab word event (if it's not) inside parenthesis") assert len(matches) == 1 assert matches[0].value == "word" assert not matches.markers class TestUnicode(object): def test_rebulk_simple(self): input_string = u"敏捷的棕色狐狸跳過懶狗" rebulk = Rebulk() rebulk.string(u"敏") rebulk.regex(u"捷") def func(input_string): i = input_string.find(u"的") if i > -1: return i, i + len(u"的") rebulk.functional(func) matches = rebulk.matches(input_string) assert len(matches) == 3 assert matches[0].value == u"敏" assert matches[1].value == u"捷" assert matches[2].value == u"的" class TestImmutable(object): def test_starting(self): input_string = "The quick brown fox jumps over the lazy dog" matches = Rebulk().string("quick").string("over").string("fox").matches(input_string) for i in range(0, len(input_string)): starting = matches.starting(i) for match in list(starting): starting.remove(match) assert len(matches) == 3 def test_ending(self): input_string = "The quick brown fox jumps over the lazy dog" matches = Rebulk().string("quick").string("over").string("fox").matches(input_string) for i in range(0, len(input_string)): starting = matches.ending(i) for match in list(starting): starting.remove(match) assert len(matches) == 3 def test_named(self): input_string = "The quick brown fox jumps over the lazy dog" matches = Rebulk().defaults(name='test').string("quick").string("over").string("fox").matches(input_string) named = matches.named('test') for match in list(named): named.remove(match) assert len(named) == 0 assert len(matches) == 3 rebulk-0.9.0/rebulk/test/test_processors.py0000664000175000017500000001354313113544037021665 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # pylint: disable=no-self-use, pointless-statement, missing-docstring, no-member, len-as-condition from ..pattern import StringPattern, RePattern from ..processors import ConflictSolver from ..rules import execute_rule from ..match import Matches def test_conflict_1(): input_string = "abcdefghijklmnopqrstuvwxyz" pattern = StringPattern("ijklmn", "kl", "abcdef", "ab", "ef", "yz") matches = Matches(pattern.matches(input_string)) execute_rule(ConflictSolver(), matches, None) values = [x.value for x in matches] assert values == ["ijklmn", "abcdef", "yz"] def test_conflict_2(): input_string = "abcdefghijklmnopqrstuvwxyz" pattern = StringPattern("ijklmn", "jklmnopqrst") matches = Matches(pattern.matches(input_string)) execute_rule(ConflictSolver(), matches, None) values = [x.value for x in matches] assert values == ["jklmnopqrst"] def test_conflict_3(): input_string = "abcdefghijklmnopqrstuvwxyz" pattern = StringPattern("ijklmnopqrst", "jklmnopqrst") matches = Matches(pattern.matches(input_string)) execute_rule(ConflictSolver(), matches, None) values = [x.value for x in matches] assert values == ["ijklmnopqrst"] def test_conflict_4(): input_string = "123456789" pattern = StringPattern("123", "456789") matches = Matches(pattern.matches(input_string)) execute_rule(ConflictSolver(), matches, None) values = [x.value for x in matches] assert values == ["123", "456789"] def test_conflict_5(): input_string = "123456789" pattern = StringPattern("123456", "789") matches = Matches(pattern.matches(input_string)) execute_rule(ConflictSolver(), matches, None) values = [x.value for x in matches] assert values == ["123456", "789"] def test_prefer_longer_parent(): input_string = "xxx.1x02.xxx" re1 = RePattern("([0-9]+)x([0-9]+)", name='prefer', children=True, formatter=int) re2 = RePattern("x([0-9]+)", name='skip', children=True) matches = Matches(re1.matches(input_string)) matches.extend(re2.matches(input_string)) execute_rule(ConflictSolver(), matches, None) assert len(matches) == 2 assert matches[0].value == 1 assert matches[1].value == 2 def test_conflict_solver_1(): input_string = "123456789" re1 = StringPattern("2345678", conflict_solver=lambda match, conflicting: '__default__') re2 = StringPattern("34567") matches = Matches(re1.matches(input_string)) matches.extend(re2.matches(input_string)) execute_rule(ConflictSolver(), matches, None) assert len(matches) == 1 assert matches[0].value == "2345678" def test_conflict_solver_2(): input_string = "123456789" re1 = StringPattern("2345678", conflict_solver=lambda match, conflicting: '__default__') re2 = StringPattern("34567", conflict_solver=lambda match, conflicting: conflicting) matches = Matches(re1.matches(input_string)) matches.extend(re2.matches(input_string)) execute_rule(ConflictSolver(), matches, None) assert len(matches) == 1 assert matches[0].value == "34567" def test_conflict_solver_3(): input_string = "123456789" re1 = StringPattern("2345678", conflict_solver=lambda match, conflicting: match) re2 = StringPattern("34567") matches = Matches(re1.matches(input_string)) matches.extend(re2.matches(input_string)) execute_rule(ConflictSolver(), matches, None) assert len(matches) == 1 assert matches[0].value == "34567" def test_conflict_solver_4(): input_string = "123456789" re1 = StringPattern("2345678") re2 = StringPattern("34567", conflict_solver=lambda match, conflicting: conflicting) matches = Matches(re1.matches(input_string)) matches.extend(re2.matches(input_string)) execute_rule(ConflictSolver(), matches, None) assert len(matches) == 1 assert matches[0].value == "34567" def test_conflict_solver_5(): input_string = "123456789" re1 = StringPattern("2345678", conflict_solver=lambda match, conflicting: conflicting) re2 = StringPattern("34567") matches = Matches(re1.matches(input_string)) matches.extend(re2.matches(input_string)) execute_rule(ConflictSolver(), matches, None) assert len(matches) == 1 assert matches[0].value == "2345678" def test_conflict_solver_6(): input_string = "123456789" re1 = StringPattern("2345678") re2 = StringPattern("34567", conflict_solver=lambda match, conflicting: conflicting) matches = Matches(re1.matches(input_string)) matches.extend(re2.matches(input_string)) execute_rule(ConflictSolver(), matches, None) assert len(matches) == 1 assert matches[0].value == "34567" def test_conflict_solver_7(): input_string = "102" re1 = StringPattern("102") re2 = StringPattern("02") matches = Matches(re2.matches(input_string)) matches.extend(re1.matches(input_string)) execute_rule(ConflictSolver(), matches, None) assert len(matches) == 1 assert matches[0].value == "102" def test_unresolved(): input_string = "123456789" re1 = StringPattern("23456") re2 = StringPattern("34567") matches = Matches(re1.matches(input_string)) matches.extend(re2.matches(input_string)) execute_rule(ConflictSolver(), matches, None) assert len(matches) == 2 re1 = StringPattern("34567") re2 = StringPattern("2345678", conflict_solver=lambda match, conflicting: None) matches = Matches(re1.matches(input_string)) matches.extend(re2.matches(input_string)) execute_rule(ConflictSolver(), matches, None) assert len(matches) == 2 re1 = StringPattern("34567", conflict_solver=lambda match, conflicting: None) re2 = StringPattern("2345678") matches = Matches(re1.matches(input_string)) matches.extend(re2.matches(input_string)) execute_rule(ConflictSolver(), matches, None) assert len(matches) == 2 rebulk-0.9.0/rebulk/test/__init__.py0000664000175000017500000000016413113544037020156 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # pylint: disable=no-self-use, pointless-statement, missing-docstring rebulk-0.9.0/rebulk/test/rebulk_rules_module.py0000664000175000017500000000245613113544037022470 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # pylint: disable=no-self-use, pointless-statement, missing-docstring, invalid-name, len-as-condition from rebulk.rules import Rule, RemoveMatch, CustomRule class RemoveAllButLastYear(Rule): consequence = RemoveMatch def when(self, matches, context): entries = matches.named('year') return entries[:-1] class PrefixedSuffixedYear(CustomRule): def when(self, matches, context): toRemove = [] years = matches.named('year') for year in years: if not matches.previous(year, lambda p: p.name == 'yearPrefix') and \ not matches.next(year, lambda n: n.name == 'yearSuffix'): toRemove.append(year) return toRemove def then(self, matches, when_response, context): for to_remove in when_response: matches.remove(to_remove) class PrefixedSuffixedYearNoLambda(Rule): consequence = RemoveMatch def when(self, matches, context): toRemove = [] years = matches.named('year') for year in years: if not [m for m in matches.previous(year) if m.name == 'yearPrefix'] and \ not [m for m in matches.next(year) if m.name == 'yearSuffix']: toRemove.append(year) return toRemove rebulk-0.9.0/rebulk/test/test_debug.py0000664000175000017500000000551413113544037020550 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # pylint: disable=no-self-use, pointless-statement, missing-docstring, protected-access, invalid-name, len-as-condition from ..pattern import StringPattern from ..rebulk import Rebulk from ..match import Match from .. import debug from .default_rules_module import RuleRemove0 class TestDebug(object): #request.addfinalizer(disable_debug) debug.DEBUG = True pattern = StringPattern(1, 3, value="es") match = Match(1, 3, value="es") rule = RuleRemove0() input_string = "This is a debug test" rebulk = Rebulk().string("debug") \ .string("is") matches = rebulk.matches(input_string) debug.DEBUG = False @classmethod def setup_class(cls): debug.DEBUG = True @classmethod def teardown_class(cls): debug.DEBUG = False def test_pattern(self): assert self.pattern.defined_at.lineno == 20 assert self.pattern.defined_at.name == 'rebulk.test.test_debug' assert self.pattern.defined_at.filename.endswith('test_debug.py') assert str(self.pattern.defined_at) == 'test_debug.py#L20' assert repr(self.pattern) == '' def test_match(self): assert self.match.defined_at.lineno == 22 assert self.match.defined_at.name == 'rebulk.test.test_debug' assert self.match.defined_at.filename.endswith('test_debug.py') assert str(self.match.defined_at) == 'test_debug.py#L22' def test_rule(self): assert self.rule.defined_at.lineno == 23 assert self.rule.defined_at.name == 'rebulk.test.test_debug' assert self.rule.defined_at.filename.endswith('test_debug.py') assert str(self.rule.defined_at) == 'test_debug.py#L23' assert repr(self.rule) == '' def test_rebulk(self): """ This test fails on travis CI, can't find out why there's 1 line offset ... """ assert self.rebulk._patterns[0].defined_at.lineno in [26, 27] assert self.rebulk._patterns[0].defined_at.name == 'rebulk.test.test_debug' assert self.rebulk._patterns[0].defined_at.filename.endswith('test_debug.py') assert str(self.rebulk._patterns[0].defined_at) in ['test_debug.py#L26', 'test_debug.py#L27'] assert self.rebulk._patterns[1].defined_at.lineno in [27, 28] assert self.rebulk._patterns[1].defined_at.name == 'rebulk.test.test_debug' assert self.rebulk._patterns[1].defined_at.filename.endswith('test_debug.py') assert str(self.rebulk._patterns[1].defined_at) in ['test_debug.py#L27', 'test_debug.py#L28'] assert self.matches[0].defined_at == self.rebulk._patterns[0].defined_at assert self.matches[1].defined_at == self.rebulk._patterns[1].defined_at def test_repr(self): str(self.matches) rebulk-0.9.0/rebulk/test/default_rules_module.py0000664000175000017500000000440413113544037022623 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # pylint: disable=no-self-use, pointless-statement, missing-docstring, invalid-name, len-as-condition from ..match import Match from ..rules import Rule, RemoveMatch, AppendMatch, RenameMatch, AppendTags, RemoveTags class RuleRemove0(Rule): consequence = RemoveMatch def when(self, matches, context): return matches[0] class RuleAppend0(Rule): consequence = AppendMatch() def when(self, matches, context): return Match(5, 10) class RuleRename0(Rule): consequence = [RenameMatch('renamed')] def when(self, matches, context): return [Match(5, 10, name="original")] class RuleRemove1(Rule): consequence = [RemoveMatch()] def when(self, matches, context): return [matches[0]] class RuleAppend1(Rule): consequence = [AppendMatch] def when(self, matches, context): return [Match(5, 10)] class RuleRename1(Rule): consequence = RenameMatch('renamed') def when(self, matches, context): return [Match(5, 10, name="original")] class RuleAppend2(Rule): consequence = [AppendMatch('renamed')] properties = {'renamed': [None]} def when(self, matches, context): return [Match(5, 10)] class RuleRename2(Rule): consequence = RenameMatch('renamed') def when(self, matches, context): return Match(5, 10, name="original") class RuleAppend3(Rule): consequence = AppendMatch('renamed') properties = {'renamed': [None]} def when(self, matches, context): return [Match(5, 10)] class RuleRename3(Rule): consequence = [RenameMatch('renamed')] def when(self, matches, context): return Match(5, 10, name="original") class RuleAppendTags0(Rule): consequence = AppendTags(['new-tag']) def when(self, matches, context): return matches.named('tags', 0) class RuleRemoveTags0(Rule): consequence = RemoveTags(['new-tag']) def when(self, matches, context): return matches.named('tags', 0) class RuleAppendTags1(Rule): consequence = AppendTags(['new-tag']) def when(self, matches, context): return matches.named('tags') class RuleRemoveTags1(Rule): consequence = RemoveTags(['new-tag']) def when(self, matches, context): return matches.named('tags') rebulk-0.9.0/rebulk/test/test_chain.py0000664000175000017500000003125313113544037020543 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # pylint: disable=no-self-use, pointless-statement, missing-docstring, no-member, len-as-condition import re from functools import partial from ..validators import chars_surround from ..rebulk import Rebulk, FunctionalPattern, RePattern, StringPattern def test_chain_close(): rebulk = Rebulk() ret = rebulk.chain().close() assert ret == rebulk assert len(rebulk.effective_patterns()) == 1 def test_build_chain(): rebulk = Rebulk() def digit(input_string): i = input_string.find("1849") if i > -1: return i, i + len("1849") ret = rebulk.chain() \ .functional(digit) \ .string("test").repeater(2) \ .string("x").repeater('{1,3}') \ .string("optional").repeater('?') \ .regex("f?x").repeater('+') \ .close() assert ret == rebulk assert len(rebulk.effective_patterns()) == 1 chain = rebulk.effective_patterns()[0] assert len(chain.parts) == 5 assert isinstance(chain.parts[0].pattern, FunctionalPattern) assert chain.parts[0].repeater_start == 1 assert chain.parts[0].repeater_end == 1 assert isinstance(chain.parts[1].pattern, StringPattern) assert chain.parts[1].repeater_start == 2 assert chain.parts[1].repeater_end == 2 assert isinstance(chain.parts[2].pattern, StringPattern) assert chain.parts[2].repeater_start == 1 assert chain.parts[2].repeater_end == 3 assert isinstance(chain.parts[3].pattern, StringPattern) assert chain.parts[3].repeater_start == 0 assert chain.parts[3].repeater_end == 1 assert isinstance(chain.parts[4].pattern, RePattern) assert chain.parts[4].repeater_start == 1 assert chain.parts[4].repeater_end is None def test_chain_defaults(): rebulk = Rebulk() rebulk.defaults(validator=lambda x: True, ignore_names=['testIgnore'], children=True) rebulk.chain()\ .regex("(?Ptest)") \ .regex(" ").repeater("*") \ .regex("(?PtestIgnore)") matches = rebulk.matches("test testIgnore") assert len(matches) == 1 assert matches[0].name == "test" def test_matches(): rebulk = Rebulk() def digit(input_string): i = input_string.find("1849") if i > -1: return i, i + len("1849") input_string = "1849testtestxxfixfux_foxabc1849testtestxoptionalfoxabc" chain = rebulk.chain() \ .functional(digit) \ .string("test").hidden().repeater(2) \ .string("x").hidden().repeater('{1,3}') \ .string("optional").hidden().repeater('?') \ .regex("f.?x", name='result').repeater('+') \ .close() matches = chain.matches(input_string) assert len(matches) == 2 children = matches[0].children assert children[0].value == '1849' assert children[1].value == 'fix' assert children[2].value == 'fux' children = matches[1].children assert children[0].value == '1849' assert children[1].value == 'fox' input_string = "_1850testtestxoptionalfoxabc" matches = chain.matches(input_string) assert len(matches) == 0 input_string = "_1849testtesttesttestxoptionalfoxabc" matches = chain.matches(input_string) assert len(matches) == 0 input_string = "_1849testtestxxxxoptionalfoxabc" matches = chain.matches(input_string) assert len(matches) == 0 input_string = "_1849testtestoptionalfoxabc" matches = chain.matches(input_string) assert len(matches) == 0 input_string = "_1849testtestxoptionalabc" matches = chain.matches(input_string) assert len(matches) == 0 input_string = "_1849testtestxoptionalfaxabc" matches = chain.matches(input_string) assert len(matches) == 1 children = matches[0].children assert children[0].value == '1849' assert children[1].value == 'fax' def test_matches_2(): rebulk = Rebulk() \ .regex_defaults(flags=re.IGNORECASE) \ .chain(children=True, formatter={'episode': int}) \ .defaults(formatter={'version': int}) \ .regex(r'e(?P\d{1,4})') \ .regex(r'v(?P\d+)').repeater('?') \ .regex(r'[ex-](?P\d{1,4})').repeater('*') \ .close() matches = rebulk.matches("This is E14v2-15E16x17") assert len(matches) == 5 assert matches[0].name == 'episode' assert matches[0].value == 14 assert matches[1].name == 'version' assert matches[1].value == 2 assert matches[2].name == 'episode' assert matches[2].value == 15 assert matches[3].name == 'episode' assert matches[3].value == 16 assert matches[4].name == 'episode' assert matches[4].value == 17 def test_matches_3(): alt_dash = (r'@', r'[\W_]') # abbreviation rebulk = Rebulk() rebulk.chain(formatter={'season': int, 'episode': int}, tags=['SxxExx'], abbreviations=[alt_dash], private_names=['episodeSeparator', 'seasonSeparator'], children=True, private_parent=True, conflict_solver=lambda match, other: match if match.name in ['season', 'episode'] and other.name in ['screen_size', 'video_codec', 'audio_codec', 'audio_channels', 'container', 'date'] else '__default__') \ .regex(r'(?P\d+)@?x@?(?P\d+)') \ .regex(r'(?Px|-|\+|&)(?P\d+)').repeater('*') \ .chain() \ .regex(r'S(?P\d+)@?(?:xE|Ex|E|x)@?(?P\d+)') \ .regex(r'(?:(?PxE|Ex|E|x|-|\+|&)(?P\d+))').repeater('*') \ .chain() \ .regex(r'S(?P\d+)') \ .regex(r'(?PS|-|\+|&)(?P\d+)').repeater('*') matches = rebulk.matches("test-01x02-03") assert len(matches) == 3 assert matches[0].name == 'season' assert matches[0].value == 1 assert matches[1].name == 'episode' assert matches[1].value == 2 assert matches[2].name == 'episode' assert matches[2].value == 3 matches = rebulk.matches("test-S01E02-03") assert len(matches) == 3 assert matches[0].name == 'season' assert matches[0].value == 1 assert matches[1].name == 'episode' assert matches[1].value == 2 assert matches[2].name == 'episode' assert matches[2].value == 3 matches = rebulk.matches("test-S01-02-03-04") assert len(matches) == 4 assert matches[0].name == 'season' assert matches[0].value == 1 assert matches[1].name == 'season' assert matches[1].value == 2 assert matches[2].name == 'season' assert matches[2].value == 3 assert matches[3].name == 'season' assert matches[3].value == 4 def test_matches_4(): seps_surround = partial(chars_surround, " ") rebulk = Rebulk() rebulk.regex_defaults(flags=re.IGNORECASE) rebulk.defaults(private_names=['episodeSeparator', 'seasonSeparator'], validate_all=True, validator={'__parent__': seps_surround}, children=True, private_parent=True) rebulk.chain(formatter={'episode': int, 'version': int}) \ .defaults(validator=None) \ .regex(r'e(?P\d{1,4})') \ .regex(r'v(?P\d+)').repeater('?') \ .regex(r'(?Pe|x|-)(?P\d{1,4})').repeater('*') matches = rebulk.matches("Some Series E01E02E03") assert len(matches) == 3 assert matches[0].value == 1 assert matches[1].value == 2 assert matches[2].value == 3 def test_matches_5(): seps_surround = partial(chars_surround, " ") rebulk = Rebulk() rebulk.regex_defaults(flags=re.IGNORECASE) rebulk.defaults(private_names=['episodeSeparator', 'seasonSeparator'], validate_all=True, validator={'__parent__': seps_surround}, children=True, private_parent=True) rebulk.chain(formatter={'episode': int, 'version': int}) \ .defaults(validator=None) \ .regex(r'e(?P\d{1,4})') \ .regex(r'v(?P\d+)').repeater('?') \ .regex(r'(?Pe|x|-)(?P\d{1,4})').repeater('{2,3}') matches = rebulk.matches("Some Series E01E02E03") assert len(matches) == 3 matches = rebulk.matches("Some Series E01E02") assert len(matches) == 0 matches = rebulk.matches("Some Series E01E02E03E04E05E06") # Parent can't be validated, so no results at all assert len(matches) == 0 def test_matches_6(): rebulk = Rebulk() rebulk.regex_defaults(flags=re.IGNORECASE) rebulk.defaults(private_names=['episodeSeparator', 'seasonSeparator'], validate_all=True, validator=None, children=True, private_parent=True) rebulk.chain(formatter={'episode': int, 'version': int}) \ .defaults(validator=None) \ .regex(r'e(?P\d{1,4})') \ .regex(r'v(?P\d+)').repeater('?') \ .regex(r'(?Pe|x|-)(?P\d{1,4})').repeater('{2,3}') matches = rebulk.matches("Some Series E01E02E03") assert len(matches) == 3 matches = rebulk.matches("Some Series E01E02") assert len(matches) == 0 matches = rebulk.matches("Some Series E01E02E03E04E05E06") # No validator on parent, so it should give 4 episodes. assert len(matches) == 4 def test_matches_7(): seps_surround = partial(chars_surround, ' .-/') rebulk = Rebulk() rebulk.regex_defaults(flags=re.IGNORECASE) rebulk.defaults(children=True, private_parent=True) rebulk.chain(). \ regex(r'S(?P\d+)', validate_all=True, validator={'__parent__': seps_surround}). \ regex(r'[ -](?P\d+)', validator=seps_surround).repeater('*') matches = rebulk.matches("Some S01") assert len(matches) == 1 matches[0].value = 1 matches = rebulk.matches("Some S01-02") assert len(matches) == 2 matches[0].value = 1 matches[1].value = 2 matches = rebulk.matches("programs4/Some S01-02") assert len(matches) == 2 matches[0].value = 1 matches[1].value = 2 matches = rebulk.matches("programs4/SomeS01middle.S02-03.andS04here") assert len(matches) == 2 matches[0].value = 2 matches[1].value = 3 matches = rebulk.matches("Some 02.and.S04-05.here") assert len(matches) == 2 matches[0].value = 4 matches[1].value = 5 def test_chain_breaker(): def chain_breaker(matches): seasons = matches.named('season') if len(seasons) > 1: if seasons[-1].value - seasons[-2].value > 10: return True return False seps_surround = partial(chars_surround, ' .-/') rebulk = Rebulk() rebulk.regex_defaults(flags=re.IGNORECASE) rebulk.defaults(children=True, private_parent=True, formatter={'season': int}) rebulk.chain(chain_breaker=chain_breaker). \ regex(r'S(?P\d+)', validate_all=True, validator={'__parent__': seps_surround}). \ regex(r'[ -](?P\d+)', validator=seps_surround).repeater('*') matches = rebulk.matches("Some S01-02-03-50-51") assert len(matches) == 3 matches[0].value = 1 matches[1].value = 2 matches[2].value = 3 def test_chain_breaker_defaults(): def chain_breaker(matches): seasons = matches.named('season') if len(seasons) > 1: if seasons[-1].value - seasons[-2].value > 10: return True return False seps_surround = partial(chars_surround, ' .-/') rebulk = Rebulk() rebulk.regex_defaults(flags=re.IGNORECASE) rebulk.defaults(chain_breaker=chain_breaker, children=True, private_parent=True, formatter={'season': int}) rebulk.chain(). \ regex(r'S(?P\d+)', validate_all=True, validator={'__parent__': seps_surround}). \ regex(r'[ -](?P\d+)', validator=seps_surround).repeater('*') matches = rebulk.matches("Some S01-02-03-50-51") assert len(matches) == 3 matches[0].value = 1 matches[1].value = 2 matches[2].value = 3 def test_chain_breaker_defaults2(): def chain_breaker(matches): seasons = matches.named('season') if len(seasons) > 1: if seasons[-1].value - seasons[-2].value > 10: return True return False seps_surround = partial(chars_surround, ' .-/') rebulk = Rebulk() rebulk.regex_defaults(flags=re.IGNORECASE) rebulk.chain_defaults(chain_breaker=chain_breaker) rebulk.defaults(children=True, private_parent=True, formatter={'season': int}) rebulk.chain(). \ regex(r'S(?P\d+)', validate_all=True, validator={'__parent__': seps_surround}). \ regex(r'[ -](?P\d+)', validator=seps_surround).repeater('*') matches = rebulk.matches("Some S01-02-03-50-51") assert len(matches) == 3 matches[0].value = 1 matches[1].value = 2 matches[2].value = 3 rebulk-0.9.0/rebulk/test/test_match.py0000664000175000017500000004736513113544037020570 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # pylint: disable=no-self-use, pointless-statement, missing-docstring, unneeded-not, len-as-condition import pytest import six from ..match import Match, Matches from ..pattern import StringPattern, RePattern from ..formatters import formatters class TestMatchClass(object): def test_repr(self): match1 = Match(1, 3, value="es") assert repr(match1) == '' match2 = Match(0, 4, value="test", private=True, name="abc", tags=['one', 'two']) assert repr(match2) == '' def test_names(self): parent = Match(0, 10, name="test") parent.children.append(Match(0, 10, name="child1", parent=parent)) parent.children.append(Match(0, 10, name="child2", parent=parent)) assert set(parent.names) == set(["child1", "child2"]) def test_equality(self): match1 = Match(1, 3, value="es") match2 = Match(1, 3, value="es") other = object() assert hash(match1) == hash(match2) assert hash(match1) != hash(other) assert match1 == match2 assert not match1 == other def test_inequality(self): match1 = Match(0, 2, value="te") match2 = Match(2, 4, value="st") match3 = Match(0, 2, value="other") other = object() assert hash(match1) != hash(match2) assert hash(match1) != hash(match3) assert match1 != other assert match1 != match2 assert match1 != match3 def test_length(self): match1 = Match(0, 4, value="test") match2 = Match(0, 2, value="spanIsUsed") assert len(match1) == 4 assert len(match2) == 2 def test_compare(self): match1 = Match(0, 2, value="te") match2 = Match(2, 4, value="st") other = object() assert match1 < match2 assert match1 <= match2 assert match2 > match1 assert match2 >= match1 if six.PY3: with pytest.raises(TypeError): match1 < other with pytest.raises(TypeError): match1 <= other with pytest.raises(TypeError): match1 > other with pytest.raises(TypeError): match1 >= other else: assert match1 < other assert match1 <= other assert not match1 > other assert not match1 >= other def test_value(self): match1 = Match(1, 3) match1.value = "test" assert match1.value == "test" class TestMatchesClass(object): match1 = Match(0, 2, value="te", name="start") match2 = Match(2, 3, value="s", tags="tag1") match3 = Match(3, 4, value="t", tags=["tag1", "tag2"]) match4 = Match(2, 4, value="st", name="end") def test_tag(self): matches = Matches() matches.append(self.match1) matches.append(self.match2) matches.append(self.match3) matches.append(self.match4) assert "start" in matches.names assert "end" in matches.names assert "tag1" in matches.tags assert "tag2" in matches.tags tag1 = matches.tagged("tag1") assert len(tag1) == 2 assert tag1[0] == self.match2 assert tag1[1] == self.match3 tag2 = matches.tagged("tag2") assert len(tag2) == 1 assert tag2[0] == self.match3 start = matches.named("start") assert len(start) == 1 assert start[0] == self.match1 end = matches.named("end") assert len(end) == 1 assert end[0] == self.match4 def test_base(self): matches = Matches() matches.append(self.match1) assert len(matches) == 1 assert repr(matches) == repr([self.match1]) assert list(matches.starting(0)) == [self.match1] assert list(matches.ending(2)) == [self.match1] matches.append(self.match2) matches.append(self.match3) matches.append(self.match4) assert len(matches) == 4 assert list(matches.starting(2)) == [self.match2, self.match4] assert list(matches.starting(3)) == [self.match3] assert list(matches.ending(3)) == [self.match2] assert list(matches.ending(4)) == [self.match3, self.match4] assert list(matches.range()) == [self.match1, self.match2, self.match4, self.match3] assert list(matches.range(0)) == [self.match1, self.match2, self.match4, self.match3] assert list(matches.range(0, 3)) == [self.match1, self.match2, self.match4] assert list(matches.range(2, 3)) == [self.match2, self.match4] assert list(matches.range(3, 4)) == [self.match4, self.match3] matches.remove(self.match1) assert len(matches) == 3 assert len(matches.starting(0)) == 0 assert len(matches.ending(2)) == 0 matches.clear() assert len(matches) == 0 assert len(matches.starting(0)) == 0 assert len(matches.starting(2)) == 0 assert len(matches.starting(3)) == 0 assert len(matches.ending(2)) == 0 assert len(matches.ending(3)) == 0 assert len(matches.ending(4)) == 0 def test_get_slices(self): matches = Matches() matches.append(self.match1) matches.append(self.match2) matches.append(self.match3) matches.append(self.match4) slice_matches = matches[1:3] assert isinstance(slice_matches, Matches) assert len(slice_matches) == 2 assert slice_matches[0] == self.match2 assert slice_matches[1] == self.match3 def test_remove_slices(self): matches = Matches() matches.append(self.match1) matches.append(self.match2) matches.append(self.match3) matches.append(self.match4) del matches[1:3] assert len(matches) == 2 assert matches[0] == self.match1 assert matches[1] == self.match4 def test_set_slices(self): matches = Matches() matches.append(self.match1) matches.append(self.match2) matches.append(self.match3) matches.append(self.match4) matches[1:3] = self.match1, self.match4 assert len(matches) == 4 assert matches[0] == self.match1 assert matches[1] == self.match1 assert matches[2] == self.match4 assert matches[3] == self.match4 def test_set_index(self): matches = Matches() matches.append(self.match1) matches.append(self.match2) matches.append(self.match3) matches[1] = self.match4 assert len(matches) == 3 assert matches[0] == self.match1 assert matches[1] == self.match4 assert matches[2] == self.match3 def test_constructor(self): matches = Matches([self.match1, self.match2, self.match3, self.match4]) assert len(matches) == 4 assert list(matches.starting(0)) == [self.match1] assert list(matches.ending(2)) == [self.match1] assert list(matches.starting(2)) == [self.match2, self.match4] assert list(matches.starting(3)) == [self.match3] assert list(matches.ending(3)) == [self.match2] assert list(matches.ending(4)) == [self.match3, self.match4] def test_constructor_kwargs(self): matches = Matches([self.match1, self.match2, self.match3, self.match4], input_string="test") assert len(matches) == 4 assert matches.input_string == "test" assert list(matches.starting(0)) == [self.match1] assert list(matches.ending(2)) == [self.match1] assert list(matches.starting(2)) == [self.match2, self.match4] assert list(matches.starting(3)) == [self.match3] assert list(matches.ending(3)) == [self.match2] assert list(matches.ending(4)) == [self.match3, self.match4] def test_crop(self): input_string = "abcdefghijklmnopqrstuvwxyz" match1 = Match(1, 10, input_string=input_string) match2 = Match(0, 2, input_string=input_string) match3 = Match(8, 15, input_string=input_string) ret = match1.crop([match2, match3.span]) assert len(ret) == 1 assert ret[0].span == (2, 8) assert ret[0].value == "cdefgh" ret = match1.crop((1, 10)) assert len(ret) == 0 ret = match1.crop((1, 3)) assert len(ret) == 1 assert ret[0].span == (3, 10) ret = match1.crop((7, 10)) assert len(ret) == 1 assert ret[0].span == (1, 7) ret = match1.crop((0, 12)) assert len(ret) == 0 ret = match1.crop((4, 6)) assert len(ret) == 2 assert ret[0].span == (1, 4) assert ret[1].span == (6, 10) ret = match1.crop([(3, 5), (7, 9)]) assert len(ret) == 3 assert ret[0].span == (1, 3) assert ret[1].span == (5, 7) assert ret[2].span == (9, 10) def test_split(self): input_string = "123 +word1 - word2 + word3 456" match = Match(3, len(input_string) - 3, input_string=input_string) splitted = match.split(" -+") assert len(splitted) == 3 assert [split.value for split in splitted] == ["word1", "word2", "word3"] class TestMaches(object): def test_names(self): input_string = "One Two Three" matches = Matches() matches.extend(StringPattern("One", name="1-str", tags=["One", "str"]).matches(input_string)) matches.extend(RePattern("One", name="1-re", tags=["One", "re"]).matches(input_string)) matches.extend(StringPattern("Two", name="2-str", tags=["Two", "str"]).matches(input_string)) matches.extend(RePattern("Two", name="2-re", tags=["Two", "re"]).matches(input_string)) matches.extend(StringPattern("Three", name="3-str", tags=["Three", "str"]).matches(input_string)) matches.extend(RePattern("Three", name="3-re", tags=["Three", "re"]).matches(input_string)) assert set(matches.names) == set(["1-str", "1-re", "2-str", "2-re", "3-str", "3-re"]) def test_filters(self): input_string = "One Two Three" matches = Matches() matches.extend(StringPattern("One", name="1-str", tags=["One", "str"]).matches(input_string)) matches.extend(RePattern("One", name="1-re", tags=["One", "re"]).matches(input_string)) matches.extend(StringPattern("Two", name="2-str", tags=["Two", "str"]).matches(input_string)) matches.extend(RePattern("Two", name="2-re", tags=["Two", "re"]).matches(input_string)) matches.extend(StringPattern("Three", name="3-str", tags=["Three", "str"]).matches(input_string)) matches.extend(RePattern("Three", name="3-re", tags=["Three", "re"]).matches(input_string)) selection = matches.starting(0) assert len(selection) == 2 selection = matches.starting(0, lambda m: "str" in m.tags) assert len(selection) == 1 assert selection[0].pattern.name == "1-str" selection = matches.ending(7, predicate=lambda m: "str" in m.tags) assert len(selection) == 1 assert selection[0].pattern.name == "2-str" selection = matches.previous(matches.named("2-str")[0]) assert len(selection) == 2 assert selection[0].pattern.name == "1-str" assert selection[1].pattern.name == "1-re" selection = matches.previous(matches.named("2-str", 0), lambda m: "str" in m.tags) assert len(selection) == 1 assert selection[0].pattern.name == "1-str" selection = matches.next(matches.named("2-str", 0)) assert len(selection) == 2 assert selection[0].pattern.name == "3-str" assert selection[1].pattern.name == "3-re" selection = matches.next(matches.named("2-str", 0), index=0, predicate=lambda m: "re" in m.tags) assert selection is not None assert selection.pattern.name == "3-re" selection = matches.next(matches.named("2-str", index=0), lambda m: "re" in m.tags) assert len(selection) == 1 assert selection[0].pattern.name == "3-re" selection = matches.named("2-str", lambda m: "re" in m.tags) assert len(selection) == 0 selection = matches.named("2-re", lambda m: "re" in m.tags, 0) assert selection is not None assert selection.name == "2-re" # pylint:disable=no-member selection = matches.named("2-re", lambda m: "re" in m.tags) assert len(selection) == 1 assert selection[0].name == "2-re" selection = matches.named("2-re", lambda m: "re" in m.tags, index=1000) assert selection is None def test_raw(self): input_string = "0123456789" match = Match(0, 10, input_string=input_string, formatter=lambda s: s*2) assert match.value == match.raw * 2 assert match.raw == input_string match.raw_end = 9 match.raw_start = 1 assert match.value == match.raw * 2 assert match.raw == input_string[1:9] match.raw_end = None match.raw_start = None assert match.value == match.raw * 2 assert match.raw == input_string def test_formatter_chain(self): input_string = "100" match = Match(0, 3, input_string=input_string, formatter=formatters(int, lambda s: s*2, lambda s: s+10)) assert match.raw == input_string assert match.value == 100 * 2 + 10 def test_to_dict(self): input_string = "One Two Two Three" matches = Matches() matches.extend(StringPattern("One", name="1", tags=["One", "str"]).matches(input_string)) matches.extend(RePattern("One", name="1", tags=["One", "re"]).matches(input_string)) matches.extend(StringPattern("Two", name="2", tags=["Two", "str"]).matches(input_string)) matches.extend(RePattern("Two", name="2", tags=["Two", "re"]).matches(input_string)) matches.extend(RePattern("Two", name="2", tags=["Two", "reBis"]).matches(input_string)) matches.extend(StringPattern("Three", name="3", tags=["Three", "str"]).matches(input_string)) matches.extend(RePattern("Three", name="3bis", tags=["Three", "re"]).matches(input_string)) matches.extend(RePattern(r"(\w+)", name="words").matches(input_string)) kvalues = matches.to_dict(first_value=True) assert kvalues == {"1": "One", "2": "Two", "3": "Three", "3bis": "Three", "words": "One"} assert kvalues.values_list["words"] == ["One", "Two", "Three"] kvalues = matches.to_dict(enforce_list=True) assert kvalues["words"] == ["One", "Two", "Three"] kvalues = matches.to_dict(details=True) assert kvalues["1"].value == "One" assert len(kvalues["2"]) == 2 assert kvalues["2"][0].value == "Two" assert kvalues["2"][1].value == "Two" assert kvalues["3"].value == "Three" assert kvalues["3bis"].value == "Three" assert len(kvalues["words"]) == 4 assert kvalues["words"][0].value == "One" assert kvalues["words"][1].value == "Two" assert kvalues["words"][2].value == "Two" assert kvalues["words"][3].value == "Three" kvalues = matches.to_dict(details=True) assert kvalues["1"].value == "One" assert len(kvalues.values_list["2"]) == 2 assert kvalues.values_list["2"][0].value == "Two" assert kvalues.values_list["2"][1].value == "Two" assert kvalues["3"].value == "Three" assert kvalues["3bis"].value == "Three" assert len(kvalues.values_list["words"]) == 4 assert kvalues.values_list["words"][0].value == "One" assert kvalues.values_list["words"][1].value == "Two" assert kvalues.values_list["words"][2].value == "Two" assert kvalues.values_list["words"][3].value == "Three" def test_chains(self): input_string = "wordX 10 20 30 40 wordA, wordB, wordC 70 80 wordX" matches = Matches(input_string=input_string) matches.extend(RePattern(r"\d+", name="digit").matches(input_string)) matches.extend(RePattern("[a-zA-Z]+", name="word").matches(input_string)) assert len(matches) == 11 a_start = input_string.find('wordA') b_start = input_string.find('wordB') b_end = b_start + len('wordB') c_start = input_string.find('wordC') c_end = c_start + len('wordC') chain_before = matches.chain_before(b_start, " ,", predicate=lambda match: match.name == "word") assert len(chain_before) == 1 assert chain_before[0].value == 'wordA' chain_before = matches.chain_before(Match(b_start, b_start), " ,", predicate=lambda match: match.name == "word") assert len(chain_before) == 1 assert chain_before[0].value == 'wordA' chain_before = matches.chain_before(b_start, " ,", predicate=lambda match: match.name == "digit") assert len(chain_before) == 0 chain_before = matches.chain_before(a_start, " ,", predicate=lambda match: match.name == "digit") assert len(chain_before) == 4 assert [match.value for match in chain_before] == ["40", "30", "20", "10"] chain_after = matches.chain_after(b_end, " ,", predicate=lambda match: match.name == "word") assert len(chain_after) == 1 assert chain_after[0].value == 'wordC' chain_after = matches.chain_after(Match(b_end, b_end), " ,", predicate=lambda match: match.name == "word") assert len(chain_after) == 1 assert chain_after[0].value == 'wordC' chain_after = matches.chain_after(b_end, " ,", predicate=lambda match: match.name == "digit") assert len(chain_after) == 0 chain_after = matches.chain_after(c_end, " ,", predicate=lambda match: match.name == "digit") assert len(chain_after) == 2 assert [match.value for match in chain_after] == ["70", "80"] chain_after = matches.chain_after(c_end, " ,", end=10000, predicate=lambda match: match.name == "digit") assert len(chain_after) == 2 assert [match.value for match in chain_after] == ["70", "80"] def test_holes(self): input_string = '1'*10+'2'*10+'3'*10+'4'*10+'5'*10+'6'*10+'7'*10 hole1 = Match(0, 10, input_string=input_string) hole2 = Match(20, 30, input_string=input_string) hole3 = Match(30, 40, input_string=input_string) hole4 = Match(60, 70, input_string=input_string) matches = Matches([hole1, hole2], input_string=input_string) matches.append(hole3) matches.append(hole4) holes = list(matches.holes()) assert len(holes) == 2 assert holes[0].span == (10, 20) assert holes[0].value == '2'*10 assert holes[1].span == (40, 60) assert holes[1].value == '5' * 10 + '6' * 10 holes = list(matches.holes(5, 15)) assert len(holes) == 1 assert holes[0].span == (10, 15) assert holes[0].value == '2'*5 holes = list(matches.holes(5, 15, formatter=lambda value: "formatted")) assert len(holes) == 1 assert holes[0].span == (10, 15) assert holes[0].value == "formatted" holes = list(matches.holes(5, 15, predicate=lambda hole: False)) assert len(holes) == 0 def test_holes_empty(self): input_string = "Test hole on empty matches" matches = Matches(input_string=input_string) holes = matches.holes() assert len(holes) == 1 assert holes[0].value == input_string def test_holes_seps(self): input_string = "Test hole - with many separators + included" match = StringPattern("many").matches(input_string) matches = Matches(match, input_string) holes = matches.holes() assert len(holes) == 2 holes = matches.holes(seps="-+") assert len(holes) == 4 assert [hole.value for hole in holes] == ["Test hole ", " with ", " separators ", " included"] rebulk-0.9.0/rebulk/test/test_rules.py0000664000175000017500000001247613113544037020621 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # pylint: disable=no-self-use, pointless-statement, missing-docstring, invalid-name, no-member, len-as-condition import pytest from rebulk.test.default_rules_module import RuleRemove0, RuleAppend0, RuleRename0, RuleAppend1, RuleRemove1, \ RuleRename1, RuleAppend2, RuleRename2, RuleAppend3, RuleRename3, RuleAppendTags0, RuleRemoveTags0, \ RuleAppendTags1, RuleRemoveTags1 from ..rules import Rules from ..match import Matches, Match from .rules_module import Rule1, Rule2, Rule3, Rule0, Rule1Disabled from . import rules_module as rm def test_rule_priority(): matches = Matches([Match(1, 2)]) rules = Rules(Rule1, Rule2()) rules.execute_all_rules(matches, {}) assert len(matches) == 0 matches = Matches([Match(1, 2)]) rules = Rules(Rule1(), Rule0) rules.execute_all_rules(matches, {}) assert len(matches) == 1 assert matches[0] == Match(3, 4) def test_rules_duplicates(): matches = Matches([Match(1, 2)]) rules = Rules(Rule1, Rule1) with pytest.raises(ValueError): rules.execute_all_rules(matches, {}) def test_rule_disabled(): matches = Matches([Match(1, 2)]) rules = Rules(Rule1Disabled(), Rule2()) rules.execute_all_rules(matches, {}) assert len(matches) == 2 assert matches[0] == Match(1, 2) assert matches[1] == Match(3, 4) def test_rule_when(): matches = Matches([Match(1, 2)]) rules = Rules(Rule3()) rules.execute_all_rules(matches, {'when': False}) assert len(matches) == 1 assert matches[0] == Match(1, 2) matches = Matches([Match(1, 2)]) rules.execute_all_rules(matches, {'when': True}) assert len(matches) == 2 assert matches[0] == Match(1, 2) assert matches[1] == Match(3, 4) class TestDefaultRules(object): def test_remove(self): rules = Rules(RuleRemove0) matches = Matches([Match(1, 2)]) rules.execute_all_rules(matches, {}) assert len(matches) == 0 rules = Rules(RuleRemove1) matches = Matches([Match(1, 2)]) rules.execute_all_rules(matches, {}) assert len(matches) == 0 def test_append(self): rules = Rules(RuleAppend0) matches = Matches([Match(1, 2)]) rules.execute_all_rules(matches, {}) assert len(matches) == 2 rules = Rules(RuleAppend1) matches = Matches([Match(1, 2)]) rules.execute_all_rules(matches, {}) assert len(matches) == 2 rules = Rules(RuleAppend2) matches = Matches([Match(1, 2)]) rules.execute_all_rules(matches, {}) assert len(matches) == 2 assert len(matches.named('renamed')) == 1 rules = Rules(RuleAppend3) matches = Matches([Match(1, 2)]) rules.execute_all_rules(matches, {}) assert len(matches) == 2 assert len(matches.named('renamed')) == 1 def test_rename(self): rules = Rules(RuleRename0) matches = Matches([Match(1, 2, name='original')]) rules.execute_all_rules(matches, {}) assert len(matches.named('original')) == 1 assert len(matches.named('renamed')) == 0 rules = Rules(RuleRename1) matches = Matches([Match(5, 10, name='original')]) rules.execute_all_rules(matches, {}) assert len(matches.named('original')) == 0 assert len(matches.named('renamed')) == 1 rules = Rules(RuleRename2) matches = Matches([Match(5, 10, name='original')]) rules.execute_all_rules(matches, {}) assert len(matches.named('original')) == 0 assert len(matches.named('renamed')) == 1 rules = Rules(RuleRename3) matches = Matches([Match(5, 10, name='original')]) rules.execute_all_rules(matches, {}) assert len(matches.named('original')) == 0 assert len(matches.named('renamed')) == 1 def test_append_tags(self): rules = Rules(RuleAppendTags0) matches = Matches([Match(1, 2, name='tags', tags=['other'])]) rules.execute_all_rules(matches, {}) assert len(matches.named('tags')) == 1 assert matches.named('tags', index=0).tags == ['other', 'new-tag'] rules = Rules(RuleAppendTags1) matches = Matches([Match(1, 2, name='tags', tags=['other'])]) rules.execute_all_rules(matches, {}) assert len(matches.named('tags')) == 1 assert matches.named('tags', index=0).tags == ['other', 'new-tag'] def test_remove_tags(self): rules = Rules(RuleRemoveTags0) matches = Matches([Match(1, 2, name='tags', tags=['other', 'new-tag'])]) rules.execute_all_rules(matches, {}) assert len(matches.named('tags')) == 1 assert matches.named('tags', index=0).tags == ['other'] rules = Rules(RuleRemoveTags1) matches = Matches([Match(1, 2, name='tags', tags=['other', 'new-tag'])]) rules.execute_all_rules(matches, {}) assert len(matches.named('tags')) == 1 assert matches.named('tags', index=0).tags == ['other'] def test_rule_module(): rules = Rules(rm) matches = Matches([Match(1, 2)]) rules.execute_all_rules(matches, {}) assert len(matches) == 1 def test_rule_repr(): assert str(Rule0()) == "" assert str(Rule1()) == "" assert str(Rule2()) == "" assert str(Rule1Disabled()) == "" rebulk-0.9.0/rebulk/test/test_pattern.py0000664000175000017500000007121413113544037021137 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # pylint: disable=no-self-use, pointless-statement, missing-docstring, unbalanced-tuple-unpacking, len-as-condition import re import pytest from ..pattern import StringPattern, RePattern, FunctionalPattern, REGEX_AVAILABLE from ..match import Match class TestStringPattern(object): """ Tests for StringPattern matching """ input_string = "An Abyssinian fly playing a Celtic violin was annoyed by trashy flags on " \ "which were the Hebrew letter qoph." def test_single(self): pattern = StringPattern("Celtic") matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (28, 34) assert matches[0].value == "Celtic" def test_repr(self): pattern = StringPattern("Celtic") assert repr(pattern) == '' def test_ignore_case(self): pattern = StringPattern("celtic", ignore_case=False) matches = list(pattern.matches(self.input_string)) assert len(matches) == 0 pattern = StringPattern("celtic", ignore_case=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert matches[0].value == "Celtic" def test_private_names(self): pattern = StringPattern("celtic", name="test", private_names=["test"], ignore_case=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert matches[0].private def test_ignore_names(self): pattern = StringPattern("celtic", name="test", ignore_names=["test"], ignore_case=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 0 def test_no_match(self): pattern = StringPattern("Python") matches = list(pattern.matches(self.input_string)) assert not matches def test_multiple_patterns(self): pattern = StringPattern("playing", "annoyed", "Hebrew") matches = list(pattern.matches(self.input_string)) assert len(matches) == 3 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (18, 25) assert matches[0].value == "playing" assert isinstance(matches[1], Match) assert matches[1].pattern == pattern assert matches[1].span == (46, 53) assert matches[1].value == "annoyed" assert isinstance(matches[2], Match) assert matches[2].pattern == pattern assert matches[2].span == (88, 94) assert matches[2].value == "Hebrew" def test_start_end_kwargs(self): pattern = StringPattern("Abyssinian", start=20, end=40) matches = list(pattern.matches(self.input_string)) assert len(matches) == 0 def test_matches_kwargs(self): pattern = StringPattern("Abyssinian", name="test", value="AB") matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert matches[0].name == "test" assert matches[0].value == "AB" def test_post_processor(self): def post_processor(matches, pattern): assert len(matches) == 1 assert isinstance(pattern, StringPattern) return [] pattern = StringPattern("Abyssinian", name="test", value="AB", post_processor=post_processor) matches = list(pattern.matches(self.input_string)) assert len(matches) == 0 class TestRePattern(object): """ Tests for RePattern matching """ input_string = "An Abyssinian fly playing a Celtic violin was annoyed by trashy flags on " \ "which were the Hebrew letter qoph." def test_single_compiled(self): pattern = RePattern(re.compile("Celt.?c")) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (28, 34) assert matches[0].value == "Celtic" def test_single_string(self): pattern = RePattern("Celt.?c") matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (28, 34) assert matches[0].value == "Celtic" def test_single_kwargs(self): pattern = RePattern({"pattern": "celt.?c", "flags": re.IGNORECASE}) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (28, 34) assert matches[0].value == "Celtic" def test_single_vargs(self): pattern = RePattern(("celt.?c", re.IGNORECASE)) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (28, 34) assert matches[0].value == "Celtic" def test_no_match(self): pattern = RePattern("abc.?def") matches = list(pattern.matches(self.input_string)) assert len(matches) == 0 def test_shortcuts(self): pattern = RePattern("Celtic-violin", abbreviations=[("-", r"[\W_]+")]) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 pattern = RePattern({"pattern": "celtic-violin", "flags": re.IGNORECASE}, abbreviations=[("-", r"[\W_]+")]) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 def test_multiple_patterns(self): pattern = RePattern("pla.?ing", "ann.?yed", "Heb.?ew") matches = list(pattern.matches(self.input_string)) assert len(matches) == 3 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (18, 25) assert matches[0].value == "playing" assert isinstance(matches[1], Match) assert matches[1].pattern == pattern assert matches[1].span == (46, 53) assert matches[1].value == "annoyed" assert isinstance(matches[2], Match) assert matches[2].pattern == pattern assert matches[2].span == (88, 94) assert matches[2].value == "Hebrew" def test_unnamed_groups(self): pattern = RePattern(r"(Celt.?c)\s+(\w+)") matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 parent = matches[0] assert isinstance(parent, Match) assert parent.pattern == pattern assert parent.span == (28, 41) assert parent.name is None assert parent.value == "Celtic violin" assert len(parent.children) == 2 group1, group2 = parent.children assert isinstance(group1, Match) assert group1.pattern == pattern assert group1.span == (28, 34) assert group1.name is None assert group1.value == "Celtic" assert group1.parent == parent assert isinstance(group2, Match) assert group2.pattern == pattern assert group2.span == (35, 41) assert group2.name is None assert group2.value == "violin" assert group2.parent == parent def test_named_groups(self): pattern = RePattern(r"(?PCelt.?c)\s+(?P\w+)") matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 parent = matches[0] assert isinstance(parent, Match) assert parent.pattern == pattern assert parent.span == (28, 41) assert parent.name is None assert parent.value == "Celtic violin" assert len(parent.children) == 2 group1, group2 = parent.children assert isinstance(group1, Match) assert group1.pattern == pattern assert group1.span == (28, 34) assert group1.name == "param1" assert group1.value == "Celtic" assert group1.parent == parent assert isinstance(group2, Match) assert group2.pattern == pattern assert group2.span == (35, 41) assert group2.name == "param2" assert group2.value == "violin" assert group2.parent == parent def test_children(self): pattern = RePattern(r"(?PCelt.?c)\s+(?P\w+)", children=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 2 group1, group2 = matches assert isinstance(group1, Match) assert group1.pattern == pattern assert group1.span == (28, 34) assert group1.name == "param1" assert group1.value == "Celtic" assert isinstance(group2, Match) assert group2.pattern == pattern assert group2.span == (35, 41) assert group2.name == "param2" assert group2.value == "violin" def test_children_parent_private(self): pattern = RePattern(r"(?PCelt.?c)\s+(?P\w+)", children=True, private_parent=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 3 parent, group1, group2 = matches assert isinstance(group1, Match) assert parent.private assert parent.pattern == pattern assert parent.span == (28, 41) assert parent.name is None assert parent.value == "Celtic violin" assert isinstance(group1, Match) assert not group1.private assert group1.pattern == pattern assert group1.span == (28, 34) assert group1.name == "param1" assert group1.value == "Celtic" assert isinstance(group2, Match) assert not group2.private assert group2.pattern == pattern assert group2.span == (35, 41) assert group2.name == "param2" assert group2.value == "violin" def test_parent_children_private(self): pattern = RePattern(r"(?PCelt.?c)\s+(?P\w+)", private_children=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 3 parent, group1, group2 = matches assert isinstance(group1, Match) assert not parent.private assert parent.pattern == pattern assert parent.span == (28, 41) assert parent.name is None assert parent.value == "Celtic violin" assert isinstance(group1, Match) assert group1.private assert group1.pattern == pattern assert group1.span == (28, 34) assert group1.name == "param1" assert group1.value == "Celtic" assert isinstance(group2, Match) assert group2.private assert group2.pattern == pattern assert group2.span == (35, 41) assert group2.name == "param2" assert group2.value == "violin" def test_every(self): pattern = RePattern(r"(?PCelt.?c)\s+(?P\w+)", every=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 3 parent, group1, group2 = matches assert isinstance(group1, Match) assert not parent.private assert parent.pattern == pattern assert parent.span == (28, 41) assert parent.name is None assert parent.value == "Celtic violin" assert isinstance(group1, Match) assert not group1.private assert group1.pattern == pattern assert group1.span == (28, 34) assert group1.name == "param1" assert group1.value == "Celtic" assert isinstance(group2, Match) assert not group2.private assert group2.pattern == pattern assert group2.span == (35, 41) assert group2.name == "param2" assert group2.value == "violin" def test_private_names(self): pattern = RePattern(r"(?PCelt.?c)\s+(?P\w+)", private_names=["param2"], children=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 2 assert matches[0].name == "param1" assert not matches[0].private assert matches[1].name == "param2" assert matches[1].private def test_ignore_names(self): pattern = RePattern(r"(?PCelt.?c)\s+(?P\w+)", ignore_names=["param2"], children=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert matches[0].name == "param1" def test_matches_kwargs(self): pattern = RePattern("He.rew", name="test", value="HE") matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert matches[0].name == "test" assert matches[0].value == "HE" pattern = RePattern("H(e.)(rew)", name="test", value="HE") matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert matches[0].name == "test" assert matches[0].value == "HE" children = matches[0].children assert len(children) == 2 assert children[0].name == "test" assert children[0].value == "HE" assert children[1].name == "test" assert children[1].value == "HE" pattern = RePattern("H(?Pe.)(?Prew)", name="test", value="HE") matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert matches[0].name == "test" assert matches[0].value == "HE" children = matches[0].children assert len(children) == 2 assert children[0].name == "first" assert children[0].value == "HE" assert children[1].name == "second" assert children[1].value == "HE" class TestFunctionalPattern(object): """ Tests for FunctionalPattern matching """ input_string = "An Abyssinian fly playing a Celtic violin was annoyed by trashy flags on " \ "which were the Hebrew letter qoph." def test_single_vargs(self): def func(input_string): i = input_string.find("fly") if i > -1: return i, i + len("fly"), "fly", "functional" pattern = FunctionalPattern(func) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (14, 17) assert matches[0].name == "functional" assert matches[0].value == "fly" def test_single_kwargs(self): def func(input_string): i = input_string.find("fly") if i > -1: return {"start": i, "end": i + len("fly"), "name": "functional"} pattern = FunctionalPattern(func) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (14, 17) assert matches[0].name == "functional" assert matches[0].value == "fly" def test_multiple_objects(self): def func(input_string): i = input_string.find("fly") matches = [] if i > -1: matches.append((i, i + len("fly"), {'name': "functional"})) i = input_string.find("annoyed") if i > -1: matches.append((i, i + len("annoyed"))) i = input_string.find("Hebrew") if i > -1: matches.append({"start": i, "end": i + len("Hebrew")}) return matches pattern = FunctionalPattern(func) matches = list(pattern.matches(self.input_string)) assert len(matches) == 3 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (14, 17) assert matches[0].name == "functional" assert matches[0].value == "fly" assert isinstance(matches[1], Match) assert matches[1].pattern == pattern assert matches[1].span == (46, 53) assert matches[1].value == "annoyed" assert isinstance(matches[2], Match) assert matches[2].pattern == pattern assert matches[2].span == (88, 94) assert matches[2].value == "Hebrew" def test_multiple_generator(self): def func(input_string): i = input_string.find("fly") if i > -1: yield (i, i + len("fly"), {'name': "functional"}) i = input_string.find("annoyed") if i > -1: yield (i, i + len("annoyed")) i = input_string.find("Hebrew") if i > -1: yield (i, {"end": i + len("Hebrew")}) pattern = FunctionalPattern(func) matches = list(pattern.matches(self.input_string)) assert len(matches) == 3 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (14, 17) assert matches[0].name == "functional" assert matches[0].value == "fly" assert isinstance(matches[1], Match) assert matches[1].pattern == pattern assert matches[1].span == (46, 53) assert matches[1].value == "annoyed" assert isinstance(matches[2], Match) assert matches[2].pattern == pattern assert matches[2].span == (88, 94) assert matches[2].value == "Hebrew" def test_no_match(self): pattern = FunctionalPattern(lambda x: None) matches = list(pattern.matches(self.input_string)) assert len(matches) == 0 def test_multiple_patterns(self): def playing(input_string): i = input_string.find("playing") if i > -1: return i, i + len("playing") def annoyed(input_string): i = input_string.find("annoyed") if i > -1: return i, i + len("annoyed") def hebrew(input_string): i = input_string.find("Hebrew") if i > -1: return i, i + len("Hebrew") pattern = FunctionalPattern(playing, annoyed, hebrew) matches = list(pattern.matches(self.input_string)) assert len(matches) == 3 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (18, 25) assert matches[0].value == "playing" assert isinstance(matches[1], Match) assert matches[1].pattern == pattern assert matches[1].span == (46, 53) assert matches[1].value == "annoyed" assert isinstance(matches[2], Match) assert matches[2].pattern == pattern assert matches[2].span == (88, 94) assert matches[2].value == "Hebrew" def test_matches_kwargs(self): def playing(input_string): i = input_string.find("playing") if i > -1: return i, i + len("playing") pattern = FunctionalPattern(playing, name="test", value="PLAY") matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert matches[0].name == "test" assert matches[0].value == "PLAY" class TestValue(object): """ Tests for value option """ input_string = "This string contains 1849 a number" def test_str_value(self): pattern = StringPattern("1849", name="dummy", value="test") matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (21, 25) assert matches[0].value == "test" def test_dict_child_value(self): pattern = RePattern(r"(?Pcont.?ins)\s+(?P\d+)", formatter={'intParam': lambda x: int(x) * 2, 'strParam': lambda x: "really " + x}, format_all=True, value={'intParam': 'INT_PARAM_VALUE'}) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 parent = matches[0] assert len(parent.children) == 2 group1, group2 = parent.children assert isinstance(group1, Match) assert group1.pattern == pattern assert group1.span == (12, 20) assert group1.value == "really contains" assert isinstance(group2, Match) assert group2.pattern == pattern assert group2.span == (21, 25) assert group2.value == 'INT_PARAM_VALUE' def test_dict_default_value(self): pattern = RePattern(r"(?Pcont.?ins)\s+(?P\d+)", formatter={'intParam': lambda x: int(x) * 2, 'strParam': lambda x: "really " + x}, format_all=True, value={'__children__': 'CHILD', 'strParam': 'STR_VALUE', '__parent__': 'PARENT'}) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 parent = matches[0] assert parent.value == "PARENT" assert len(parent.children) == 2 group1, group2 = parent.children assert isinstance(group1, Match) assert group1.pattern == pattern assert group1.span == (12, 20) assert group1.value == "STR_VALUE" assert isinstance(group2, Match) assert group2.pattern == pattern assert group2.span == (21, 25) assert group2.value == "CHILD" class TestFormatter(object): """ Tests for formatter option """ input_string = "This string contains 1849 a number" def test_single_string(self): pattern = StringPattern("1849", name="dummy", formatter=lambda x: int(x) / 2) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (21, 25) assert matches[0].value == 1849 / 2 def test_single_re_no_group(self): pattern = RePattern(r"\d+", formatter=lambda x: int(x) * 2) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (21, 25) assert matches[0].value == 1849 * 2 def test_single_re_named_groups(self): pattern = RePattern(r"(?Pcont.?ins)\s+(?P\d+)", formatter={'intParam': lambda x: int(x) * 2, 'strParam': lambda x: "really " + x}, format_all=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 parent = matches[0] assert len(parent.children) == 2 group1, group2 = parent.children assert isinstance(group1, Match) assert group1.pattern == pattern assert group1.span == (12, 20) assert group1.value == "really contains" assert isinstance(group2, Match) assert group2.pattern == pattern assert group2.span == (21, 25) assert group2.value == 1849 * 2 def test_repeated_captures_option(self): pattern = RePattern(r"\[(\d+)\](?:-(\d+))*") matches = list(pattern.matches("[02]-03-04-05-06")) assert len(matches) == 1 match = matches[0] if REGEX_AVAILABLE: assert len(match.children) == 5 assert [child.value for child in match.children] == ["02", "03", "04", "05", "06"] else: assert len(match.children) == 2 assert [child.value for child in match.children] == ["02", "06"] with pytest.raises(NotImplementedError): RePattern(r"\[(\d+)\](?:-(\d+))*", repeated_captures=True) pattern = RePattern(r"\[(\d+)\](?:-(\d+))*", repeated_captures=False) matches = list(pattern.matches("[02]-03-04-05-06")) assert len(matches) == 1 match = matches[0] assert len(match.children) == 2 assert [child.value for child in match.children] == ["02", "06"] def test_single_functional(self): def digit(input_string): i = input_string.find("1849") if i > -1: return i, i + len("1849") pattern = FunctionalPattern(digit, formatter=lambda x: int(x) * 3) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 assert isinstance(matches[0], Match) assert matches[0].pattern == pattern assert matches[0].span == (21, 25) assert matches[0].value == 1849 * 3 class TestValidator(object): """ Tests for validator option """ input_string = "This string contains 1849 a number" @staticmethod def true_validator(match): return int(match.value) < 1850 @staticmethod def false_validator(match): return int(match.value) >= 1850 def test_single_string(self): pattern = StringPattern("1849", name="dummy", validator=self.false_validator) matches = list(pattern.matches(self.input_string)) assert len(matches) == 0 pattern = StringPattern("1849", validator=self.true_validator) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 def test_single_re_no_group(self): pattern = RePattern(r"\d+", validator=self.false_validator) matches = list(pattern.matches(self.input_string)) assert len(matches) == 0 pattern = RePattern(r"\d+", validator=self.true_validator) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 def test_single_re_named_groups(self): pattern = RePattern(r"(?Pcont.?ins)\s+(?P\d+)", validator={'intParam': self.false_validator}, validate_all=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 0 pattern = RePattern(r"(?Pcont.?ins)\s+(?P\d+)", validator={'intParam': self.true_validator}, validate_all=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 def test_validate_all(self): pattern = RePattern(r"contains (?P\d+)", formatter=int, validator=lambda match: match.value < 100, children=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 0 pattern = RePattern(r"contains (?P\d+)", formatter=int, validator=lambda match: match.value > 100, children=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 def invalid_func(match): if match.name == 'intParam': return True return match.value.startswith('abc') pattern = RePattern(r"contains (?P\d+)", formatter=int, validator=invalid_func, validate_all=True, children=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 0 def func(match): if match.name == 'intParam': return True return match.value.startswith('contains') pattern = RePattern(r"contains (?P\d+)", formatter=int, validator=func, validate_all=True, children=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 def test_format_all(self): pattern = RePattern(r"contains (?P\d+)", formatter=int, children=True) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 for match in matches: assert match.value is not None with pytest.raises(ValueError): pattern = RePattern(r"contains (?P\d+)", formatter=int, format_all=True) matches = list(pattern.matches(self.input_string)) for match in matches: assert match.value is not None def test_single_functional(self): def digit(input_string): i = input_string.find("1849") if i > -1: return i, i + len("1849") pattern = FunctionalPattern(digit, validator=self.false_validator) matches = list(pattern.matches(self.input_string)) assert len(matches) == 0 pattern = FunctionalPattern(digit, validator=self.true_validator) matches = list(pattern.matches(self.input_string)) assert len(matches) == 1 rebulk-0.9.0/rebulk/test/test_loose.py0000664000175000017500000000536413113544037020606 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # pylint: disable=no-self-use, pointless-statement, missing-docstring, invalid-name, len-as-condition from ..loose import call def test_loose_function(): def func(v1, v2, v3=3, v4=4): return v1 + v2 + v3 + v4 assert call(func, 1, 2) == func(1, 2) assert call(func, 1, 2, 3, 5) == func(1, 2, 3, 5) assert call(func, 1, 2, v3=4, v4=5) == func(1, 2, v3=4, v4=5) assert call(func, 1, 2, 3, 4, 5) == func(1, 2, 3, 4) assert call(func, 1, 2, 3, 4, more=5) == func(1, 2, 3, 4) def test_loose_varargs_function(): def func(v1, v2, *args): return v1 + v2 + args[0] if len(args) > 0 else 3 + args[1] if len(args) > 1 else 4 assert call(func, 1, 2) == func(1, 2) assert call(func, 1, 2, 3, 5) == func(1, 2, 3, 5) assert call(func, 1, 2, 3, 4, 5) == func(1, 2, 3, 4) def test_loose_kwargs_function(): def func(v1, v2, **kwargs): return v1 + v2 + kwargs.get('v3', 3) + kwargs.get('v4', 4) assert call(func, v1=1, v2=2) == func(v1=1, v2=2) assert call(func, v1=1, v2=2, v3=3, v4=5) == func(v1=1, v2=2, v3=3, v4=5) def test_loose_class(): class Dummy(object): def __init__(self, v1, v2, v3=3, v4=4): self.v1 = v1 self.v2 = v2 self.v3 = v3 self.v4 = v4 def call(self): return self.v1 + self.v2 + self.v3 + self.v4 assert call(Dummy, 1, 2).call() == Dummy(1, 2).call() assert call(Dummy, 1, 2, 3, 5).call() == Dummy(1, 2, 3, 5).call() assert call(Dummy, 1, 2, v3=4, v4=5).call() == Dummy(1, 2, v3=4, v4=5).call() assert call(Dummy, 1, 2, 3, 4, 5).call() == Dummy(1, 2, 3, 4).call() assert call(Dummy, 1, 2, 3, 4, more=5).call() == Dummy(1, 2, 3, 4).call() def test_loose_varargs_class(): class Dummy(object): def __init__(self, v1, v2, *args): self.v1 = v1 self.v2 = v2 self.v3 = args[0] if len(args) > 0 else 3 self.v4 = args[1] if len(args) > 1 else 4 def call(self): return self.v1 + self.v2 + self.v3 + self.v4 assert call(Dummy, 1, 2).call() == Dummy(1, 2).call() assert call(Dummy, 1, 2, 3, 5).call() == Dummy(1, 2, 3, 5).call() assert call(Dummy, 1, 2, 3, 4, 5).call() == Dummy(1, 2, 3, 4).call() def test_loose_kwargs_class(): class Dummy(object): def __init__(self, v1, v2, **kwargs): self.v1 = v1 self.v2 = v2 self.v3 = kwargs.get('v3', 3) self.v4 = kwargs.get('v4', 4) def call(self): return self.v1 + self.v2 + self.v3 + self.v4 assert call(Dummy, v1=1, v2=2).call() == Dummy(v1=1, v2=2).call() assert call(Dummy, v1=1, v2=2, v3=3, v4=5).call() == Dummy(v1=1, v2=2, v3=3, v4=5).call() rebulk-0.9.0/rebulk/loose.py0000664000175000017500000001251313113544037016562 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Various utilities functions """ import inspect import sys from .utils import is_iterable if sys.version_info < (3, 4, 0): # pragma: no cover def _constructor(class_): """ Retrieves constructor from given class :param class_: :type class_: class :return: constructor from given class :rtype: callable """ return class_.__init__ else: # pragma: no cover def _constructor(class_): """ Retrieves constructor from given class :param class_: :type class_: class :return: constructor from given class :rtype: callable """ return class_ def call(function, *args, **kwargs): """ Call a function or constructor with given args and kwargs after removing args and kwargs that doesn't match function or constructor signature :param function: Function or constructor to call :type function: callable :param args: :type args: :param kwargs: :type kwargs: :return: sale vakye as default function call :rtype: object """ func = constructor_args if inspect.isclass(function) else function_args call_args, call_kwargs = func(function, *args, **kwargs) return function(*call_args, **call_kwargs) def function_args(callable_, *args, **kwargs): """ Return (args, kwargs) matching the function signature :param callable: callable to inspect :type callable: callable :param args: :type args: :param kwargs: :type kwargs: :return: (args, kwargs) matching the function signature :rtype: tuple """ argspec = inspect.getargspec(callable_) # pylint:disable=deprecated-method return argspec_args(argspec, False, *args, **kwargs) def constructor_args(class_, *args, **kwargs): """ Return (args, kwargs) matching the function signature :param callable: callable to inspect :type callable: Callable :param args: :type args: :param kwargs: :type kwargs: :return: (args, kwargs) matching the function signature :rtype: tuple """ argspec = inspect.getargspec(_constructor(class_)) # pylint:disable=deprecated-method return argspec_args(argspec, True, *args, **kwargs) def argspec_args(argspec, constructor, *args, **kwargs): """ Return (args, kwargs) matching the argspec object :param argspec: argspec to use :type argspec: argspec :param constructor: is it a constructor ? :type constructor: bool :param args: :type args: :param kwargs: :type kwargs: :return: (args, kwargs) matching the function signature :rtype: tuple """ if argspec.keywords: call_kwarg = kwargs else: call_kwarg = dict((k, kwargs[k]) for k in kwargs if k in argspec.args) # Python 2.6 dict comprehension if argspec.varargs: call_args = args else: call_args = args[:len(argspec.args) - (1 if constructor else 0)] return call_args, call_kwarg def ensure_list(param): """ Retrieves a list from given parameter. :param param: :type param: :return: :rtype: """ if not param: param = [] elif not is_iterable(param): param = [param] return param def ensure_dict(param, default_value, default_key=None): """ Retrieves a dict and a default value from given parameter. if parameter is not a dict, it will be promoted as the default value. :param param: :type param: :param default_value: :type default_value: :param default_key: :type default_key: :return: :rtype: """ if not param: param = default_value if not isinstance(param, dict): if param: default_value = param return {default_key: param}, default_value return param, default_value def filter_index(collection, predicate=None, index=None): """ Filter collection with predicate function and index. If index is not found, returns None. :param collection: :type collection: collection supporting iteration and slicing :param predicate: function to filter the collection with :type predicate: function :param index: position of a single element to retrieve :type index: int :return: filtered list, or single element of filtered list if index is defined :rtype: list or object """ if index is None and isinstance(predicate, int): index = predicate predicate = None if predicate: collection = collection.__class__(filter(predicate, collection)) if index is not None: try: collection = collection[index] except IndexError: collection = None return collection def set_defaults(defaults, kwargs): """ Set defaults from defaults dict to kwargs dict :param defaults: :type defaults: :param kwargs: :type kwargs: :return: :rtype: """ for key, value in defaults.items(): if key not in kwargs and value is not None: kwargs[key] = value elif isinstance(value, list) and isinstance(kwargs[key], list): kwargs[key] = list(value) + kwargs[key] elif isinstance(value, dict) and isinstance(kwargs[key], dict): set_defaults(value, kwargs[key]) elif key in kwargs and value is None: kwargs[key] = None rebulk-0.9.0/rebulk/processors.py0000664000175000017500000000653413113544037017651 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Processor functions """ from logging import getLogger from .utils import IdentitySet from .rules import Rule, RemoveMatch log = getLogger(__name__).log DEFAULT = '__default__' POST_PROCESS = -2048 PRE_PROCESS = 2048 def _default_conflict_solver(match, conflicting_match): """ Default conflict solver for matches, shorter matches if they conflicts with longer ones :param conflicting_match: :type conflicting_match: :param match: :type match: :return: :rtype: """ if len(conflicting_match.initiator) < len(match.initiator): return conflicting_match elif len(match.initiator) < len(conflicting_match.initiator): return match return None class ConflictSolver(Rule): """ Remove conflicting matches. """ priority = PRE_PROCESS consequence = RemoveMatch @property def default_conflict_solver(self): # pylint:disable=no-self-use """ Default conflict solver to use. """ return _default_conflict_solver def when(self, matches, context): # pylint:disable=too-many-nested-blocks to_remove_matches = IdentitySet() public_matches = [match for match in matches if not match.private] public_matches.sort(key=len) for match in public_matches: conflicting_matches = matches.conflicting(match) if conflicting_matches: # keep the match only if it's the longest conflicting_matches = [conflicting_match for conflicting_match in conflicting_matches if not conflicting_match.private] conflicting_matches.sort(key=len) for conflicting_match in conflicting_matches: conflict_solvers = [(self.default_conflict_solver, False)] if match.conflict_solver: conflict_solvers.append((match.conflict_solver, False)) if conflicting_match.conflict_solver: conflict_solvers.append((conflicting_match.conflict_solver, True)) for conflict_solver, reverse in reversed(conflict_solvers): if reverse: to_remove = conflict_solver(conflicting_match, match) else: to_remove = conflict_solver(match, conflicting_match) if to_remove == DEFAULT: continue if to_remove and to_remove not in to_remove_matches: both_matches = [match, conflicting_match] both_matches.remove(to_remove) to_keep = both_matches[0] if to_keep not in to_remove_matches: log(self.log_level, "Conflicting match %s will be removed in favor of match %s", to_remove, to_keep) to_remove_matches.add(to_remove) break return to_remove_matches class PrivateRemover(Rule): """ Removes private matches rule. """ priority = POST_PROCESS consequence = RemoveMatch def when(self, matches, context): return [match for match in matches if match.private] rebulk-0.9.0/rebulk/toposort.py0000664000175000017500000000477113113544037017341 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright 2014 True Blade Systems, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Original: # - https://bitbucket.org/ericvsmith/toposort (1.4) # Modifications: # - merged Pull request #2 for CyclicDependency error # - import reduce as original name # - support python 2.6 dict comprehension # pylint: skip-file from functools import reduce class CyclicDependency(ValueError): def __init__(self, cyclic): s = 'Cyclic dependencies exist among these items: {0}'.format(', '.join(repr(x) for x in cyclic.items())) super(CyclicDependency, self).__init__(s) self.cyclic = cyclic def toposort(data): """ Dependencies are expressed as a dictionary whose keys are items and whose values are a set of dependent items. Output is a list of sets in topological order. The first set consists of items with no dependences, each subsequent set consists of items that depend upon items in the preceeding sets. :param data: :type data: :return: :rtype: """ # Special case empty input. if len(data) == 0: return # Copy the input so as to leave it unmodified. data = data.copy() # Ignore self dependencies. for k, v in data.items(): v.discard(k) # Find all items that don't depend on anything. extra_items_in_deps = reduce(set.union, data.values()) - set(data.keys()) # Add empty dependences where needed. data.update(dict((item, set()) for item in extra_items_in_deps)) while True: ordered = set(item for item, dep in data.items() if len(dep) == 0) if not ordered: break yield ordered data = dict((item, (dep - ordered)) for item, dep in data.items() if item not in ordered) if len(data) != 0: raise CyclicDependency(data) def toposort_flatten(data, sort=True): """ Returns a single list of dependencies. For any set returned by toposort(), those items are sorted and appended to the result (just to make the results deterministic). :param data: :type data: :param sort: :type sort: :return: Single list of dependencies. :rtype: list """ result = [] for d in toposort(data): result.extend((sorted if sort else list)(d)) return result rebulk-0.9.0/rebulk/rebulk.py0000664000175000017500000002377213113544037016736 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- """ Entry point functions and classes for Rebulk """ from logging import getLogger from .match import Matches from .pattern import RePattern, StringPattern, FunctionalPattern from .chain import Chain from .processors import ConflictSolver, PrivateRemover from .loose import set_defaults from .utils import extend_safe from .rules import Rules log = getLogger(__name__).log class Rebulk(object): r""" Regular expression, string and function based patterns are declared in a ``Rebulk`` object. It use a fluent API to chain ``string``, ``regex``, and ``functional`` methods to define various patterns types. .. code-block:: python >>> from rebulk import Rebulk >>> bulk = Rebulk().string('brown').regex(r'qu\w+').functional(lambda s: (20, 25)) When ``Rebulk`` object is fully configured, you can call ``matches`` method with an input string to retrieve all ``Match`` objects found by registered pattern. .. code-block:: python >>> bulk.matches("The quick brown fox jumps over the lazy dog") [, , ] If multiple ``Match`` objects are found at the same position, only the longer one is kept. .. code-block:: python >>> bulk = Rebulk().string('lakers').string('la') >>> bulk.matches("the lakers are from la") [, ] """ # pylint:disable=protected-access def __init__(self, disabled=lambda context: False, default_rules=True): """ Creates a new Rebulk object. :param disabled: if True, this pattern is disabled. Can also be a function(context). :type disabled: bool|function :param default_rules: use default rules :type default_rules: :return: :rtype: """ if not callable(disabled): self.disabled = lambda context: disabled else: self.disabled = disabled self._patterns = [] self._rules = Rules() if default_rules: self.rules(ConflictSolver, PrivateRemover) self._defaults = {} self._regex_defaults = {} self._string_defaults = {} self._functional_defaults = {} self._chain_defaults = {} self._rebulks = [] def pattern(self, *pattern): """ Add patterns objects :param pattern: :type pattern: rebulk.pattern.Pattern :return: self :rtype: Rebulk """ self._patterns.extend(pattern) return self def defaults(self, **kwargs): """ Define default keyword arguments for all patterns :param kwargs: :type kwargs: :return: :rtype: """ self._defaults = kwargs return self def regex_defaults(self, **kwargs): """ Define default keyword arguments for functional patterns. :param kwargs: :type kwargs: :return: :rtype: """ self._regex_defaults = kwargs return self def regex(self, *pattern, **kwargs): """ Add re pattern :param pattern: :type pattern: :return: self :rtype: Rebulk """ self.pattern(self.build_re(*pattern, **kwargs)) return self def build_re(self, *pattern, **kwargs): """ Builds a new regular expression pattern :param pattern: :type pattern: :param kwargs: :type kwargs: :return: :rtype: """ set_defaults(self._regex_defaults, kwargs) set_defaults(self._defaults, kwargs) return RePattern(*pattern, **kwargs) def string_defaults(self, **kwargs): """ Define default keyword arguments for string patterns. :param kwargs: :type kwargs: :return: :rtype: """ self._string_defaults = kwargs return self def string(self, *pattern, **kwargs): """ Add string pattern :param pattern: :type pattern: :return: self :rtype: Rebulk """ self.pattern(self.build_string(*pattern, **kwargs)) return self def build_string(self, *pattern, **kwargs): """ Builds a new string pattern :param pattern: :type pattern: :param kwargs: :type kwargs: :return: :rtype: """ set_defaults(self._string_defaults, kwargs) set_defaults(self._defaults, kwargs) return StringPattern(*pattern, **kwargs) def functional_defaults(self, **kwargs): """ Define default keyword arguments for functional patterns. :param kwargs: :type kwargs: :return: :rtype: """ self._functional_defaults = kwargs return self def functional(self, *pattern, **kwargs): """ Add functional pattern :param pattern: :type pattern: :return: self :rtype: Rebulk """ self.pattern(self.build_functional(*pattern, **kwargs)) return self def build_functional(self, *pattern, **kwargs): """ Builds a new functional pattern :param pattern: :type pattern: :param kwargs: :type kwargs: :return: :rtype: """ set_defaults(self._functional_defaults, kwargs) set_defaults(self._defaults, kwargs) return FunctionalPattern(*pattern, **kwargs) def chain_defaults(self, **kwargs): """ Define default keyword arguments for patterns chain. :param kwargs: :type kwargs: :return: :rtype: """ self._chain_defaults = kwargs return self def chain(self, **kwargs): """ Add patterns chain, using configuration of this rebulk :param pattern: :type pattern: :param kwargs: :type kwargs: :return: :rtype: """ chain = self.build_chain(**kwargs) self._patterns.append(chain) return chain def build_chain(self, **kwargs): """ Builds a new patterns chain :param pattern: :type pattern: :param kwargs: :type kwargs: :return: :rtype: """ set_defaults(self._chain_defaults, kwargs) set_defaults(self._defaults, kwargs) return Chain(self, **kwargs) def rules(self, *rules): """ Add rules as a module, class or instance. :param rules: :type rules: list[Rule] :return: """ self._rules.load(*rules) return self def rebulk(self, *rebulks): """ Add a children rebulk object :param rebulks: :type rebulks: Rebulk :return: """ self._rebulks.extend(rebulks) return self def matches(self, string, context=None): """ Search for all matches with current configuration against input_string :param string: string to search into :type string: str :param context: context to use :type context: dict :return: A custom list of matches :rtype: Matches """ matches = Matches(input_string=string) if context is None: context = {} self._matches_patterns(matches, context) self._execute_rules(matches, context) return matches def effective_rules(self, context=None): """ Get effective rules for this rebulk object and its children. :param context: :type context: :return: :rtype: """ rules = Rules() rules.extend(self._rules) for rebulk in self._rebulks: if not rebulk.disabled(context): extend_safe(rules, rebulk._rules) return rules def _execute_rules(self, matches, context): """ Execute rules for this rebulk and children. :param matches: :type matches: :param context: :type context: :return: :rtype: """ if not self.disabled(context): rules = self.effective_rules(context) rules.execute_all_rules(matches, context) def effective_patterns(self, context=None): """ Get effective patterns for this rebulk object and its children. :param context: :type context: :return: :rtype: """ patterns = list(self._patterns) for rebulk in self._rebulks: if not rebulk.disabled(context): extend_safe(patterns, rebulk._patterns) return patterns def _matches_patterns(self, matches, context): """ Search for all matches with current paterns agains input_string :param matches: matches list :type matches: Matches :param context: context to use :type context: dict :return: :rtype: """ if not self.disabled(context): patterns = self.effective_patterns(context) for pattern in patterns: if not pattern.disabled(context): pattern_matches = pattern.matches(matches.input_string, context) if pattern_matches: log(pattern.log_level, "Pattern has %s match(es). (%s)", len(pattern_matches), pattern) else: pass # log(pattern.log_level, "Pattern doesn't match. (%s)" % (pattern,)) for match in pattern_matches: if match.marker: log(pattern.log_level, "Marker found. (%s)", match) matches.markers.append(match) else: log(pattern.log_level, "Match found. (%s)", match) matches.append(match) else: log(pattern.log_level, "Pattern is disabled. (%s)", pattern) rebulk-0.9.0/setup.py0000664000175000017500000000504513113544037015317 0ustar toilaltoilal00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- import io import re import sys from setuptools import setup, find_packages with io.open('README.rst', 'r', encoding='utf-8') as f: readme = f.read() install_requires = ['six'] if sys.version_info < (2, 7): install_requires.extend(['ordereddict']) native_requires = ['regex'] setup_requires = ['pytest-runner'] dev_require = ['pytest>=2.7.3', 'pytest-capturelog', 'zest.releaser[recommended]', 'pylint', 'tox'] tests_require = ['pytest'] with io.open('rebulk/__version__.py', 'r') as f: version = re.search(r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]$', f.read(), re.MULTILINE).group(1) args = dict(name='rebulk', version=version, description='Rebulk - Define simple search patterns in bulk to perform advanced matching on any string.', long_description=readme, # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers classifiers=['Development Status :: 5 - Production/Stable', 'License :: OSI Approved :: MIT License', 'Operating System :: OS Independent', 'Intended Audience :: Developers', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Topic :: Software Development :: Libraries :: Python Modules' ], keywords='re regexp regular expression search pattern string match', author='Rémi Alvergnat', author_email='toilal.dev@gmail.com', url='https://github.com/Toilal/rebulk/', download_url='https://pypi.python.org/packages/source/r/rebulk/rebulk-%s.tar.gz' % version, license='MIT', packages=find_packages(), include_package_data=True, setup_requires=setup_requires, install_requires=install_requires, tests_require=tests_require, test_suite='rebulk.test', zip_safe=True, extras_require={ 'test': tests_require, 'dev': dev_require, 'native': native_requires } ) setup(**args)