From 71dd5bc11b06c8c4d2f737924cad10ac911caeae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Tue, 6 Mar 2018 16:06:36 +0100 Subject: [PATCH] Path rewriting when packing. Doesn't work with sequences, nor with split dirname/basename fields. --- blender_asset_tracer/blendfile/__init__.py | 6 +- blender_asset_tracer/blendfile/dna.py | 17 +- blender_asset_tracer/bpathlib.py | 25 ++- blender_asset_tracer/cli/pack.py | 16 +- blender_asset_tracer/pack/__init__.py | 211 +++++++++++++++--- blender_asset_tracer/tracer/result.py | 13 +- .../blendfiles/subdir/doubly_linked_up.blend | Bin 0 -> 341336 bytes tests/test_bpathlib.py | 27 +++ tests/test_tracer.py | 8 + 9 files changed, 285 insertions(+), 38 deletions(-) create mode 100644 tests/blendfiles/subdir/doubly_linked_up.blend diff --git a/blender_asset_tracer/blendfile/__init__.py b/blender_asset_tracer/blendfile/__init__.py index f8d3671..1b5a8b3 100644 --- a/blender_asset_tracer/blendfile/__init__.py +++ b/blender_asset_tracer/blendfile/__init__.py @@ -63,6 +63,7 @@ class BlendFile: self._is_modified = False fileobj = path.open(mode, buffering=FILE_BUFFER_SIZE) + fileobj.seek(0, os.SEEK_SET) magic = fileobj.read(len(BLENDFILE_MAGIC)) if magic == BLENDFILE_MAGIC: @@ -170,6 +171,9 @@ class BlendFile: if not self.fileobj: return + if self._is_modified: + log.debug('closing blend file %s after it was modified', self.raw_filepath) + if self._is_modified and self.is_compressed: log.debug("recompressing modified blend file %s", self.raw_filepath) self.fileobj.seek(os.SEEK_SET, 0) @@ -290,7 +294,7 @@ class BlendFile: abspath = relpath.absolute(root) my_log = self.log.getChild('abspath') - my_log.info('Resolved %s relative to %s to %s', relpath, self.filepath, abspath) + my_log.debug('Resolved %s relative to %s to %s', relpath, self.filepath, abspath) return abspath diff --git a/blender_asset_tracer/blendfile/dna.py b/blender_asset_tracer/blendfile/dna.py index 4dfa869..154e489 100644 --- a/blender_asset_tracer/blendfile/dna.py +++ b/blender_asset_tracer/blendfile/dna.py @@ -1,12 +1,14 @@ +import logging +import os import typing -import os - -from . import dna_io, header, exceptions +from . import header, exceptions # Either a simple path b'propname', or a tuple (b'parentprop', b'actualprop', arrayindex) FieldPath = typing.Union[bytes, typing.Iterable[typing.Union[bytes, int]]] +log = logging.getLogger(__name__) + class Name: """dna.Name is a C-type name stored in the DNA as bytes.""" @@ -83,6 +85,8 @@ class Field: class Struct: """dna.Struct is a C-type structure stored in the DNA.""" + log = log.getChild('Struct') + def __init__(self, dna_type_id: bytes, size: int = None): """ :param dna_type_id: name of the struct in C, like b'AlembicObjectPath'. @@ -268,7 +272,7 @@ class Struct: struct on disk (e.g. the start of the BlendFileBlock containing the data). """ - assert (type(path) == bytes) + assert isinstance(path, bytes), 'path should be bytes, but is %s' % type(path) field, offset = self.field_from_path(file_header.pointer_size, path) @@ -283,6 +287,11 @@ class Struct: fileobj.seek(offset, os.SEEK_CUR) + if self.log.isEnabledFor(logging.DEBUG): + filepos = fileobj.tell() + thing = 'string' if isinstance(value, str) else 'bytes' + self.log.debug('writing %s %r at file offset %d / %x', thing, value, filepos, filepos) + if isinstance(value, str): return endian.write_string(fileobj, value, dna_name.array_size) else: diff --git a/blender_asset_tracer/bpathlib.py b/blender_asset_tracer/bpathlib.py index 0e836e3..30be080 100644 --- a/blender_asset_tracer/bpathlib.py +++ b/blender_asset_tracer/bpathlib.py @@ -21,6 +21,29 @@ class BlendPath(bytes): return bytes.__new__(cls, path.encode('utf-8')) return bytes.__new__(cls, path) + @classmethod + def mkrelative(cls, asset_path: pathlib.Path, bfile_path: pathlib.Path) -> 'BlendPath': + """Construct a BlendPath to the asset relative to the blend file.""" + from collections import deque + + bdir_parts = deque(bfile_path.absolute().parent.parts) + asset_parts = deque(asset_path.absolute().parts) + + # Remove matching initial parts. What is left in bdir_parts represents + # the number of '..' we need. What is left in asset_parts represents + # what we need after the '../../../'. + while bdir_parts: + if bdir_parts[0] != asset_parts[0]: + break + bdir_parts.popleft() + asset_parts.popleft() + + rel_asset = pathlib.Path(*asset_parts) + # TODO(Sybren): should we use sys.getfilesystemencoding() instead? + rel_bytes = str(rel_asset).encode('utf-8') + as_bytes = b'//' + len(bdir_parts) * b'../' + rel_bytes + return cls(as_bytes) + def __str__(self) -> str: """Decodes the path as UTF-8, replacing undecodable bytes. @@ -76,7 +99,7 @@ class BlendPath(bytes): return False - def absolute(self, root: bytes=None) -> 'BlendPath': + def absolute(self, root: bytes = None) -> 'BlendPath': """Determine absolute path. :param root: root directory to compute paths relative to. diff --git a/blender_asset_tracer/cli/pack.py b/blender_asset_tracer/cli/pack.py index 38c9fda..86f2438 100644 --- a/blender_asset_tracer/cli/pack.py +++ b/blender_asset_tracer/cli/pack.py @@ -32,8 +32,8 @@ def add_parser(subparsers): def cli_pack(args): bpath, ppath, tpath = paths_from_cli(args) packer = pack.Packer(bpath, ppath, tpath, args.noop) - packer.investigate() - packer.pack() + packer.strategise() + packer.execute() def paths_from_cli(args) -> (pathlib.Path, pathlib.Path, pathlib.Path): @@ -45,6 +45,9 @@ def paths_from_cli(args) -> (pathlib.Path, pathlib.Path, pathlib.Path): if not bpath.exists(): log.critical('File %s does not exist', bpath) sys.exit(3) + if bpath.is_dir(): + log.critical('%s is a directory, should be a blend file') + sys.exit(3) tpath = args.target if tpath.exists() and not tpath.is_dir(): @@ -60,10 +63,19 @@ def paths_from_cli(args) -> (pathlib.Path, pathlib.Path, pathlib.Path): if not ppath.exists(): log.critical('Project directory %s does not exist', ppath) sys.exit(5) + if not ppath.is_dir(): + log.warning('Project path %s is not a directory; using the parent %s', ppath, ppath.parent) + ppath = ppath.parent + try: bpath.absolute().relative_to(ppath) except ValueError: log.critical('Project directory %s does not contain blend file %s', args.project, bpath.absolute()) sys.exit(5) + + log.info('Blend file to pack: %s', bpath) + log.info('Project path: %s', ppath) + log.info('Pack will be created in: %s', tpath) + return bpath, ppath, tpath diff --git a/blender_asset_tracer/pack/__init__.py b/blender_asset_tracer/pack/__init__.py index 67a941a..0d8b824 100644 --- a/blender_asset_tracer/pack/__init__.py +++ b/blender_asset_tracer/pack/__init__.py @@ -1,14 +1,30 @@ +import collections +import enum import functools import logging import pathlib import shutil +import typing -from blender_asset_tracer import tracer +from blender_asset_tracer import tracer, bpathlib, blendfile from blender_asset_tracer.cli import common +from blender_asset_tracer.tracer import result log = logging.getLogger(__name__) +class PathAction(enum.Enum): + KEEP_PATH = 1 + FIND_NEW_LOCATION = 2 + + +class AssetAction: + def __init__(self): + self.path_action = PathAction.KEEP_PATH + self.usages = [] # which data blocks are referring to this asset + self.new_path = None + + class Packer: def __init__(self, blendfile: pathlib.Path, @@ -26,41 +42,180 @@ class Packer: if noop: log.warning('Running in no-op mode, only showing what will be done.') - def investigate(self): - pass + # Filled by strategise() + self._actions = collections.defaultdict(AssetAction) + self._rewrites = collections.defaultdict(list) + self._packed_paths = {} # from path in project to path in BAT Pack dir. - def pack(self): + def strategise(self): + """Determine what to do with the assets. + + Places an asset into one of these categories: + - Can be copied as-is, nothing smart required. + - Blend files referring to this asset need to be rewritten. + """ + + # The blendfile that we pack is generally not its own dependency, so + # we have to explicitly add it to the _packed_paths. + bfile_path = self.blendfile.absolute() + self._packed_paths[bfile_path] = self.target / bfile_path.relative_to(self.project) + act = self._actions[bfile_path] + act.path_action = PathAction.KEEP_PATH + + new_location_paths = set() for usage in tracer.deps(self.blendfile): - if usage.asset_path.is_absolute(): - raise NotImplementedError('Sorry, cannot handle absolute paths yet: %s' % usage) + # Needing rewriting is not a per-asset thing, but a per-asset-per- + # blendfile thing, since different blendfiles can refer to it in + # different ways (for example with relative and absolute paths). + asset_path = usage.abspath + bfile_path = usage.block.bfile.filepath.absolute() - for assetpath in usage.files(): - self._copy_to_target(assetpath) + path_in_project = self._path_in_project(asset_path) + use_as_is = usage.asset_path.is_blendfile_relative() and path_in_project + needs_rewriting = not use_as_is - log.info('Copied %d files to %s', len(self._already_copied), self.target) + act = self._actions[asset_path] + assert isinstance(act, AssetAction) - def _copy_to_target(self, assetpath: pathlib.Path): + act.usages.append(usage) + if needs_rewriting: + log.info('%s needs rewritten path to %s', bfile_path, usage.asset_path) + act.path_action = PathAction.FIND_NEW_LOCATION + new_location_paths.add(asset_path) + else: + log.info('%s can keep using %s', bfile_path, usage.asset_path) + self._packed_paths[asset_path] = self.target / asset_path.relative_to(self.project) + + self._find_new_paths(new_location_paths) + self._group_rewrites() + + + def _find_new_paths(self, asset_paths: typing.Set[pathlib.Path]): + """Find new locations in the BAT Pack for the given assets.""" + + for path in asset_paths: + act = self._actions[path] + assert isinstance(act, AssetAction) + # Like a join, but ignoring the fact that 'path' is absolute. + act.new_path = pathlib.Path(self.target, '_outside_project', *path.parts[1:]) + self._packed_paths[path] = act.new_path + + def _group_rewrites(self): + """For each blend file, collect which fields need rewriting. + + This ensures that the execute() step has to visit each blend file + only once. + """ + + for action in self._actions.values(): + if action.path_action != PathAction.FIND_NEW_LOCATION: + # This asset doesn't require a new location, so no rewriting necessary. + continue + + for usage in action.usages: + bfile_path = usage.block.bfile.filepath.absolute().resolve() + self._rewrites[bfile_path].append(usage) + + def _path_in_project(self, path: pathlib.Path) -> bool: try: - assetpath = assetpath.resolve() - except FileNotFoundError: - log.error('Dependency %s does not exist', assetpath) + # MUST use resolve(), otherwise /path/to/proj/../../asset.png + # will return True (relative_to will return ../../asset.png). + path.resolve().relative_to(self.project) + except ValueError: + return False + return True - if assetpath in self._already_copied: - log.debug('Already copied %s', assetpath) - return - self._already_copied.add(assetpath) + def execute(self): + """Execute the strategy.""" + assert self._actions, 'Run strategise() first' - relpath = self._shorten(assetpath) - if relpath.is_absolute(): - raise NotImplementedError( - 'Sorry, cannot handle paths outside project directory yet: %s is not in %s' - % (relpath, self.project)) + self._copy_files_to_target() + if not self.noop: + self._rewrite_paths() + + def _copy_files_to_target(self): + """Copy all assets to the target directoy. + + This creates the BAT Pack but does not yet do any path rewriting. + """ + log.info('Executing %d copy actions', len(self._actions)) + for asset_path, action in self._actions.items(): + self._copy_asset_and_deps(asset_path, action) - full_target = self.target / relpath - full_target.parent.mkdir(parents=True, exist_ok=True) if self.noop: - print('%s → %s' % (assetpath, full_target)) + msg = 'Would copy' else: - print(relpath) - # TODO(Sybren): when we target Py 3.6+, remove the str() calls. - shutil.copyfile(str(assetpath), str(full_target)) + msg = 'Copied' + log.info('%s %d files to %s', msg, len(self._already_copied), self.target) + + def _rewrite_paths(self): + """Rewrite paths to the new location of the assets.""" + + for bfile_path, rewrites in self._rewrites.items(): + assert isinstance(bfile_path, pathlib.Path) + bfile_pp = self._packed_paths[bfile_path] + + log.info('Rewriting %s', bfile_pp) + + with blendfile.BlendFile(bfile_pp, 'rb+') as bfile: + for usage in rewrites: + assert isinstance(usage, result.BlockUsage) + asset_pp = self._packed_paths[usage.abspath] + assert isinstance(asset_pp, pathlib.Path) + + log.debug(' - %s is packed at %s', usage.asset_path, asset_pp) + relpath = bpathlib.BlendPath.mkrelative(asset_pp, bfile_pp) + if relpath == usage.asset_path: + log.info(' - %s remained at %s', usage.asset_path, relpath) + continue + + log.info(' - %s moved to %s', usage.asset_path, relpath) + + # Find the same block in the newly copied file. + block = bfile.dereference_pointer(usage.block.addr_old) + log.info(' - updating field %s of block %s', + usage.path_full_field.name.name_only, block) + written = block.set(usage.path_full_field.name.name_only, relpath) + log.info(' - written %d bytes', written) + bfile.fileobj.flush() + + def _copy_asset_and_deps(self, asset_path: pathlib.Path, action: AssetAction): + log.info('Copying %s and dependencies', asset_path) + + # Copy the asset itself. + packed_path = self._packed_paths[asset_path] + self._copy_to_target(asset_path, packed_path) + + # Copy its dependencies. + for usage in action.usages: + for file_path in usage.files(): + # TODO(Sybren): handle sequences properly! + packed_path = self._packed_paths[file_path] + self._copy_to_target(file_path, packed_path) + + def _copy_to_target(self, asset_path: pathlib.Path, target: pathlib.Path): + if self._is_already_copied(asset_path): + return + + print('%s → %s' % (asset_path, target)) + if self.noop: + return + + target.parent.mkdir(parents=True, exist_ok=True) + # TODO(Sybren): when we target Py 3.6+, remove the str() calls. + shutil.copyfile(str(asset_path), str(target)) + + def _is_already_copied(self, asset_path: pathlib.Path) -> bool: + try: + asset_path = asset_path.resolve() + except FileNotFoundError: + log.error('Dependency %s does not exist', asset_path) + return True + + if asset_path in self._already_copied: + log.debug('Already copied %s', asset_path) + return True + + # Assume the copy will happen soon. + self._already_copied.add(asset_path) + return False diff --git a/blender_asset_tracer/tracer/result.py b/blender_asset_tracer/tracer/result.py index 9c2c2d6..e26da08 100644 --- a/blender_asset_tracer/tracer/result.py +++ b/blender_asset_tracer/tracer/result.py @@ -67,6 +67,7 @@ class BlockUsage: self.path_full_field = path_full_field self.path_dir_field = path_dir_field self.path_base_field = path_base_field + self._abspath = None # cached by __fspath__() @staticmethod def guess_block_name(block: blendfile.BlendFileBlock) -> bytes: @@ -97,8 +98,7 @@ class BlockUsage: It is assumed that paths are valid UTF-8. """ - bpath = self.block.bfile.abspath(self.asset_path) - path = bpath.to_path() + path = self.__fspath__() if not self.is_sequence: if not path.exists(): log.warning('Path %s does not exist for %s', path, self) @@ -110,3 +110,12 @@ class BlockUsage: yield from file_sequence.expand_sequence(path) except file_sequence.DoesNotExist: log.warning('Path %s does not exist for %s', path, self) + + def __fspath__(self) -> pathlib.Path: + """Determine the absolute path of the asset on the filesystem.""" + if self._abspath is None: + bpath = self.block.bfile.abspath(self.asset_path) + self._abspath = bpath.to_path().resolve() + return self._abspath + + abspath = property(__fspath__) diff --git a/tests/blendfiles/subdir/doubly_linked_up.blend b/tests/blendfiles/subdir/doubly_linked_up.blend new file mode 100644 index 0000000000000000000000000000000000000000..fe45cb4e4c03833c5479ea8ef02cfb0975d5d948 GIT binary patch literal 341336 zcmeFa3t(JVb?<%TM>2$vq#-E@q>Vzjsc{KToDc%UmMq(eQXD6>od-~mM$*U{ENR5d z$d8oPBBXSHmQr3#LMdsXV4yq;CFPNrB(y37E|jl?KJM30xV`@PxTOzTT5cQPwf6q6 z|2eZYBhP3g+p+f~qjP@eoW0LJYwzc48$=I$3PqdaSX&U5XV3q191$* zF%ZW<90PF-#4!-ZKpX>c48$=I$3PqdaSX&U5XV3q191$*F%ZW<90PF-#4!-ZKpX>c z48$=I$3PqdaSX&U5XV3q1IOJMkS<9M>mPZ<>B$j?K{-r&TA%wPkAF|}2xxx~W}YYd z@y6qu8-YPtWY2j1&yCNCyd<9gCvxw$c5H*PnLXqA-&)L0l&#|Vf1>o{!jEH6irO=t z{|k@f6R~7G|DTAxwzzE`lluZ#@4Sckkn}SpNyuli@Ka2Wiif_5AvW07z>LJ?WOy96=f9on+V9%u z;Zv3`zB^}m1niw|!2*|Ro0;iG?S58${v z|1}))Lc2@)_krvf&~sh;edgxw8C`#D!*)XLeNc|Zp2z(B&qh|qK=xdZ{hp1^qRbzc z=YRIdVxMQDu_W_@QmZ|WtMh+Jjy6`Bjlgk#{%0E-=a(b`gHo$KW)E-Ls?(is%25hW80k`JlAYp7H#DLUh@pH8P(6ix$c!Y(<08a(l+}{|VcT3u<^g z{}&Xt6ROal9F0BW`F}!n?GXc48$=I$3PqdaSX&U5XV3q191$*F%ZW< z90PF-#4!-ZKpX>c48$=I$3PqdaSX&U5XV3q191$*F%ZW<90PF-#4!-ZKpX>c48$=I z$3PqdaSX&U5XV3q191$*F%ZW<90SL63|zP6#=hPaN%FC+FM0ca?oX0a@Q-eGcXwa0 zJUOH5l*B)B)f->>Sy`W(xqGiple3a#Gu=`UkLk%>lchbAhRK?-(nMiRW#3S_Fu7(= zsl2N)l^-sw8Ol$r85%E4jugt5<|~y#_0notmY3I53zcfcuNp0m7bfe?`Mjmmm3Q5``ek~2hqn1?x2#%*XS!AUbF+`W!o{us zFa6ZG_O1HmhhA{~jN5-OwLNayuw%nz5)3=ee`(ea5B|`3-8^sQE5qeNp`+foCYd?) z))m?xUCGMiAC|9lb7x@()=#+?4Y}jB{f1NPkKEAvd^<6%4V2w=$)^3a54-gT{?~{6 z^jE<){mvbJ`3puH?(gbvu57Nmq)u->tnI4(ZXXY`p?6IzEl5SaIb)1r{O@3W? zM)q~JjJ=%v*DI{g^OB#Czb|#${=CdRExE|~P-c@E{Uh6+mz?J2WC`}wY>Lga)cdY< zA<_;@l`%k*!c5U}{ z*)@9OOEzxVygeD%wt4HO&D(50>GUUDKA7^!Hn%1wB_~^#$K#C=NF%T;S*EXC^l?}o zN!K!a36pNKfVp0j$qo4X__LT=Req12{=pW`^E%C67iKp4P2Kh20nEGU*z^5;1y*%Z z&!pE&d(9eNYd8IY256>d^nD+an9lU1cSP#1qs_v2R+IZzm;KBu>+bi|&iglaU!Yk% z?JrO76J*Oa&jVH_dN1gnyYJTfKkNVc%U~B$dS%+Hd5xCSv2AxAtR8GPXY$a$UhoCo z-X3ya<`SFFPPdli=3NJmO@-0?^mw&{8no!#u~FG}U0)}ac3M8%x86UUk%e|&QtxwR z<7?a7y)5HSr?t0v|IEI*-a~TR$~~-Iww<-B|E=}gYrBfWrOAP*a%rl9!b>=@c3C^D zUAedTc3FG1UBml^$9r>`iiO)ABQtRoK1yFUoehZSC!kyZ1&8VVWC#l6#NK z>Q&$9eN^?gDA;Azq0j zK00qa6L7LXwuba)t^+gcb*UbsK8}14Gd-t0dhs=WyC1vjwf4EcE+3R@>OXGi|Mu;2 z-$2Jfn%it#mMmY!z386w4*cAQzD?1}L*G%jSe}o3ai8V`Jvx8xCtl;`=j;E=WxJ#K z=yC^XM^%4K{$T#MwY@8~J(}z2RO6;a9=z`p>vY*)pZRCSz6SW070-J>pFhO&z_(8c z{9(19jMMZy$(}RWNNB&DCkrfYUy@Fkd#+kN{@SPG#eCgtyyX6?e!R@i9@%$cyJn;< zR?kw6m)SU8GGVuV4yWlRHeM`lt&Eo`DQ?$wd3)LW<(u_>nSH!|yc`}G(e8KKrd~+f zF(ZSvetqwTbnVNe4y^`P5SNWA5+bbtLU2 z>$h;4Zejgsacij`rMP`&Bz&D@HS6o7(b0*i!cJS#*>u%b{}~mVT5aYS=LuP8>*s6N z?&3(HWEFHcJ+#HQD|d~bT6Je*#@c1uS-TFrxPE&*j^UDgvv_g5{-P8(FB z=Wq65?Xq@QyAE9I+hy(5c1;up%K1t8tl|TD1w|7;)2f?JDdmPF4pd7WT=`%uXB3W&dtR2>_ezeQltFLj21Fss*4_8a&Yz2!n{~HfJ z&%N%p>a1PX4r|xgJN-RYYp=#@XrLnBRH+tr?z7U1H`V&H4{MjTgYD||{b=oV?OLiq zFAb7ggLMzK3+=FW&Guk?A#U2Pa$&RsbJy*54ur3TtzFg*Yu74k7uu`kUNu~rn3_}L z;wvb@mRtK~-XmFlHa zm0iUp7-Y@bW$mzb*`Zi_mG?}Q3nLx2=|G$LRCar9yT6}rt?PWM`KW1k8Ckj#fM z(!FeR-#6Tn-&ZIni*a2!eE3YQ);$jIpX158Ym9BD)2z4rJ@X{_-m0JMt-ZjHZ=3Qw z!1DD{u+edCDNYu)7Z!dJsNbI~PpexKfm7ufK5}n3*WJI>cHJv0?Xx5LQ3Wj+62^ zkg3hvy?`XyvOP&2lkKhVicQ84>fmI{b~mc3`^Gy<@oh}8;+AH#{k^>?+p|m(NuAfH zKknJSx@vkaxYph^v*osZ8WUTSPEmil;0ZjJd-i&FZrW7G%$OXH@k^WZ`}X|Alzgdr z!FO=n8(A{$((%~6LBn{X^w2?BY40)Xw~#d6_MWwF)97(y-^S^oPTz4~;rG?3{u5=H z#!|n-mA+$aqq)m{4{YxGq=w7b346_&Gln=Q9;Hf^?D zv*lLKrp>l%w%p3uwAJlw`_`s5+T^5`@AQgX@UZ1N)jUG`Nj^K^J{KUlj(o=Nk#(Nk z%FLgc9{mnzlBhp^p-;deJf=LdK`_8B~wLPvsNFby?#%=itM_!Ds6e=TmiqI z(Q=9U4Sjs-mmLkF*YVjS^SbTZd~a;i8~bh=&v*6_$t0P_>$xW1Z_f6rwdH6|Z+oHt zUVgKE=GObqVA*2+XF zPdxdN`ww1n=VyQQD?8lx$kPgRo9rWGU6);!otGT>mu~O*+UD)|f8dfkU!+@Ja{Z?D z(|p$^>U2Z@1$D?)C*Qa%~x2&`BMQQ(q(&kS|J9W=` zELCa0wpsZ;IW9exKScXCzy6-j?O6X{?=3(2%_eQvQmsF%pQQx7uCE2{Jkn|Odh78F zx6I8x$9+~S_boq_do`D2x5>mmyLidx_4R^&V$IHb-J$il&g**7Z(=^sWww6%Rw*Z7 zzZvphSl9oBTkAfTre(5^?b|y4)cc)Mp|vAhx6b!}-~Z;tfj|B&_c__~&cDvJ=g@h6 zT00lhL4Pf-4L80f^S7?BgEYfV_t=&B_VB@1U-80=Zb{c^?79W59goYrw)xO!eY<3~ z;ls+=c2@3NFYxb6Sbb^XTeOQ@Uv&w}8R&LdLU(V{&eduF9 zZW38LZ96Ns7yGmNd@23=Joh^=R?fDwa<^fBR-cvIe`+s?|>P|oVJatHj2RK~@& zvvOlE^v7rQrRD1PXWLo1Z(%%HeQCLe-K%XoKHJX99Y8s&&&usTwZ5EfXXW;yoYiOL zHtxf5r~B3Nw!M|V4dty~D<6&{D{tFd`Bf-y_1b>J@nq#~dn^C% zPxC&pdTqbW%G>rC~x&zx$yk6^0vK|A47So*V-SBZ!2%x zTluR|-s-h-&5qx;xAHlZw|edTu;Z|CVf(l3t^Bus(#PNGwer@Eu)J+=ew4R*t-KvaxPRN;%AbewR#zT|U-L*aALxGdT6mRQef3Iu>ZvoQUWBaV@Zn`i?%_vW{xSQ<&vW@l4d0{5 zt?=JFnO#}`{S&QEABTSQuddu(nCiHnk%n5im1uXv^4)*F$=9+%?!@Zj9|QJFoBg$G zd$(>d^8qP4yMfcpy%_n5$8tI36{pFsKwadX&1$S)o{d-i8rhxHq~9B{yGnn%^67P( z^xx-y`!2U)#OKnO)@`%^SoH?~8*#Z`^V3$VuzsFWO9zF%hU z*i@7;q`#%5kEcpd8$HJ6UGHDNYTV?PuH?HnzF*E+Q9SjWCiOMi$E~uh&j{<+rr+N2 zJ@dCKFJG?bjXi3g_Wfdftf$&9z0wFf@4hDU+Fm>VWVYc0A#S)%7g~SUPW9)l^>_c1 z8l1=X{*mwBWD(B8$9|x7^(8i4r1Mb6#+C96A9@~Y#H^3Q^Dx~0ShMwu^@H_G?#aGi ztiOCae|=*zbMwR2=EM7ild~N^Lk@T?4*EJj)NM0PpFaQk9@((>4td?tCGVu4E$5;9 zR$f>CvS-MXRm?kcxzw+ppKs&=tx3N^X79QEAi3OT=dJTtt+alzez1O-J>B<<^_Oqo z-O>+R9!lG){P&Kt{qkkRKi$sHY25VDWWDbfIl;62@<`X(E{%07kNN8NwVaYX6BYd+ z8EdiDR`$I3+gQI?KUlxi&hY(W{pI$2@Xt2+7TnR-kdM&38&2^X^y=hZt!t)_(}o_~ zddh}GpGSV^xvKfZHh=)?NqCp|jOuE%0bd_JM~1uf4zMQZ%U@~x+Q4)xV*T+6v1v>^j5#)0Ohb{e6S{z^`iQ zum1jzKC~U@$cCc6l z>u4Ti4VaOcuH+i|*%kRPS}sxKLvy8jh3ww0-RsQ_;XPm61GanIcCX#;y@&ViKOnE^ z?cV4^lC7>-@o3k>%X}87Ey_LQ@Ac;1hkqvt)BdyYn(FMvIbiPJ{Jq`-nA&RqD`&3( za*fK*{9vO$VBBMx`Ty&g(P%vLO(e11x_ahUq^#cS#dOYVv(x2X@1tE8xo6}0vP&&q z?~zz(yuydpq`w`BCM2)ws=wEp`y<@zJr(zQF%9c!m-~O+-{W2N8wP`u{?3s;jBUMN%D)ZnWjxyTo@M%!@%|AX zH+|WSx4&6XXRKdzzES;J%L-kI$E&)|s_VV}PoZBfK)?Kd!|q;u|1|zRo%i~wmAC03 z{QC{H5BPt_!Is-}?9IME`rp!iznmrUwEgRV((u-H*SDkg+57AMy_de5ckH-v>-K@0 zb_~d``swQuYe{Rzj3n#7WP)H`Omr^!sw*!{TIdvGJ7K=i|iq1qIXN94Sr| zCM)g!azUr%H!Wzd^#`%+aUZ8sBv#o+_#GQvXK}K)Se*KA_i@ci#^xjC9}N_TJss-roJeyby6x(m2_5<#fNg?ytqk;$m@{eKq`q zaaC7HAU)2?Sbn6fq2#LSwEXr3?X~_Wo|%c0uCX{hrG7I<7AK2~#VPm8@Ds*WSTsG( zsX}?QRG!FB4j00W=HX7u-?X5;);H+1CUH8WeltfFCyR^4seeEGgmD!X%^YW`Qq^Dk z9WGSbP*kVoZ<4)s-_-72>yP4}|10w%Nmki-O24(7Zf|k2xLBNOGw>6}Ra(N&rN>#R z%2x@))kow`%imC_=120?{1JCF&j#O>I33Jf>nu)ZH7H|ovbb2BW?ut8VO)hp)8i~n zSEr`i%rdinTUhxU7qr*==Se$CV0zY9~Wy|RNM)#ZO{+A#0)k~$#?>l!|zSHkl z>oL6I{~SL2U;{t>l&%aO7AK2~#cB3+@Ds*WP;5?|b{6E{?Ur}zT73^Oj8nViuXFor zd3Ry+9k0!dCtYA3zp%m97AK2~#VJ>VpD?b%qTz9l>u*I2Oy#R%t^Hemr{z0&y<*35S|(2VJIpqoF0u_W zQ;Ul_}z8!{d~H^nN1TWB6ot9sW*Dd8Hae7vGu)-E6i;Kmn|4r}{##LA}91rbgo1KsvQhvL(?HendmfyUfz1APa55?mLC4X9#$)R)$`CRUthm9wT zi^Xa7&F~Y(Rah__4?h2CJ)h~c{9@!!eVOZ>9-sN?r^AC4wm4Z_EKa$%z)u)gVbN>1 zY`9_b){QqV^qqu`%a6;yLnLFW+rK0To7WQWlk-l;lRYd>jox*!I9XgQPW^9%pD?bh zE}Qy)7Zv|3>H=Q4bXtBfUblP`=bass#p$WGATzZ%SzIhmwYR}f7+0AhZg$Rbwt3=p zT7EIkyZf5NDf^y+9k<2F;$m@{eLMVwab?@vbk1?M`NE~s@{94h<(?*SI@b;|GqpHb zTr5tx--4eot};d3?409l^My;NL&h>c0zq!nn$o z(fK*Y+2#wEPRlRG>z03l$HNy~`g!>9VR5p!Se$Bi!%rAjVYxZS+2#wEPRlRG>y~dc zx!&n(;_zW{vbb2BX77QYFs{OKIL?K?ZgKyP_`+ZJEXM1WPc@0t`QgC|TbwK|7N^{A z!%rAjVbM9`q0JXAot9sW*Db%*Bu@38{PIU`ak98rociAdKiRnY>N$1)wpcoz@Ufl& z`|?2;(Z<|q`Np-jxAZ1_uICOG(@%5Nf9J$jS)42`7N^?pz)u)gx#yoz7pEIG?AW~R z`VCw3%o(1pR7(@>{mZ7Emfz_1sqb`(7^}qv{qpBp#K~f@!uI*XIV#o{#k zZukk~s&=TWE>0K^*~67z(%xMx?6I2XpLSaQrgnDLq$%e#iPQ21+gqG0E*7WU@4`01GU&`lCS-(}myZ3X6k5HrEW3V_`Tr5sj z)Z*9wPe+WCN_?tRKJr-7x*LqAw#whq&d%&$g6S6#CtJKieq%r%`aRw7p>dj(h4#5? z{i=fAx|)4|?D!5G@W*Gz zZEXmSPk#EmAme;t$EI~2t>d%fvE#GP&)ad=zWcj-Kf7PP-);Gvbe?3qmGRQT4^Gkr z{Qj~B-=x3bWS^ny|Aapu4_}%j_hy<~`+skC z-y6|5>2mvCmVHla7T?pd?{C>}nb~iH*>8N=_qQ@tC+|lhQjmpbo~gff=p*mGr}e-4 zX7qf?t$Mcq4Jk}#pX$G#RXexw_q4`7=6}O$FMi8Q+dU)IS~>eZP~-9sZ}RQ4-vatn zz}eQ%owwuZ)>VUVk+SkVEt@v{p4Net7bW^^?NL{MP(*84>3YbLak)c^ZF-5Uh-q2H;JuP7c^x!H3|f3<$? zLmkKALu< z!3LrjcYNkI^O^b0eskEoXWu`y-z>D>&b05N+9BEZ_r56K%G2NOTE6_zt||EjtUjFI zzVH23J7bqSFKycYG<*;B{KkH}?c?5W_rY`KH!El7QLbV6^ZY4bzjfBh_fV7P%Q+~1 zEt-XW54G8Eo$2>bPnDjsu^4_2wf}YS+gIT?Otn3oJZA5P-!5vLk2kB^ z`o;Re`o*@l{_^}uiRHTu*IfG8is=_I4ZnwK>;2aD*Z0dk@)AV* zB}q<~-#UA=>&7m9+BVIn*>T+Hx6ZVd?CY9Wb=7|>E%&SFm)AbW-LK1G+I)|#tvT>a z-ygMSwcjr{$#L8H_UE#@7Q(>aa%-)1$In({_my4#^sR}lK972V&+C&)p?mxA^!QY3 zFRNQPApaWo-@oqnr{iC9%N+LiGZJKt^BZNb=<_Tr*X=%5OZgJnNZ0E_b5#3ncl}I) zmN(Y--m`qJP?lx2TT+|2+#R>R2c2F2)A+Y*tiB6_^%n;9UFceq?*Bsft@tea-!Dt+ z(`+oe{*-{#X4&<*fS(lbX#qbu;L`(sO2B6Xd}hFB1^g2MpB?a113o8U?UC&9{bayT z3;4W%&ky+N0Y4+)3j+SBfPXq*?cr?ux&yu_;AaMWalp?C_`d~wNx(l7@T!2H9q{Ua ze>ULf1bk`0&kcA@z?ao=JU`<3aXg6)+KPTX;0`3iX zN5HQLcr4&@z^@MYbphWK@OuOPNWk|6{7Asx4EV8tzZdWi1AaW<-1hqTo*nQ70YB)= z^LmT^>CF6Qa#`Ttr>n$1ATQaV>CF6Qa#`Ttr>n$1A zTk_?>_+A_E6#-uv@bdz`D&Xe_e09Jt2>68ozbN2q0$vyJ`ha@^?hSZDzMjUd_;zi$nX&vJ|e?MWcY{-ACciB zGJHgakI3*589pMzM`ZYj3?GrMjUd_;zi$nX&vJ|e?MWcY{-ACciBGJHgakI3*589pMzN94r&3Hd1f zLWW<+@CzA!A;T|Z_=OC=kl`0H{6dCb$nXmpej&pzWcY;)zmVY;TJOeLWW<+@CzA!A;T|Z_=OC=kl`0H{6dCb$nXmpej&pzWcY;)zmVY< zGW$iFVZh$ z_=OC=kl`0H{6dCb$nXmpej&pzWcY;)zmVYuK?IWXoWVDZr_L0#( zGWOYH)Y@6lzn?s_U%pCw>M?q-jscNQ}(`2+50+W@9UJk zuT%EEPTBi9W$){hy{}XDzE0Wu+F1T+bT=Y%Yd^jBv-_36g}dwd694b9b3Ok3X)^x3 zQt}FaJtdzJ@Oc40GvMb0d{w}`0smaUI|6=1!1(<)whzD8M8@x{knwv6{tX$gx5&tk$nb@6{}*n3 zY2A2v!?`c3W1O$HeJ&h7xtG+J|Ncko$J_c~JYF3z%0EkYAR{>Us4uUqMi~6-dY%dR zYkyO}{<4631D*=X-}FD~%ik2NKPy=O=AgchVf#%Rc5Jv;+FTp<=i3UoIOz4k9;_JgnV!TwlVn-4eEEvx^cANi2UcF>o?76@4~y5YHrP~aQo}F9 zx``D}uiGm3npf`Ec;N~W`Pg||R`o;Re`lbJ;eZN?L`TAbG zF-iX8p|oz{-b)@<{-iv=j1_m`;C~1F6PSJ}SP!&`^h?rv$EiA=PfgBFk`<>&jdw58 zr)@I-RO|n38CN=v!-v*#TCy@(jur1t9;>Uhb_e?9DI>mLKKvZ#r~dcf=(zS_Kh6Et z9zm$T$pZ2uAz{XeN4@a?ee`aga)J*vxY zxqkDlS8N)%X~#gdR2r`gRLl9v%4n%PVFivb?X>)kHuo1cN6(hQ!-o%lT&8z$cDW1Q{3MM!=G`oxY&5geF)ANV*ies!hhIqwE03YD>7;|3VUiRW#L~KhmzG&EjNnu{ha!#?KaD+UPj<6pA~?TC_%|Ac4+3MAZ%{6#_1-R zv+HXYJZ@!e+CkTGKQmIdKO3V=WKz`_p`<|3TY#k|@97A?0ko^Hlh^S-xZI z(|X)o!+htQt}iF&(C0yk05#vK$@85Jw%1yooSc$86J_3=e5_^}^ zOzR4@0R5NxJZIIK_VZB9cWnRRd1AZHeeiyle;KFad^}&N4wR+}<-A;=Z1oYRotD4R zc37-Vltv0i++U*&zAE0;-1!`?{29)LGkTur__gtBa=*@P|DRu3cgNoxy8qtVkgI3IM}E2IkILigF8TBaKd$bp<_*uj=8S{IfBdgrE&q+R-(L6Jk3W9@)o&YmK(>8g%XM$;`P|mmtozObAJjIi z`{xzopIiUv-ku+Q_t4R%rk>>BEmxg=_pdzohA&>e;dvkb=?B06<98qYtG{|}-wXC# z_Jwo5dqLlY%kOn<&~|9s_0efOIz1lWij(i}TkrZC_JJM!e9Lxx=3Nim^;4fe`1;4+ zC*@{(F1i1iJrDlzL-#-J8=t)YwtxDG2Y&SJ(gv&N-DiC7MPHx!!sl=4+SgOOsrG;_ z*SswI(0hc9A2U7w{=fcy-6QY3w&&wtK5tGNt&E03=?ipk_{t+&){CUvL(A#)s`10h+O+Xji?P(VBXRemy5w)}yf;g=r}t@}eC3fx z)+Nd9o0{+EtmL%hR4sPY9?Nh?Q)0R9p1aRqZ@b>URop5EWB2#}OIoDIW{+IveE?gg z)9u@;g^8)`lJ@8Clp@)EHLBsZbNzkre}6jehd;wl@58iz#NRKsX;?>YCVgMauao!t zjWr%e)r93+<8Fh7T)e+gZ6;l(YKM!hh>pW#w!;D`&@V^;x+Km)DoG z?W~+_XZ0ChhykGcTO|uuA)cxOZOCn4+uqt6?%&GW_Ex@z@>Z{v3)^AkZF?(k{cH7F zIXgaUmzB5et-P(bdaeD9%HJy++xQ9JkFk2Je0UsIpPfIty~S30=G0TWmp|qPTrSDF z_Po#d_f>3a`)PHm$K5L%Tlufaycy5XT%Htze z&BCTD{4oreoTQfitKZ4@2^&>f9=>UvJ^%EoXI*2@`fcrcVACY|$|DzS@Y{4JGjr}F zYJMc|IW>OBI($}0~|1IKwe|PeP~koY^TA_u3S}m=-IE^xiR-9 zKhAUS@YDWxo#|em&SI*?T8T?geapD=+?F?OYeVhdZ)yMH_3jzUIpCt-M*~V-Of}$t@lf=z~g6Hx$pe`GkWY<`?$X!n)^dP zwQUwYeaA+5hee*J%X79*GADT+y~l?>_`t>&yy^5!N%FRhIv?)&L#zK};|sPvN!B-h zXnzk%A6r~rXZ?MI_-vmpkLHILau)k`bXwkyW_hwndb}&C{lR|sxfUIH+e^c{3ROQ6 zZM#;d8pB)8{ew&#B_Q)W?7W|6lZLA-?lulB?zXY@hp|m>DUDB0EIjN!)c=t+ zr{&Yyya#jd4EyKW@lw9UH}})Z678SA`^+0Q=Du@u`X}8_Hebc-;%8N_xBfAYg#D9g zdfjZNp6j%{HAeG;!)GpAwERF_bj!IP$oOXI&L5YD6u} zle>%M(&R*8vgHApDbg)9RHw`BB^}FpyOMXgPWUferlCK7&)_t zb06MW_c;MuZqq+}>%c?bS$FKNQyU(A(?f^e{ud7>$psr9_z$0lzv(;Yahz^!r$w0fT1BA;^XJ)}~gb z8u#;L!*oAc4~8|Q*DD*Zt@hKxuGZ=PJ1uWDNj|YmeYjZpgpT>guKB>m{ucYm+R^S* z`$_YObU%&zNw-VnK9Tw2Q=;ej4XxKYd&;)UmZNF72G%unq06lPwEVKVdJWR`X`AMh z)qBNwy6xS)<8+y>i_3jHVjPbDIA|Z)Q{RW#qVJcur?kE4L(geDuXXCb^~ufkZM(XM zdcoyW$e)-`;r?w7c~)H^fx&l$ulsMvPfZmkcZM4tffrUPtyGWCf9J#QYc8+Pr#^># z3e(!>kxyZo*5v2LuBv}OB!~OfHl6&X^B?}7XS`MNmwV-T^zUn4+r8=GFMjp2k^|hg z;T4BID{V;RwNZM1^V-LHAO7Oj2W5TZhxYfN41yfu(du=2VcAOBhEB^{O z##8T2kF|K6u4UfGur{?a)wpXumF_1!PwUIO&*Aa)zm3-?Vn1m8^E)=zDDtJANJzxd&2mtQZwJ~r=%z4%A3dH560 zyH#9wS>Jj0e$-tzvaiEmeCy1^pO}8BtZ)3#{&v?5#KC-2J2-zlt}9IHHx&wPb}t*z zX?d$iuN#Z$BaP+hXWhN=z)|v1x}W)cka-=BezAVaJ&5s({8Fb}_8+BwO83)RKUu$6KUo~C|BP+AtuQ(+Z@m;tleVP2 zX{Y6FZ%flpD>jZDrG85HbL4)~*Ps2kFJZ4g!}}EWIYs;YqP=fzpQp;c{?z)cywx|0 z`fWe<`A&PC$Ja-AT^rVC<*h#JC)*F}!Tm9{ z{f*qM{`>s?d&Ea5v4GX-`##yi={*Ns`qyXvS?>&1FLzU2uaElevMl$qgU|VAw_WJG z?bD{s+L2xF_qCMqo7=b9+5WU8Hs5I4XuU3rj~Ia% zff#{SBH(^qq32@Rbj6Cf+n*+jUM$bi(NTO)IQ3BKzPaUe$%FTOq9^m+RlOEz9qxK_ zk$^pA7S|w|lgDrV;`iNWFH`sV<^J!C+%s+d)cd0|B6_-#OELpT@60+5e_vBJDGarH_sF%Vjcaar=^V zN;=$Z+nMzj{>m=&L2r+I7g5H6K5TuGFh4{-$ovq$=WBVRFPHx9+txQ;8cI4y5B<>5 zvDD_n9nb7-F+WVlhDOl(RHxy*v2ADD%=EQjBp zord}0V~6)Y@Z5pJpV4VKfA}-~F+cR7WBkHvlf~3;X8EDTtyzBf=zFHnC%rwt@!)jx z{1Evd^F#dm4$bZ(YJNCfPUQaKm6>+8HQUks!`e$@eu(q8!8vDRB|CH4`rZA*H09LmLRcVXO&F>w`_8aZ~ zp_WU=&{S$=47YnC6jeE$&nAoD}~dtbTC zzYCUWpxk%dIG*2k?Cu}-|3b_U>(6H!A2x2Zw`|_lh09`oI5$Swn1%Cm#vde9LZv0%xAI>S!X?`gGuCG0s=7;z0 z*@|n0-_$;T*hzk9*W*U{;c{zH-8D)Vs#pCqynh(Jznpt_{QRMhm5*0??YC=_#nNwO z`Ju(FE=C|m;6#sr{;FoOpzo(N{`dOQc)9nN(|^>iX?`dr7XAAvc0F#C zAEqs|9A@q`%n!r&m-}OWn1-?LeZl&i#5S`0(BjrCKWzE^W#og*53fRgh`iDEYg5S& z%Y}TUlLWD&{IHf^`uxz2HJ#S?Ma&P=$b@q-KMW%hIYuBxAVwf_|L~Ob!-5u<`R^av zzj0|>*H1M+blIn0+;)E0$^ApS9*6m%-Xlnla&BJeo9cgqRPKrK`^(?WfAs#fubt}o ztAE-5z-ga;*XL?6Kg@J?HV?_pr<+)QXmM+nA4&<_!`1IEU)=orDaZ$zANC?YMBbS0 z+0XTD+mtWwDoiGqT@|isl{?B0`-fwGnBHU7kY~@maNgLqQ})mJ{&E@%KX9`g&d-gX zFBAX92*e1)2(%J`g?~S#rQf$n|3UD!^FzBP)E`A_-%qjYahM;vi##h-pXy`o^hoy) zXJdZoL&x}q*Cvap-^}tui(9k&u;u%Q$OoAp{v7f{{WrKkSmE6Azak8eAkZ_OxX-ZSVUjR?1H`51El0DRw<>lpm(|S=62S zm^*EhA3g`afA}={{li+!4}ItuzwkO_G4-2SerR#)I6p)_$o%jX$PbY>W*X;aeSWxR zQ=u@WZ!$0BE@DUdVQp;b?;nQ8T%Q}ne?Mhze9|Q+OMaamah!`0h!KbpI8p@MWpByy z!zZP?Z~OkCUf=M$Hul>#Qb%j=FWdFFQGS@d$80&w+-alyF#G%1voSwRdv?w}3dSO!F7*lQ4g=Wj2<4zoljT^7#2fi%%H8>~fnAV`^nAws9IG5F-#H zFkb|GeyIP(axyb_yZQ6O`F*4L;mWkicJo8KXIS^!H_}M?PI2?6y}xYN^Wn7P!DnFc!`C+D0nq8yPO)NjOxOJQ#A|GUa_-5pX$Q#o= z`#H%Ei#x~U^M}dv!d0zuNBLp@t73kb<}w;`9Wyo!=Z&-L{TPe)4}Bcw#xJ|v=I6%G zg*^U=5r`3p5ojp_>F?V#xP6$+_x^JF+h~n<M~zwfF0@*MvADY*yN#^1N`!I8gqJqoAXfWL2Jach!TIQa<0&2QX&-7#(tb?O@pM^seP{Fa`5utgrrWaDtn7TciQPZ6xHZcUTmJn+Hc9Y=7&C1h?kF@ zU6*W{ZesbN#jRO>*z)~D%moY&#oI@%L@g7+Q?d*wn9Uw!Y=@9yg2;h!HsHBe3xNFn#Z-aS+}6%l<}% zZg5odL%SX?Rem@d^TSN1H@ilqn^=BmaqBogL_Wy;@IK^+$Q#o=`?U@yp}=LyJ!szwC0G4`XU&EVgkPBM>7HBQReC+-;F1 z`+e*ur@L-9KkVrDZR~p7C_i*Z?Am3%oI4HgABO+FUhbi_@$-l5Te}{GQ*Mxc{t$6% zmLInK{xb4G=7$d=KSbV`?%B`vZM&&BIXt%JhWyUS;^@AG}?b zbK$(PZI_O#m>;IG@FP3R;r!hA`7-fuj6jS)j6f?9SlawBy?vOpnIHDb_V(m&+i1?X zalR)%e~9bxQssyJF+a=wpbQ8-DEp8p>hsXz+A3lcs5P4&|XFsR;;q>@abyGRNCtTMeyA#FzX|Vt{ zb9qqz{+J)8<3uB)W5uT7ym5BDA6qd$^l_LQzwC0GpBq0H^7to4AVwfYprr^bZGM=! zA=xxPym!x5Tq}Ho7vuMB?0VcNKTO~AR*&jq?(~SCKYVy?{QRL09^z-$r0kR%q@O=T z+&az=kq9dN(9c* zjqv@Hx!ce8{&ITlm|ISlxbH9fx8)R@=7+Mb?mcA74^!7^aeK7({<2+<8|8;qldoSX zdwud8=7-_$WB14WFb!iSpGf=6V(K@u`-c{{X8B>uzi)$lkon;cksl&&%rwr;YJONM zRmT?e&a$t}y^xxlgN1vV!|pZ6>>W#=AI{lxUB4tr%n#>A$d+_1TR!*0H4WmIZ1yFN zZGLSzqPE568%-On_wA2=V+3LZVg!yHf$aUmxm)W$x1gU*9335%dkK%MtM^e-ci%58 zt@&Z*{kS&s!(Q3mp4pmP%Ma~(+$cXx+oVp_$J}X{ABNvwuEqS&hmP^n7>3Vu6Uz@R zZq4$;mcPG@e31F!P{`bCMrU=64mk`%9%=3(OHa$`5OI#{4iHAKE9`b1s}W zw(Zh!74ILWvG5~1%i;Xo`1vyNZ;U{UK#V{u5%BpTzMnFuz^>2 zoB3g9-%qjY@lxf7voSwRdv;D?n+$q!4T z`p+*Pqwg>Gzi#RC!@2i1tsit6?;nO^BFpjqVKy3ZK1Lu$AVxqVu+;A_^QzTueweu* zmF=n4?jPFqxKVzX*5gebe>wNX`1!;7IA(JZn@_i}{LtdoEI(}d{bl5X z%n#2-eu%s=-Ls#Q{BU}xTFwtw!!<2)NB0kNwWZGw=N^gmgCE!N{pGn4vL!J;v`EBh zj6jS)jDSU8iU0kS^v&F(njhNrc&YNk{+J)y0Fr4o56RA_n^=BmaqBogL_Wy;@B-wA z$Q#o=`?GMN7)^u9m z7coCfBNNWW{4k72mxE>ekfbIdn5HFQqs>Ky1SEpQM>mK zEg!7=ZnNZwE#-%HJ#LgAruTsK`l*k()A0S}@cSvVF+cR7WBjtYh|Q;)Sbk`6TWEfG zgM5GVF8R__ZvChCes+J7yg+s__r6)WUz@vO^G)OV$%5g+rZOm6*_T#6`@-vIw0+^@ z&|j>p`(301-#z7Jx?K&^L(jO*t?&Pn);_;5_FIqd*Ydd*x8M8h^=^OKuES4&hqhB= zuFrE6g2y2oPxerBlPn)k^V&8$o{SrH@d^3p|In3gJa^Iu8kknfYg}8|ZoX}FUwVDe z=LHJEW9);SACK-|tDUbMwyx7-(*4-+G&+CuI+wlf>;9CjjWUaeIo+<6ez9DP-FSY> zX{YqqmVSvR^}gP8%6d=tk^BBfoxgScn6P>2Te4EuFZIK`sr$c4c4n*x;o~v$faC@8 z^pC^)wN)+#;WFK>r@?l0%j`JKS9YA~y(+6=ai?}&(EVQ~RU2O;^Lm_VE_AWmv5)=5 zt`B_ME>3jnx4YQ=PTkjp?L5%q&~@%EqpP9upPO&FAwSi4RZC0ldiZqNdOmM%y{{)IpI`qg^OmH*h^lbu)A<+{w~ zwVrNSX7%>TydPibbwJB#jMF$LjI;UE;(VrTH{YYvI9ncazU*YaK4qNeYs@_BEbr0y z=zeU!8)d%H`LEk)zgxKtneBW$mnB=Sm-Ql>+$H|Khi1SUUu19Td;s>+xgXm{A0=GVt#x;UIbL9 z%Y_QEtlK(%ETHwVNQ^*?z|o38$N5z=ccd0MT89$%6C)5K&|w5LhpNl3aPRqu`4#e< z8#eTni^ID*YK7%juh5%(c=UhgoEzPHchgthtkX?fH(dU;d{=Vs*WdS|i*E57Y1_BU zime-N*nGd-C|f-#=}fYEs$AHetRBf%^U3PbV!0xV#`E%bZ?Z4BJ=r@^oRmL#A)VW& zbE~IH#YsttlAYz!^i;AtKd#TUNp;^;A(0zOZaO-i-dKcVmHh6)NaA)P zH>i?oshS_x8EM0w;)v`~?wa|HuX=e>m6Fqyq&Qrf9FUde!f<|kIGM`Jc2nijl-!Ih zN{YIAYTrO{vQo`Y4i^%wLvLugJ-CW4zih4SSC>uYt79+oxOyrtFO>D5^TTq>OxGsW z!o-wRG$J>6cNfZ)VrkMXmgC6co|mnCc`~Md^uTmFJeHr_DYxCK#R<8omYGKRIE8s)Cvi8sFk#bQ=IxOhl zq%v08v#YQ#nUH2`byKB^w(@cb_jtZ48|%Ic`Pv9?SLGk2ErZefSdzza_BNEFE`AbX0C)Cly&Nr*vVUI3W$&H$0xmFN97^kIQf^7WNDj_Q{dUQTRo6 zPRp8PJiku{|LXi?aYBYset4{q=)6R~EQ>`6GNLOllM~R-4phb^d}_gg?1D;323El> zckN56Q~8|**JU!Ahr}Vt-g03o*{6T1do+60J??hAtkN?bCb;}%VkX(^lq-^|NS!7! z_6@F7r>Debes|Lq8TGEkQw5om?w4@u-+k_{bAzI5i_VM`rev(@oF9p@!+d2*Mqp)X zpC6p=M&W=&wOX9qSxH={5BR|&!|!==>Pj@VEtLVBiVmcMTt{6oVv92oav>D!4VT1U zQ!=jH-^s#GcN&klX09#`y;2;Rtk!qbrg!rSA!dK23_|%UQjov5YvCzrTQXFhu8hg~ zGv%A-(GO_X-qL7A&omv2IxS1rmGg4mPxw(Ug5T@n;v%6X#*-=EJU`L)O{#6CTuhQZ zW5waIfzotU44%kEE*VO8B_oB=0kN>gPEK(ZvQDI!PGoFP>2y!N?546&WvVc&izbR? zw~33d-&TH~SytEvg^6NSc`RQZ(P=p^7g}FN{61N6yUR}u={l*`HkVn^ty?LxZcE)_ zM9xy3$|)+YaeKDS)O5Pad(2fgK0V>uJ0dR91-s;pB%5N9T;X?)=`xWL>fTw-?-teR z!tvs$t5ajIESC+}BsoXN-O*I{$Z4-@Dr5PP(jJ|=T@>i{CNr{VQkS{+s&q!q80kK_ zO1QCt>A={uT(i`u=>WZ4)G8^9yU46o9moY>NOBF)rd&4U1k-b@H00olm%H)ds&s?c z`D?ON6)nicVo1bOk;v&8qvyPn+Nk6wVx0k3$e<#>J13W%igeOQQ8E;X$z^C5+)x_w zC)@y7j>aWRvTbFb|1;qHGvLRXZm&85>czdVcR>2CTpW@M^8il|pK}dV%LTa*x+({J zu2U*jq_keZCf%$*4nJR<937w5O9j>qO^;hNq$r_6TNN~B;C?W zmri9!N`hQ=7wyTsBsz(VcfEv8ia-4zEKJJFhAGLrcgs^wT3J7!Yb7Hq4MW5_Nl!<~ z8U2F2I&ovlo%py$$uf@;f6bvhxFgn#NUM_SU0SNS#mF8_Vn_Dubbp83UmZ%4K9qOv zbG;yvE&0<~XIy>aSs81ZiCwOLB=;;8dcnc}3pfRF}cmg>OO z7lyXX8myy8>$hqgP-Foi4T2TEC8Hci~16Tb6EaOHjEb-g>2yPkU6w zJCe}tn~;7iOVTYJrO`zXN%#5GR67z2rC0pb#<_dizYamMWI|u}NR2X0`#}JG=@UeM z4oMUX1JdjAQrgRNwNKz31s}2uLO*XR7>_GgbZ$xtvJYRp2&QS@S7LXXZk*{fyXu-ccks!I1$?a-i8Q>#6mgCd%`eArqvb!{%?9|K0s2uBL zVO(Ao>#GUQ4-`pSzpasZUE|eQ-78~LTOu=d-s{QZeatzzDCaeO(^ru4`dR<3O?Jwe zQ*k@>bGnV5*8}N_4C>nKIqC}5EpS^*7AvJp1@1!Qj!SyDT5^SaZ#$)^EeFP(G}rpS z|Cg~h0kG^S%fG9aFav=wgn&T^i3mEh+bjWsAY`UzCDWN^dNP?1@TPCCm+9`?>D#xL z0U_>DQKPa15RE(TxZ@u8C@xV^<4W9d#~t_o?|I&;bI$FVt;4U%NEeSR`Y62g*bCBec&C;5OH!evl z3!)arV6-eQ6`WTnMt5at zJH}pcg85UmZWIo zUNOVHJ74-bvv`-5&;zkt5-i=an?%!4(2+`*(N)wf;2PDOv4i+yQq4iXjVG1t)8p$qM<(`?%8Fo2@VS;wGgCd1aU z>PFO#;+OQg(@0NgbIt^DaerDokmmQNd43O~Wn$)8W0r_DPk-!gu?gDZVcg1xh!HBP$9;~5iwA52l z=s(vwvs(!^aV2f0MO0#IZAJ;LUXTG6;i_~vz`q7o#W7kDYtL<<3Sd&GwH7gGYIh~1 z3pHaElR?p9WC(u|MX1mh1bfSfBr^!^8Q3KxNUcZPjJwAlbR$*ie*GNC!yv6r9tuYR z%9VcN*UD8>eJ?ardJEFAC`aQi*!Gg_E$Rc;!P((;H5-gVf62PVrNx-QEfiea1l?t{ zCs-5WWw9~up;K#ZY8<6i;YXk}uf;e&z1&&aHk^-bI43R)pp%_^Z4+5<3)tFSlshxN zs4XPFuJoY3G8(M){Tdan2l92lR4SohiTos#42;9e(c>n_HvSfa)`LgVB9b2A5!HW(sr+fp86$V<2v){heUUy={!fmMY=N*?a zY&tFZm-ls3T>Tubxu?Y3MXv56Ln0OsoN0goC>GNUsw+_pyS{GZ3kVW=2iY=9>xodE zv1O*kYCd#TK(U5}ehZ#O&wA+jWJBn$Y)Tiufp~{(hhTSOnzP0)&Am z7@OVHq~*++u2G$T)$4$fjYPW}dfRaf z(->F+W-+O&Fjwg9J&zgzRwfnh3--wURFxhXOe)5yaQI&83Yc-eqATiYJJUor?ES-!K-fjDBdz zKzULm3Tun4L(Xltrq|FRyArA!Rsjn+B1T-&ZjXgRK+%Z#^`&%DBoy*SBj~+@ThBKb z_JWG_H?mqm6X@=(qx_>gz;ac_*spGThJ!cO6MLcxS@VhI2hABkFZ*1c9yr<@D-$My zhQ`%aFHi)$vX!e+c`mH2*5i+*Vp;l)vH2yq8bQ+%&<~4^19=v20J(t4K!`HeX)e1c z*Z1#3=MC`$1ITt#mq;f~9qXpKf^9WYNcg&-3!X#g4k$uo*XU9($jaq#8Fe zvGOYP_v09t06JP-m|Hgv536Hm#TbN@spkt6#=IOr|19WO8MG(72~V`Xcska>SdST_ z1z9UJ<|Q6VK+AJ!b=_BLNW*3vX;s?-6dJL>YL`aFv=uOQ1`wj|)EP6F(ag4tK}5k4 zP{|%&|oa+-l%7t92PL zRG>VZ2k&+Ee1B!eINh3K2BJ0JS+Oa183|N?2Y`wa1a);xs5kNi|FY?JEK~#u;TnXjq18EOB9OZuJP- z7c?ty9~X?5BYJujVxx6`%0jhbhlF=C;mv4!48dUmEaQbP+!pT|D?Q^$t>`-1+E^&5 z8H z%cHxL^(pY6@)b28Y%<#|Flu*3!jQRDd<9yYXpS)!AqSbm#L~GQ$r_WoG$gp0#qMg+ zC(n1MmqBZQoDgZ7&m0^~<1Q6`o7X|P5svpHikqVA@W($_Q=?AjdKKC4f) zeC5l)JKD8Fq9>`Hq{x}9@s=4795K-Fz^kchgO!MsEr;+F(UNW|oI|PKDx5_%NN~Wd z&i*C^Y)u=JH#*X4mz>5+wx)NybxZ0l9x1t95lPc(eP+LS4c5Sx7DJwfIvE2f`kBjN zJo4HDtJqG!`)ox-?e+G9bf;G~&`OWlLYl=)4QPPTqMSBlQUVLN#Yil+f+?0{(;%pD z3(|WR?eNM1n$@f+W_7h^VZwcBwJk+vY{i604idr=ipxnqES?gK4p4@OA9i&3*109D zK!!-&*hu=%mJ$~Ed<|b7lU1natogRl<%v$p^)3GMo_yg)}Sx|#5$~Bm&@g-9L4sI6zrD*VKf=;v; z`HjqF;`?CzT%M)|zEXj)M+hh2@L2#_qm!`+Za*^BF9qaRlsG6Ug&f@Gdx(UriZc@{ z4o%2r>V`tZ7jz(zDW1D;*EN(K#5XNQ!}XyNK{c|OX8UP&BO$N>uBeWL-`u9OHaA&o z1CwOO5b^XL(r$ZE69=#ZN_e!0qDtRr{+{c8B@XE4pngOE@t2aH9Ndz0J6`w*+*<$J zz>D1Ma>715V+^v)30Q)e7JTO%Nn;Dxy2%;FQ`tr}8vZvDA-t}^-z5*{Jv5_GA^CI}Nb6)UwD#DTW7I^lum>Vm zBh(4B*4JoIMor!v6{>Q3n5AacwOV9>@gSFoHE_rPd7flIbveFGJzO2TtDTu+SrZ;_ z1Q%e?mAfDFvxZYzTI9pfdTU0V(aJb-tZi#7YZ06581s~eqTQX{u1sR9(HkUKoDGqy zri%NM1Qyt_;O1E9@|K)EVlG?j-pONTztxK)pxp@#FV2GN-DP884>$9N$5v+r7AT^q zpUsl4&fv+)x};xA9mbz7ip`yM?*a`rbLu54tG>8S)4ObgXH_4>$R46Ljb>qsoKX2m z#li&0hZAu!E0;XC_93H-vl6R8PMBNK?#|x1A6`Vhu^!Mub+XWa(8E+(4`}JszCE&= zqHr-cB~&5LA^!x?ya*$kFvAoT%RJ61lB7ZH$kr4{qcV>?vI$cTAX^*4;s~us#JM0q2QKgmqkccuZ8wN)ce*XqI0(6b!JZLvgc+Lwcr zC>maniqYSANx0>^BNpSJ*M~*t4e`%u2}5XP!f|434IF{iPu@95QH68|F~4&^NFS46 z8;X|ws_^I)=u4iH#?uUjQkM6DATs5ts9Dz)%^8EEnnD?P!7axfz~9<>MCnhCNWX0U zL{N+o94N8N6RvG|^|GA9l|iHh%g;tF)k%+R0@a|^LD3=CY7s#SCO)qp(Mb5h7!2ZK z?$Clyt;@a)vWo~N+CHojzGPXVXH7Ta+*jozK2`AxQ)f<`X^o#s7p870k*N|n)0&z* zbvBna;!}0}-1xC{;m9Q6c)DOw&mn#)q$y-&E(3rN zg>Uq06PGuU1Eva-xng*8%TbfMyHTerBr?5OhGnzM^JFUBK7UlhYMCL@mZC>{q{bb4r3 zVCkZ9MiscnD~lhmLPc1r07Xmm%e~rHWXBBc!j0cI!AS< z;Q)S@x?m01FZ4w-*otJciPk$StGJYkX`=TTW~(VK>{jqduF>xBl zLQ`PP@~!AKX0Y_ic>~OF5;A&LYJCx=DFm{3J1Phl%$@a#COtVhJ3U$W0Y4x8)|5>? zT8Qe9GIZ7n+;JgvCs*dxm1g>oec$J&*N(}9)uouNdW*cDbU4~~GPBw{i`FuRDJL{i zL|>gZ0my$7)M|1$RcK%{6An-QqkxGuLxU9ua&t|A_CmLt@wlezj5rNEhs>@aRj$Dn z;Zeg+TQ0V1`dQEq-ZaJ8iHIy3XpX?fB5O-sdps7(W2ONxI^5mL&&3tW59rPa;XxP9 zFaoQAfsU@g+QI{Lw7}?#*5v}2Nn}V>B-IclUnxgnJl$si$=6Kx@twoM1#pEk0G&aQukGx6ExH6Y)O^VZmCz zS>S(m^YAt&4NcCiO&Q-)l-K#@Ns)`CIdq?K6JnTlM$B0C<~>kOrs@7{r;8SeA~=NE zId<`MSX97Slnkbrt45i2W}y&d#N3Dn&9TgJETB&{L;;$ucHv*lb5Fw$tEHmGn4e!> zom(hwFl!JcBsf1xac(d1aP7>^_P3ZR{AZB@gkP3PyI$$0&1eBST{DD+)>YK(YvsWL zR#6I5!6l30EvbF6K`@VYnXJ=LhSo(3Ac~&bvYSR;$mZSEd)1wpSNJ#xgg6qjYvS>?|95P#d;F zYDMpnDr_c*X)RAN?iF+L;8cHeoNXA)c23}d4BM0w2$MMczkc;V)K??`MXW=PiaDF> z*1J^H`FgiYc>}buvHe9x(O3d9`N*jhhfuS@8nf&Vm^Dwm&CbP(VaqK!%r=~e6#B*? zYQsY|R=_)0`FVFUnDu@;SOt_1a8U@R;-zFBMfu2@^7a|mkioybWC~_O{2Biq_wQlU zRIp5#CaAQfNlDxOm4M=is1Euew`5BO_*5g~e$GP2a9c&yUio>UZZ^!aXkMJQdhku# z`oW`0t^(U}k1tSQWkn4M)?Wk z3}nVWngp;_m)8=pp1m=AK7AwDnU|3^a>gS7z%lUHW4F=t%B#s4ihcm?#~{VT4i zr7k*>!NzfSK5_-)jtxMMb66p$@@2t~8ekY9f=Gx;)hW>cy@~G=igSc<=OwL;E(ItX zJ2QFzD>wxq)xW^IW&fP&TdsV`i;*bj7o@ykKP#eXyAkir-7Q48k+mtL#EI6ajBI9K zq}^l4p}fX?b`Y#mVhRA|x;SUJDJHM3hzDnPv%Dnl_tLsdKxoa+WwI`52;!$HHGXNL zlqN>05lUVMLMhqHmq#Cjhrnxt!PeC?sR)de6qvH3;Urh;KnM`hl?f8D?-!=6tbGXV z(3g5hPGNNcn-;`Nc{h{htw;iz2vpxZx|kO=0YYV~oh=+Syi{lB+I>ir5S6hl0Iw=q zIX6jdlp%kyuN`68{$_Hk4Z3A4Tj)>_onm@K*`(o_MU z%SK#%5K!^SE zIi*dmPD{jvvaVVAk5}|`XDQymE2o)3+tHwhKv+nkf)J&yLZ0lO(^_4_d2kKi!RhG& zj+)+#M_q%hlHNKSehDBSxb-7a$-q+?T;{eq-tD~6!!v+wX-q4c%c%}tBl#Zg(8@)B z%6NoJ)`@T=StMrQ*&sJ){FWeq z@DtL8qy7!sEZJZ*CA87GnSi$1^$p_+h@I_`6+W%(hk6_$Kcu1fF98y6Lkz#XS7YB= zZw|XMtSG9;j0R&l1uc^<3?rB1L|`;Jl>4Lorz z0cf#4^Vsk*7_EvVkVUS-?p4fZ+*t0{qLjprlX%QfRuxCr_p=GoMAjxt6oOJlx3tAx zmXy#?^jBc(a8Dd0G1bjY=_&U1}ys#6;s{7-O(TM_M9z~CqR5{Rv&N54sw_V?gU^ma zL8Ybbf#M>YL}fAk;L`jSIc2ts`H3nqgto56kpvz!k1&4Q==IP>$3S9V^%RHO3YvnM zMR6U2$&A1daC}pvb-Bl|Z9NxM?>N}uDq9xX(gx}SVQd~I<54s$a$e_&*$VVj#h3y_ z+wA1tTPdz2j>&+Lv6%{3S|*+@Gq^bx6Epy{PDEvC9x7N45{KZ|%(QZ2AV*A*%~XwB z=YxSUO=LNzmRc})H=8*vw4SXgZid;R-?y| zF_&~xdDc?2<2;OYommyqGdwlIyNapEESzK6zY2a6pEt~au*)G9dyyDsL*UWlvvNq$ zfLD7Fw1H>VvtKL6)kEK=#Ur&ttRkI6BtL1bQ}93@=B#^bFQ9A6OH)xq-CPlGBlH_` zajV*`%VOP1If&X`BR7r58z5(odkMSvJ<0HhtriXmw%#R@gINZ0>^JM;sK<0YI?i0m zUb-Fwt&)QrcOgkn0-aa&Y9j*^0tXLNNA)D%Jf;W2~ zpr7<1K(L`ACS_3tl3|s~bzlWsE^gbLcL2r-;W+!X8JeSK><8n)mb=hv*dab7XD{S( zmsf=$8NMh8@k?<4Lpgz(_@(UAqD&6z0E^sp*?CAQ3mtgfnHJfN@=$i`bb|IkMvSjl zey+l7WV)u-e0*Nmvz&zUz}})`C>4{Kj-Uy*yMiV!%Q>)$*7C{QPGlPwb89IIJ zdpOjJ!3}WE(l0QAdQZfc2kQdJg0eFJl~f#ysSU0{8FCxay|Gm>10}lFNYe?Rgy9iF z#O%&V2^YjT5Dk8)ihu&EBI{p0uCf|wdmf|G$0@Oe8kb#Tpctn(XRL!wvPw()tG89g zm}=mR)Lv^vOa#DtNt9F#0gy*R{(b6i85UMYT>!4)6+7V+R~``U)+uHT?lvB-J&!tZ zL_lS@6N6v~gX%7M9on@fje!c}E=3O=5uYWuhj^(ds1kZYPM{8FIWj}K^D^;lkb@Gr zBhW?Au{7n4bg(SY%Q*QntFf(iUzABD7NuZZ69;MMSEQY@fBN8Z0MnFcb{!dj#Si<6 zgKaCCvCfFQF1CR5ByA4n()@tN2SrtYi&fWos&b2uMr zrRPlH&LZZKi{^M8{Ybn(9GRo_yeStna^Vuq0>hh#8LfWi0 z1JY6-&PZnw;g7{)$%`EP1BYAEp%W3W*k5K#R%q#4v#V@77uE^ask}Zy0myjjU{;kn zg48ShC0U$j#_s-zvcnR_5>5>VFvz`%!wGU$&SqNlp*9P+4Br5s=NcJE`_W%HcLBI~ z*rAJN6O(Wsh-zINvj@K+Jy=k6Q+Bi$7Q#@#?h3pfpD#N8&(mxLt9E%oIYbl7(s=)mNLT-8d`yp zj+u?LD80u56(nb{MZ0kO9k=7BI8|DS9N@ivHi^MfAO35a5w#;->fjd%EbDdwrLJ~W zjO>UTT9Hv_b>x$3_{`g8hHp_u+GLzri#A6^!rBpM8!<)&+UiDeXst@s1sPRc1>{#n ze4sJ-OKl64MhxfrB^@DI=f@E?RkfDJKT6e!bp&OX>9h<-0(V86Rk(m6v==Ek={Ig) z<C~Enjg+>LKgE`Iylql!dknUB**1^_y=VTmQ6$zP6s+zzXrf8!cm!jvuuca!k zo~nAv)wR(%C#7W2leMvc5kngc8Q76yjeVWx`!1Wu^HnVruZrdOuQTM#ofWex4;6S9 zez;0OmE2huDbW~qSQWHF+~-K+Rdi|qhtE@D#uuD8n1OMnnWw!9_Iryr76-3;>ukSb z$<_%*t-g3MRdQ;hq{PR{g{M)*jO?hboazqqJ7k!Es=-jqU}&Cm`#C9jvQdh!bf98u z9YbVp6kFfz{qO-$xe+~hN4v_}(YCuc*uHD&Jfy}m%AKvobJ#kX{V!FK6v~-K24gNp zYGCY3o*-^6=B#A#UAyTELh)*>WWL_!`eqI#VbY>Ux!a|3ZnOazrKD>6GG+0I!Gh3n z<;O;%Q2`{5lMY@FJ~vvmN{&4x1~b@9)2Lu;Z!;syCXFifd*$_G-9Sdrt)MD`P}Xh; z$tyUE(;Hga5Hl9igYiN{O=Th~eQU1ZVUAoMArw(-XCvxG8Buc#Vyc;ZT#xGauJba3 zO7nG|z!n|-K%Ph%3ZB7CBl#T_gWVsj2bU|8<6ve;<;q*`LJ_Knb;!y^SW~7wE)}uv zQ4#wLD-!!Z6tfo42WcpUb;l^pbhtu4H3Zr)!d!s5`7Q%{2O8KaFT$EU3}iH*X-B>+ zR_eO;o92D@t%IHmVI;)82C0r5zY3VBPHC~$DO633l%$46vS@<~7PcVK)^13Tq?1;Z z>M21bF}QF(Gs#7iN0KzauT4;`lB!cB8gHESDrVqRr=$_Rk+#K1#j~Y^kSlLwi#%PX zww`>M?6^rD@RupTH}a>RF3!09?wj)u3?D`2Y{iZ{z_&MFnN zZ7a(!Sg7(O1sRcoqss7M8@kWA6&kBkgB9=;l#g9?LrxD?(#=&3x1@zu<=EMAFjd_j z22PRho8X13W*on z9d3N+4;a#fw)k#w8pP->wo{IAOE{OK^IaG6OPoi?=9q;33;zyyy~LJ!Qw$=kY?@kI zzViUe*8l+AI3R^KM{0Y1ACQ&W!mG?)y3$?vP2{eWHv?`?FI~7KT0E${Y_gxFca-P2 z4zHB;J&vmYwnCMRS~7YMJ1os`xCWzvuM%PU39YfdwG-(u@>Z2J8tlEu_pfeq;g_0;eraQrV!6^tU*NIOoJl99=yu(%SH8CqPy&Bj(HrTqfn4FXnJ=Yi`Ck-c?lP_~q%9MG@!N)=kD-pApAJwa(xaew6AIRo1liHsZ!SZnN}+ zwa2+koY)_!K%`jrF@-K_mn~XTqMi+9nGyD=lZq?Q$LvBKwJeb+#T|MEHkYNMWZ~-s zbm{A=F=Pmrt=P=lZ6%k1*3Dnqwju|IY<`VQ_P@$!3-xoiEj2PDh%;z{^KvJ+=I;)K zkw6M#blchNETBRCyujx?P;%(BX>otP(GoD2OegV&#t+QX((!9dP<~q{^*Nm&ImP#+ zk)!+N%)S_+aq!7jW*Q?zy09-O=S5v3GjG5cr29Y<~02b-5PE|_M)uLZz%e3 zp{4yVW}lYvGwhv#tEHYTcXS?2(z$E&+vH3B$C1GXMjfB9GaIm(<&=4LOzSSsd3OPh zMqmFa9*2Q6G_lnUj?nppWyeEXU8l7b3=4jwF`VQW2ka9fw1Y!LYIXEUt^W(&E%dqc~PV&b^ex<~NoJ zU8MzGmhrrR$BMS)fT03kwZjkcVr`sJYcQZ78GR{``CtnR##5H4i4bydIon0#Cc`?_ zgc6L!01$ip40Ij}TQj5OI#|JU(MIw2?Me^gSvoNu6o>`q1wUy=63$5jYUY%tGAC(ILI6u3Y ziBjCI4@v0EEgjy+8ea_q?fe9*JI#;Vmv#QIKU*<-gjJYkU!Aufw{Pu^Lub>JG&Nf% zsqWaeVoo{+lcx+5Py6G8E#z=1z{>172i!2B6Ht#>Qd2&WMTimypU&(tm4**SU~x{8 z7pb`OMf({|#ezvSka}%fs~`>|6l5}<=A{=i74us>4YdEt_{*LLA`0R0qxp!he#MEH z5YEAM5UKEh=Gcx9m|@6#nwj@V#^E$tw=jm1jgV_K60ytGM#xet5hD!+7Dst zf;4VjerN4NFRJ5{Awl++VId;= zRO$o|#UX9Bd?l^;G*-9i+@9csWT=dFi-o3W{Ka6vq=2BH191kYKmU5V?K9pXTDtnR zbrhN-@$Elsy9j`=bf{HuO~t-3NmUixt^ZVP2}l ze3T{qxHCSqyUamHo4_=S$S&~6Uh#w+VFcLfAu}&xEdGi@blw~~Hwlr64g))!_(b#h zV<#lxLYW>RWXZYoEJvxTkH>}xkvEwz!|}m520SA53ep6dW~r=7$dw0IwxZEtV8z|n z8@il|C@?UKP{UoIEYeDEI-KArzsp^S2a*z5zirY74FXRqOyuw9Da=kz2?00T)el z1?RB$8D<5iXN8R<#;=ssq_d`=vQ;`is%{?gSc^^jCi^iMvM3*bk%ML!Z+^nQE3N1VQM%14RSYX#du*w!zp#SA#*kc7z z(_P2`Lk{SRmLfN&g?O+I!CdNyY->V|BF&@N(M$}ivbFJASKDmC8pM@E$;qjfQAP1m zO>xzVO$AE1wXLvhU5pE!0KQqf9DOHnvcxBR^vj3*r1w3!a=t|Fh{);wdd?zthrXaQ z$G2ekJ%BO;2H+&@ldhD)Z7oO)fCFXS_?^IGxFu5?=8D4_gWpkU#FVFa&pWs{ib{AM zasrP4YZt5C=sTjosE#OQTJ0wc+3?l0$T3qnsS4^W4%3Xv;4u}%1^uy7ZGFaSeGxhl zXPF7z=)eFoCL)nJrgez20!AOpdrik!La&(LnP&IO`J> zbFn(pk_M@+q2mndRPMeW>ALv^^uW#qSDV)9$iY^da5yuRTaLCh;<>@ueIn9hF$V@j zTCoFPFJJSfXvsk^lE52|o)Pn;r@4NdS-@&&z@L2#YH)P2K&=x6Y`vyHQUdLW$EOt# zP3Gq{)GFv)00r4)v~vLf$k@NbaegZ~&iANzsqBUv@o+-6jzhFGKu|IJngdAi(FUqa zV6wx#o~I9EcV-$H3@Pq&NCB~%$SL*8C+Fd(c)=0_SGz}xpP+GZ@9LFF9j;io+4!sH zo@ZV;t{mwg?k6`j55}^q7?>Hv<`Z&-&V|dR9?o0=5zoOmnu{4FSh#ZZX?8L!mFO&F zFSEn8s2Z@rB9+6wD7l!6&@LDrKv7`hla|Qji!Zjseq-7`kG4^$`XKr^ya~dQkEIfk zIcz!l?uO=AQ!BcakGf#Oa!lVofH*--&P3ktZHT2%# z$uQXT7qE&zfd~a9=30>jzmIZ)b|YQ+s_m3AiPEoI3+E&G=Ds)iX#oJO&_}mVdfz7LI><$ z8=nzZ7j%vtJQ&M3FS&@vlJoZuy$}_Pyi!*hdo@t%mvr3IOnH_Xb%6sTih;YUoP7U4 znii@wk3A$F@FM-?hY4V9`J)$8Qd!B0gTtl4Sh8YKS_heRe(YP*cYX5Ov0Ly8+D_RZ zYW_0fl1ngWuyjoZ6cG=^MH?V$Ry20>!6@deX4|S63tz{>=&O+8krko7VnP-s3q2r$ z-G*X?;K21MBKeHP?r-Tp(T2!>mG4o34f)Jdyik$njV_sPxh{l))D~4Z4xHS(e8E#& zsQhIG3nLEZm<;+V|jE^h29~K?>9bT+a?%9N#~s7rP5qSi@+9XSlYNMC&q{kOXm1I0&=+s09j7<+X} zoxOB*rtsd_xoe$mr19v6Y{_XX(lHTL1wNLiV_(CN)f*H4_ut@jSG7eo;eP<%wf z+U(iPDjSp7@GU|;!s?ddQ;HcN$BwFOZ~$;-8Dd7R@&d{HSyjO5tm0r)NTfGDYA{hI z%SCz>dc!%LaP_@KpH3}bs{n4F_*4lTV3&{>0N03^uKJ|!*x`b-7Mon!91O7-u1_?T zHB4bUBbgPv*^n6i3@F{7tHm24bzQox}>j(MTB3zWEXb!>GHb@{tRCsy`ojV7y@tF+R zBlPiUYk%50khb@yZNxjivr5{RNRh7;WxPN&eC-Q{+}Qahjn_;Ucy4*;Cqt{l<5D{$ zEg(j_RQxG)p{2FfjV}@+1?XUAOcI%Tlt1WqB|yt5P>SX>lcc;734m<@_v$b#5f&eV zu1Me&9YqJx072@7&^a>jD7s0Tu%HT3T6!T}@l5cQuRu0FZR5Ft42DimAG8*s#!$pp zwo$)=6kt#ENF>etk!|r`2n^Fp?4{@1k=C5Yw5rE(hdUop9o__O5ynR=h;W@dZ;efl z)ea77#4A7Uz$k8BV7}bf-gh9w!|$&i)iE9{AzNw;30Aa+$)P0R3(N!+rMonNIu))Q zU(cs7%)D49Q;ttF#pSvA*e2uVFqKqR0#KdCwJ2FivKSHU5RE||Kr2SjW>)=`J{tk@ zDRZ(1#Nl(Z9c??QRXX#0Z%O;eDjiSBC|{lPv4x;{p8<)Bu=YcWZK%&?x0=|z0M0Rz z^9GBT`L-OE-+|)~2lC=zxYXvzRy)dwd<3m7S+d^bS@-1N^ag0f;Q7-hQZ=xfwQM$G zGl;&Z2PVP>$^5Z^A|jo4>_S!y%Bve?qhb%FwhdEPbU?~gCnB!nIP-0djC?ma(zt1< zV0>uUv1k=LKO@ht_s)1O1oNH=McSJ@Ns(|MPz)};K5S1Ur^VK{>DZ{@WZo&~c;1EP zc;5Buc&^W<7Y_J~p?UM6&6!e66}?YOCfM9+JWciv?@wg+s;Ar@A^=&Oi4l?|nG9XijfEM*QH@c8xBfaS$X+wNhN$-C)9GJv9d zW-WN#k_u5VKhFECgeVb|JV?$kVQ-}U_AZfMSAK`w`PeRk?})w*mh%cy;rnK`XEb5u&nlYLIJ9gygU3}!K7_y82sdalRYpzf(On1SR5v8xeR41ortuB&gzK}WoP zIccRtp+`Ee3rs0EgCTRWI_g%L?p-O#6$kPLYMWM7+7qYvgtAZT4+vs)#NG`m(Wl_f zGQ+bL@|Sp@0QsD+$4Rq_OA%v;3?+nmBYl&xL%Bkl5g{kI`&FGX1TUOrEFaOrYij@` z;EEU8FhgOnhX-$B`a*IJSPh};t={+^byC+%knB1!`O!}Vv9*? zv(HbPbrg}mdK@WCCL*fxoRL+8O5;kwnM!zD0x?yh#@4!n7Z9uvMYR`t_#C&&%%;C6fvFBRO zzV3SBP^H{!>{*eG{1tX{kk2%Zq=1$h4rq4_YNa(I22#xeefffvf#%=ysvPJCudb@H zW|QG^MKo+I!4e(F_v=IGbswPM4=%LX0PlzB#=I;I9MP+Ya`=Ivp-#oRM97d?+U+`~ zMw%%YUsYf^!xzE6tk&NxQdap`5eSL0NP<+@>?at*zZW^*`Xmo2z*OC!2g&KD+h16e z*+rKSh#fx=SqGX~fv=;$8`xb_v8=U$W4BP3uerXNd96Q%dU=`ylG8~`9C zdI_+zJn#9uME<&-TJXoz)VugTvlm#2YJFvZm-R-qHo7`;T&H@+f-tt2oLdV&C-`Zb zY#E7oQN3r_g+jK^=eK&eavUZIhjY(y8NHJ7$D^f5Th;l^63V1Gk*J4`%o3lR`*5$6 zY%4Fz1nTN6p@+a$$T*hQRH~HdqsGYfHuV&Fo0iFpo4ga*=M|%YW>a!ROOI$s^jZA1 z&3d&tH3+;V1mUYj(%;Y4*U1^}obQS1*xfxU7Oj?3Sr~CV$b20w47qax3whT|W*%}5 zEQKX%AWt9>Pm+kO5e`)ARDO~K3^91D1P&TP_=<&7r=;&SQ)dG2#Tgzn93JkhgjZ#l zBBj6&_Zl9BjxoMu!TuCT2y6mNz#+KqXW#R3LdQwZh} zXQJ`ILsyFvMlaMBB!ab8*cORR*x2xgXUl{fjddcSyyMNe>FX$S zs88boJ=~kx@)g$0S#I(qgVh*Fq+)HpsSG4aIo9lqswB3{VrKE7xwEfNTWN@-a=Sa==c~$g`nn2_-a} zfA9j?)&vz&4=LcIs#vDR(Bcbr^r~^Dh^8xII-!Kg)t74`YEtOU4)O~pa$&inb9XR( zfbeA27<2z~b?MuyIROIoeB9%*!$Z)>0#x`qbAa(!ch#=Z&=*81`@8roImbEYUF2-}C4dv6ASY~|a=QW(7^FC% zU1EFwMiZaUoVGn7txCsNt353`j7vj~nMI=<%tcSfzDWSh$vABc6pR?KWu*_Jnoo~X z23Q^@7`a8l4X3hVsz5E$_%yo5CJXi4&qp!E9EX08m2;&UDs;J+BRfOoyvMCR; zW+bcu?vd_kyo8cG59d<3;IFZf6`U8&5vaPW?_FU=lEoD`hx8(T$Q6T=CBvoAs4Hz(L`L7bRNy<|R@Ce2CFZ)dZS5 zbNitmbA|Twine0&!4exFX)sBlfmi}-Cr;QYF@ggrM8B#89PBtqzZVC$+Ydkw^S7My ztxlVz%pTMTXgwNP;=3 zT;anYX^{u4$6}(=Mx+v~OAikRN}( z*=yE1N%KH-P(4w1O@jsHZCp^fBJQH(^PCGO@@b-o*X>4{qFXGV;;7J; z6&to#N;y~*=_bP^QHX8GNTsDx>KDmRVZ`%yQ!U4phalhNT^YiM+T&?^w0y*y8TKNN zjNBd?0;+_h9a^a!+qQrZ?H|j#wv0Z#$^l7}3;~h$V$BF?GSsn667FehI~?hY`cX6C zdf+&e;t>^LWuX;s1d9yWQz7En#04u2yUv|D1|>fa(MK+VC6${h4ToJIp2EH2-mM)1 zUuI^QeG_iY&V$*Ti?{Om7FeZpHYuVNo{M_4))ykENT0+=j&$IQ!QPwX9k^(DeaPgz zzmBZE(&8zxuXK=~w0tk@PZtiP3kPW|PFHP_Q^ya8#r86fV{RBoeZfV?jVL#tUJMOt zroeoZp%^kgEYZk~ckAgaQt{Pg;Bq#T>Vv@bP!_71U<-mFdy;Ka_e zjCi&y$6!>B8F3qZfl~^+K2n^&6j6|u(Na}=!k}Qouwiuw2>p{)^bsXl+tpN== zhBj3nPlf5?dx!!t*JC-$mpdQ2(||?r2;6b>2t=kta6LH@&>OCWHRl9b%nY9RG%pG% z@9bU}Ddo%AFj8Qd&_OfnP9=O124r7e^rFEJ}QYH`>-Y?FCc9_u3WFR5tEHlic#RgKz|fxECiF z1YYaz8ug_~0kdf%Fuc3W;!fBASxJ|(Y;6w4CZ3^m%`2G<$4PL}@hl>t4TP5;xN#sW zYaF9tgbSS;C0U(__}xl&$b>v>?>S+Ap`xF3BARhj+KvF$Tq3=&eHyZKXRbb@5<7u5 z{nns=xP{i@W+Q#TGT7KE{B)-26+cBf=!C0Od>Dvs-A}7Xes&?K(jjMnaE0_lSG@Zx zJ3HVUj6~0{z>N_T4HfdmIYBz@c@~r0EHH%mMf12j?t}TPlCGJk<-X2z1h0fPP((M| zp>tG-gL|B9*AJ{~hC+G^aQfANAx5i8Mij+C2cH5&}-t1r{JEd{MU0tF#h zoX`|xdcYWPpo*7^5kCqPpDmni6D|--hLu((A0+9xhDj;Qt&tZpY_tNUN02fa9pe)g zu{d>r17o3aM+OwkNPEC0FP%T`W#aR+<17>_7P3;i;pIP;zlh$7uclPVyw;qtk&iO7AWVB^-ULft4cW!$5zFa-$V2*E)#Mu9L#__&|1#)o43Tzr`tY& zu`CV}Yb;n3aQQg5w%~kl#g&Vpe3_loUxm+Z%GcUO{o(LNO`PHmta$7C+C{eA;m*^hRN38MQZClrG=2qZauM{Yu zPEryJcXx;X;^0`0L}U!JKco1~}h zr1`3NH%3(-um}Cw@oM%0p9RR~p6s&3OVXg5mWe2z{9tq$no1bH@aEPV%V3{3$K)7! z)UaDweBeqW05#soDUEKme@&Sw~`{J|888 zx$zdTT!Uj|ink6rKdk%qFks_L9)N7?2_NlJRvHN&OOPkKA&%QV3$NABSCsZT8;|_h zVHC_u^*UnRLXxku&;f8*Hy_`TeHl!t_Yr!nT#7Vwx$7E(9CcmzeVN>&`Yf)c`*VC@ zdbLEA&2~(;NOp-T`(T|-RGb?8F-!p`t+-eDNF%rw;c7Og=mBmz8g+Bg5YdA|zAP4C z&Bl1>wp_^@>H4MXItzR*eU1-aG^)YXbI{{HeKsZUq|G|DK>21Q;Ji?5l(QI$x-|32 zux8RP3Rj=KWAf-v4<`*RPTl^s11)X?@}t$u!aXzOegArsGW?^=iYj~YjV-=aS0Wqo z!#afrhkuU9M1Bfx;;-ehn^iJRhM;~@XMd#QleeAC{Nu^h?h$K>(`i%MM8>!seGgBHn5V;Y7tg}v z(F7&wmbvZ262BEmhmaKg95u$v%q2zC`jOMeri$*3GoZJ*wW%fKnRwv|oh~~rSBDg3XV}k& zEofX|HZi?IyR(kls#EnNx^-~&STOSwyq;b$jUV=F`;NmXh11cMjR`CUCzlU%42H+; zh|Rj&$zw^GP4nkun)j`zXOR5V6sMfb&Yi_@r-ndu*Uz26&F-kqr#LKpb(r(@m2(*WG~LP;gES6spVX0= zG`gZg@f`c}+~2%A|=&j8aL16p>RH=hK9KZ#x%P-YZQU)0Vo4 zv%bXd#5pmE6G!29)5H;rPLZSfhsp1(`$6O0jTP^~?BVR*EA?-Wk8n>M(=h>MiKK~> zD~-gI6haGC;c1xQDe3jylPVRxJ_5a?@%$9`yN<^j-7h6rlgp@H0KD1vUFA|aCR-`adR+-IasQ4 zG(GwP&Ol?gonvk#Eezxy;ZPAI@xiJ*gX4e)>W#z93}oC6@gK-Ils~FDka+?#*g(cq zcb=`pvx9>+4l3I5IOQbg^L_d1#hfwls>UXPx?Fey^OfNt?)B#I8k>bZVW2|>HBfju zeC~u1%~an$1p}3ifHd%W@G{Hwj$tQ_H2%zBtAYAjra)pg7b-Q5%?4!BTZ{!fPp0e|jw&e`eV>+OA zmwAgRc{xG%25ajKV$4p1nQ*(C13AX`m*ynr$L!vYi~T^2z-i}>8~-)eZ7G=OY+d#S zmO&^U21<|U+`rCD;Gkx6&4Tgim5u3MHAKy#!)q`)RmmBSJ?;&Hw9whW69GEdY|fF{ zvHDI;Yw=Qcxn-D7s@j;lOyO_J6xI;_oEc|*8Gt5B2 zt)l%)m&}2lJ2iLrrH^)wSuV%Upi~nBLq`tdaO8-ITV92i>7bq^1fDV$Pwl7_6#Z0p zHVDg<&qJL;wJQ0peJJF-_9VwTrS|d3S@D!@aZBeq7prM&Pk5WzBz$o?%<+wL>%v!u z!B<{-JV*j#sxnP9{37X0XQ2bfFuQ%aUB}0H^y#*cU^=4XW-=3b=GNoss8yfcwSd-M znmp@vj>?6(BqrcQN6IElN1C`RNM!m$LoU?W`H<(l5JsKF+}2+t1L1P6D;L?4Y$94n9J^_Anma8YRr1vPl2HKiON97L^;CS(RP19kDG|bqt}tQ92LPHr>gjUhNBv0X<*iR6(t2Zz z^WsyT$EGImNj>UMSRT^XHgCHP8Mli0PE|kBS#zZ`SfY&zo0;e08m04(Q0kXQ@u(Kig;{~WJ`H{(;M3gaUA*i|LpCH+tWZaY2S^TKi2DSvAK zWP`4np+LlScFu@|zzN}fJ{Jl8Dp1S4?RPAU#bwGWyMCu!Z}*4zyqoN1$ECbtb>@t-`oO_$CzG%4UPMJkT_v?$1g(*4YiesOba3Z1@H{2%=#&qiy`7I9 z+*+N!o%C8zo783~bpkGs4|t+bbJsN3K_zF_EElQ<)NEWvs9xre^r=$Y7y~L9@9jO|2%A@MWBPk~)U`9tw z$8FPnn1bn*!<>c?w*$Y9_$JuKxG%5X0d}X^=fMIW|1^+wq7MZ4V9|l>!wA-kfDav- z-XT*}2;&k#^Y%pyHF>NCTB~k3i(d?GnFEEvW5CHE$PzaXQ?3#?l7u*ARA>+Q%nCGA zFL+B#*%c(g7xjA}D*1%~&|UOgRocJ_5eq1-vfHBgJ8v}wt*exgs&jVUfJ(703{_wwU0M9t3RTbg-bshJCBIkmYw zGPTd(&$$k1y8x!Bb5G%Ab!qMt?sYqBPBDL>`)uBCbhxwX1k&g9RT2^-)%&ijwcf4Z}j9w*$d9!67Z#`IfTw6X*&o^uNZR9V~%$$_* zr*=j-YE}=Rh9Ygutu^!Omy*`K zSrW5S(0BpZpowOof(S-b+g?Ck;-97*H&u4p9I<0ri5`4Gm?xZHcrj_NgO7A};Q*Wv zVQ`yt00*u!w;qbtn)l}Rsd-eVe)+!W%{iUMjHq)-p7qd|OKMYNcH(gk)ERv#6RrB0i%^9rnpNYtu^uxv&aTxI`e@nGPO=zu8o={RQ{M}IPx;oMUYX0042 zJb;Cn(>>1c8AL8W;`ctfMv2qa&|wd;QbP9-pW*}cIa&`r`Q!SGG=w~t!9>Bz<^<-Y z&RTcH-@eFMg-b70ZncMdE1*)h2duqx{+p~aJpuFkvdT$S#x9Of$#y~5iTHV zHH+b(kzejbf^x(tSd}NG(bVJ#tIsN>Nhz%|)QKulO05J?7qeEfF%zXqL!ouc5h2#9Z%5du=Qk13 z)(l8Pd4w;6K`X0R&?)J0MRirTF0?&XZ?qg$NDS5-PPIS6D^Pcs?OC|6~3+H zB&Wt>-=5>a>_@&igkHo0OSlRwD{f)4DXjk)cp`yxC_}Iq&+Hp;EPz_lFK^EpShMk; zxID{H76thx;#Hb%nQB=j!U${qL&A0IX?O(hc{@3KXmZ|y0W$E<@;%Dj9!b_!)u3$f<*v$vf&eA}s` zw~il072th*wSFbU^-A3mdN3#bnxex4sjQ0~$cq7S7Ajmb!SERf?9gr$;RAIqmuK8} zxrS?`IM_(FatE5`wHrRr14WH)$&xTomSvWKJdGf>ak*5KVUYIFZqh}_c#P8QwmlVI z-;dEoYFeGLnI!OQv6%>siN1n(gyt0udBk9P+wD7Z8fiz3l5NhbleHmUia3F6WesqK z)oN81%M?J(*rO`17I&3n;!v_%hvXT=Qqlgbs>&g`Ha&iov&E(D@v99!Oq`1}PqO1? zzgBAN_c>AG-$`kp6%4U}w$8@4?R6gFO(AwP&D~`eQu%@^vnK>gDSVJ}>a= zV?1a_;iXU5QDLy@aoH;Hev<#>V?5xpRW5zZWvdN7>}+PB9^*lm6kqy~OR5Y$pmI}s zj3-=Le(57Fty7r)YMG!uke*_p9SpbrP>JWkzJ zlqJ(kJ7)8eCMP+Fue0J>`y0Udc=fRTJoaM`!yd~y75pL{1$6nb>z?hbV!#(Rew<43 z;#$!5=dyF=vD-V&hF^wR6?%`;A|m0OOu3IYdIyf2j>GF7`)LPYF7vULkMl75anwf@ zRLxxqNaMJ_b!_g#rxEA4c4sEgig}nr?U_StQ^Y;y1nOE=AOFt6Fbt)kG|b;<{@b1O zm(reeEn$@Slez9mH>7*gz3IIa?MXLNeqVa0!YYLYitrF_fpbOX=2XC%h%hBWzP zH=XWzA|F_w-n}D{*6(|V{0v&yGc-xh_ApnghJZ)YxcffR zZzXjPb8wz{d<$=;ao^2z_R*8QK#F=y>%*g@w$gc?eUs;QmC@SEU6cOXO^b{CDRr%5 zi~?|YK0U{Oj0A1&5rmDNpa=WXU9@{sdW7G^^R({bpT;luVpJc&dR^(oCAEMqpBa}4$sXtnci>y6C!``$y zv~Ni86aU`N8@J0GSM*6z>^w0IM5B1k*I?>*eDRlFNm zzH8`a>Ybo`FZm~OkJHd9PuZ8QeL`YZzFae+JJN%qChNrp4qIG}_Og-ZKdw!|zjQB@u>*UrWxjNPVp9kEUl+=Q)Jy2+t*4 z&z(0=_v5JdMCw0}J3gNJ&nLWqyiefnPo&;n?tdX+jF!~@Pa=FW=}#eiD)CRF<$YYQ zBmHdd-Op2=K-TjPP>8XArI? zyrLSX(ez5FFr-_3UGW0$NFFf_k?SPBSu3b^Ff;hM$*SP1zahP7$tWrq1&G+bBOr`gXS!b9J73 z?;!6rjOY^x8d=TborKqtuX%eNBOPt0^qD-nMc!S6Y1(a5e}*tidX6y9eGAkPw(byK z4+LFcoaPBgg#+|uu1+F;d*9ylo{Wq&PAT{ z2ErSeb;0Oo5#Gdmy_s;2-%n$@D}6TMbAX6vR$~+I{kg8QD}5g2pHKJ#!WR&%cl7eno!vR|08I1=7BXp1qauHp1Hp@1R_?|DA+)5#G)7 zzM617;XQ<}A$%?2Y9MrkkO)ISswluHArUkWn&TG$v7-b*?vP<#c?WX&L7uL)p>=U% z`Z~k>A_&v|FyTkY`%&ur7~#hWKf%iRN%9{g{1oA*2|ok8 z{4A^K=ji*-v!b*Heu3~1;TH+N#G3p7tL&Gl`zwTBCHxxUVZyHyeuMCvg#EPtLBekl zew*++-1`XOcL~2o_4yJizn?_@3C8*;7>B#ll|#eC!TtcqQwUcPp2~fD zhF%Wt)fgU3PaFD-bT#)qop25Hh2Ne*yukW1hrq|=UrTrvam}Y-;<<#69eM>&6gchK z-18j5b<`8=JeTYBgd4c$rWjyQUwDB3l zUqN^mm{u761B}ZnN#9Jk9$0#1weG>i)IUrZCmbOhB^)ChC!8RhBnThAit8I`Xpz9PMzal9~eC@nEI%Y-*V zb)LfetZ;9a@LRMi8aKGE#O;BDDZiVr#uy)fLOqeW>5;C-O80`7$?Mba4Z`NoQRt3v zk7!Q3r)bm`@1eE0P2DCOYyDj$?+t`E5Ku_Ygjt@HvFfC43&?^9f%-_(HhY0T{{4n812tP{rF~W}%euD6m-1{Km zrwBhy_!;tkmhf|gpC|mn&~Zjyb2N&SJeq!yaMD;qaFWt5k^TVTdUD^=n6qD|EzN6l zo_>Y)ewFZRgog>gPWTPNZxTL8_$|V36Ml#A2;p}Lzeo6e!XFU+knl%@4-p>a9siiV z{R#0uCHxuT&k27)_)Efv34cW&{+jSNgukV)e@FOx^8bPG5%T_#@K415neZ=!e>}(YJQ0TKNnEca zJely6Vfb6}o=SLt{_NqpOnXloj(NPA^wSBV=hu+;4DNX*;bREb5}rl)Sn_{?@`qSU z&mMkRdJgrkBRp645pJOT;|R~A?#C0JKP)&Y>-$yd1;asiKY_AOBr4O-{oF;4MD&q|+2I5Io|cRxYyL>ht%J<9#TN5j_=KhE>7 zppW9`^ml^vNy4iLw-8PdCJ46@o=N#>u9L&3;du&9xhlPy=bs@=4GZVtmP`MH!)~Mf za|F?S@p-~=;s=E1Zl|5|ggfZpYld%tChkgil721Wb%g7f&zIB2XVO-Sa2H{k&?d|f zW~nnrm?tcdULJ3YesaFIENQ=j||?%N!GHRCv(wn)F8zUci0cjwLF*JHfR{TGMD z@n4nRFnl(>k$XRj`fnP(4LPHXspjdb^k(YaGkjh8Y{KUdKG);>@#*u1HO9^HjCavE ze?HIu0?NLSa4&6t5$P``oFgtA@+IWIh47{1m3RCy;$KereT1)YUxtwxQu<2bUq#)w z65d95JK-IK`w8zPyo>N|!dDaC!@c5vzJ}}95*{EtlQzC?_+0vW+W7|H^BW1@MEGXH zw+x?2@1@SS626VG`*y;2(9Rw7@jJPG7x#QO;eCYf8NQu4X^xHHtc=6?^u5D(r0*Mk zP5S=fJJSygzc&5g@axhK4S!~O|8Oh)@bF#fM~0`{1V{<^s9#9QIEC8T;ux7l%MB)e}(>D z&-GWi{u<$7!moS$7t(Lgm)+^g^qaKvLF)e&WrCC6rd;&+cep-6zrlX#cPalp!tWFQ zfPBH!AG&@UI4k8T{SkQ|qWo&4Iq7{LrR~@8o+G6Hn0x<(a5Yk(^aOuOy+6y({1D?X z%Cn!uI{PE8A0j-;=&S8N=bm56&kQ)e({29+`G3hcKLNhxH*-79zF&_tD*eTW{mj?7 z{km;E>%7|$joX8Ss3f&ogJ=f9n*TWaMH>JPf=WmCXT=v1?WnVu$ zyh4r9^mjb>?|J`!;QEo_E;;B#SobyET%~@OalhN|`H$55r~DooU%pG>{{6G_d+1Dh zJh8_;cc*_DUQPcxyq5lrGQo#nLojkZWBc#J3#{g=&^arf(ti;Clki`J|0eto;eQGL zN4Og4TQK)Cj4zXvhDO$DU+>o^3H>Af_ilHCIO!41-=^PPbFn$J)rfDy18$SM?KZ@p zi_VU4k6`fWmU&Uvja+2Tw$l|OFHKJvxi0PExx1GW+6?YwFDvv%Y|f62dkm2UHL3)?~QzQS|522`J<^%*ckbm3_r1sHn~q)qb=Im9+9?bG+iYAy5R>Lm!9ekBVPyg zD{~d|^Ts?!`_WK+7VW-?d)~}dxappe2hwNL*5{D^T*BuO-az^16TX1(g@k(vU&Olp z;*qb<>;D_lm(bU@5WbZ9Uq<+H!hQKU*Q2E>@N$5jJr8;%7}HwQ+>zmDtI6TX44A8na%qVUu=l2(1`DZh#M7Vz`&T)&xcH5#>mlkdoI z5^Lw})cqFjc`xBx33|70^E$jPeK+~ zk3l^1r_kD6=YD;6`o59(rSGTi4-kHkdOt+a8hJnAS**by=K3RqA0_-4;l~NWFF!%} zN&5aE;im{cP52pt*2d5Bte+$NJawK){U!SS3&gKSLm2RUIh=GI)}ZUsFM1ut`|si2 zU&?L9di!4Rn#MEW?gKpI+4S+3x#w4?`>TXsBRov`uk*a$fX4hLZGMpWZ;|)gTz_Ze z`>HmuI;G#G{_hcfpZFgT{*drT|DSDqf7Ql5+WZjVQJ(Y1k9!}wM9TlveTMfL`GJfJ ze=z;|$PcBzpbgQ?>(P(~Y$ESc|HFj8qEF8fzR}v`dOaG{pnvEdDO3L6aNUnqHSz@; zqv>yH^X~}PThpp>LpMqI2f|72DY*6c$d6U@=OfhrN7q9hqpxcFpJ@A^-G0o=zfk92 zN&nl(k7u|`>EB6zlpvh=AB@F+68|r*|IPJ(2=5{69{CB{i}_Q#dkFta{{Io^ZUTKK z*o`zYs&zsZ@iziHSCD=JVHaUH;fdtG0Bvzu!%w2(m4xFw`^lqMrl*VsKG+<3Ft5Mp zcXK^mmFsBz>__ALw7gEAN;`W9Pa|ASc>4cq>@2{eNVWxB-I-*DaS|ND;O?%$CBZ$o zySux)ySp#4xa+dGyTf7&EDj4S@cz@C0e0DY-_7^^sp^tbr>d)~tIGyrkY-GX1+lrl zNdDts#)WI784rD=9@Jyh+I%0%b*P$&Z0SqOb1HR9#-ZaOBR)tUB7tRpR2y|bg<1}( zgvjwhBIw14cMye=m^8W|yBqa93GtFbGRq;_re9QY{8A9MkIt-Pl>RdV4$<$E_mLSd zC1L83ZaeKTagL}|T$|r`M;Np9f5+&2Z|cVPX6mSNNrRad(t&(Sq$iyWkP(t_lQN-4 zX2=3rAsb|e92TF-Y4Lv($v2MlsSc}LmZQ{7d4nFMtuyB-qz?3A96$z&}TexCVVJE{B zmmZkj_d=I<<=XxElALEXULui;Rn1rXP2ioLn~QRSNEvl)sE)oBcPb zlm7l2?@)A*dbJLDH3F{CK3*a26(epI;!3>r_&wygk#_87^xl9@8!ZdfCd|#?W7bJ# zAmyHJLEcsb35#Sov;fzyI~LPg?+Fe4!}Y91rEWla2SrjQ8)(2;RKw7Q*av2 zz*#s4=ivfegiCPQBJ*We)fMbl(J>b7)HTaB+8P-@WGoi<8|WlD-!$@Yo#*yCIlNBZ z&3Du-a@;WMY1d?crST)3-6Hg zC%lIb@DaDa;1hg?FQ5V$>jfPGzyg5~1Xi#?G_ZpMoZt#%#0)&xz0k#So>@v$@92TI zRdC=P6%uHUy~GIQJCiW6xQ>k(2jW6Jhz|)M6cU0D5)nQzVUu7czskB_DgKFeEJz+CIM#zMJX2=3rAsb|e9FP-o1>RM;36}@*22NJ_0_8g- zLgf#1)UpC|La@mx3H`C4t<2fjy;vnEi!DId^oI@H=ghgyf< zdiWVOz(&{vn_&xVg>4{XMcV@(@~v;SH9K(I3A$(9)e%t zFdTuSa16qcn26bWS?_b4xF_HwoWk$4k#F8!8<3MWRmz&ylRAA9Zb4V= zsnOQm#xDK+JD3vYF6M7=5ALJu19*t;kGTFF9>WvpLtkq@Ez#4!Khz(A&(yQP=am0b z^&G$Cq&JdxRVm&-U5xgfwF&6+62DjQ8s0!x(tR8Fg0(Rc?}2*9z4()GGG1V|KlJap z{s150FZdKye#Ow~GkgIRM7s)lkgfv20)Y?&ad{rBL98Fc9u4d;0k>A@=)ms8&joJm z9`It14#C*(kk)Mo!G0GrMi48>AQt|yLHcQN@QVx5KE=a~4+$U?5`r%%L?wd6LBT3X zkXt3iEg2+7-xQD%QbB6urNK-K=^#C1AY4Ys1eqZVWQA<_WrrNtb3!icxgig_o zHG;;_1Z0e(sUcfdwD2B^`o<}O*$nsQQR%h_dQBat-6dV=AIbNod`BeF-*8P^Ot{w2 z2HHY9Xb&BrBXok!=-LIdD|ACncaVD;$qJg3tfuLKK0V>bx}~dLxc7!WP(XjB`eOEj zXvpdx^hOQ9G}~x-cbIMTK>Ypf^dRhm;qUD=Z8mO0i8~C2!w49O+bD>nZ5fTuW3+el zr{0m>fES`eur*YLV8(!$ z5DQ{M9Ec0?AU-63P)G}gW^!anx6Gj{{E-55BF3_+`_GH6=A)vN>MhY30DTWWsxEM zk8+shjWo=4TOQ5mlW7&K(X@(Ik5@UFGPYBX@b#_IzP?ortPZWARmMkxwMJH_*4QfF-*(l+>hELZP))5NS~IKk z4P$5?;7;-!$~q!heV0rPEG-Rwt?+9NZJ;f* zgZ9t?IzlJtY%Qz0SYv5jt+BOk);L;s^3lT@SLQ)oDClm3T zMEJ>={_xGbx9k zt*O-p%5kGLTx~M$xvnN;h1!(uyM>I~)@0fp-dj)NE}I5!ig-&b1L4$sVLJ_)MLI{tf{qV{~BMyy46$C_`^syjTZM`!%6*@ zu>R-WEYoMC`y5^vaaj|MIR`ynVZH{RF$SAfdqeq1U3_aiV={)9j(2-{?H%r~;ZJxE zAFLU)*o6Ct{V(_gpWzGeVXCMMO1H8804xv)L14A%$_DZ-maz-D2hq5;AZmKb{yabq>J9TbRwq&9P(L^7M5K20>{;dtMn zYYIqd%So1V5-cZSEh-sqb%>J+9aAGK4WzZ@(t=qT&5o{rgvp_$!#_P_AYMk&$z;pV z8UW@jaLaU#;&jAW&FNn3s`@egVG z+v5}}oNy6P%E*VVN@JEmMp-C_dwHk;6>+Zwm7xk$MVD%}U=<0~@vi|jiBk(|<6j5r zV(+6nR6WAhw}o-fBLqZ6d$0>VVviq|phIFm})xow`6m>Qz_#;?pKf6R-8`zCVSsu#NUMvp$w7q@=U-&O+I z|11Y{Tw?&?2HHxpV*Q`~-^ySRWil9E(q|cBlfFwhbyeC~v(1$@YbgH1K;~wP@LeVM zU^v$!NPi^d^NPN)d<#nbl=o(sP3ouY5{Mwr5#(8^QG^=}V_+;;(9VnfvGSJ4s)-jljaOtX`boQh%9Z$4Pht3Ok~Z1*)WGNa|u5W=EDM52#a7b zEP>7VHK=~pYUG;YhfL%x0RJ9R{hMs4X_b5!DiS(n$o}Xu?vDB zCAAf|ZN%9QJB)i*o_?@WJ8|E|^=^n{r$i{}@3EE9_QF2c4+r2N`~rvIS2zqu;3yn} z<8T5_!YMe7Zf9)ew6n-Rhc4$y_X5b+)qVnZB=3-KU6B!Eyz z2tG&zi6IFjg=CN%Qb0;b1*stoq=j^l9x^~i$OM@o3uJ|CkR5VBPRIqhArIt*e2^c) zpa2wvLQoirKv5_L#i0b0gm8#}QcxPoKv^gU<)H#pgi25usz6n!29Z!5YCuh>1+}9w zPm5U>>Op;I01crLG=?V76q-SEXaOyu6|{yn&=%T3d*}cip%Zk5F3=UaL3ii@J)sx$ zhCa|2`aypf00UtV42B^v6o$cY7y%<;6pV&3Fc!wac$feaVG>M^R>^oar(lt#B z+BhG(l;QxTWV9y@gDPlKqgB+V!E~4bGhr6YhB+`7=D~be01IIeEQTep6qb?Rau#l^ z03W-cEWlkb(pVWy#?7muPgUHi8g8r5%j|1c!`=LbmUi|$-#)9kH_i1(+8@T8u&;r& zunyM4&uq?+ymZy7YXgWYbFgWmWNaY)jmX{vn_&xVg>A4McEC>91-l8m2U&YzAMA$% za1egM?-2Zo{V*JXqi_tj<8T5_!YMcny=ddkpxasO=a79KWCijC;#`DFTwjjnR#)IE zT!ZUy18%}C{BINP4uq4JyU3Au@^4(Sw&)wJI+AHx%P3V*;ecn&Y%CGlUu zYjk?U^;>ucf5LnC03YEm_ynIx{|hkqr{pD}Lwv@G0_^m!?Tq`_8QTXd*dQ9%!GWI> zT;L|G2RAQ7=Q)4E7C7>t2B1EN(<>=0%I)`S(}`ma2X&YVKc!ZUQn4a zvp`nJ2H7D8;^eW%)AHIKDxbZkmfv2BesL}8aV_d`EiKIMQ3VJi_3^Y` zn?68o{AwG11qoXSzr^$x%x|(fS`2pl(R0VYu2$GykM9ZEJklx(#mH-MC;=rQoVXDn z{bP||3VUfNgI`&D9jzQXmABXDo1#84>m!qP(B6PCng&=KaNUqJXcq}z2}Fm=m{p)E zRKqV4vpUqU%lug*t){&(&tqfaH#X$eB0ZT?N~bm9d#nlWO>nQJnR%#&8TRJT!jLEXLzqLsF6ERNT0#zJ1+BryPDn|o4YY-J&>lK~q}h@C+6jF+Q;uEi zEi@Jun4@6~eq&)TyEI+E8wefD^Ag4(XFN=>x6&pOW`w<+R@Bm3n?%}^Npp%__F{L? zasqEH;yKh*${;SfoAVgv+^p<74Wa)#4O!E_%4BaXcG)956LS`N&xScL7ro}eeB2kn zLVJ5{kzMBZ&H07JcIj`+x4!I0XYV9&mfAaL%V0UI;GV3schpv)%WC{&uJ$L)HLw=9 zb;w)~Kf?yxHe$-Y`aK}?t}-`zka^%MtaYeh=|tIfB7dF8pIdE0{$|2&vAem?Znf1& z%dNKIzMV4K0XtzAVRpkF*bDpYA!@%}cDS-$hcsm#>>zpk#omQ>z^V@6_A4BQBZNN+ z$Lw8=ch_;;PQXbx1*h>VKzW|QJZqN`9+^Lresp)E9-Jf0dHm!XG6vx;*n1dZF5-U4 z-qWZPm+`;C^;NhA@||)Wz2#kcm}hSy<9&PCO)GWm2L7GcRT~ZHaTxVO)}TsQxz9I| zb&LGpwx`$b*!xg-duxFKZMD0^`_0}L8FF1f-Lv=m&fY&N9A!akS5zB-TnRVutNVT8 z``EE7>B^ea2VBeA%!indpeXTv$9zosUUq^9sr>4RJ->Pif50<%4lnG3@f(cpgGuAt zc+N}8Ka8EgHlUaEFMj6!!Kv&NP7m~=eh3qj93|#?dW9aZ;SE%v%-^C@HOfZTHNV5{ zPk0X>;3ND6vVOV=dH96=Gf2PX3nr5wN^@|+3Iu=!0wD;jV1sBNdll`N6)_zgf8qoe zaYM9Wn%g1kw1zWII2^r)|BK$N!6E&B+xy@_hUjMQeMm-~GRw?MTGIYTcgPsQ2=0@4 zZb+~r8Koe*rALz1NYave;V)+kPm+uijY5vNn`7-E4(cZO*j+7ikp3|?nYWekoS5V# zmP2M+Bu==BjZQK~?_(FXgnz)ji-SHAFD_x@L43zJ(lFZ`b1xC!D7c3@#v8ht>!wBC z1mrS4L403So_y@)rkjEv-!Zr)hO#`P@^nSA%iFKJtdZ}@{g!e_8Za5T5=ZVc<8zKF zXeieb#-9gMhV;dfIHnr;Ns3O%$h*vMrwW*cj8K&vw-k`lF`e)9>6F0qulFofl#Zz} z(?D7<=eH#-S(iFPOXo1posl`*Kd2As3FBi2IwFlc$$Vi3+)TaczmR?=$P8H^D`a!b zGVWb=$87YJu`s^v>HEoAiD1$YICX?DGqfDY^53(Z*hMGNGZ#pIH3{v9soNZMo37=? zT}}|nLppgKbB+5U`vYYDHw!zVJ?ezYM;KG4|5-A1&yRZ;6o9$ND2Q1Ir0p(Dy(r?C zZ?uy|u@{5lPy$LqI7C1x#{y&AMDkx69prw9o@MYe-w*P>n6H&ZuIM0ZL1fQ=ImbfA zm?#_Sf~lM6TTPXxVC6nnAbv$?&-{5M;#LM(hug#$!&>z9*^%^oQSYxYL5q!gDr*?! zzDS)*VBEhYUv-qUq&#JfZWZKL1(|n}vo2&Ev8)-chFc`@symj_rknRx>Xg|IeJeY& zuE;%+d@ZA_BoF4Ery9tp2_4W`!X>4CM{)vz6T9dj^IwwF`nf<|pr1@ipQsO;@dMtMtJl|4P}96uY+)n3Ah9_`74l)JP~ z9Z07mbi%DOd64j392@ZYrb}1+yFqv80X-daxPNnaw&tM!oWDI=QU`jWi}@^xt{t^t zIl5$gIm24%l zk?m0ZNl(UYg99R1mt%eh4RFYuEqkPqJJ7L7OQtpvXA^OxkF-fk!IM46(2+4w@-qa6 z!Z6A}=ADLP9|0p_6i7KqnU2ODgZefGb1aO5@h|}cj{ObI^6JV~aMA{LVLYAr51$3$V+#knH1=xw(a0&qdxMWG#jzuoRZz zz8qG-N>~M};U~vd>Wl16mi(Q;wpCk$yY#izVy;8K&d6JjJ(v@Qq@MnaeFJQSO~~F1 zTVN~5y7z6E+hGUnB+M?@4SQg(W1E(X(>oY_h$?egA8$TeQvdc5NA>{h=N=q@gD{x( z_ZQ4Vl)X7{lq3Rg!$I6K-NQeg#CATjQxorpEH=a{sW%D zbH`3<swej5K zVeR>K`e1(&|2^&>qU3!v!tA1*|8Z`?ToWMQtg`PUh4vS5r7vX8#nMl7>_+x(Ty~@5 zPVKYt%*!4W(N*;1oo?U5yJZhy_7KKg6D@vU9D8|>?ZtgB?$T%Qw?}yL!73lE(pJlT z)}5?zcbe^q1$&@#A8q?S;_f4Es0t!%6`otGlQoPyLuOk{ztp*(GL$w}+6A-xqB-5l z?)1kwzcFO`979!2lIU_aiu>ba!-8K z!RS*M@lXEUjayhH;8aw8&2OZo$V)`J=DwiQUv-oGCZ;Tspkq?_dzp!xGqSdTJh8`; zx+?FrWQ0o&DIg`Jg4B=((n7kZdmwG9na{IEpH|9V(yOAMqfUM+N2z1!jeMNvUFI)8 z#?_FM5%)}x8M#>?D`bQ0kOOi;F31geATQ*D{LTweX-FPq-yD5LL$8ZGGpsR#XkeZ< z$=oq<3P$N&MZfevgt`1bgpt#V{P{88b0euCQV*mL?K4g?l0Jd>nfrkk@BvW>UFKu< z(dCpQ8QWkEBdY9*P!>hG7h{6ho94Vuxr)D8u0Bpf3i{i%gq5B&cam{=e_c1*q6)~a2$i5RRDr6HS>0vb&|P%7 zi!OJyYEEfe7;i+L^ogny#_Z#9J{tC#&fm0J_*Fos+UQY-kK($x*Ms`FHvl;wVm|e< zA!Xdic~@)fyr(sB-qD&m?`xSkL5dkW(z>rTGtznxCC_YMr7R>psq5qT29}{p#3TlK)odWa>qKh%%6K2U_FS2HHY9XpdeU(6b}* zIzeaLxfsDgJ)sx$#;p(ZC0-;aU-feqLVx!E1U#Y+6w>5dS$1P|jp~991SywBb&3 zZANS6*hi4Rk%X82&M3^$QE@wv&KQvKM49g%D|Q%<{{-}(NIbK=o@$fOeKPJoPU@OM zKBvMouBT(pfSE80X2Tqq>wLzO#kzlxGcjt=X4P~&k8+dmYkxhH)4rI4lAz5MDw zk8(BJ+*jnC=g|3@GBf4L7{UVQ8{(PI@IvQXo;ULhJ=x>nrF~vRSuQ3oK28mjaXeYE zAmdUpMzsXlOO3qziQhYIne&~t99Fsnxjx`0uGhd?Sm*p;$P+)2+md;5 z^Nb29n~(p+PfjVL?}=VNJ3rBue;eDDQ&={j>qd}sU)xbu^OW#k%Kz3n&$$E`~l;>{3`#2Fz#y0ohz85(KX@4m{UH0tm z!%fC^-Abd!EZ;4%XT-lxMAv29Wxw;OIzW2AM;RNwc!YOB}TLCoWuV-T!4#k$r;3xOkW2mZ|vq- zp_iRDog$&FiKdgJy28J!aFI6p8giseuM=O+o4tW~6Qtdf`<1|AM~*|?qMqJ%IyfE6 z+@mAk{8Dam_KC=9#q}M`yTtts?!g0O+!qrPSe)qpkMU3P`4B%jE9enr<26o}J+e_%c%owDfmZLYvW`7_@~_!s!Ugjety-Z;HRIg~@sUd9P^>|>%{ zT(Sq_UPQfh7FF+@A$p(+)+2Z){Yjkn@BuzLW01DE%Q`Oh|DfY1+&^Q=xb+uI&S9o( zB}}ZZGT4-_G?&?j(Ot38?VmEt_&!d<<6UT^8$cW%C*zs2;(c|u81C`EUI!Z23BFzj zacy;le!Z5t2p^~DnfKdAT{YV>8{wiEaT9S5B~8X%T~fZBCxEV@#M?-Hm%i{B+FBn^ zU?PMh*TR&OcrJ+KL_Sk)62o-6l2V_n%0qlFL?=uzW(dT9m|Vw#*boQeLOfS8<9@i= zI1t~J9K9Jg!XAMc9FW3zj>In%q|cuaQ_d3bxl&TT{&76?!Y>hiiCw9XL0=Hra>htf zS8C+T89!oAW9XUGB_{&X2Slgju5^@%{~0mc#1yXdyFyeJ$cnsdgvky$ASdK<<>Pya^CoE9b90>s@T}%y{Tf0en1o+r+?qgBkUcDtuIyuJ#&vVTv_Ni4Xa(|)YmIvw>}{bPw1*D3 zb%ajP8KgYB5VtFIgYLM=UYQ=)dqOX+dqW@S3;m!!41j^IOlXyfCN&dv%G4eFEC@4*S z%(1epM*SUSYr=iYqL0RJ49J-rV=>3Ucvn(wf-9>&(Upy7N5*sb)*zp?(L&C@lkb#C zuIxNJre6{6^<;FL0@(s`;2x@`x^n6<@h?o9It}+QPQsLT-gM;8fSIn`NM(K#`)rs) zn7J?y<{RPj&`#!|Z1SM5^u2i=X+O+9x2ccMkrx?x36nP}4D%DTH4;X?K*Km`GlbJP z7g@6F3&_htbap#(=!-~C_Ipd7$E#+*j z6@;A*D`6F^hM!;!tc7*39)5-m$dNj^5jir((p3x7Cw}cS7SJ~#ce6|Ojm!RVGi(^? zNgqYN{k9Nq9{JgdDPvCCFt;Of2grBjPOf*sZjiD2J(zo8A1q_Mem~{`I0(PMA&|K- znKP4i`B$zFga15*BiN6^F*uI?C*UNUg41vY&cZqTWxwTl>=)o7T!L@&ede6rW!$d7 zRk#M%;Rd?PT;MCXiTxI`Zo?h?zMmJo%k^(?5AMSQcnFW+cX$kPW{2FbC)l6DAMgz1 zOz`K(egU#C=OyMV++V{Rcnj~~PmnXj-(y}xmjBF$4_tpF&R-zwP(N|~8NPsQ!qPy8 z0I)zH1c4Q75Do0$04KP>?Pd)Rc-;k5bO^>R1Y)>luehAy;Z`x-5h|8DRK?nC^4u(-XOK>xUiwGad@+iQNVD zByRTVLNfPwmE1i`rGS*Ak;+|2PmL+#)pq(pGJhjys&wYrNJBbl(O2g2(qT$Hmiv|- zdj`k|nb1kbYBOVIfvj}svSDV29FUXi;DEwlV&ZXxeZeGaeE~4jm%Xw=> z^)S*a00rF>RVGzTpN}pHX1t8Nxl1dtQWVImfgpW-%xZC7>jPLj;rpAMs0L zmVvU6h-?435#_ip4;7#yRD#M-1*$?d^piFq5>v*>s$neP!;d3HGMY%#h2sGVxj%Y03OFb30u3vlJ(^zh5CXY5!#p zsIX)PotBW+kW5wm+kdXia?SceKH53++g&J#>JM&;~PT zhg(hz4o6malq_>CL{CGWG5^6kAp-vh{N)`b=ZZ*L;#W#{andlWNbxJq`>BN9i##Q! zAK07trcN?;VN-o5qrRlo53|3!G%`yQue2d^0C5Hy>G2)zE~9hiF@9wXzsZCd9OWnS zhQLtrFbsx+tlQ{`%n?R?W-I}FVe|_Fd2fv(%xL#1`b6@Mm2Y<0zb<9Tw>YxK@;r?r z%y{C-`m_l=FB9Em(a)_Wq1R-X0`eUAIJtkSyBzO1kyT!w<}R;KC;SZjXCiAB%;tIy z%tgjL%=xeY7Q!NT1${9rfu&q8bH~$`lkN&wiLB(vq(?=*9cq=khPE1h!fy?7*TOpR zug_YK{bz9_pFR10-GF@~Y=X_O1!Ui_tkK(weVe zVJ^rTu6>yM;ecD#{)M!8LFOTlcb3d&|BC%E9D$>745W;Y zV{IUQ>;$QfTXo}ppC;`yjdgh zhj{MM_BQqF4&230`fS0RiYJjqIdfLcHTi%h2=fx;{!6*A1BRTs)hpayQ_gRY zUl{jf^h?b=H#ho&Z@=nTi@sVdWY$8a%;7ZCix9tpMSc&cx&DrDQU-+$`SRNhtouiH zFZ6kj`4oS*yt4@NfwVrl$7n#yp~Ve|0un%elATkLUh<9GCS-99(Y!>5qANUIRU5*++6RcM$M35tWYV zeiZ#fIF;N1taQiEEbAcRJ*S+l$dWcy^7Wo;8`sf1ZK;oK3E$R`#nM=w3z5UpDC|z+ zx{P@K@Y060B1Sc0hIqWOqQe|Gu)uKd2*l?x4r^nEm!R#EXlpc<{o}iTf^oe81x!-_x18 zBPo8A;`JVau#hEC$*ch%<(s$Cnxur_d8*p(w9t( z&fTkaj-_dP|*7PMj29bu`xta3-xD8$Zz@CH|>EzV}jN z$~po`Ck@CmRhaj(eB-C(Ivu2k43H5rL1xGTSs@!_M~57q!K#uPq;h(?)Bks(rtg-kiA7*|CBVGY02!)_96oH~p3>}MOmVlBV{Wm!yFC2RWex;x^ zl!3BP4)^l#kbXo3t}9}%1oBN>nd>T06{OEojdF~H>Ri_#jF&hyF>7&M8|pw^%CjES zhs>N+)`0vq^hh6w?{C6NKddp~nqY5=*$lHew1Ae-3R*)O;lMA))6{EXOH~; z3VjybyFxeU4zdTY2mVR)A)K%zQE%*hpfAX8fJj@>4|^u= zWq-^8Fp#i&xtD{m55_Lz05;m=A>?1$wxuu>_j+n5ho})@9EF;C~lmU#dSMv0MDL7 zEhOwBkp9j7Ja5I^#&u`%xg8zkJf|I)J8|EI`)-dpcO!G{ zdprY;_takeM5qi_t4<9Ceub^?1Dp0kt0KLw|`J_AzM`_hj)i`zNEo`(zAsr$P5US%wY z>q~GMuHb*w(@(#K{W|s=a1&%K{ubtKxP#vVWX@1Ssb`W$v#jpo{u}r7o@W^2OT)+}{%R9sKDTu2-^-(%*YV>sk2K40d^urko!vznT%DJ{awl{~ML_xoBIYuXlhk z7 z0WU;{UH}flwet&5b z!};A8Q|E-p{PueaX4~(>EfFM!B;LF#DI`N)atPv`ngUav=q9 zAoNTJ>A^p5CC?pel#TnD0e3IqrEi&$JY+&fX2{|lXFO|Jv3EzuV1B_QP$g2?2ru8@ z+40Ze9jniFO`vYcFPco?{+a!xoXE*VxZK|He0NHi@p>Mw{NjnM*q=x^nK7deNtoO8 z?WAwji&0^|>hPb0zuarL%I9^f{N4$A7;*}r$5lL9Fx*oR`R06&8FzvugzpM-%q}^< z=TgWUp$Z#%@=o@Ct3yR8uVPRfKY6Z7(HAb^y+~RPRg#I)aQvihZKM838AWhi3Z#r> zj6=o?N~4FIL0bm1ER=)tPys4JIKRr1j4{$m-cVIJN}fNxD)@`6s+iRv5~@QDs0p>8 zHq?Q-P!H-u184}1pfNOorqB$ULknmLt)Mlufws^N+LNyi-pQ2hWXg7ORN0z!t|R(& z0$I1(nKJ1DU7;I9@(d=|r|8|iQ@QU`i940J@=e2DA>wq^9y4;lZ|z8U+N)leayD~s z((D6$xp)1%@{2aph&%0Ty2e@^%2%F=7S`!J>(lhWfV`@|cLudg>@weA`m;8i_UL;z z`US`yNLoIA9mfnWap@z#VDIc7!kg|Aehz)xzsoZHzLz%#mz5+{tU8)dlyH=H)S?O z<0h1lj1~ISk{@J$^Isa3XX;c`9Jx2K0_0bOBu}Qi5u`EFyZi?^rn{uE;$L+%{rx(w z{O*3Q`j`8?`Um-D-bDUS-|1u4k5S$=Kgby6UHgL!f1MfST}PWHd7__Z)S>lXucbfY z^sz>L-^i6IZ(LM(IYUAGq}(}q=>PHG{5AdY zhCW-qUQaNtw|>1g_1pIKTIQBG3qMM}SsoM7LF7z=$uPyc!+qQ*`rpSY-_F$M;xk%5XL^=MYxf z)w!7SK=hpt{yMS%`$F6o(Y`E(C9o8h!E#uE-%40TxYbvp#iZX53#nUCI% liTaA>PVGPk>9^hHT`-ychm5DmnLazc#mW{fOt>HZ{tvP`kpKVy literal 0 HcmV?d00001 diff --git a/tests/test_bpathlib.py b/tests/test_bpathlib.py index c91c83b..b6fcb4f 100644 --- a/tests/test_bpathlib.py +++ b/tests/test_bpathlib.py @@ -1,3 +1,4 @@ +from pathlib import Path import unittest from blender_asset_tracer.bpathlib import BlendPath @@ -52,3 +53,29 @@ class BlendPathTest(unittest.TestCase): self.assertEqual(b'/root/and/parent.blend', b'/root/and' / BlendPath(b'parent.blend')) with self.assertRaises(ValueError): b'/root/and' / BlendPath(b'/parent.blend') + + def test_mkrelative(self): + self.assertEqual(b'//asset.png', BlendPath.mkrelative( + Path('/path/to/asset.png'), + Path('/path/to/bfile.blend'), + )) + self.assertEqual(b'//to/asset.png', BlendPath.mkrelative( + Path('/path/to/asset.png'), + Path('/path/bfile.blend'), + )) + self.assertEqual(b'//../of/asset.png', BlendPath.mkrelative( + Path('/path/of/asset.png'), + Path('/path/to/bfile.blend'), + )) + self.assertEqual(b'//../../path/of/asset.png', BlendPath.mkrelative( + Path('/path/of/asset.png'), + Path('/some/weird/bfile.blend'), + )) + self.assertEqual(b'//very/very/very/very/very/deep/asset.png', BlendPath.mkrelative( + Path('/path/to/very/very/very/very/very/deep/asset.png'), + Path('/path/to/bfile.blend'), + )) + self.assertEqual(b'//../../../../../../../../shallow/asset.png', BlendPath.mkrelative( + Path('/shallow/asset.png'), + Path('/path/to/very/very/very/very/very/deep/bfile.blend'), + )) diff --git a/tests/test_tracer.py b/tests/test_tracer.py index 5e05da2..e32394a 100644 --- a/tests/test_tracer.py +++ b/tests/test_tracer.py @@ -212,6 +212,14 @@ class DepsTest(AbstractTracerTest): # b'//textures/Textures/Buildings/buildings_roof_04-color.png', False), }) + def test_usage_abspath(self): + deps = [dep for dep in tracer.deps(self.blendfiles / 'doubly_linked.blend') + if dep.asset_path == b'//material_textures.blend'] + usage = deps[0] + + expect = self.blendfiles / 'material_textures.blend' + self.assertEqual(expect, usage.abspath) + def test_sim_data(self): self.assert_deps('T53562/bam_pack_bug.blend', { b'OBEmitter.modifiers[0]': Expect(