From 6ed8500c544445908ba0d639a2aec212733b4fa0 Mon Sep 17 00:00:00 2001 From: hsorby Date: Fri, 14 May 2021 10:07:58 +1200 Subject: [PATCH 01/15] Update internal plugins to work with QtWidgets PySide2. Add changes for creating an application on Windows. --- .gitignore | 1 + docs/manual/MAP-install-setup.rst | 20 +++++++++++++++++--- res/pyinstaller/create_application.py | 8 ++++++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index a976da0c..bddaa796 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ parts/ sdist/ var/ #package/ # We are using this name in the source hopefully doesn't come back to bite us. +package/*.exe *.egg-info/ .installed.cfg *.egg diff --git a/docs/manual/MAP-install-setup.rst b/docs/manual/MAP-install-setup.rst index 5ca80d3c..ac10cdb0 100644 --- a/docs/manual/MAP-install-setup.rst +++ b/docs/manual/MAP-install-setup.rst @@ -4,11 +4,15 @@ MAP Client Installation and Setup Guide ======================================= -This document describes how to install and setup the MAP Client software for use on your machine. The MAP Client software is a Python application that uses the PySide Qt library bindings. +This document describes how to install and setup the MAP Client software for use on your machine. +The MAP Client software is a Python application that uses the PySide Qt library bindings. -The `Installation`_ section details getting the MAP Client and it's dependencies installed on your system. There are two main ways of getting the MAP Client installed on your operating system. This document will cover both of those methods. For users and plugin developers the suggested method is to `Install Using Pip`_, for developers of the MAP Client framework the suggested method is to `Install Using Bazaar`_. +The `Installation`_ section details getting the MAP Client and it's dependencies installed on your system. +There are two main ways of getting the MAP Client installed on your operating system. This document will cover both of those methods. +For users and plugin developers the suggested method is to `Install Using Pip`_, for developers of the MAP Client framework the suggested method is to `Install Using Bazaar`_. -The `Install Using Pip`_ method is covered first followed by the instructions on how to `Install Using Bazaar`_. For most operating systems Python is already installed but for some, most notably Windows based operating systems, it is not. For instructions on installing Python for Windows based operating systems see the `Installing Python on Windows`_ section. +The `Install Using Pip`_ method is covered first followed by the instructions on how to `Install Using Pre-Built Binary`_. +For most operating systems Python is already installed but for some, most notably Windows based operating systems, it is not. For instructions on installing Python for Windows based operating systems see the `Installing Python on Windows`_ section. The `Setup`_ section details getting the MAP Client setup with external plugins. @@ -16,6 +20,16 @@ The `Setup`_ section details getting the MAP Client setup with external plugins. Installation ------------ +Install Using Pre-Built Binary +------------------------------ + +For both Windows and macOS there are installer applications available from: + + https://github.com/MusculoskeletalAtlasProject/mapclient/releases/download/v0.15.0.rc.2/MAP-Client-0.15.0.exe + +Download and install the package. + + Install Using Pip ================= diff --git a/res/pyinstaller/create_application.py b/res/pyinstaller/create_application.py index 4be04178..9eb4c5df 100644 --- a/res/pyinstaller/create_application.py +++ b/res/pyinstaller/create_application.py @@ -10,7 +10,8 @@ run_command = [ '../../src/mapclient/application.py', - '-n', 'MAPClient', + '-n', 'MAP-Client', + # '--debug', 'noarchive', '--windowed', '--noconfirm', '--hidden-import', 'scipy', @@ -19,7 +20,7 @@ '--hidden-import', 'mapclientplugins', '--hidden-import', 'opencmiss.utils', '--hidden-import', 'opencmiss.zincwidgets', - f'--additional-hooks-dir=hooks', + '--additional-hooks-dir=hooks', ] @@ -38,6 +39,9 @@ run_command.append(f'--add-binary={rel_rcc_exe}:PySide2/') run_command.append(f'--add-binary={rel_uic_exe}:PySide2/') +elif platform.system() == "Windows": + win_icon = os.path.join('..', 'win', 'MAP-Client.ico') + run_command.append(f'--icon={win_icon}') print('Running command: ', run_command) PyInstaller.__main__.run(run_command) From 65c1e5b8c2d00e557f481cc536c80ef7c7e78770 Mon Sep 17 00:00:00 2001 From: hsorby Date: Thu, 20 May 2021 10:57:23 +1200 Subject: [PATCH 02/15] QPen is part of QtGui not QtWidgets. --- src/mapclient/view/workflow/workflowgraphicsitems.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mapclient/view/workflow/workflowgraphicsitems.py b/src/mapclient/view/workflow/workflowgraphicsitems.py index bdec7512..cf83017c 100644 --- a/src/mapclient/view/workflow/workflowgraphicsitems.py +++ b/src/mapclient/view/workflow/workflowgraphicsitems.py @@ -75,7 +75,7 @@ def paint(self, painter, option, widget): if line.length() == 0.0: return - painter.setPen(QtWidgets.QPen(QtCore.Qt.black, 1, QtCore.Qt.DashLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)) + painter.setPen(QtGui.QPen(QtCore.Qt.black, 1, QtCore.Qt.DashLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin)) painter.drawLine(line) painter.drawPixmap(midPoint.x() - 8, midPoint.y() - 8, self._pixmap) From c2cac6d5e04cdf1a14da71bd40d1c28904cc5457 Mon Sep 17 00:00:00 2001 From: hsorby Date: Thu, 20 May 2021 10:59:00 +1200 Subject: [PATCH 03/15] Ignore .dmg files under macos directories. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index bddaa796..37601892 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ sdist/ var/ #package/ # We are using this name in the source hopefully doesn't come back to bite us. package/*.exe +macos/*.dmg *.egg-info/ .installed.cfg *.egg From fb549fd4bd204dfa6de43a852648266b28260478 Mon Sep 17 00:00:00 2001 From: hsorby Date: Thu, 20 May 2021 11:01:01 +1200 Subject: [PATCH 04/15] Add create installer script for macOS with background image. --- res/macos/create_installer.sh | 16 ++++++++++++++++ res/macos/map-client-dmg-background.png | Bin 0 -> 76427 bytes 2 files changed, 16 insertions(+) create mode 100755 res/macos/create_installer.sh create mode 100644 res/macos/map-client-dmg-background.png diff --git a/res/macos/create_installer.sh b/res/macos/create_installer.sh new file mode 100755 index 00000000..9877ba70 --- /dev/null +++ b/res/macos/create_installer.sh @@ -0,0 +1,16 @@ +#!/bin/sh +version=0.15.0 +test -f MAP-Client-$version.dmg && rm MAP-Client-$version.dmg +# --volicon "application_icon.icns" \ +create-dmg \ + --volname "MAP-Client-$version" \ + --background "map-client-dmg-background.png" \ + --window-pos 200 120 \ + --window-size 800 400 \ + --icon-size 100 \ + --icon "MAP-Client.app" 200 190 \ + --hide-extension "MAP-Client.app" \ + --app-drop-link 600 185 \ + "MAP-Client-$version.dmg" \ + "../pyinstaller/dist/" + diff --git a/res/macos/map-client-dmg-background.png b/res/macos/map-client-dmg-background.png new file mode 100644 index 0000000000000000000000000000000000000000..3d4197682dc69b4c83890c63d2ac29ba183d2dd1 GIT binary patch literal 76427 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 ap)DUpR0J6j^Id0*iOIf0dvo^Kh5j4kVbG}n literal 0 HcmV?d00001 From 952ae0763e83aca972b66fd47793ea63a37f1d4f Mon Sep 17 00:00:00 2001 From: hsorby Date: Thu, 20 May 2021 11:05:51 +1200 Subject: [PATCH 05/15] Be more precise about what to ignore. --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 37601892..ba76a0ab 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,7 @@ sdist/ var/ #package/ # We are using this name in the source hopefully doesn't come back to bite us. package/*.exe -macos/*.dmg +res/macos/*.dmg *.egg-info/ .installed.cfg *.egg From e469de601cfd5c381e8a2ce29b16be5e45982117 Mon Sep 17 00:00:00 2001 From: hsorby Date: Thu, 20 May 2021 11:25:11 +1200 Subject: [PATCH 06/15] Don't make show_options_dialog method private. --- src/mapclient/application.py | 4 +++- src/mapclient/view/mainwindow.py | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/mapclient/application.py b/src/mapclient/application.py index 9eaf497e..19248054 100755 --- a/src/mapclient/application.py +++ b/src/mapclient/application.py @@ -120,11 +120,13 @@ def windows_main(app_args): window.setup_application() if not window.check_application_setup(): - window._show_options_dialog(current_tab=1) + window.show_options_dialog(current_tab=1) window.load_packages() window.load_plugins() + # Determine if we are in internal workflow mode. + if app_args.workflow: window.open_workflow(app_args.workflow) diff --git a/src/mapclient/view/mainwindow.py b/src/mapclient/view/mainwindow.py index 5d1dcc4e..5e3989b4 100644 --- a/src/mapclient/view/mainwindow.py +++ b/src/mapclient/view/mainwindow.py @@ -191,7 +191,7 @@ def _make_connections(self): self._action_Quit.triggered.connect(self.quit_application) self._action_About.triggered.connect(self.about) self._action_LogInformation.triggered.connect(self._show_log_information_dialog) - self._action_Options.triggered.connect(self._show_options_dialog) + self._action_Options.triggered.connect(self.show_options_dialog) self._action_PluginManager.triggered.connect(self._show_plugin_manager_dialog) self._action_PackageManager.triggered.connect(self._show_package_manager_dialog) self._action_PluginWizard.triggered.connect(self._show_plugin_wizard_dialog) @@ -305,7 +305,7 @@ def _show_log_information_dialog(self): dlg.setModal(True) dlg.exec_() - def _show_options_dialog(self, current_tab=0): + def show_options_dialog(self, current_tab=0): from mapclient.view.managers.options.optionsdialog import OptionsDialog om = self._model.optionsManager() From 32518120392fe16b9a2646bec72111d30db1bb24 Mon Sep 17 00:00:00 2001 From: hsorby Date: Thu, 20 May 2021 12:57:21 +1200 Subject: [PATCH 07/15] Ignore internal_workflow.zip archive. --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ba76a0ab..4f1beb72 100644 --- a/.gitignore +++ b/.gitignore @@ -68,4 +68,5 @@ target/ # Intellij projects .idea/ - +# Internal workflow zip +internal_workflow.zip From d3b39da5a660d2a94166c7c2a29665328d9f6e8a Mon Sep 17 00:00:00 2001 From: hsorby Date: Tue, 25 May 2021 11:22:35 +1200 Subject: [PATCH 08/15] Add in an internal workflow with some management for creating a workflow. --- src/mapclient/application.py | 48 +++++++++++++++++-- src/mapclient/core/managers/optionsmanager.py | 23 ++++----- src/mapclient/core/utils.py | 2 +- src/mapclient/settings/definitions.py | 6 +++ src/mapclient/settings/general.py | 6 +++ 5 files changed, 70 insertions(+), 15 deletions(-) diff --git a/src/mapclient/application.py b/src/mapclient/application.py index 19248054..8186339b 100755 --- a/src/mapclient/application.py +++ b/src/mapclient/application.py @@ -26,18 +26,22 @@ import locale import logging +import zipfile from logging import handlers +from mapclient.core.utils import is_frozen, find_file +from mapclient.settings.definitions import INTERNAL_WORKFLOW_ZIP, INTERNAL_WORKFLOW_AVAILABLE, INTERNAL_WORKFLOW_DIR, UNSET_FLAG + os.environ['ETS_TOOLKIT'] = 'qt4' # With PEP366 we need to conditionally import the settings module based on # whether we are executing the file directly of indirectly. This is my # workaround. if __package__: from .settings import info - from .settings.general import get_log_location + from .settings.general import get_log_location, get_default_internal_workflow_dir else: from mapclient.settings import info - from mapclient.settings.general import get_log_location + from mapclient.settings.general import get_log_location, get_default_internal_workflow_dir logger = logging.getLogger('mapclient.application') @@ -125,7 +129,45 @@ def windows_main(app_args): window.load_packages() window.load_plugins() - # Determine if we are in internal workflow mode. + # Determine if we have an internal workflow. + if is_frozen(): + internal_workflow_zip = os.path.join(sys._MEIPASS, INTERNAL_WORKFLOW_ZIP) + else: + file_dir = os.path.dirname(os.path.abspath(__file__)) + internal_workflow_zip = os.path.realpath(os.path.join(file_dir, '..', INTERNAL_WORKFLOW_ZIP)) + + if os.path.isfile(internal_workflow_zip): + # We have an internal workflow set the option as active. + om = model.optionsManager() + om.setOption(INTERNAL_WORKFLOW_AVAILABLE, True) + + # Work out internal workflow directory and create if it doesn't exist. + internal_workflow_dir = om.getOption(INTERNAL_WORKFLOW_DIR) + if internal_workflow_dir == UNSET_FLAG or not os.path.isdir(internal_workflow_dir): + internal_workflow_dir = get_default_internal_workflow_dir() + if not os.path.isdir(internal_workflow_dir): + logger.info(f"Creating internal workflow(s) directory '{internal_workflow_dir}'") + os.mkdir(internal_workflow_dir) + + om.setOption(INTERNAL_WORKFLOW_DIR, internal_workflow_dir) + + # Test if a workflow is present. + workflow_file = find_file('.workflow.conf', internal_workflow_dir) + if workflow_file is None: + # No workflow exists in the workflow directory so we will + # unzip the stored workflow(s) into this location. + logger.info("Decompressing internal workflow(s) ...") + archive = zipfile.ZipFile(internal_workflow_zip) + archive.extractall(f"{internal_workflow_dir}") + + # Should definitely have a workflow now. + workflow_file = find_file('.workflow.conf', internal_workflow_dir) + default_workflow_directory = os.path.dirname(workflow_file) + + # Set workflow to internal workflow if None is currently present. + if app_args.workflow is None: + app_args.workflow = default_workflow_directory + logger.info("Loading internal default workflow.") if app_args.workflow: window.open_workflow(app_args.workflow) diff --git a/src/mapclient/core/managers/optionsmanager.py b/src/mapclient/core/managers/optionsmanager.py index 57b449fa..614756b4 100644 --- a/src/mapclient/core/managers/optionsmanager.py +++ b/src/mapclient/core/managers/optionsmanager.py @@ -5,26 +5,29 @@ """ from mapclient.core.utils import which from mapclient.settings.general import get_virtualenv_directory -from mapclient.settings.definitions import SHOW_STEP_NAMES, INTERNAL_EXE, \ - DONT_CREATE_VIRTUAL_ENV, OPTIONS_SETTINGS_TAG, \ +from mapclient.settings.definitions import SHOW_STEP_NAMES, INTERNAL_EXE, UNSET_FLAG, \ + DONT_CREATE_VIRTUAL_ENV, OPTIONS_SETTINGS_TAG, INTERNAL_WORKFLOW_AVAILABLE, INTERNAL_WORKFLOW_DIR, \ VIRTUAL_ENV_PATH, GIT_EXE, PYSIDE_UIC_EXE, PYSIDE_RCC_EXE, PREVIOUS_PW_WRITE_STEP_LOCATION, \ PREVIOUS_PW_ICON_LOCATION, CHECK_TOOLS_ON_STARTUP, USE_EXTERNAL_GIT, USE_EXTERNAL_RCC, USE_EXTERNAL_UIC def _is_boolean(option): - return option in [SHOW_STEP_NAMES, CHECK_TOOLS_ON_STARTUP, DONT_CREATE_VIRTUAL_ENV, USE_EXTERNAL_GIT, USE_EXTERNAL_RCC, USE_EXTERNAL_UIC] + return option in [SHOW_STEP_NAMES, CHECK_TOOLS_ON_STARTUP, DONT_CREATE_VIRTUAL_ENV, + USE_EXTERNAL_GIT, USE_EXTERNAL_RCC, USE_EXTERNAL_UIC, INTERNAL_WORKFLOW_AVAILABLE] class OptionsManager(object): def __init__(self): - self._options = {SHOW_STEP_NAMES: True, DONT_CREATE_VIRTUAL_ENV: False, CHECK_TOOLS_ON_STARTUP: True, - USE_EXTERNAL_GIT: False, USE_EXTERNAL_RCC: False, USE_EXTERNAL_UIC: False, - VIRTUAL_ENV_PATH: get_virtualenv_directory(), GIT_EXE: which('git'), - PYSIDE_RCC_EXE: INTERNAL_EXE, PYSIDE_UIC_EXE: INTERNAL_EXE, - - PREVIOUS_PW_WRITE_STEP_LOCATION: '', PREVIOUS_PW_ICON_LOCATION: ''} # Set default values + self._options = { + SHOW_STEP_NAMES: True, DONT_CREATE_VIRTUAL_ENV: False, CHECK_TOOLS_ON_STARTUP: True, + USE_EXTERNAL_GIT: False, USE_EXTERNAL_RCC: False, USE_EXTERNAL_UIC: False, + VIRTUAL_ENV_PATH: get_virtualenv_directory(), GIT_EXE: which('git'), + PYSIDE_RCC_EXE: INTERNAL_EXE, PYSIDE_UIC_EXE: INTERNAL_EXE, + PREVIOUS_PW_WRITE_STEP_LOCATION: '', PREVIOUS_PW_ICON_LOCATION: '', + INTERNAL_WORKFLOW_AVAILABLE: False, INTERNAL_WORKFLOW_DIR: UNSET_FLAG, + } def getOptions(self): return self._options @@ -56,5 +59,3 @@ def readSettings(self, settings): else: self._options[option] = settings.value(option) settings.endGroup() - - diff --git a/src/mapclient/core/utils.py b/src/mapclient/core/utils.py index 1fa74fba..2445f3c3 100644 --- a/src/mapclient/core/utils.py +++ b/src/mapclient/core/utils.py @@ -29,7 +29,7 @@ def is_frozen(): - return getattr(sys, 'frozen', False) # new py2exe + return getattr(sys, 'frozen', False) def convertExceptionToMessage(e): diff --git a/src/mapclient/settings/definitions.py b/src/mapclient/settings/definitions.py index 74ab63a0..6a63fd92 100644 --- a/src/mapclient/settings/definitions.py +++ b/src/mapclient/settings/definitions.py @@ -52,4 +52,10 @@ PREVIOUS_PW_WRITE_STEP_LOCATION = 'previous_write_step_location' PREVIOUS_PW_ICON_LOCATION = 'previous_icon_location' +UNSET_FLAG = '' INTERNAL_EXE = '' + +INTERNAL_WORKFLOWS_DIR = 'MAPClient-Workflows' +INTERNAL_WORKFLOW_ZIP = 'internal_workflow.zip' +INTERNAL_WORKFLOW_AVAILABLE = 'internal_workflow_available' +INTERNAL_WORKFLOW_DIR = 'internal_workflow_directory' diff --git a/src/mapclient/settings/general.py b/src/mapclient/settings/general.py index b17a0fd8..3d2c85ee 100644 --- a/src/mapclient/settings/general.py +++ b/src/mapclient/settings/general.py @@ -18,8 +18,10 @@ along with MAP Client. If not, see .. """ import os +import tempfile from PySide2 import QtCore +from mapclient.settings.definitions import INTERNAL_WORKFLOWS_DIR from mapclient.settings.info import VERSION_STRING @@ -50,6 +52,10 @@ def get_virtualenv_directory(): return _get_app_directory('venv_' + VERSION_STRING) +def get_default_internal_workflow_dir(): + return os.path.join(tempfile.gettempdir(), INTERNAL_WORKFLOWS_DIR) + + def get_virtualenv_site_packages_directory(virtualenv_dir): print('Confirm path on other OSes, so far only checked on Windows.') return os.path.join(virtualenv_dir, 'Lib', 'site-packages') From 3e0adaf87d7efb51bdac9e2016b1091082e6ccb9 Mon Sep 17 00:00:00 2001 From: hsorby Date: Tue, 25 May 2021 11:51:58 +1200 Subject: [PATCH 09/15] Add option in OptionDialog to manage internal workflow directory. --- src/mapclient/application.py | 35 +++++--- src/mapclient/settings/definitions.py | 2 +- .../view/managers/options/optionsdialog.py | 18 ++++- .../view/managers/options/qt/optionsdialog.ui | 81 +++++++++++++------ .../managers/options/ui/ui_optionsdialog.py | 56 ++++++++++--- 5 files changed, 138 insertions(+), 54 deletions(-) diff --git a/src/mapclient/application.py b/src/mapclient/application.py index 8186339b..5433743b 100755 --- a/src/mapclient/application.py +++ b/src/mapclient/application.py @@ -129,6 +129,22 @@ def windows_main(app_args): window.load_packages() window.load_plugins() + prepare_internal_workflow(app_args, model) + + if app_args.workflow: + window.open_workflow(app_args.workflow) + + if app_args.execute: + wm = model.workflowManager() + if wm.canExecute(): + window.execute() + else: + logger.error('Could not execute workflow.') + + return app.exec_() + + +def prepare_internal_workflow(app_args, model): # Determine if we have an internal workflow. if is_frozen(): internal_workflow_zip = os.path.join(sys._MEIPASS, INTERNAL_WORKFLOW_ZIP) @@ -136,9 +152,9 @@ def windows_main(app_args): file_dir = os.path.dirname(os.path.abspath(__file__)) internal_workflow_zip = os.path.realpath(os.path.join(file_dir, '..', INTERNAL_WORKFLOW_ZIP)) + om = model.optionsManager() if os.path.isfile(internal_workflow_zip): # We have an internal workflow set the option as active. - om = model.optionsManager() om.setOption(INTERNAL_WORKFLOW_AVAILABLE, True) # Work out internal workflow directory and create if it doesn't exist. @@ -168,18 +184,8 @@ def windows_main(app_args): if app_args.workflow is None: app_args.workflow = default_workflow_directory logger.info("Loading internal default workflow.") - - if app_args.workflow: - window.open_workflow(app_args.workflow) - - if app_args.execute: - wm = model.workflowManager() - if wm.canExecute(): - window.execute() - else: - logger.error('Could not execute workflow.') - - return app.exec_() + else: + om.setOption(INTERNAL_WORKFLOW_AVAILABLE, False) class ConsumeOutput(object): @@ -216,6 +222,9 @@ def non_gui_main(app_args): pam.load() pm.load() + + prepare_internal_workflow(app_args, model) + try: wm.load(app_args.workflow) except Exception: diff --git a/src/mapclient/settings/definitions.py b/src/mapclient/settings/definitions.py index 6a63fd92..1197ced5 100644 --- a/src/mapclient/settings/definitions.py +++ b/src/mapclient/settings/definitions.py @@ -58,4 +58,4 @@ INTERNAL_WORKFLOWS_DIR = 'MAPClient-Workflows' INTERNAL_WORKFLOW_ZIP = 'internal_workflow.zip' INTERNAL_WORKFLOW_AVAILABLE = 'internal_workflow_available' -INTERNAL_WORKFLOW_DIR = 'internal_workflow_directory' +INTERNAL_WORKFLOW_DIR = 'lineEditInternalWorkflowDirectory' diff --git a/src/mapclient/view/managers/options/optionsdialog.py b/src/mapclient/view/managers/options/optionsdialog.py index 6da5d653..3a36d603 100644 --- a/src/mapclient/view/managers/options/optionsdialog.py +++ b/src/mapclient/view/managers/options/optionsdialog.py @@ -12,7 +12,7 @@ from mapclient.core.checks import WizardToolChecks, VCSChecks from mapclient.view.syntaxhighlighter import SyntaxHighlighter from mapclient.settings.definitions import VIRTUAL_ENVIRONMENT_STRING, \ - WIZARD_TOOL_STRING, PMR_TOOL_STRING + WIZARD_TOOL_STRING, PMR_TOOL_STRING, INTERNAL_WORKFLOW_AVAILABLE class OptionsDialog(QtWidgets.QDialog): @@ -46,6 +46,7 @@ def _make_connections(self): self._ui.checkBoxUseExternalGit.clicked.connect(self._use_external_star_clicked) self._ui.checkBoxUseExternalPySideRCC.clicked.connect(self._use_external_star_clicked) self._ui.checkBoxUseExternalPySideUIC.clicked.connect(self._use_external_star_clicked) + self._ui.pushButtonInternalWorkflowDirectory.clicked.connect(self._internal_workflow_directory_button_clicked) def _update_ui(self): self._ui.lineEditGitExecutable.setEnabled(self._ui.checkBoxUseExternalGit.isChecked()) @@ -54,6 +55,15 @@ def _update_ui(self): self._ui.pushButtonPySideRCC.setEnabled(self._ui.checkBoxUseExternalPySideRCC.isChecked()) self._ui.lineEditPySideUIC.setEnabled(self._ui.checkBoxUseExternalPySideUIC.isChecked()) self._ui.pushButtonPySideUIC.setEnabled(self._ui.checkBoxUseExternalPySideUIC.isChecked()) + if INTERNAL_WORKFLOW_AVAILABLE in self._original_options: + self._ui.groupBoxInternalWorkflowDirectory.setVisible(self._original_options[INTERNAL_WORKFLOW_AVAILABLE]) + + def _internal_workflow_directory_button_clicked(self): + directory = QtWidgets.QFileDialog.getExistingDirectory(self, caption='Select internal workflow directory', + dir=self._location) + if directory: + self._ui.lineEditInternalWorkflowDirectory.setText(directory) + self._location = directory def _pyside_rcc_button_clicked(self): rcc_program, _ = QtWidgets.QFileDialog.getOpenFileName(self, caption='Select PySide Resource Compiler', @@ -135,6 +145,7 @@ def load(self, options): pysidercc_option = self._ui.lineEditPySideRCC.objectName() pysideuic_option = self._ui.lineEditPySideUIC.objectName() vcs_option = self._ui.lineEditGitExecutable.objectName() + internal_directory_option = self._ui.lineEditInternalWorkflowDirectory.objectName() if step_name_option in options: self._ui.checkBoxShowStepNames.setChecked(options[step_name_option]) if check_tools_option in options: @@ -151,6 +162,8 @@ def load(self, options): self._ui.lineEditPySideUIC.setText(options[pysideuic_option]) if vcs_option in options: self._ui.lineEditGitExecutable.setText(options[vcs_option]) + if internal_directory_option in options: + self._ui.lineEditInternalWorkflowDirectory.setText(options[internal_directory_option]) self._update_ui() self._test_tools() @@ -163,7 +176,8 @@ def save(self): self._ui.checkBoxUseExternalPySideUIC.objectName(): self._ui.checkBoxUseExternalPySideUIC.isChecked(), self._ui.lineEditPySideRCC.objectName(): self._ui.lineEditPySideRCC.text(), self._ui.lineEditPySideUIC.objectName(): self._ui.lineEditPySideUIC.text(), - self._ui.lineEditGitExecutable.objectName(): self._ui.lineEditGitExecutable.text()} + self._ui.lineEditGitExecutable.objectName(): self._ui.lineEditGitExecutable.text(), + self._ui.lineEditInternalWorkflowDirectory.objectName(): self._ui.lineEditInternalWorkflowDirectory.text()} return options diff --git a/src/mapclient/view/managers/options/qt/optionsdialog.ui b/src/mapclient/view/managers/options/qt/optionsdialog.ui index 2f8013df..97c32bca 100644 --- a/src/mapclient/view/managers/options/qt/optionsdialog.ui +++ b/src/mapclient/view/managers/options/qt/optionsdialog.ui @@ -6,8 +6,8 @@ 0 0 - 525 - 579 + 581 + 637 @@ -27,14 +27,65 @@ - 1 + 0 &General - - + + + + + + + + + + + Check tools on application start + + + true + + + + + + + Show step names + + + true + + + + + + + + + + Internal workflow directory + + + + + + + + + Select the internal workflow directory. + + + ... + + + + + + + Qt::Vertical @@ -47,26 +98,6 @@ - - - - Show step names - - - true - - - - - - - Check tools on application start - - - true - - - diff --git a/src/mapclient/view/managers/options/ui/ui_optionsdialog.py b/src/mapclient/view/managers/options/ui/ui_optionsdialog.py index 7419de77..bf1cfb57 100644 --- a/src/mapclient/view/managers/options/ui/ui_optionsdialog.py +++ b/src/mapclient/view/managers/options/ui/ui_optionsdialog.py @@ -17,7 +17,7 @@ class Ui_OptionsDialog(object): def setupUi(self, OptionsDialog): if not OptionsDialog.objectName(): OptionsDialog.setObjectName(u"OptionsDialog") - OptionsDialog.resize(525, 579) + OptionsDialog.resize(581, 637) self.gridLayout = QGridLayout(OptionsDialog) self.gridLayout.setObjectName(u"gridLayout") self.buttonBox = QDialogButtonBox(OptionsDialog) @@ -31,23 +31,47 @@ def setupUi(self, OptionsDialog): self.tabWidget.setObjectName(u"tabWidget") self.tabGeneral = QWidget() self.tabGeneral.setObjectName(u"tabGeneral") - self.gridLayout_3 = QGridLayout(self.tabGeneral) - self.gridLayout_3.setObjectName(u"gridLayout_3") - self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + self.verticalLayout_4 = QVBoxLayout(self.tabGeneral) + self.verticalLayout_4.setObjectName(u"verticalLayout_4") + self.groupBox = QGroupBox(self.tabGeneral) + self.groupBox.setObjectName(u"groupBox") + self.verticalLayout_6 = QVBoxLayout(self.groupBox) + self.verticalLayout_6.setObjectName(u"verticalLayout_6") + self.checkBoxCheckToolsOnStartup = QCheckBox(self.groupBox) + self.checkBoxCheckToolsOnStartup.setObjectName(u"checkBoxCheckToolsOnStartup") + self.checkBoxCheckToolsOnStartup.setChecked(True) - self.gridLayout_3.addItem(self.verticalSpacer, 2, 1, 1, 1) + self.verticalLayout_6.addWidget(self.checkBoxCheckToolsOnStartup) - self.checkBoxShowStepNames = QCheckBox(self.tabGeneral) + self.checkBoxShowStepNames = QCheckBox(self.groupBox) self.checkBoxShowStepNames.setObjectName(u"checkBoxShowStepNames") self.checkBoxShowStepNames.setChecked(True) - self.gridLayout_3.addWidget(self.checkBoxShowStepNames, 0, 0, 1, 1) + self.verticalLayout_6.addWidget(self.checkBoxShowStepNames) - self.checkBoxCheckToolsOnStartup = QCheckBox(self.tabGeneral) - self.checkBoxCheckToolsOnStartup.setObjectName(u"checkBoxCheckToolsOnStartup") - self.checkBoxCheckToolsOnStartup.setChecked(True) - self.gridLayout_3.addWidget(self.checkBoxCheckToolsOnStartup, 1, 0, 1, 1) + self.verticalLayout_4.addWidget(self.groupBox) + + self.groupBoxInternalWorkflowDirectory = QGroupBox(self.tabGeneral) + self.groupBoxInternalWorkflowDirectory.setObjectName(u"groupBoxInternalWorkflowDirectory") + self.horizontalLayout_4 = QHBoxLayout(self.groupBoxInternalWorkflowDirectory) + self.horizontalLayout_4.setObjectName(u"horizontalLayout_4") + self.lineEditInternalWorkflowDirectory = QLineEdit(self.groupBoxInternalWorkflowDirectory) + self.lineEditInternalWorkflowDirectory.setObjectName(u"lineEditInternalWorkflowDirectory") + + self.horizontalLayout_4.addWidget(self.lineEditInternalWorkflowDirectory) + + self.pushButtonInternalWorkflowDirectory = QPushButton(self.groupBoxInternalWorkflowDirectory) + self.pushButtonInternalWorkflowDirectory.setObjectName(u"pushButtonInternalWorkflowDirectory") + + self.horizontalLayout_4.addWidget(self.pushButtonInternalWorkflowDirectory) + + + self.verticalLayout_4.addWidget(self.groupBoxInternalWorkflowDirectory) + + self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + + self.verticalLayout_4.addItem(self.verticalSpacer) self.tabWidget.addTab(self.tabGeneral, "") self.tabToolSettings = QWidget() @@ -192,7 +216,7 @@ def setupUi(self, OptionsDialog): self.buttonBox.accepted.connect(OptionsDialog.accept) self.buttonBox.rejected.connect(OptionsDialog.reject) - self.tabWidget.setCurrentIndex(1) + self.tabWidget.setCurrentIndex(0) QMetaObject.connectSlotsByName(OptionsDialog) @@ -200,8 +224,14 @@ def setupUi(self, OptionsDialog): def retranslateUi(self, OptionsDialog): OptionsDialog.setWindowTitle(QCoreApplication.translate("OptionsDialog", u"Options", None)) - self.checkBoxShowStepNames.setText(QCoreApplication.translate("OptionsDialog", u"Show step names", None)) + self.groupBox.setTitle("") self.checkBoxCheckToolsOnStartup.setText(QCoreApplication.translate("OptionsDialog", u"Check tools on application start", None)) + self.checkBoxShowStepNames.setText(QCoreApplication.translate("OptionsDialog", u"Show step names", None)) + self.groupBoxInternalWorkflowDirectory.setTitle(QCoreApplication.translate("OptionsDialog", u"Internal workflow directory", None)) +#if QT_CONFIG(tooltip) + self.pushButtonInternalWorkflowDirectory.setToolTip(QCoreApplication.translate("OptionsDialog", u"Select the internal workflow directory.", None)) +#endif // QT_CONFIG(tooltip) + self.pushButtonInternalWorkflowDirectory.setText(QCoreApplication.translate("OptionsDialog", u"...", None)) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabGeneral), QCoreApplication.translate("OptionsDialog", u"&General", None)) self.groupBoxStepWizard.setTitle(QCoreApplication.translate("OptionsDialog", u"Step Wizard", None)) self.checkBoxUseExternalPySideRCC.setText(QCoreApplication.translate("OptionsDialog", u"Use external PySide resource compiler (rcc)", None)) From 85214844265dd69b49fea5fd8fec95c9247852a5 Mon Sep 17 00:00:00 2001 From: hsorby Date: Tue, 25 May 2021 11:59:36 +1200 Subject: [PATCH 10/15] Tidy up use of prepare_internal_workflow. --- src/mapclient/application.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/mapclient/application.py b/src/mapclient/application.py index 5433743b..7bbc3f6c 100755 --- a/src/mapclient/application.py +++ b/src/mapclient/application.py @@ -129,7 +129,8 @@ def windows_main(app_args): window.load_packages() window.load_plugins() - prepare_internal_workflow(app_args, model) + om = model.optionsManager() + prepare_internal_workflow(app_args, om) if app_args.workflow: window.open_workflow(app_args.workflow) @@ -144,7 +145,7 @@ def windows_main(app_args): return app.exec_() -def prepare_internal_workflow(app_args, model): +def prepare_internal_workflow(app_args, om): # Determine if we have an internal workflow. if is_frozen(): internal_workflow_zip = os.path.join(sys._MEIPASS, INTERNAL_WORKFLOW_ZIP) @@ -152,7 +153,6 @@ def prepare_internal_workflow(app_args, model): file_dir = os.path.dirname(os.path.abspath(__file__)) internal_workflow_zip = os.path.realpath(os.path.join(file_dir, '..', INTERNAL_WORKFLOW_ZIP)) - om = model.optionsManager() if os.path.isfile(internal_workflow_zip): # We have an internal workflow set the option as active. om.setOption(INTERNAL_WORKFLOW_AVAILABLE, True) @@ -219,11 +219,12 @@ def non_gui_main(app_args): wm = model.workflowManager() pm = model.pluginManager() pam = model.package_manager() + om = model.optionsManager() pam.load() pm.load() - prepare_internal_workflow(app_args, model) + prepare_internal_workflow(app_args, om) try: wm.load(app_args.workflow) From d901dab8a1625e24c1fdeaa48e14f39bd6055401 Mon Sep 17 00:00:00 2001 From: hsorby Date: Tue, 25 May 2021 12:00:57 +1200 Subject: [PATCH 11/15] Rename non_gui_main to sans_gui_main. --- src/mapclient/application.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mapclient/application.py b/src/mapclient/application.py index 7bbc3f6c..5bf6162c 100755 --- a/src/mapclient/application.py +++ b/src/mapclient/application.py @@ -196,7 +196,7 @@ def write(self, message): self.messages.append(message) -def non_gui_main(app_args): +def sans_gui_main(app_args): locale.setlocale(locale.LC_ALL, '') from PySide2 import QtGui @@ -256,7 +256,7 @@ def main(): sys.exit(-2) if args.headless and args.workflow: - sys.exit(non_gui_main(args)) + sys.exit(sans_gui_main(args)) else: sys.exit(windows_main(args)) From d7d0b5421b8d7550e6fa6c00900b7beac64ad9bd Mon Sep 17 00:00:00 2001 From: hsorby Date: Thu, 27 May 2021 11:52:12 +1200 Subject: [PATCH 12/15] Correct setup for plugin wizard to use long_description_content_type. --- .../hooks/hook-mapclientplugins.py | 17 +++++++- .../tools/pluginwizard/skeletonstrings.py | 40 ++++++++++--------- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/res/pyinstaller/hooks/hook-mapclientplugins.py b/res/pyinstaller/hooks/hook-mapclientplugins.py index 3364c346..33e939e8 100644 --- a/res/pyinstaller/hooks/hook-mapclientplugins.py +++ b/res/pyinstaller/hooks/hook-mapclientplugins.py @@ -1,4 +1,17 @@ -from PyInstaller.utils.hooks import collect_data_files +import os +from PyInstaller.utils.hooks import collect_data_files, collect_submodules, get_package_paths +import mapclientplugins + +print("==================================") +print(mapclientplugins.__path__) +# hidden = [] +# for p in mapclientplugins.__path__: +# d = os.path.dirname(p) +# print(collect_submodules('mapclientplugins')) +# print(get_package_paths('mapclientplugins')) +# print(collect_data_files('mapclientplugins', include_py_files=True, excludes=['__pycache__'])) +print("==================================") datas = collect_data_files('mapclientplugins', include_py_files=True, excludes=['__pycache__']) -hiddenimports = ['imghdr'] +# hiddenimports = ['imghdr', 'mapclientplugins', 'mapclientplugins.datatrimmerstep'] +# hiddenimports = (['mapclientplugins']) diff --git a/src/mapclient/tools/pluginwizard/skeletonstrings.py b/src/mapclient/tools/pluginwizard/skeletonstrings.py index 8f0b72aa..e5334723 100644 --- a/src/mapclient/tools/pluginwizard/skeletonstrings.py +++ b/src/mapclient/tools/pluginwizard/skeletonstrings.py @@ -338,16 +338,17 @@ def validate(self): SETUP_DIR = os.path.dirname(os.path.abspath(__file__)) + # List all of your Python package dependencies in the # requirements.txt file - def readfile(filename, split=False): with io.open(filename, encoding="utf-8") as stream: if split: return stream.read().split("\\n") return stream.read() + readme = readfile("README.rst", split=True)[3:] # skip title # For requirements not hosted on PyPi place listings # into the 'requirements.txt' file. @@ -365,24 +366,25 @@ def run(self): setup(name=%(name)r, - version=%(version)r, - description=%(description)r, - long_description='\\n'.join(readme) + source_license, - classifiers=[ - "Development Status :: 3 - Alpha", - "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python", - ], - cmdclass={'install': InstallCommand,}, - author=%(author)r, - author_email=%(author_email)r, - url=%(url)r, - packages=find_packages(exclude=['ez_setup',]), - namespace_packages=%(namespace_packages)r, - include_package_data=True, - zip_safe=False, - install_requires=requires, - ) + version=%(version)r, + description=%(description)r, + long_description='\\n'.join(readme) + source_license, + long_description_content_type='text/x-rst', + classifiers=[ + "Development Status :: 3 - Alpha", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", + ], + cmdclass={'install': InstallCommand,}, + author=%(author)r, + author_email=%(author_email)r, + url=%(url)r, + packages=find_packages(exclude=['ez_setup',]), + namespace_packages=%(namespace_packages)r, + include_package_data=True, + zip_safe=False, + install_requires=requires, +) """ From 3abb1b6e0170e36beba65f176a14948c4508fb19 Mon Sep 17 00:00:00 2001 From: hsorby Date: Fri, 28 May 2021 08:49:05 +1200 Subject: [PATCH 13/15] Improve creation of macOS binary. Update skeleton strings for setup.py. Add setup.plugins.py file for adding mapclientplugins dir to namespace path of python environment. --- res/macos/MAP-Client.icns | Bin 0 -> 72816 bytes res/pyinstaller/create_application.py | 11 +- .../hooks/hook-mapclientplugins.py | 20 +- .../tools/pluginwizard/skeletonstrings.py | 227 ++---------------- src/setup.plugins.py | 45 ++++ 5 files changed, 81 insertions(+), 222 deletions(-) create mode 100644 res/macos/MAP-Client.icns create mode 100644 src/setup.plugins.py diff --git a/res/macos/MAP-Client.icns b/res/macos/MAP-Client.icns new file mode 100644 index 0000000000000000000000000000000000000000..e66bceb83f3cbd3d1af859539c8ce8266f4e4a17 GIT binary patch literal 72816 zcmZ6y1B@?BtOxpEnf{vTG?_GM2JJs1 z8%F>Tj@>^a2G0MuIRF5Fu}~l&fQ1f){tu&=I=S0f*fA0OhXMb`<^SXVqlfm-+}HsC z0R9jD*Fhm5{znG@Z)9ub0QA2Q;lGi{$k@ab0Q$c&5C8=5KQsT+f&X{ie=_#{f98yS z<$o0cO#h?xf9C!N{%`yL$)FHGK>siODgj{rQvw2jfr0{nezgI}0s;~e3jbgFH3pCZ zfP@`P44h1i2@Kr{jze^p zGS3E)cw=74J>b=OLFt#b`&>R+-5I?O5VMzi>A|1HLolRewEkkj_*yYHc&_M?ekc!| zfp2J`G@8yd1%8VfWt!!M)wCdzjEpxdFaeY?*JqzJa29na$rr>Y@X*HJj0bzV9FM`n zACQC=;k7vRbF%2BF8q3^6cK{T#`N=O!4C3}(V0?Z6hZG<4vLLysF)d z3j$MW_g~)2YNl>V>UT|}7>)6WGx?^3pn}=E&ZV>QjKo*xuo~C0*zS5SA+gmNA8%WI zE3vCD`qDUi!!8lucYdnRJ>T6pr4Q3`4jVPbg$@P)nNfoybM!?OVakjBjc0Y7hib^M zXh4x5ir+!qIR@qsJ!BAqL7_D{r597_W1Te2^ubUCc#jOn949DZ``o>WJUpkH|3TbC z)9KHsmcq+H{Z}E>r(gy{&~OwD?}a*Tslq3@6N6pCz&u*Ugw>CgQ(^&&rYBQ4TbW>I zdl40>ETS(3T8NUg_R3lR7p&^o;EEKDN_cAwxXl7qR#*b!Ug)e>H}JAS=IYjqXzaaa zORZtwmTZjE=PXr^w8OU28Etphdku+s!VXGrE=8X0Se=8)DG|(kc$sdegpHS6nm3dr=&o1Hezp5l+;rFrLujp$aDkNih@5rig7L0+iTbjPk2j(gK>oiLh6o zuf+wKAmkG5B^I_CLJHp$kmjKcC5pE|cxg*!{DOF@4G_Z0--M&!?Jkn~whRwQa(6xU z5T>LNCD8f++qlCSUntq6JLTp(cCs7lz(Iivw%BnLH~vmpZ#jx-*KQX{TfJcovLKG^z8`g`DQ zrt(tWol~)fwHJYE$jr#Cf0tcj_;_MSgARF9196*-E)~6nt-Uory7h2vJ|ky#sjWrU zjfXg%E|);>Fv2iJ3O#s6!MWe#8UJxX<@{hXL^%EXF4aK|djp8DYABwn)F;1JgCL*+ zVxk?{{JZ?vDx<@f;8wtN#DfGcFJkIWc37(mFLYi{!2zkt>K!tNts}(=-@#K@Kbery zHqoC0$8Ns~Ufmqkh=4$J(~AobF?71ln?UWOWp(0}(ttY9s^C`;(dfx{e`&ABWrdny zY?NI@ct==(^ZD1q-~xsIXXEwqiu61|(GjJ(8WnA548K!rH*|I&CO4R$pNqzWPLsdw zM-~_7>NFs-798NoGRf{tc|WM6NHS+6_}K&Lw5d`waJQrZ)mCBWzRU(@-q|2XpEA|7 zYMnWW;WjH8IuR0w@~o45wS#$ir3K!%O(@(1jfjG_C8D3dCw+idL#k!`1=plzrkAL7 zdkl(i+*L_Vn2l8GIy10Z$#uF37IRo}8e29g9Bpgk>o?5~|0NRR?h7`X8~@pQ8-kuX6El81IO@=!mkW0 zmdM((tpzK^vf~%6Nl{5BC+5?-h(H$_{fZnR>03z4~YWL{=4%*Cs!`TQvT z7MPu7i=h?h?I&2>ToQA$d|AQrk8SeKjbHo}9>#p{pLZM=<`~O0G)ZcwznBY*NxVGe z5LI#2Bt{U1+dl*0*D#Kg1}4^d7Ma?llc?q1GCWla_D&^`#$@dYjb%|OHfwN>gZ(AT z1d<@n`+7NQ>x8vm^|uaHMz1QeeSB9|jw0KHc~ZPpo{G^6vwL@y8s#g`ndzH{_iySP zrj%B{5?!3dJ#WQi{P>{Wn7BxdC7uNfr-x4qE+N11{t=ez;vGEjOGyyKnf^B1B;`g?Q3HgXbzgLi(65A zOI(Q-6xn_r={0e!YD9E-w=|`IY8=1!IAX;S$xgC5`Op@~=Na4$p7)@AQA!|b_$kfl zSNrqz!!8j2e|}puuWi>H3B`bf+hX`?PUX@5M6kud4)OMH z_po=H(LZ^6BBBaRu%7%-*Zzfnp|xI)jIXsHOG7Ts~Uk@_X|JArm>kO_SM|FQ&N?UzG$jBq56m5Pc&xY4J^0UoC;AA*slf@ z`7YR0>rCnzmp|2>%>w3%+q?Ze$*mNv+$Rdqjj=GSMd~Ps7rD20v#L*hxuS_65oH+4 z7zI2OI_h#QUacB%Jw7@rXyP0_Y8Xbak;K91Y7(hAk5cUL)GQkis!{y#m{ zi_sa}zz&>cpwq%;h%W))>P{+WEDf|d0w7aNU{2EYzaBR+^m(MT=CgyuIx@N42_YEN z4kR?2dlIp1#%Ov2bl2(-Grs;x5k$Y5{G+RBOsA(aK=`1AQhqwY2x`LIXEElGR6xD1Rxa4{Rk))V@_CJU4hc{9=&T%!Px_QG>Aj`XOb zcK_bQ+B_37J$%^q5+z>EMf=(5g!Jz^;>O}diSy7jhE&@{x$~hFC=Xa>uu;ZDmca)6 z1iHdccc|?Ju;fBPwCFxJ;0zJ$3opg2<|V%coouS+e`OYOya_1x11Cd1lyrZr@7W6_ zIuRLv##C`~;m_7$$Q-wCeScu<*v#pfiT;{x_9}Qqip0|~LxsYB48(UwH6dpb{^EI| zM(>+`glb^@b^Qw~cI)2R9pXPT2V?1|T7HqOAy#{Gjj?0@FDa)MdpC!Zt!GujEPmb9 zWSOPD_LFKktypILJFd*q2SWbi$3fsq{*%g|9{-+Lhx!lwa-;%&H`dM*qI7{X+{8X% z3$qC(N_llq*c6jH>0j)(xmM{E!#syP>Lo-n^T$(9%D%49kq}qXG{kLYF(s>R7ik!F z^hnz_zZ8Zj?*>mhP!pCz>0+zT^xC+XG-D^^uEVvU0zTrHbmT(I%T8-V3t?yUJgpb0 zx=1BG@kaQ6l^s~X1yONFULOIt{p-E>MoRRW3X~1L~>}(-7-w(F*w|WwuAz?h4uKJT^6i*X&zu)vxFcOzPmY-vx8Za?Lp3vvnb9C{EFML-rx}I10#YmGpSa={QhiSh5z~-1XhZ32cb<|r z8LVltBhz=!=9hfq+pSCx_Z)U!L|Fvsfmi_?6~+~Ch~h+)+z z)iaUVA`lxKG)w>*!xX5Z~3r;op|BPBC4wa`!2Mq(-}Pj-RRB+O+GP6 zC9LZXKFp35WV$&*5=D;2%olRjIAJVuuQs|&l6&WXILw3qm;|NppFLi1J_GDuPqqH0 zaXWOunI6z{jS&SA;uh6glnX5*U5xs6)qNerQoZ-azLD5T2d0;T9v|0Yr(3lm$cxl|*2OGh))Wz!3M7Y@i#)1F?LW<@GNO&X0S=Lc`MYEL;edS5 zv;h%s*dd`>gXlJIHtQ8}q`5|goULA<*gkFAR%*%V8O>NUP(tG3O#VY>K24)s=FQag7hp!EC*KPv6Pbq^ETo>b5R;FA0B>c z4_Q3ZbLgOmf8F(h7khVdpcw6vAR%zA1nrm?Kl|=s0seEC8nhea`CIM#jdKWDA>)$T zFLDbt`${r>{0$NtFQN24lI4

7pxs|&xMJ*;Kl7#_H~hXJ96S2|mKS6hw z6MKtQQ6XFa{%4gSPcWoAHZgQxcE%mJI@5W~8wjhlq~ZMNr$n*4V6!1vg6oX9lmR;+ z7BPhG4>_F*;ag1h!)`q7XpJZS4Mwt>vmyOpsBbr7C(=(L_cCgmP=b;$=YFA1w6bYN z@d3-AG4$QPuW2m%G3lVppez&l5h`9$pkN!f9qbP*P<41WWs~|fkk~)1q z0`r}9E#=y73^vZ+T_L%Hu3(<>bSQHdejyx zFtK{iT@)J5x>#~Wr?ge^zNsl|5kebbQ4d3ptzwZjiS4FMy&{v(e)-LzyQ^48BeutQ z^AQZ8B^;0=1L|^ipR8doDP*9JFNQMX6gy5U=;>OcB>XSi9LY8oLE6*BH?Vq2nJsmi zD;F`_QII7p^a{Ckw!&gc^2rKhmYPs?yKXbqetycXVC#HTR z=i|g(WM>F@ucE?%5qS9G95=HKn2cZl%9rxalC#J#UG(kFJ^1o;dQkgapM6U^CT{ z887ZX(RznPX0dT)C?mZOVXQ`ROYNvV?R!m-Ma$i+1p^Jut(cK>$u$&ol)_qNPz`Xk zr+cl}=ZS>MwuYfSyw)ye{G!`*kMf5E zNp@T)G}-GRMA&PcILn579Oznu&5bq!-v0!!rvDj3k>m$Qv>)FAy4(1AH=)M)aWXE( z$#emWQGI*|(iE33%AjqRg+zFs&}(_shG_{0;JuvRsES}-{bZEXY65W}ah$P>Ib zyo^ywyC!K;=z0GyhFMaednMyNI}-xe%!i@d4TjoM`|9g|t+v!-BsA z`V2Ir*9F5?GoIamgXpwnw$5SgD*A(*EooYF4cSSGjj&4P>sWZNxZHHP{UkU`En^{* zQFL~VI%dD|p-2yW7xymGoe_^+DlD~?4Mm;JA+}$+z@dRtxbBV*YY+;!d3_HQje9X4317=?GaKOkddTJ@gXSdY31(nm ziJn#sB+L&$)~8;`R9(8drbR?LY%)fnSH&XSFPq+jf|jM&jOnep7j*mdkLQcXpg(0=U1Kw z!*9K(bn%>Juu@x_50k?}_bAbfss8J;#cNq2do>M0PoR<{BuYEK7IoJ{r9Aesen|v1 zWOy|4XDr*sR2rN@gzarKtV;D53@(C=v;kUL60yw}3&XMNbk)Wf;ZBqqcFNs>nUxEL zjr!?;+|C058z-;n(PWax6X?4Evm>WU62NM_E6y2YSf@{;r}jMZ7Q12IfTLNWQ9|XB z9ye~GqW7eJWy?YExz2-!q5^hl7tOzmRy`0^6z|zXJP{~p`h?gj^Tq7%c7hyFP;Ceq z-C}D2txid;H*-BLV2#{T;{CSPVrym5wbbh!RbW%$W^<-~khyIDKRZ}c{^q=lAF8-l zV~FXv3N_73=SsndaD3}bJs=#z5IexW?bn$f1<92u?Y4;jw)iXKY_>F*I?Tk($DPz~ zfu(6KUbPZ*hTG;i-5#xPf`biMC;Rw%@%2qq9F|PXl#Lc3%GY&YizX(dZ$K8BMH$?p z36zk#r(>HGyP#b4bL&H|$N4VnEe~*6z;6$MOl|d=Bp44BtgZPgy8mk2(69uSkza98 zX^f@-H^w5|K6n(3A{An!`H(MaFS78?VKMW9?9Q4x=}NvGl4qBTa=bN&MqA62QhSdh zcrQYQGiCLkTgtVPCD+p_=D%YvUwIo28`~F#U?I0}YythHo)SIn!rN*SLa#sZ5C%6P zaEJJFz1B_EoV@ssLt^O)UpNU)24L4JFmH-AcVE2LdVDbsfj&&=!TQ>wF`Qi+Z~7Cm zclc0xWe~dEZ?B55dDX|EKFXY}H9CApKFnjyu1*+6EY%xczIpk$cE#H@14Z7+*#7ofZ$t=E#;gB zyhjv$u#}AiwP^Ec?n8Q~FzF`pZ6c$f)yJvQZ_P;kl7c(hL28GTPaJy(f$Bm80w4i0&}k_>Y)c*KX^sQdE z3yzI1a>3{fD_FR!3(6PyCTS!~CrGMN)vlJ%K>;iQA&5)9D0eUN%fC#R;STYfZnUcl zElf@Qf}du>7);}r9T$^^G?js~m7$}Z)$VIlV7$|Nvhqse^CpW z+wE|6u$7XMHWlU9!w?1;B1VV)jO=&uS1fmEp%iKHB9 zu>Bg%q=mpkh1`n#2L4Fp8w1_myYQcJQRFfMIgQo$NMHJ|aW;igP!!Sa24wXaF-=Ub z9XJvSV7|X5-|Wccwz@h{qV${A(@+UpE}r~Dj;8sn8Y9k32+31K?Ah1Bp@BEk)_V-axvKjuEl0qtFR(=OI>Fi^n!r`RLig^Ev-9wUJSaDVlAq z>notCn_&uqPobgo6;v3P`+(U+^-g>{A(gCzHd*OojqPoRYQy5p!C_xe=TqDYqHt~- z)nLX82N2Wkux|r?afc$22!pt zdjgJ<){Fr>j8mlqV=?wz$v*ouX@TO2sILsgEdzxEJJ#8SV}bFWGxO|p`D}#%5r-}f zlvUUu`L>ZLfZ}j#AA6~6Bg3s2#qhipzpZ-}x-9!cU3I#V%kqa#?e7_ry9nNTd^}0^ zxtf2|DTL?*hAh*DSza>9Im{@@X!vvirD1AiW^W3gZlQ4A!aEDfW1SluK?0wGtQB~4kufm%=C|ehm zUE1Xv)%om{ksYiKwe1ELpw~<038}=7Lzm%h(q)lYsYxWoc*QO26c>dez?pm`8r~e6blneGRlxORWSyNLyk8Y> zJuv%tT1!rw!kq#E>zG7ybhb_dMd%qF!!gx)$*a$EOLsxe9GEs^9C5*b?=VAB>`lNs2XmyaYu2e(n& zj|9`_f!VfJ)pKn+Xo>E>CcZMCKx7qkI$~62G6Rx*BJ5mhI1oq&^~d4X+4 zpIF7XLr*BR>4Cw%ox0mZ{{m#x20qx~r!MG(WuBC5N9!bNnD+>w+1SsKt3L$V$W+h| zsXU&RB8wLT$H$p=;Erq#(3;6Xq7Jb&UH2T0?Eoe-JL<3dC+)uk5$w$K4It}>ac6@J z=xGxMsAOOzs3%>QlT*+J`?c;syQJ|^67kp(Vv8p-sGJryaX{B^^yQe z+`y)VbA066>ahyMkwgz1j;!;m<3dh*pCHc&#+y4S!m81|<9`^8`vZfJ8i>-c-k&|d zBtlA0A#d>?nT(sH0!)pe2)~G}nf`CvDFg?95kEiA{Nv#EG>b7eEE=oRP$;htwEiFg zHmve)*3+d=b;}cQkP-fSZ=SQ@+Z7q}?%o9K7m+D=%mkl%D*7`Ce&7eG>t)%*$u5KI zsk?Qp95l4o!2IN|L}pHuG@!nU zxzP7n*bZ1R)}!J^ti2xI91NMHnOau+2Oq;PT5KXcbv0#%C-Ei0 z`<@qlt|Iv5h4mb*SSY2)Sn4OgR@WIQ4krq!ZHg_j=?!=dRdj$la?dTw>HIU6EYGe4 zK#z(P;h8zg*dbh*!{xIks3ZQj$Dmy{Av?)pD+Rw5BUfnn`wv+}&2n>dW?{v^_(piv zfcl6-yQ#g)&y3wKd)eMMjk?fepZo5z@jGNw!J4B+QN&-UEAs=NH1$=B=P*?M#7!c} zH}kBd+<;z{s^3K-(G+eh&4o#3R=>-jQE0K~zYtYo*?2T@&=1?fTZM6?-~Dn0*AMIc zL_oIa)evDomn3kiyfJwSpA45eED6Y7i|=q~l;kax(0QXRgplv#@3-+_^Or=Np&iR9 zsOKS;u!-cIVLt>pPf}XA^V*Xtp6m06Lw&$pY+k?!yjt+hE1`}Wj7IK0Zy77U&oE>V zwzbP>yYvvl4#kZA{+ENMFT z_mFaM-PvhmZ`!8O@dDJ9_32qO8G4yNB&c@Rua0_5iE$mW3w2#^Vb+{LSScti_u(#D zLOh`ivjk-$bpKHR`OCaZ-Lif$`%DzwKcxw#{4e(I{mNUo&VU3f>>`_ZsWqanwcz2J zkH|_@6+~z+&}Xk&0Nv%$&qnp(y%Q#?>&0GJSEfw=8RZExFNMs{7 zLdPq#L0q3b&M+1ALz&a7Z%wduws|n)WZkPfjv<+o13?B_A@E;V4Wh3M|7qo|XEE5d zWFNs}B-^L-?IPnUPR_v&y%Z=M?-#M`OH*fr-IxuVC=TzBUh9TOH6^? z0+TWdR-Q{-ZEa#N1QUIfvGbN*c@g(fK{A~uP0zS!G#FPR4F+qF+;MV|R#iOvava#V z?=(pAm00kVSdV4!ZJ_Y?`7W{_vyk!SnIJ68`^=XISXa7^~jO4HlT9 z`LK!^F0`1@ASb<7-Jo3~1nHQ{+O(wmd%R(Mss{JLSEG%$c3J=|^+h0JVg|LZ{V%fz|7K?AZ_izZl9D@mi>lg zUr=`iJkS>bwXmeI>l_igYB?6T!(T9jISl~qdaH?K(iS2v@ z02CvF`!iOPp1aCcTo(TLBBc!-C1#hZbQRa{2_weSnR?x(|KdPE$6*KeSzkU%e2#~h z1hVAkbARNHZEGS7Ej21IqsuZdK7%zyqZfUazurNiP4P_7EHPj})P;?{u=-4W5I;`9 zC!2D!rrh8+Xnf5h!_k2S#B##F$Hh^aRwoUz+jXY#GsJK8{i$i}zK?9d?AjMY<%}3t ztp}YNjd*N}=>NbON_9j6YLKdNex5p$v-y|2kgu-FiYlL!! ze<^Ywjf9wO__hj2UJL%TnV$`njY=Jy^2>1H{*{Xuat4h~UbospcNwL9;Jg0s0G!8D ztr~tJRI!jSBV0XV5%7mn}a^h6V(+fD`m+tc~f%jp9W9^~>5A03v$5y3c0P z7tZI~FP{z1-K#-Uv0&VJQ$g*D?N1;RJMTv zgx`Un=9v-La2@}pYc-Vd?34PXUa4X?zZOBz1^$PrwGj>D+)6mBPwbm8vi%TZAEn3m z;ADN{V9#h9~m{={MF`XMH0&=X3M9p6lBKRj14}!Jvi?5A4}A~xS^e@WRC@K z1}a{p{enMfn&-S?1zN7PEovA@KA9X+^u*Fl3Hrk1c9$Ssee65;_Wfj1{AL(uz;8x= z&Yl^*Sp<2uHK^BP_#B=_6`ZP(sa}71wbuh=pCr7GQqP;W7A7L}OR$&?RnU?6Aplkq0WNEv9&f{zV?X?f>;Y|iS9FC z8Og({WIq!9-M0#Xa_iPmt4XUi-(S_xZmjd}quscSD-LI-M{Ci{5JKN2%))~UF!8Q) zi(D>AFN=+{p=g<)TGD{*5BOZb5=AZ#36i6^$P*ck~#; z4X8gX_h=NC3HF{vJWZ!j_F&aYz+x(!{K*FswC1&@to&V;>QQ?_`i4gnx1@Z{ElIKi z1j1Njuzos@g0lK-yrEEevZe;h(crS5=_etZ4Sh8A{h5B@DlCPbNYlh)XF$BX(%85y ztw9PHQwE4IZGw>bD}@?NVSq&t=kTGhEAg)Up*EpNcrfY_;$?KK%K{T8Vk}`Tl*(XR z2U*wYUeJ}-SNnbp9Xi#Ke8)osjUE`XkEr+gEccDCxS&TDFR#FD$F&nT0z3H2dpqcn z;UxUPmJ&m_suom!#D^7f#@?zGrduqOKP<@~Lx7=>NoCH|z)1trcbJ73d$EJXQM%>M zpDhNSDqd_Wa+(ovy(Nqay3kDx7)o_O)u88jujkWx;L{@^J45v)pZl3i{;@Q}hqJiI zL$&Y0lwCc*?s~DssV6y-qj*TgjkV!8?$qjcJ%RMQk%_{VGKQ7?nv`kORVZ+C+x2%( zV%zc&(u9asKq;_#$Su(h)7sUvT0&=t45kUCe#ZD2`kwma%t{pTpX-(Kn2R*NThg^N z7hvo!Iu_f6XE6+D9;-~oJ2zgXIB`-p+8I;YXZ#w%o$N1F3wj#1` zqh{VF!M?}gq<5xE)KGd%x4^JT_Y#{6REtpbXat8|?CT2RIo_a1pD@g}xzQZb4sxz@9Cw|41$b{jCD>PR^g` ztO4b1sLJSok=BP~KrIzRB^$Bh6h@)=Q-fe`HkBmAW+TKjIf0umZJl~Ch&#?vmG1&ufA%#c;AG;yPJR=nDZ!=pA1kICmI4VcBE(TRGwv8#-^@!U5$QG z4|TiPaA4c<-L8o%G^m~>D4>w{E3bIarf)DfI?jRGMd3xW(~FGUmHp}m-7etAu8R&1 zXwlNtF*5K)Xp}|G`@x`^V}^vh z)}y<~}mnmJprdg@6?Jr(ub zIQt^`?;E!3OF10#BU5!!*5whWZ?@2mc=)?DNREX_lOiT~aonivq%Or*=bp zun7VWW?d|2b=uKJ3G|O#eedfhIKp*}0m-sT#u|^Ik?Tv0XF+LGfkBt{w$h z(YUvHQ&=njjZn&x!;LDj>_zn^-m))HF@;iPZOgX|0_wj7;3-(%Qk9aTu!PpW127&Z z8|MCup;VVo2)?`Ks{(9G$4EfF)4r6WO6&R3@=klmix2y{GdYC#Qw1?_$6g64s8PYf|%o!5v0KT!zjb(WgFih4go zqd~2*Lh>XJtyT(XxZXiuYhSx*L(O36?cb62{7Cf<{=Uk8u0&(Dt&ocqqxDDZ7@vY< zS|I>w`gvqeTqABmR;g09uYEf}ZZ0@*)ykc-L6I*MWiQYEj>Ok>SKvDKzXo44>o~Q) ziUylzT=3GP*Q4-H0{hX$my?Z*@%x&(?iceN(Z-pbJyaQ`tB;p?QXEPcqe5A=U}Uxn zoHb)dtjW-e3$$WJ@_1xIobQ?nQ52$jrNEu_5wM%AvNsAvImVLTswk$G_5hDwhSWtQrnUVN!3&)lk>w79 zxLaHJn?G8!P+M`b3KBL_s>R9aS`5_8Ao&mxfZc`qrq~jPKgxt^Ovp#3hwlsD6~}?y zkitYRs3o~C+_Kjl3M6{cN+aBb+rXqEH`@f+&5-T!HWZ^Pn^*g^S5n2tv##*2iH@Fj zZ6k^k@L8{d8AAgr3vff+@8Kq}TE!2ZF5{_5(WCt4_{TL2dP~Wf(^0igUJ{OffnYJ77Pl=`b0S{n{TW zLz)L+uTP8>?Hq7st$Hf|OIxd1t3bk!EV3v`CA%3XIv$E$vI`8_7T7b0zoCNmn2d3T z4feVFTsTT6_3RNAPk{EkYVrd*0tu0_`c*O}?DD>^_^ddOJd4fSs6`s42UQt0TX8%0VoHj!&Bo*HLiUtI@Mo?lc&|!dT=wKnJ8T4kBuXU5=(Fl)U7u zRJ(AbKAvRP-%p)q%7Ec{)lLCvIlBKeW47qJ(l`8(`Wb6hvEc@szwzE=VJjshlxMjPA!M$#xslD#w|CT9#h!IwnQ-VS&{@n^HGE5 z;_ErY)SsBR@QZhvIH5&73Y!25v&yb_)SavRhr)bc(!oR37f$h}wk;)>gX-zfaW4u^ z6VO|Z?1HYRBsG`yT!~h3{GFF&BL+%@4?bdVqpQYS#f}fGh+NfIIlBh1mJJ~l`l>>& zhp)PxV&F4YU|&@k&lop-kND?wVd?lI1!k3jgumtS6U#Lp0DQS9Bj0*5<=_~*+|qK) z5S1bAby@#%Cc%(}7l<~GWSsuuw30B&pJ+u9w)?=3n^q| zDAXC0K14uyI9JTSFsXu_DA-P@XW_D)Zani?%FG7=MX0W4)DBWofb9ihd2wv=5sh>} zHkeeAI5_tM1?>4%!H^O@;bsi2^&FZF4iPaG>aQZ?EifSZV?E~z3_vat^!zleY!8rR zA{7KhbAah-Vdo(1qB8qIZt~l-w@SuEEBNM*5}X|u+~QG|V2V3LKmt}mCBO+)uo?Ig zY~uG4NVED=w-~fn@8m2SPii7kXAFQ~>_Y?cMjU!vFs{$o?U4wmRz|%#wFe;&iCyip z+ZyBYGzXT{$kD9Mdi(QV5){kQS;iAf& z=8IQvGBNW$9htYg8LB;b3*$XY7BRBBE+>m0WFK?5GnMPcnjix|ekhaJ0B6&PQEH?i zl)NLt!5bIAv{)fy_7WR4GaaM7>jr7|%h66K>UA{6)x{AbS!_!r%>95ya}q$4R{3>M zEkUxkaLNUR91ke$TB%GInaWVX_D*;vdbX>$2GWukul1yV<`KnY%Ss1bTtMUrUXN~Z zWdx7Ix9rTsu+hQ#Ae!6eovfBK1faws_-XuvmPz)<){LhL6hII<_2Wkb-0SXU6Z<%M zc|V0s1-xr^Zo1lYE>I|;0bMjB1K7JRJ!kkH6{>wmGN#vf44ZjLJ|wMhO`SU-=&U2# zPJqN-F%RUYnjg)^*EPL64De~w^lp5a%J%Ran~(f?O~;A0CuMRqEqMbA8;)EQh8O-s z4oC8#=x|J3%5b1*fk_f7e|8UYUdBqwHcO@Q^pgNC!jhzWv4a=HC$= z+~DamU?hkL!27wttC#xA;$Waf{}+q|2Y)bw-oQ`@h``h?QK-{L59L%vgx~e-5%K7k z$ohi5vX6$CAZ-7JF&p?a%=?n_rh3LwBiL;c*y`9_4k;AdKx~&%;I_OVleFu_9gHU; zs@3#r7Ie&R4fttRO>eC&(|C7R&+&#d(grMWETf>cA`5&HU=Ru{M}er={Ay;T(5h2= zNVG^8y75;#c4=ILZbhEf(a6C7k|JYsSsS+}vd0&=-n5%4QnSb;+zf-CQWiK2>HgZw zt^^6B0B?0&uPpwq9gjpLi;>)ks3ep~OL6XO?4=$rZK z-7@`twZK$wrl)sX)cs)V?Z5lDKoeJ2{ETzgm=`^4#>53PC9Ps~ikZhQ42zu1O9znn4&Cp@T;xb6oj z6_jB=B03ttX_;rM*PlRn37CkBnfiM!iD8rhayVM%9m})2$Y7~|zzU5t8@s$|rM?$G zT6bvP#JNkCeJe{S%Oc(WWQsTsGUXAJgUt>o9Qc>B;_e9&&6a1K| zMm5}nqWfHJ?ZYZJ9dW9>5_)Wy%-Dg!@LmzO9z_Wn@oK*$;rx|9m6%lUX}Y* zU{dfXLn&Ew^xXu*Y_;ci{u-(jg6hg9pZWPrOcLg^*e7kKfg#F(v~e>g;I=G=)Dn_* zlt3adl+3<=FW_y}RJ|ur6-jGLdg+95&rfnWiRNj1f}4=OVCYq2g9VnVMt1@02(;n4O{-KOl%vvr*5XXZSCD5N5H zd8}&d;`O(&@pIzW9}oF-wp#|fS*mi^-_L&Sg0l3B@%wJNp5FcVgYL?+Zbu2s{A~yh zTN%Af%S)3~kEcvTk)3&w+7LR>R$x4ljtcgqld0i zr()5fH@*IV1j8Uho4tt-jffjD@1k$_KG|>u-ERUQ?b4~Nd6tK=xXoe2{Z|sikq`q@ zshmC9<)*F}Tk+FUrj67+e6Q4!Y{c;SbUy8T*zlEI9w?Nfr1cavl`3GVVlP5_b6zl? z0|5;0l=p@bm_I~^b01l}w0c61Vj?XL?vKWxBd`f^?l@Mie$NIY)=({EQ$K?n$!ud zD{Iadr`d8AZ#;(=0TtP<#lK2TEzzcHO_&$f^GCV(?O@fNhk3QWiG)$-n2rfjn1caJ zE;ZRj*=GHqGl&6i-Bi9?8mr$>e>j5C8%eG6hVuR)3O+qsXuWFAy(Jfa7sWxBPH?tc zq#i%gk7MD%em(%*vs||f&Nw<|{@)h%Um^R=DI_PV+dtrwJ{6W*OwrFe1YUvyk!KWp zjpHk<9FZQU298y-c)TzfJlW>hpd)%lOp-Nn+QB>JG9ci8|L$&?sCw)>9*I1wBi4u<<$ zTZq3X!-zW}@!}_VeW!`?s`1zc$ z#gct;FIW1h+@s9TMtzbB1j1aGfD8_UKQnNtaw-3sPFENBadK_!`kXNA*=PyN<}3(q zcsf(l6!X)AzP!rK6E>n)I1T7>u_(p>$ju#Pmo3Qx>2VutMXj%*>? zzYF~z$uW*c?PN!4I|b5kY4ce^?@o?@00$c>{yHAyyo;~BG{Mw@^-4IjOdzH>91t#0 z(=OE5a1OiSKJ8`UH>*ML+RbKor!`qLoRPXN(T|Z&CJ3pO7tIaohu|jr43pGtN?mPi zy~0o=b3W}tj!Jy&{~vK}z5?%-nLiM^l=ISq3KO&!lukBzy0pMHIj!~fT zh-uYZAxvMx3q%`DFWXlSpzsalyy16O3^#C*V;JI$pK>yX4!HB^<($))s5Fmp;a}aZ zZ{ip`uj0)H9JcEZ;nYNy6d=s5flpaGnCc$ba%)L;+D9E8cz}QS(aS(si#L-03=#MB z^fU=(G77$JTAy|jEgi>7b&t{GbOLhCfV`*?Lj0Vdvk5TI0Bv*>>8za-P@j1N%gO2c z4_$<%g>T>EzaQptzt_PLw+sGnAF{d57Oa^i5tg)U*Mv2V?Oh&V07{lFqSVM0JGN5`}eAowGP&IHof z+9lJYw2hLChdAIBKADRpF7hmTKsV&B$9~e(#(B6++NPs~6Cp4Ecqb`>y#9hO^V9W2 zKVA+*nS?LvgT|1tjzTEFw*>LHeXF}D!Mmo2I}bV45sMUF__7TJ8_pr^gD>|k%yOp{ zXqz1x+DHF?|67l2hCnpEZ()SIhDZNi32JcUd~;s?8X_Xm=vpGaF+^W7g8a@5R`0>231CH@(}-@9ID$YUU5<&#cn_yVJD1yHN?-B~)L@f& zhXuM%ev%~*tT6(u*!^s`_*notvXoH}lF{dt z_R##Duq?=b6yuNtIt68bL|75ky*;--Q9vPfr+J|xRBzF!n^!sNF&;NNEb9FFAN$fR zb`xMPKkR@A_(s%2L1Z!81+-%u165ys=FYXr*jat;a<@A!$}X$`%F!S4O6>b-)$z?% zgg-6CjR7KD`Y{pY_=m}dw5joUm zp5%q)QBk)ZAe?LI`o7+Ue-=(kM3Fig1Fx`HWE2gu6UOHT@AFcQ3AVU%ehT2b*Cbys zfB21X^H@x7V!4%_(Q$-C|6HkJ0IW5NggH0@c9l>wv>;(M zbin)hqwNOV(3|v&8S!trSZ9WtIh6Ecjrh3P`J%7+?opc`8KZA&7DuhAV2Z?|GdCeT&iBE`KTT_qliAQ&uv@w9K-GkbH5z>N8rHeGve{Ouz z&CMhKd_b;(_Ez5u`AP&4$^Qm`1Tnnk1W4d=g<32;B6YS9hS-tZRVRDwRXT(k1HXku ze<0=>6uBXRr-90HTiCsrl6vkRrccC$bI=`Qi8J6(XG}5}_9X!Y=irJsj^`)Rm?1+PYIPz9X76-or8$ z2fy;sH1*L0@pV2!*gyuERVUbkt^iY)d+kQjSB)NO=w}Q|t!u=Wfg}1AVQgsEf6(u{!>(HnqH;+I*!* z`V@>!SIdWm5H*0MA;>kIQrvulr#z_(p$6Lu*6zoNk|+DOl$OBuerbnC-o+>Q!pdGB zM(HN9@#yF!V;``$+tCylm54fOB7_y}xO z&}>vRSNjC45~mDWcp`2y;Oa&BQ?>wb!aCgV4do~}uH{qOt&*n7^2A|{g+sdf!>16i zD7*?QAfgnX^YBiCMsjy)Z;m&!9z>1MT89IeuzqdF1K5y-#r zq{)M+h0_8SlzRjEvq_n~p-1}j*(o%G_P5wu5U>`e<#yy}UkSA$b2w6pX5FW?n7IBR zMryzZ*9q_+-=9j})P9n?E1;+O@nZJ}J*=B~3b9cP^s^ zrdc}%%^&V|VjsG%mw;?Ll(!3*;wOF-iiE7h&>l?{;Eo8#E`&*ZvtoxSvAd+(lV>SI z={D6T40Hp!aEWT8N^U-wjgJz~>__-at9meJX$n-9`U7yuMA;Q7x`?qH)9ZbIh?{it zGX(M2Jt+B5Ob9lvY#cSPb;yisH>UqAEZ*ixc0;$f=+YHJ8=f9q-5Nj`e!vno75@D@ zfR9Ng(S5CJc!b=oSJXDhxgZ?+dcQyfC*B8Q>2pm|J8v)5(Ly%~bauSZz$Z4o2*RWK znQoaHIZ;WCGiCdMqN8C{GBy%9r3AK9dGugBe45MlJDsvNaX@WNbFjT(y-vd?%N(!x zC^kMQghGkq8{k)gR>7z}u8i8}3H#%|2he$uH`T94MQIH%E&e+>8uGs4;i4XXoAF_j zvk%opO=u|t@{U^PXpM^FAhxLvn?WmTgLqLinAAV(spVNT4QduB>0bv!60}5Y7X4T1 z+j0LpoMlMiD)HcoRLB!7-Qp{bmn$LBNd5kr=y+6H_;HUzQ3k$t!_<((R0zI8cVg2= zPqyS`jH2l)%t9kIg2wJAb=DZ4;`+M7{k=tBS6H97sce4Uus?5Ef48kK+t$7xw|9ST z_|Koc_tnt=Gr}cj8?AjQbRX;rKeZM`{3aCx>fMO7ZfcM-NhAxZYnU)iBbesI;YA#I zA0NdO+#Ynd$b^5#M$~mK?_OLeRKNb5zozd6s2YYE(Z{o_=SNPq1>^c^M?Vlxr^q!vfu^0#FFX6q;RDYp&w^bQn7F@{+5_*yG+P^%)N*1n?ch}N<-!eH(bFyL)w)9L&3rkVJsZP|kbTj*6>6qIXPdma zB1*PEs0>uIGhvh-A(yxan-FaIVy~4n3`jAf zuC%hq!^@JVeSmN;y#Z!s@K&Na&F1}4m_~pdMqa+%3lFoE*`L}eSJ;9x%xY&GIR`NR zPXB8_DP{6Hkl~UOW})^DC&~rvZxL)eGN7)J0XiuC=MfI!HnKo^b=E?levt0mUI6!X z`*x;==*pVLDI7_MV0MU`SX&ZB>8<%g^cKCP!Y8c8K`Ay8v}r1w zavt+YXfb#|&|9Ri*9;(5i_NMA1`MaBaJ!02mAfi~lo$gry~CgQ6i%_#F4pSbU1RNG zoX7BN1yw4f;DRBQ+17bc&VpeS${Ga~#TKH-m?9CyCY}f6+1UGfS-)M*A6DG7X}B)j z=hTWU3$(~OXR$n#7@Gh&h=#m!oj<)v0FS&=qH>9h8Nws4!veJtU3syz;P7od0XPpM z238OgD=9%?ys3agmCvHz%>$&Ncq~NPKuk=agDe!S9Cb~TX>Euxq`;u#Sr}E5l7?)B z@pPA50Hqgy$>!oaycCuHEoTUln<(TR(q@@Z_AcX3QCOYdm4*5Z+zT62q`YS>U~0Mz zqDO*VN_XQ5sCd@hFelbsYG!E?aF`tBBsK3l*0C~0>Y=3=mtxjN#gs9SD*neEITr)d z=V;^(c)u8t03B^%2|bQzyu=-AUp^5T~x;y!Tu))FAZ{6?X?aCD8A* zw~FI)xrK}~zU(FaQ18GYy-ke85zq3w6{h`G;Bk^*q(EJDM4s#0|oy^*st2sNgW|_4u9Rj zokW@;w|WK*{FV%+P8H7b{CQT)0J2KcZYKGJ^#oc5QfcT-?DVB%AL?-i#SzC4YxiEqym$H7DfE#&ds4b+bs$PsZmIf9}P znp}&^VulZ9QQB6g#=1j;%5UoZ%#4&v zbnY}&`vj0SKT$i;Bwf&Vi4sjV`aVLK=f8$R{qD;u64ot-7!QTP)Upwv;S&oAtChttTpRUcyN>(qutV6ksb5SaJ%AJH1Tz?9 z2ySrC$#^hlV_@r1Cq`}of z6|uYQUNJnEv8o?yvN}CjRv*3H#?r;^bKZ>KsM<`bEo$X=IGAcQ_bbW4Z&?}RaQ7;t z&of~^h0cq$uSvt{H?%MJ; zmt=G4^XFtMRLA7kN!ty9Pam^6*{dKd(0|tYTC0ewhJ7pME$)ACMp#kC1xm$c8LI6| zNAbxIcDrd>Q1k-lAhN=?uOSk|G%$nM{#?OdwcWI&q$F9R@sY5g3=WT5pSZ~STo~_? zu2+z*ePQ;1LM7WjP(Es|@^4N?FcvKmM#ZXGXl)x`L~6Hvom7r;vOE5 zoGr}Kwwn^J70tb@p`in@K2(09|1q3Ynmwr;M4IxoktSC-z*1U2AD(BWw!U*IvpAh9 zu+ucl!FU;6gbf|-!!jP{;)j$53a1kJJU4d;ti|t4Ldy}DfU9c@3_Y;MJEOtAV^}P} zuCp31k;GM}(TMA7z=1u;<|Ajp(lW|K{f&MxY6l(bS`Qs`*K_pqD>A_9E~NY4vcm}V zt!tJW>ALW{lR3I75rWEhKq;60!K$)97&zT@4Yui7ILCb^9d=p6b`ycq73f0A>VKh!YkX(EOako z*%v|xNZZBab@x4_tV{a%WJ2^ZMfH2f3o=QAUD{rK{0Nz$J-jp8&_oD2{Eq-ofhy~C z!w9YN1LtB{q1FrJ52ASj6Y@*SamF^7_xHMZk$NcHS-PPRMTNuhVoGJ#LciK6i?Iaa z=Q6RWk9jhZq5+E@VptnMc=2q;eILX()g`4vt?~3qmdRCWF0)J>O~mvQe!=t9%E{to zyWvC&T#j^cRx4s_@e5RXjejb2a{fD2Xk_pG>GWRDbDC}XO>r(_$Fpk`amL>>?$$hxEG3@yt%`*< zH@O{w<9F29J@C)T;4+wFfKt|+5Oj{&PWw86+dqam?2xzNFzIP}_D(k-E2C7PnVDVh zlRj+j!E*-%WV2qb1VJP52SDTPvZmRFc%JmK@w3Xv-%I6glM?HE8UBUdg}$oo+IN_< z`{7j&h`C+6%%H@vz_{W-Xzk3vs@P0YH&+`Vl)8Nx`= z=!$Mq`n;)ik@`M?Ze9nUJ=Qs!IR_^T^qhFc1O#6a=gy^*MBdZMb9O(Rfd{vGOd1c3 zC3@0*2^`@o3Lj`P1?iv@%I*L~H;&D1C@^Fj3#%S!M<(RSU`Tu=9DUancYmf?ygV;) zNNj^1o4!cT?OO}@Pgr&FU_mNHaK}eHd^>+;DZ~$Vsu-3nTDY%(m#i)Y8imt>(fC$_?GT%k6~l#Nno1G-?NQIT1jck!4nmT76JPm1yuWo6CC%^xKqUQT zzp4rQl^(iQ;OsrBx-Z}Vf0?|}SWD5D|9}5+6bWgR^m)1IRL-!d1F<;61OQgcN=Tn_ z>Cc~bH)H?;Ur%dN+ZltiEICc|=k%-lrj$YVTB`O7n0U!RVI7#1D~iZ7X(_PVO2OZq z<}yH9V35*yUB^|PJNT1KVkTqRBLv*(O>5SqaQjjM|5nM$_Bet|$+LV)t^?(mNCKiQ zKh%CBN|aOFe49)bVah}fMC{DZd+2)oI%rj1_zBs&aR&M8eQsCN2%N#$BgbNw# z!&_jaArEV%h~EU{#4WbNHPa3(_dgdR;7w=__1OnQ6B~@{nMwRg%TWMZ{CP#*cj zbz+Vv9D?i!`dnB$VSRb$D|2`xXY*I~nD_#sk|td>GBcw|!C&05zdCtj_{$Q}u|nM{ zjzE?2e5Kt6TgZ2m_VoAFJt;T85|}oyM}v)TqP(b;476=~8gt@= zmirXFZZxQUI*iYP{r1HOO-DodTp+;H^B?d4%Cmj5nDmq$2Do4`ovCuy+4L$VQ|0$k z7czVDgq4_ZX4m_U%0=ziF2B{Q3z?k*LMwl>nnC5|@W;OQ8juiwu6%aQ6HxP|BZMWS zPT^f}+7xltYJi(!+V5RD+7~0I9MdU|iQBf_Xbt7c?h@BUY_ikP4*lOcDIImc>#v*Q zy`r)y6m$a;0SlMIra)h50-mB%cS?C1*|-l&y%_F1?L)&rZw}+D=WP|)R+3ANi9VO? z?P`%^CsF%irvDmmYKd}dOoWM-3E@HDgNH{LVaDQT*@pn7vrX|qA)@pm64h51@}>A8 z9&S+}<4zYx$`U|HA$BE{bx7+~G8Ku<)$*Nz6@h{gZy+Wr5ro#YWWHSIxlC89CMqEM zVE=#8tC-3S*tJiB%Xi=ZfANb!h^cs}uE0bhf`b2Vz>Og$gw`QdERX+gHn7mB7_E%$ zf3}$=GlZ)R`Er#uG(s2UmOhsd1h==PzdI?3e)uGN^g~@bhNS`Sq!H^BQS#dIe$sWU z)o5WWm_p6I|73SaEAk3ys*kS4!UsS9fBt$Lq^FZrt+#!KYh9G&tbXU6GLJ}D$IvC+ zw7y)&LXvjMFc$rpw&wo|H{sKU!AQbbyn}#CHhuc9!4ntfBnLi`xt~j9(`)cokNW8_3t_R4Q7yG|7ALm=$?RzcsJW`!gY7B zOdv0-EW+~{)4w*Q#6CcqP*Kt6m|u~uuOYJgURzhv&L6Y7mJFZZNF1jFD*-e{uzE_4A!|hxat0nW`p8si{uOMTd0{6Ep1S5_sqxpU!lsdJ8 z$T2sstckrlr)62+yX>o>AbwB}7Yj2j0HDnoc6fV)vprOGjqav;f;lH$**(_Uz|m4p z994KSgUjb;ocF~%H!y3%QTgib6>-&z6CSS6Aoa(zsX?VzVm0C5n{vMCYA`^%UZkx1 z^#4!)3Bj7g(v-BHP6V3HAkz*5umIcr3e9umxVm&8=It7pc(puXDaf;lqz+6_9BG$v zLf>qxn&hlHUZ2e5{8W$^JbyDwipR7C%^!TY;ha${@4bif^gHzSy6k=wOTJ|dXCS1Z zY?{Jrvn(SW&`Wz84+LEpVE;Qb|58Bfu#QKX*AWiOAB-`48e`MQ548aM%$gY_M@c|M zo#L^ZS8_+C$k+s(g zM1{+PTbTA-{upFirT+sml4gz0tKTTk`eB1l)GdcpCLJSS&Ua4e2qQ1Qq;$gCwQ!UN ze1vP|YTOr2YMT9fN=w46B@UL*>=1N}(CubZravTiGIJoe!{1MT|9^jW1_%9r{}@Tk z0yV<0GyJb0ANgN(nQC(t2(ClIkDKQ< zR>gDhS?Ld^VU3Fc_22Kf5<>&fF$EOVt&DNSB{Zlu#xga0Ag@#}RsT=f@(&Y9!*?%f zLZckI)c*N=4`Lq9j&R>D-`*pX-li7zV z*)%4Lz1NQ{+<^^P)qejC=Jwy3aTA#BKHF)ppX4yW=3T`M&w4Oi+-7 zgp~g**3OKX1NPmUF-QYq7dcKe6%NHnf&{+1b%Wo<0LPfRazy4Y5kqo;+~iE9&up67 zVki!F!S`&E=vV7%^0z<)^L?LRflo_HWuMk5oub1SEubf+&isCKBr^fkyjMW+a7G0y-lz2vPu_7Zd7~NJ8gjj z$Yt;>hiEqh6~nqw;HNPyv?f_s|3s1&gujl?#ZYA)x2eUUAYQ*OB&hthH`DKUgm6L( z%2e=92OY&R@X<|cL_AHQG2nM&;XisOKEnuNLl&(jC5*gBN9n#&prP0t61uaDc#^E3 z0HQhPuugdT%9z<6_#f@R)}6H+e=5>HGNfxd=4lrj=>e~`*XJysiH3ZbPYeh)*f&Ib zGF)=i6&h@@zCh^20bQKInyrk+3xy;Xyqb7dYR#aIiQaGoFUQ;nM-C~h>wg}e z4qMDcd3!kDd}~$$a0{l@#Cuz+^A@Np2W8QWplo7}48UHbP;8RCEO269o;lwv(5Cj= zwg<4{b^jTz zIhK)3aB59JZh;(Wh3=}{d-ntx{IsV@hKm}NtI(4M%4X_(p=o z&G-J){85b0^FSQK{*EHofPLlV0!MsH={E~yc~6?Q#W%|x682>mewnw=yR^@6J{H7N z_+W;vG_a<273CRLF$NDk)HD4f^n%5<@v;)CgHckY#2u7hK>a&q0RXwci~ew6PZ z`TTIxdRk^7a(=)o5!%y0a_sX=0`%wCfJ(YFfqmk;5}p;*dpBJ}X#uMhKH0AxWh!q1 z%=Hpc6=tnv6>|x{IeQyYV=vEy2f(4|g1D69Q2D^w?{&j4H5?+e^M#cEZ!800Tv)ji zl&Nc&ZvqnnXw*s@kK&@hjTK=AU9pl{c;u7AFOo1nqf4|}%VXnS!L zy!TqtARa4wE3PWbqun%1MplCw`tuIZtM18#gw`dGu0R-R-_((2$GMo3=S?`PL{siI z7957yMl3dC>285Y%<0pmAiH0if`LxfC~c~p2OXTg-qfSXzj{;Ta2sniCvmg7$zg*) zWU@l$YIj;AenYxlaSs<3xeySyeK*R*Pd;|)ci*_>`tj~?OI;7CcES5rgTl=Fcg!pr zjDUMMF3FFD)h!V2z`#D%m-`j2qBhkIXUIM^{sijp;1D)y%s6Gr#2Vv98_Z%z2jY>V zwIiaXxZ~+>=ybcCkgcN()fVP1xzAsTv*v1~M-0Eru?mD&u#yh`L6{G!^9^<<%oZ2J zJNe8Qgvzj!3sJoXK-EzHcwBTIZ-jAr%|l2Qp-P7a&(r)u^i>l^K?riY*v0UL>hazo z5*9&w@>ML55pwh=!9Vp2co_E{&Khx1UZJgPXm)q_iS{|SMYZDE)k?BOl)z=2`bt}~ zmsgs6nN{Y1XM!?3RfcYRU^WCwl-XBGt@X0|5!CRDAzuz4G#gV6%>?|AdrA`S>s9mw=D7*)(;zXQTW57Zl3I`L5u3>RRJnui?Q+hf5 zVa_m~E&P;O$ww}D%)G0TeIzyiU%(8*{rLEP%=iT+ij+I*PP5tl3-LIY;zH^jU!>@q zuPkSFDbhAl-H4QRZA`17wdL3H{{x1%e;L-+GldMtK3@82Xb^nmI@~Y*Q=~^+rh`n| zNb2o-&VkUuiUGT5#DWBFQbk z;FKR?>_mwqp19j8%!Y~b?!}j4lI!3sEfoa7*^z?q(<7%3(%@!F;y2(!0F?@*Rs-j+ zFrQ=o*y?$h1D@dthDPhHV~dOPD?~KA^$F8H8ilCE!xMdX%!(9CS<65NG$|_ zSiJ_hmGO-uDCnGq;BNmo1f=h8?l+@ds&w(siwMpBXz;5n8tZSL^kS<@Nfx&c?wUJ9 zvOvMcy%;^?-iBPSjjQ=EPqp*LM%yhkGqm=z#tBmtGemCAP$g-aqzoqIiu?z9MovKI z4RFh9)e`$%*35@N3nw`TZlD!#V_NX9eO9cJgycs6Y)CEz{P*93qq4SZ=r-;5Q$YZ< zB@jq-!SdByD5plipy^Y5v+2r#ApS0mW;oWtzdv}fa)LQnLsemw){O7xIFqbtAGGzM z5#`SL)7*)fq?ZYH&s59`T^K{XRS=GZB5`4M4hlYmH7P5of0CD$v++~xUV)| z>fP_vy!X%E|7z$kI45g5ix2ov(Nl4zflQEK8(KjL1?ZNkyyKtb~8# z8LV~@+8=k-zi4DuX$s4)2k;34~hg>YB z>@OloYiA*iYAc1N!555`J&-^rD~C=Y_F_pfH%uVjN9-p7q)nM*m(~NZ2dIh3QJ5G2 zwoPkpe4EXDfpxesNt*4mlDVV9tTZP$URPQ24>-3$|K+(Eo9 z%nzbdP7I}}z~)nKfB+uU{p#EPh3XXO(=udV22G!fqBWcSAeSK|Im`qL70}rD(VNKA zA)VXyeR7B)4mq8n(Wkb(b&vG)PB|duvpRO2e^Uz%Ezsc62eOVu2R1^9Q7oAtxgIsk zsoGu{gI#%fVESs=$P#wPY96gg8-0Rzm@{PB0qYicjA6d9tw_tqtHOzbW_tz{)N*h!8J*kiS0; ztN9e9DL4U)-T+^g47aIRF!i2fy_|B9o~zz;IjdpG?)kDJ^ls9ka-{2UH|Cx%HIA`A z4V39#bKhE0Mn|PSvI2^>BQvI;4!-(M+(wKG=zNH3aMZ*|bloj8d;|MWuL!KXWX6TI z<&U_2*=n}wZwRdHqrs2?R=R6Gqk6Gv!r2Ct*3S*2XA94ECOa4*FziNW`*BeJsU2D3De`sAvPHunWWoXX1YIe!ll8DO?iFl(}n#3t*Y;IFywo2n(p z?xw33eCh~uFQhRhi`^)ESqpz=E$;}}HAm*U2w5$M86o#ohJ4?-k2s6Cb5`-NJplJ` z88GkK?W{+A61=$qnlT0$lS^iO4#1h{!#3%4SfxJ(21kr@6V(aujw8*T)G;LBZs(Cc zRTlVFRFCezZGz11A(ej;u)$ni0THXhYtOPLi@|i7`?9FtI1f-_1F?B0W7#+)l(ru~ zD4yprgw?2UpPv%J8WKZIQUiTEMfInXb^l8TdBG)EEr4trmXG1ocIAju3g`MN=RIgB z;h*6`M>JP)Qs4D%2jy<`=khJ89B%XWA<}0+8VZ1RiI3WSJY0l|n4zMxik4Aq=#K1V z(4r5ftR&@sxGuDod$=Y34Ufz4^|4-Rnf+pFqROQMkoN_RKebI%ZpU`%_>M z9x#C8{%ud`=pk8Zm`)QJcz;l2R>G=urEcJg;PT$bBw=IF79@uRIztJ->+5)LJ-fGu=!(n43#t;g|3Pi-crn zJyf3gB3;=Ge7Cb(8DP-B!x8SAmc`6X#<&nC;%+}8e!S~(@L?*I7^I= zrq5hi0JQnIY#g^{VjNh)aB1E&J0kE|IqW&)zl0Rh$?Z#@@LHiEc@EQ_uKaKZ`+a>! ziuli0dpKmIP7C(c$wLl|i2Fd;OQv+5cEF~=tem%!zfuNeV~pvKDOB1E?fK?Q+i7a6 z@C?)L(U9N-XBk1e@BvT3qZKY2Xtwf%VV@?oroZ(DN9zsbGNL``baidmh5Q&pinz!~Sg@C5>dG8m>8wj=; zz;psWW_ZlgT&u~_;6$25Y;Aig>$8na;9Y$ZDkl(PnxXS&2!i?q>$gtH%R?+buKQr6 zyy@#M-hGkV434-Hq%wl#b9v#rNpk>33Qe_UQ@Pz z0L_vkj`zWsalyp;TQ2>9ZA2qKwVg#-&j7Gn@w0=O+jxVeGRKAso(UTL2&}=-YP4P; zASgnrB{))TlR{7JTnTc-u)ntv0+XoFfR7jCt$BrTCAKtR!&W=B$eisad<J!l8cb)CTv!<+6_a^e&V5IsG>$)g zG{qx*?C<3Wv~Jky2kZbpm(_mS#U#1FO4CZ)dD0~&XH1UI`OoRQhDx*oleOnJlP~V; zoDVDjLo}ms822gvdP+YzW%05d!EwhKX;}(n{H=)bj_jxYOnl9&9|Rz)pGr8_4QsAx zyCKK*ek$l<^{pl!+j;_6K!ouo!tV0C3#q&}4?=*D%J080(lqh>nRtU#9QzGrFApU0 zbSZJ0urr^dckfXbrnDoTcNh|m|1q%;x{k?l~mt{f*tLeedHwJ7dfwZGddUeoRYi7ClF&-f?KQ{jvSerQ_@9KPhm3v z@E7GD2Aac2-1mE{+%`sTFyJ7hSvBKohK^vrCj}~ZFpA!Wlj?p@{NJF3;=Y+avv@g} zX+9fYkeYz|$(FWbd4NakVy~91Z1;$vzMXPuBlW6m5R&WR$b5|qY>$~2$avhISXv@) z5B>!3;jaM^I$shPI!*?GF@dofXuXG~bMmD_aZ zDeYFNHQv*}AG6A2bkUF@)e7>gjJ|Z} z0Yw*pCyzjetd;O$YyQ#moTdBe5pkI;a|asJ+NSkzjqfX{M3BvBbV?yTH)m)yo^3Y0 zN>Lqf@Z&_QJbHO;;wV|GGowB!92!MX$LI9Q&t(EMGcK9IJfpHaBP`Yb1AK3GT&wdl zLW8sHO%I2Gh^Re zTujIcNj8Ho8cX>fWMn24yXwEhkS=hj4`9SRpZI)m1m;`N?&HNQknoN@|6WvIHYXZ&9)C9oh=X~-FX~V5?cR57IpVB)bPXxN1$$99L4xzo;DozJjh6gDq(3VpnAGE~6$QP(WvfX~xXCG_7$)LMV?VaIgKUPpATDhOgY~TEq#=YRL;!#r z$6M}1^Gfl`!^^FF6-9xDnTd?e*xtA5i#S(s()`4dgiC{SRxRSiA|;RWIaN=jD%Jy@ zDrTOT>Q-I1D+MBg0TUX8o9I%{9mOEEN*9dX`g4TWxz)NeB9nZ=ZiuWFC}c@OH*r(=5;R|v{be7x{Bz)H2!RI$?G zG!a6~5o{dV2Y@VASP?|*ss@ip=Kp@Mp@vOa>h#Yrb05SD8UJb2GEiFO=E#o1NkD}l*@%rb-PpoMc$UFA9cmSV~Ua45IEoyU-pKc2Cr?>00lLtW%Sdjyj~GIH)y;Qj}Gs zpCTKTef6wPDJ#Y>`dSMV!#xq=t^th(4+er=rLg-FWu9#U2sI+OQpTd(Sg>ST(_FktsjulDD1cucbG+uS9x?wU}PBo9#`Z*#lWHrl_Zxwpr{Uky&{Vkr&`s zHT2AYWjlSGT%pQW;?*2xPH^adi~Y^ytK8ia90m#6_lzW(In+Nt_~iwpjeULF9JhM! z5D_R@EeR}#|N7rYQbsZjtT@s-#t|QSPjO>7!mw{2$8C-gxev%A|*>qEVYKWM(A7gNf$n4EV z=n9c|DD9<93p6VrZ3?t>hVr+j>CEus?%RCv;Exo-(tNCm`~#`2+!e_}p$Htf6WN^3 zVhI&J%=+?7IJUt$E*4oB*yCS>oLD$^)Ye}6aG zZ>{PW1*SGV2m*iD$ef(6DgmYQcSV}Gii&!PrO#M}aKA#+@J-IN%3qR z^zk&;;GY^H^q35S&hpV_=ssoYgAQ-bH7 zcFo68`W_f|1FRx7}9q<8Gu*Os@1#}A%w{9!5TnT zFLrHpp$|4BJ-c4TLNK_x95E>ucPD+yUX6(*FdyZnXc}tEItVJ}FKlO=vIukrW!L)~VU)K1ixIzJ)hhz!SAJ){MU*3499{pW+V;9C78 zLX6`R#%OnrV5xU7(&9G5A`Z`He_Y_}VnqpK|1PMXSnomb$In}NFwfJ}d__N1LFobK zYrDHQUscSj{FugWxB|k-Ze<#fwA;cCjNnoR?=NNYI>xBD7+BoY0WSPHQ1M*tdgy=# ziG{Q}4wSI~x0;FsVV3jV9s@dPU==0`zTh)aU=G;)09z{e=f6Inlj#3_>tt10Y@yS1 zJ8ld*9uFn#o0{c`#apCGP_^F4J{&M)yOxah4rZ>4<9o1uj<0=96Y(@|hGzXI-giU^ z`6a~kfrzjJG_%(MOU`*O$U|iwh&1-}{@4%i;t#+9!a)W#T3ygh+GzZEdVzrSmBe|h z=ut$(6^}QSWjQd~cF-h23V*gBtEoK=K_{h+v?}6YWpGr=ANu2K z`+)eY=)){S|B(?wrIn>-|XAw7G-D(l( zAEeZu8hwzUS7Vw+Nhvj+INAi|*_hV%_TWe!U@j~)jy!artcTZ5nT(%4DglIe#XHDp9AV61?8UxIHOScFt{y zVHrn2n5D>}@Mto-#j?oWdSg6f<>T`8(N zYqrC@O$^2^t2kzII8W$Lyi+6!D|0$S#-enoW|9vBl++ZZ*y#U6c832ZkqNfT-8b0@ ztzz#jRhLkQdo6iBy`HD@oZti<%2m6Bwo@CKE7P6XcK8u-xMH}Mr~=3pa8azm?AaHpGi>2fXF?+h$@wW@aZlv(AvzgV-6rv^eoOujs->;Y}LuANiPEL`c z-~f6sD+Me4(B;jkZm%p`CRTx+WZc1@vhT^N@G!rgvFb!5jV3+i2qr22SFGH*UV=Uw zO!Uz;G^B`+6+FeVJFXO;zT#2J`GjO|^|8RspAuwj)nsf<>o^wK*bU z1_Is{nWJdmFC?h-&|lUKmj;xM^9Tg3#i9cW5I+eNe%Idz{XkfeSilrxkpZLtOOeTb zS0vhDb>!j#t>N6`CI*MLBN4h6`pdus2+ zEda$ct-wX4c%fOq*YaSx0${^xyhR^TnIKAM=!N67A)w3x`#cvO**UmK2tOEhNTD?6 zuSuaqxAX{5{dXEi#d79s2i$7~syq5d%Iv>v)Mn#a-d$eWhcp=}*3sMNC)H-q;Oau; zm+L&L5=)z=VTe*6`*P}-Ph$Mo>3gM!z$LV{Znxxe2i~vLj4~kv1f+JsdeL7@(AMLuWR}MZ9tO07`YWH z@4BtGQ;ojv=D~)u=-!x%aKwWZC@puPpX^oO6$p1YYK$TF=FPUKbTz*_+j|b_;-Wqg~Uth@@2?jZYu;!AcT$+M%VMS z;qV!QeicQkV*7T>XDbrK={^C_e$rQ{W6cU~#ruh6T=jltW`xyBm0y!-bx~~OCmNWQo?2JIt zx$VH9ke}#ilvUGou}e5WHifqoiWjId$K}HIc_X(T3H;XURL^G3Agx&*Y+QQH67dGi zne5`YDQrm=w_Fw@Hq&@my}c2TZ0snjO!&To%41?e!GDU>rB_$_PlG>feDZTl+}W7p z_akgIc&ZQceD|hUFbcsaCY6LmVU=2Bh#K7^Iboj&`5Q*k$q(=>$7?VaNbgMYN zoALg9wm3z1;t!A$e97lo_4h{cr8=!N6kUV!BuE31wP(geEzPjzP}NV@VUtse7zQ+& zI=GAsNdQzA!|duwyz4{#spXY*|3^r|z^KRNyn|zRqFyp=*-K#35elGb1=)wzb*3v! zCRXZvcu1eP;Bfp?vT+i4Mw3C0CuUwgJfbB@=(-L&t(f}$6n|74GpdZBwNKahICTo4 z$+mZJadZ*9oSrtMq(FIBg2M=})*@N$CXEC?TqQ=q<9b(pNzh@8epbOXH<7hWsPeL1 z>6yoSWC=gzpG>pr7DI{7cD%d&I&mUK(9uZHCEj@lA<62D2xA3_Z=Bb4`h7f)K5Ut$ zdSKH9c&l=`cumOhNYQXFf8do9TKPEE?x>$kIYk1|5Ev}xO%>!LtXp?=6$MpC_q3w@ zKO~^t@*Vq?MO$V1EZ1f_tx*x9D-$p|Ox{QT%K0S+>Tke(wae^}UGK z4+0yl_v0yMdvZ(R#N`^|2wAH7*qY94AG=pnjyxR1IhlT6GOt*uHc#u5*_%gQN*;^S zfe^jDdTGD-Je}3GR0idlQ_lEBtpij3F~W1sQ3Qv-Sv6eG?6j=Lk1KV^GqM_Ojg_5A z#)5vbZZl}QJ(gRgC{B7ALL3d1#!OJGkYoQYyUvcF2W7mEUIusfP{Srk#E5{9(Ows) zFmQ2z-k~Z!Xy}DsCsFoO=!Ss1y2$bhiOtX5W`5eooLI z#Vn*dIGD$!N61u-)I$FSOFY8W@|G}i#C(4bJhWu9%n)8grhXToFwl8fl8Ah2oCULO zi*?)-CBSZIW_~(`Zn`RUZF=oooR<48rwo*hf1ptpBl=YwJ0Mf1Icz?~j2L2Hp2HV0 zh5-Tz5uru!4=l&&>1EidIH=@Grsejee)S9OME(i6eTcW(jr-I;f_4wm=k*|dq(9V* z-U$_xwFSnZb`a&m4A?R`lhL8#e(&6KVj^XX!5KCCHp--NkW!u3Ks4j(L6`(Y?m8NC zHz3iFyF#mm9iyd9M<_OMGIDjVMzExWx}F3n#R58u3Xvvwv5_iaHqZBfsBrk7^~j!Q zsL4Qx+LqjX(=rl;BXoucr$5fW?^NQp5kN{d- zu5T8Nsra<9)hKJ_=0Mb|Zj;C~S1u!rvnyCTK-U@; z8ok7xpZ(u?s-qlvD0eTXb96sjn3>5EN=B0Z98ZV#@a&D$Fx{85JAa|#@@H2G9U+h zzZalgyBph@_#hw3ggE}V&^L2Jb1nt2rx*V;NzcLYCBbgYnL2ivbeQtMC#b7&`c~ed zazm8TA&!Q$8ky(+AF~kOkVW@b_+VKk;r0^&$2z0#p}0@Oa;6h#V|3={#E=)VG%8eQ z5|5}#%HIopAs8pAOROY;>^Hr=sPDcP&$&TsSC#zVuoeEK)1m{~c{(bUlU~+z-3&_J(SVw;&yIU^KbQ?SNk;4_L~Iw0V;LDhjDmq*6Xb_Ut>q+ zz<>Ao#^5x@Qp=qmA*O$AbSZB9;lgKYVvXc3vKurL$CHpV#Qs)upl*@!5+qt^u z&bU?kY@tXXGmVhGHNP$FGLZj&_52m!ccFL=?qAJq1HRrs_1Ay+~{M=wGAozWmf$;kK0Ibj!tRD}$+7E}{xC=}8JHYQ# z!SMB0@NMD!s8Dxt;O?dSQea63eO!aSmN*l^-(2`R>LdxjYBU|+VD8!bQGj)_;n)ED zozYJJBJ2QIAf!!TKMdt=2R-Njr1=_xs5#a5r%anWvqqeww>H%XKA&GE z?4*jZk5^fcL7N_-hZ|4psI9I-Rc3>#!=^Z8fATM+rFL;RsICPrO;V!mnx%#u!2u)2 zh9nq57P9oFqwgmCc}oztiiXSsXZW)JCOyM7EZvGwn$0PnQ!x8uW#P^xfx^h_up%e$ zS%wIIzcAT*xT}L(Lm^Z^!?o32ud0(m8C5&jEdVhOFy=04v@u(?1$)OvJt3ms*_2i8 z=a+n)7a{RIGSLIiYSkQVQAO=Tj-uY)pB2ArfnO99?wE?GQB{nc&cthqc{WeQ%UFI3 z-Tqu|z|OY#ygEFoKYr^ktg}eDt@g5#l|u{p^KzN|;uWlj88F3-utRp*oX&92-YDC+ z4*XBGiHyj`XYAdTPU6*H>(w5f!}wxA+RqX8F-k|@r#>D4_bfi*5p|}lyt6nEjVFSD z7hUMB7@N`hlFO|uJ#d8N9j?1E@&10bwY?v3;+)Fe;FN?or8?93 z$;kxAaM}FtNu!u7?HFQHn`K4S<==N<&rF>-z9BVDAQ5<)&^jw9els!@M56@9t=-6$ zg+6yDGfGni0+J-G_h)(=@LRC1_Hl9h0{;7FdE^-@jba;m>B~GDGw-l4W|x%6>fAUP zmp@{aJ;!!iBlE0BejIll`>xSmc+O|R8q9dCb)q^07Cg6WyKfBS!9QH!Fs<`z;BdXJ z(g*in4T94d8Zd6&Dzz|Qd>jz-)khDSBE zq_NAurvxSi5R2zLjeu11^IXlM`*u-+|t&70)3@W zLdY@B@|E`{XCX!;d!+!`9CbSW?jNn&rVbn27L!V%0=F!!RTy}!+SPM%W&3hzJ_h`y z*!V2RjB9gZzS|?~oem+<4G7u)74cB8p-K~5bf~A<&yW0*ervH*dPpx2hP+GPf|105 zu1T-2yOJKq32uBZan5xA5vLREAw&9krQ?qH|03*=tnsb2Q_UzbJyiRjhm|x@`iC%R z+()$6yb_%sx)Yc9)jy>^xY(nSxqcSt!SVJD%fzj{cjGMm^_)Z>F)G%hw|-8=}C02kuVp_Y{vN->owHJI+K7z z(K_eamN2@gY-2iqXC3PeP0slKGTL^wE~=n3HUQ->d_ zm;V%5Q;NIGic9w2BxCk(ggVnj#C$UmKec*nIQ@UP&E>JjWU^e1`lK-_>A8shHfbqN zKl}5Vgzb2if~{C}v%WBOFDjqom6K)5yWxkIMCFVS?Mt|SK{n+79u}T~0(`ETYWA#>Gn!iYhynLWBnZ%y=*PSiUQet744hHa&E zRO&}8a~+_V;6dNV(nRtI-JdF^{o0_r0VDZ#Q^pue2cnyraqK!jDZNo|M0b~~s{2#i z*Y>53@zL4Xteg$J+0fsj{i&>Bv^{B!LV_S-UYXtbwp4F~Y>80xH zJO(ceFyhfc1YAIZaT9r7N9Up!P&I7<8M?1XnjGh4``=`$RbVXuM*DD8JFD011jv`N zTno-}b?Ds)$0Mo=n6O3DzcZnj)WF2*Wli5#wZ@o?Kqh%%NI}`tR^inc-#Zi5)eNOI z`l@HCUralG>`pO_a_P%H?$y}xS*~G*X~u`Sl9WMWvo)Ea@Q;~^0V3G7CTfxbw_oGx zL5r4-_nfZXrt-~R>IiSY>jG?zr#_Fw%<0~08Pa!3oZ?%jlkX61drPjSUX6Z}r|p%O zp>z7o+7P#b377B>VNuqjo%-$!7G(5NmBt2R{eBjh>zi3{`P|>eDEs8Lpf(chTvG74 z!gBrvxV-Ry0fiXKlTvr_(@(C)$GES;5MwMH+C&8`Ui+~Uq`_peqKy2QF`AaU^zPAj zy?Kg`CZ`7!N_VQm>=JlWn;FAOnwhyDr~CGwH5R0D-a1`foH_m4f?fcG4Bg6Pr4q9# z`5h(c)g|89nV6Et$KN5CewR~&;l-wSXwdHK{`de_l1Qitx|?v$=7VRvFtI@M@e#Yd zmm<-dkcCm)Tnz{gI$&wn$LFaXEHci&^LgHhT8stmajxuzsJX6T3w|zuWcwCQY;`dc zC95Wz@#tfW&(qU#&_{T&3GVoR*9T%u522wsva&gJ+2|Icqg+^+8#XOMM;D#i9kCa_ zA36RR24<(%pW>N0#v2trl@$e-OQ3H}W=sBVo}~g-r|L8_2o2Xz(?@`y?<#}_*@9+k z{UVx=DI5gA`CfEZw#ase#KEc2dhC{P_v^a9WZQ2`j_?(u;V(I;l?4$2!;Ec#+MnjY z+n0ZF{{n7YOBL{C!V=G~(Eoal+QXr>!puYt;}bo$#mWX$Ys<4 z`zN{4Ls~}{31zw5PqkOj3H%x^fm=I5Jh89C`FjukoiJQ0pk*k~qr2cFG-6ZBt_%E$ z)uT*FQzGvK{EVEJ$22?UqK8Qh2|$w3ooe-i;@oQrS&iWzO-u?KSU0T_#~!!F5FlFy zt6cH9R*y(j#>3)Ar91~#A7MXK!CcgzEARA}o!PuSiKrS)tTSyci)c5JTWUw5CIS^U zg^~nuO9);?m^Z!ququl%`g!2=NtJh9bw@zvG5XK zzlMym(B{Ly9~riugx_LA8HxnqPL|yg-cr(3wEA18P$77*ao_|9lQ9te;8y#j79HU( zN}3T)ZNq&fWWk0@f&s3?JFr_XIWK36Q>HWyE6^m{mKwZ)d6rJ2ET7~n7bAP`EO}|{D%1W%iRC4m*7c@h> zZ1DicjWetpRt`vkyG%4Ppl~`LWm|P+x0Es4rq|uH=l}o#YKO+_94TzQ74v0OBYUX7 z*8fDZ{5{E^xGIGZt<`zuRYmn=9piegprhYjyW|<-i0{`sX8w(PJAw0;a@WW(29Wz1 zk3oZrP<Mn%w1-DIBkSwwe+m7AUaCl0(2AExY zz<>Z=bEeKpjGunri!hP*_0z~K2Dz7!<-Rm?P5tLqdAa%_LI=I z!~|e-8+bw$fa(|v&80Q!bZF#NtkTE|s51hfFmK9=rb{0KAu}gWRKz@#aS5ILP`Nme z>@Vd)mqDd%TH60==aAY)4>NGVzc7sHp5O3(%8_F<4h@&#P$D;-N+3pC49qy;u7>eADA`TW+&a&8|8v#O ziJCzNWwpZ`C=`m0FPbU4Ys%~?0Vn8}WFW$VF?%{jq*s?enRF8V7#5iB@R8+K7*&DEIU-2zst(}GjlT6vmc^G_XnR&SacVq-*QrraQ) zDNNQSP}b>{N#OCLoIZ@rjK^b|h^f`Wi67uAOb3

zD;#v0H<>90Pkii2N_7pIGRF zIWKQtp%|GK2|J}f_)uzwrUDFaFj$P$AWXyGIS02FpWGe8fWqF-Z@Ow;iC6oNmN_~X zbp?nA`E?=!K?(t#m6IL=8{Rr2F>I=B;iQ-?s7p!!c$+S?S9u3GlZug5LXXTvJbPIq zk|$<@pQ-$Q+=XPec*}BFd>39JaO#NaPG|+pa;6{8Z+fxq=EY6($!=o zg?V!ma+)Qx{pVWi8x8ivQyzDL-ghNd)4&1M@42mb-%1eXyg$v8j{e?nCR z+PvBa@~e^scY%;!$nXkn#%;x&y!|2rsbh7Kdjo|L(R^acG#Fu{w+|?8@vysf!nvO{$X&N|X9!T`W^?sXThKrb1a z5T2i~1{Y~pAxJfd{BeXRi&G-a01{HlZ}y8LPhp9O>wD%iL8qgCPaYCYbr?-pEf7Ts zS$nn}1(WAxOFjG*h618FsY+87kz3IprHZ_Vnj$Ow%0qQbCYiJ`gONRpopZMd5%_`31pwn!o zrT-SJ7>XsGM=n!<^r}qFX)<~kr8Xt0+-za?$YoJFwMg^SaX#}I?SOYLv+uKtXgHS3 zI*{{<92b#s!AhKoHEjxhXa-KvC`HrgRJ;AUlAd?*_khoYIMoZL6^}+No>d{Mn|!xf zAT=eO%vBT#V%@8eGq)$*|5T&0-W9D2zZ~|3rh2ZAkxxk&+{|qD_6kpVX$xfQgu$Te zvPDrPF$sk7%jy1?nrd&&WlL)#Rfb^_xjVJ3aRXM{M?YpTR;uZ~ zW%4?6Oe?|G)+S66d}9-jCzGw_0_oVOH^~J+-t1-EKX2LVbdy82fryl${uFQW88bN zazHp+W2@A+`^MN;C!r$1o;C%|=4_q4xD0pBF7Bpaj^-Sv?q*V1Uh=qgsj~M%8~-hs z;AUWwd&G0`h?I4L4HeF(uo(QU>C$Xk(w_wp6`{9V6Vi@2SKfy>`OL4QWA=%&mKEGM zC20YP-n}4Yr^aeU%KJ z*eo?xF(7#zI`A3Lb;8g{W9@=EmAO%ZpQZlRK+W7f`>p*g^o2Le7dlPfts|^D3^}g$ z#5zv<`0$;~-k(7E>sFJ>b!dT^+u9=`P8c>X3HI}$$`!=>km$a5Buly^#U(=cPeAes z$X?+n^}7~~=}hI@C2f&-pZ5luE9PX^R#@d=omI8b)Wo_8TrWUSob2%_cq6poRfv5O zh#+X~%>Q0oMYQ@6w5M527X14*l`Kynl~zg9Sq^z`4pL5$tKTVMCswLRkhewJCgJ;^j`2XW!fGwx5;~1&zau(+smqQo z$!__VpNweudwzw|i)<|{;r30r12k6BOpCf*EvRM^l|3x)v-(cEc8lPIzFQWnaCCx_ zRX0~Qo8N!cP}*U@!Z|LKa90K)|14=s7z}Q~v{@#`IxM>UTglU9yfz(4`;X~ao_aL1 z@I%}$-w%uJq7N=Y0Ml4{z|1T6t@Ti~+mwINTtaKo8^d!C{>VpczwKn~HzQ~iFWuCk zXhAahKJH#|L2tFl|0wf--{*CcOoc|{f! z$uS6UnoFPmfB5crgeYhwIN3!X!;t!c+QIAACHcD?5Amj}@xT93W`8SBiMxdVHSd=I ze_DJ>fA`*drvYx5?;G572v&etGkCUt<@gkpsDSu?E-&+wnN~UUE&!z`aB~}@m&8lU z`C$?gEhd3{p~;%Z{#<$FyIA1R{Pz}8Tf_wD4D15;M-YwpkS%K5!+{m;mB*F}-}w5G z`yK+zRB(nt%YS|umiHEWB-wYMYoizTHt;6Zl^a&kj-b^?QhF&!4~u#c|9|j|pZTqP z#zxiCiCpl0>nt=7(P-i?=CZ+Ku^sz;^Dc#jQp|x9B5=a#@ZM-;Px3s;r1GHex~3qe z2&cEA`7%xfDBWl{BuAvo+)b-Q{spkzyt&=bH17LZo~FZ|pamXBSc;tUHsJ1gnxFWX?`Y|7lo_-`|4Hzq zz-7KNNZog7N({H};)wJglZfPFd%JfJuZ#FPdN-FpI)E&{*GSx9<$S^NwX=3(i&T&R zv>eTE2t8pjR-n61{{Sk4+|i;1*7dZvhDhb6sUc77Km~_FcXu43x+VW8xYlGYYKx&z z@O?@;NG;1!^5Yen1fXS*ap*a#oK(=&uU%t&=p#|VB(1Tz$Jljc+QUA+)mxA@9=amvV6X^-z)PPV{CCxsTFF#0opfN}TZ$z)vrFs5)&$@5-W z+kgjBsFB7U^4QxJoroOTj#uP?3<(baRQD*rNNx@xM5KSOmkWwG0sf`8VpgZo6%aNUPh{D9cxn^^<%6H6e?(R;o;mQhgOY)#eaRvb&VQFrX%4GF7SQ8mRvRMHA}AlZO;2rn=7aNNzYwvJAj6Vpb`Ka?7J=VooA8MppO$MRPs z+)Jr?kYP#ja!F|%pdjk}Cj^0rs_y-p#GS7I=8Yc@)aSHr>L}Yn#?Djo?JNtw*0R7h zmbc?aq|l3aw+7*e=cx)a4&hh@+}3xXj!q*%3P2yd`>Nwlzn0(SCl__60;t{bj@;prsQ{3OBFt?Y2h_KI_kYTCurp z%Z^Es7|$_9H5?}7lt~f>cYf&g3pT^V!%TK%?%Xam zw;`!Qc0m=fkATQ)@A060pG>+y&!jMaI}yx?xOlikPmv!0g;WC&m-|P`*zUL{B=@pu zOMR4fCez&Fdsc1RmJ*j<6x3gZ$v@%0ip%}c4>2JIF6I8b93kp1?Lf36zBJ3m+Pf$i zlOX|3BQy78%>+PC8!lNm=pg=hU)D`3{}$zanA(s+uxq{bUrJLty=IPB7P9vRE$Q)1 zg-4q2bq@M7C2Hl|On%e9ILQ`DY!6ZgBB^Y+Tgu`%x0xzaf3)PF#SI~7Ik8-2J->NP z<_oQ%5}R`^|;nbSIj@F7C)tkB7O778PH2lUpm#;@h2l4<*2Z#UoGb1jWQ&eq(+`x64(C18yC8{h z?k*}9v*R-$LE1k(N`~Ft)1XI%H-zsKeRJqR3($M&TZN%p>T?40DJ4-djzXM)q&57= z*d+Jq{8|V&)(G&QSYU9KP?O^FBol?egf{XY1gM#1q7=;4S~QP++CCNv?73)+TORHcAmeDKR`EZx{lYltf@~^f zv=iQ@VL=o+IU&Q6O~TvBIq_W0izmX8S8*ZMAK~^$+Q+Wsxdt)`AmkV5^#?qe4}|n0 zLdJ?c0w3se*?XctRmj3=90B~5-UdIxYt51UL!n%g?g^i^;`N9&uM2~{l(uyF zOi+n jYUxTfKcBROE*x6j0*PsLDTr6HYC7seK99cD6wadcqPV>0lw^(gbVd zrNY=D;z%_}_QDpQKn!t^~Lb&$(9Hq@~^io8ZP-~am&<{-=DEi8*`yGF+E*Nh^_rCBBy57r^pYR{1ULrTkiP3_2QWG2FW0AhFRfmj|FzAr|+$P#bRdUMEFoP*bPVkp5h1GlUqG^ z8z*==^G0P@=Kyh96b{x-1W5w6@0K-(J2{rFxKiT%md{cci`?}-MycscM->7ag11K< zp;<*+(d5S$7=JGzb-F4l8&#;=6F9Ce3Tiny|N$Y9gv7#`oj(Mp%Gs z7jh^^`U4(UgI7c}2-+pe^(8B9#w(eL3)77R?Rq`TW11WrGn(D`*J9f5=b*OZ2S<^+ zXKNfe&TWZ($C+$s<#4iNkqFms=&DQ1X(ARA{m^l*DqhO$X25FY5DR6fOWYD}F1S=~}4=D)Wpj*UqSX zt3q)x*akjM7k^J4K^^8{<(0@IR+?O=&0QOZj7XL*vfEmXnUc-D`%O!xG^}QYXYDih zP61He!6iY8Z)H`aLK8;3M#B^EMRd(#BS_ingeZTAMmU5lYmcVgICLf3R?df5-qgdo zHK{$>r>v(WFxPGSIj8M>xwOk%EkUBqVbKxZ64aHaSbMM|4}`w<8t1M7rk|)wIEV4= zAD-Ev**VFEyJM%K{KYFn|8j@B2Kd7|wc#q7FNxSR(Yygd=lDTV-_CP8;o{4I-LKry z@lXK1AU$s3gn_q6ZT7AnZ(4m$%gI926V+Yn5cK{rN%sm$2vk!>!Ky|O??MnBzX+TU zrxxCt{u~ir;x-aqB!4|^!Rm&@0+v68V5|IJg+Yy7bt=);fA49-)#Tc|fMIN7AHaf_ zF86!w(ScC;&3(W(x+a*dZBlBTi%`aMTb=e&+5K4eKh`}?H}NJ|^Hyb38yRW|{SG^t7iPExDb~B-;?7!0{#a9`pK^2jL@s;Me^E9qsxtO%@w8_L|(K2W?53d6F_cVpY7T$qY2;NrauhZd(gqx&)^X}$=7 ziGF*iMg+%gz&hSi0VJ6=@K@d-u;axVdB2M08(P0el~~Zy=toRj-8;cp`~p1p=~b{= zyN@*_k&qOA&tYe&Yf0Dk*+Hmvmr!-$VG_h0EsP^PpBd4b>`;w-vo8RZNlyJLmKYtk zAy{4uEqXU&>l4q7&H>zlUVNI#9*{Y6*RSf5OsC5jmsD8{EyG4wbFLkUa85hxs>So& zH4uyz9z||&K!1Oar$`|x%ciY5wDEptVXd2U#OsOZ5p~^OsCX6L_9AAk(8^_&xwO%% zGigJt6F!3K0~r;gkn2F(1(2Y`Ws4RWKAbnT_>GqFqoxn4;u|ryG&#!{ZGe`k2)>{3 zP8Bm`;S(p_2u}UfWQj=g)EWPH+9qoTqZCID2SNr-a~dLP2{d8AopLJo$D|~o_%x&o zWf@_EMbqkPiYdwc)`4!3P4#l#e=cVHFy;STdLWVb%2;=G% z<{w%aIY&seW^H}53|251XdFiBVz2=?^xne4mN<*ml!pINXR0k}P(%rqmxGk~w7iv6 zR_)jY#3B6ovYThNXVJ=jIS8~`PvhJkqSa4;um07rJr;nO=s&z6#d$Rn{QfWaa5NPC-hZ8^r+u5MhP1h93*W&9 zD7KM86;n_nd7-!#tq6b1J{o5*nc^m{ghW7}>GP_uV^{^6uN>N8Ke>8r8mlhxDgm=# zAo8XsCddgQS&VQ!RcLfy=(T^I!doF2_zFOzJ1sNmvHD+rlHkA)lUIcz6Ef38Z~lC+ z(zlI2^`nxqv5tfn(De?Xh030G<#d4tahJL`GUSG8rOqk>^XT}ZBM4qH{0nZ=}PFU zjAuIk9!H!l9c&>&g|+fq*Wp=f-yk$=(MEsKDj-6MO6wj59LE8ezfufzmu~4ZL;%d7 zx2bI*i1U?Q(C=jm|5uxlr8UAM;vg+~Bjalk%E9;>Ygbif6q7UF#Ai7<+mb2$rAqVX zwGTMti+1Y>J%%CYE{CV_y_D_)tkvz$#=$#5>3c?*hDxN=EGEF!g+&uMfRxJAT*lj+ z>)4Omee)eb95^AO2KGv%QgDf9#) z&A9i&SfPQR%&@DZ;_gVZl}OOm1|)E;gAAqm3F^W>=EI+~dQ5wTX`5q_Q(+Kd26YX$ zDB_BTA-g5=mA=@^(p<07>$dQEv}j5RgWN_bd5f(O*?r@24ed`bZG0U$dXfKA2ROU5 zl5QGpfK24d2`X_SH=)0nGv@V0r%2$MPB@VbS&j*J9%$eE1Aoq8&oL1!unc<3geTmu zubTs5-V<~m>c=5ff9w};I!jSg=6yxKDfi&mLG&XIkOcd)8<8< zu@4*~&O!I$tA`VQU;i$z*lR9@G`=JOSCK2k4d(kAzn-3wHSne~+u1sdpm*M4-$n_M z_o;?fsL?Fa;sfJNkkG8Dp=!lMm3h5}J!XZ7QVaath5div|8^a?h_0luY8d?DA9B-H)V-l~W11#8DIwy#UW|IBX6WrRYUqby{0>p+yOx*z?GkN7+R}U>d0~ z1L;c8=WPXJ)AbN(g3X=+4-tvKVt4i`9!+01S>~hQ2mtXSp_mz9mOs{?>C%xC<9d~{ z#ap1fVnuD#YC8V`M2%=B-8G)pDI@dl6&p(wrLyQs7O~E<%ya@_D+YE71*z)aA>D8w zh+fU-6eveaAd5JK2xspP;pMY`n0{?<)zjAI>eZNkjkd(5ER~n_k|J5Yp^W&^pNTuc zkIgbM>z(%k>3J^3QGD5_=hQ=2XkLsaM^J_+ahfc)mt3?^m@*Nv4ij53iYNwmh!ekC zY;6&(=}$$9VHapF*#b%k^8sH9h$rW3Oag>#)pLQBAM$2Qib#b(LLpBxde(aCzLmdz zIVN3b3KvW@51AOi>BNL_lcO3TCx++D*lRmaSQ>h|C2>Aw@^FkHVWW0f>#MW3yh~)2PV?B)|qR zFzL)ng!m~WJraErw5zk+P69S6ModrY$yTQJtmIJBaqK;$+#szEtil zzYj4q%t#rej8Dm4j4k4$O7n}g106_Y+aRSL`H{8o-`6-%DOKeU~BN~?>XlB zIYJ-5Q=Nel72YR|c2MO!iZY0ti(3(-Zc5+jKZ^_e8JO`t77b~`Zja{=by0$>W#;;A z+w&%3m+yuCH>V0q+zfitE^Apv_)h}Ag7GXx$JP*|%@rsEKFd|fD9=pOCEWA^p#K`8 z2#cm=(`HN9@10T}-4QSUUsk3~UYwL0?l?ql*Z!)hsKC zitcc&GV4n)>2!UA%Rn`Z_vZdZv4lHf`ftHdm)gaVxU70GL;i|%I-P82aI9fILB4FV*n3e=U^Z;;MBk{5uIxv0pVl|M_JUWYgmodqXC0&elj&CgunfvyHY=z z=U+$wPb`Nvh4)r9WjL-;-20qxsP`ks{g=y}H7VI)e&oi}FEI8}2%w$bU(K7(7s{#X zSR_`^Y{j$!g+LkPRUn}g%07AH@$3n z*z;-PR5a^Ciz^AH#d+MXDU}19l0B`8gkR!;WUJBlunbX4DkZBK-O)Q73dFzHNBFAr zl!z`qP3x3nOMRR_uP78MBhrU%l>zbyK;o4B5B?zMt^LI+AIwg`GOB4qDrvt6q?K=| ze4ILMZsTfDinu{xq}wvCxQeIyBYdhFic)d*+}@U|c_!NSHn0Qk2XX$XoV1LHjY0sw zQhdp98pff!LjP3HLl7Eq3&&pWR)CK-WfbH(6z9!HsFD1nH23ix&{myTPPv4gtx^wx z+)*4w3xS0wu z3XbPCIS}ZCRGdnrQd=xaEQdKO-FA4v)1tONIZP!lO{Hj^o)4?E?rW6QKjVJU=mujC z3(48mR{UYs?%=>rBmCwYWGRdvB&kEoaBf@9rR{v0i%9bnQJ>%V7!Q0Ki?(1JE`X+7 z+otSvzI#@J6iyb=r#8gN2Cq#J{{h02*-3&=XAYRjI7rJ+PXWQ9l2#0Oc%E;wor)o>TgycaMKorB6U=@aLqqhCqsFgGd-cP*=()wRcGY7WXi! zmxVq&huw}h`x<3g!~-tyx7j&~f3`QF3joru-X&W_KY`p8J>_%W{L`z0Ar$YVS8TBCKsteZ=UMpS zkYFCM@^rpoFo4mL_oxTgB9}mQ9;7Z-l`15dA`fT@JHmUyqLrP_@j^N6kR(WiN=g=2 zC8GgxW9(1EyfZ5QZlUOB8`k~C_l~R^-yKjx>|m%wnrHCl>@^{9-GTGApsD62O0jQ! zzwsE>e^YR5wznPel2h)ATK6@}Wm`VNn+I&Z$OIl`=Ppq;*s+?}T16-TA?ka{MbNGo zVEF+(6~C!iRg5glk|S)`n~~2RbuyJEZE(62U^%V6pBd{l@=N-9Ajxm&Mv7>*X_--` zu;6w`NeXE7iROS$)l_WGcAr8CcJ#cCMVW2_)k%34dFMsV?w>8H+S)tEq~NUw;kZvoR{~qCJ)!HbzwtRh$!k*JOU+I{5j-kK z7c0v;(flXp$a4awDTt}J0|5p#nIL@I&+a(_Yci@+I2l0S+R@Rp56J}|AmyB;Rv2EM7=Zg(G3oZzT4 zEf%`7dhkV`@)djy$MbI~To&y$t!&C^@jbNknN>(cjk{3@B}aehY^?2_zQ+Vt`jpd@ zag0kbZ-HlT=Tmn^>7)t`=sh0}!{P-MQ-Az71V-DzMFfS1Q{Oz7-jBR zql*A0d)}VBe?k=x7N$l1}ea+NHbzimBr$tbe1vS!meFg-GYKPo00004i ze=%NmHhi?DjmXdSW!)4cG+NZHg4X!QTWN|_M4$@M==Dx@ZO4UVBoJg%;Rin^Zwnoc z$``a&dGzeW2TbrImH-;59W3M;^?ps)*P-jB@h~I+04%58aR31KcFluYqu@V^fOYA{ zV=^5UI94g8p)|CYujFS)ceQ!fP*NRszK^4&TNN6pOX{6K3=ZC6%-w6F_d!jD)ic4P zBycqzbmq4upMlEhP+6^BVx2ftWE+#%rzRj-2@KFWeWvDzrwj8zMx;Mv`~_yt5awJ1 zMsL*K@-*wkjr&kSKgu|=koG%aF<#9QkO8ce1`8Tbkwg)epl7&zAZd*dVB?Ty-Usbf zS|g4!Z$?!ytkGRFMgzs)-kEM=pTjK7V+bSPg}J74x|oJIR%PkKCUv>B1z?s9`;(Aa zB=O=T2@@y#ah(KNT1 zVe+djWRb>^l=XNyPaTO8S!qHrBCtuO)TY(3*J4gFHU2d+!u@_2C}>12 zxezN!3F{C8^W3XSMehfTMqZEP@v&uJucAR(jZ=04i0CneXQ36Q?*LZKeV%*p)49Y+ zQm;j(XD1Wox074*5S4z-DjNchvP|`3JGn9U+7B^FzL(Ry#(hSunvls_Qc`G3@5c@U zIi^7VhimF~(YDhbO#ugOUFOS6^W<&UgeJu~cRlj=zH*@M>+@1DYpPb=h>vux6T8#m zW_-jzR>sc^a??BS3vRGhRBW}qPm zq$yZY$|t&Q@Te@GLxDV5k9EpM2vVRGAprRJ=&N{ve`N#7oU1=Y zQd31@NR=#KSsKE0XabTn5`S)ovnc}#sAwqk{r)JHnL?BqCxVvXz1V$CCEK$MMQ+;@MsQkAe+&(75^A7*zHC%-4_AcS z>w94?<7YG`6(}9qPrmh?ZH%MOxb5C7u$w*kgKd;HkouxxhK=EVym0jz#%fX^^{b6m z#CHGYD<3;etlBu5^pKAq2=b9RNjTt7F?9%;;q>Mjc+VIn(hJZ|?^-5I!hPpp001z| zPXho@R4SFcMCk2uz$~fn=6MNn1>B`lA?kOzQR+xM&uXs%!FQ*n?ap6drJh2IF4jK8 zXEgiEzNVzu6lVFz9TjT5Pycnn+=6V9}uM=*OiS5Y+!HaPnpEY81F3O`!RXi234x2BN!Vz zK;&|h&Gz%bZ2bjsPamEaJcup#+yft1Kfu`}?4=sUy6I@fqo~&4bjJJ?wJnILX?Ergm}!9z(>ayyK#ZcAWA77d6?Ql=h_kb;VG9JUfJc+}t*SU<_{5 zLMqZ2^pIom{ZJaxbp%zpsW5is*K-WZ6(>n_-6DExLeQGVxdknyVOEB;+H9GN%WQG3 zW@a`5G%IY=9fVdLN3>~lf|DD#9roNfu9P+RtoMzh{hV(nab*5cu-#K-&_HLmKBX3d zT>SQxAxnSW7SiPEW)Nurn7#~$>fkZJ5!zz8bblw`i$xmp{DjEkQmNaXyy@@V6J)^4 zdZWov;+Q^TG%A=^9FEAWzNw&C&AUwDQR~-a8M0CyyC>cpgHxvP9zl|k)4h(fyvW+7 zj82!u{cMYD&)H?F9gBLM)El%&xqi%Q%-bk$=GRf} z6jKVoHsO;g-{i$d;H?|E#z5lifsH>`YD`x)T~?8+=An%;euzl#nJVF%u(>e#{pa^X zN<3H-=iF3-p#pcU{9WL}OKuv!BjT)ZTw{4S^2}4moMil@lfdc=-4`y*gWjFe_~Ro< zH}lJnPo2dkg)Uf7-MD(8jaW?4mPXmD&QO%#qrGR1{MT-{aktO+h_(!1K8olDw)wyb znWAu9h8|RzwEHiR|H?sWA0e53?QnbR&=_I5>y8NJ526Qc4Z#TcL#NYOLD4Sk!aDh-JF zGarq``%)Sdlhg?Q2emI|X@Qb@yYLBTssP~0Krk7-BG=g>L|{Q8fG;eG^tY0GiB9;> zlbVW;xI+XV_}s+8iCm`Qj4=pX=CAWD6&S^PEO0}`8uJY_94g@uOcW`?evRC+AK z;ac?h!?D+efx=0M4e-RrNqio1)<=oKhS&FLhRYlSoTo7OQ+Zw;j;wSXiA%zW9XN&`o!4J_d|e=xVr%?K~P zPMPpYMUHf8<@A^*H!IKoM$IOtx0a#;Aqvo?-7;}fF`UbVjBp#heRlRx)|y5*Zz%ER zG6yfgy{Q;!i2vZ!`-1v%{nmA}J{V;NA-x-CDH67}cS4;t^IL&6B`5aGM_Xq;#-`u? za8{68=tJ`mOdKv5GP{@?+P_9D{^7AWWmE zkVA=Eu8q1elwiPEGcOzwEfvxs8aT|rCa*V7 z@1RawwTs!`a>pWJeCKdOzM~zi-zvDAe7x_xOZikX?govq46fB_afpdHyqPF-Yv{>t z!S0@19a_HuU*Ialk{wacA2YL6rpD9bM}d|JmJ=1<>@=kh=QEalJ^AGBb7R@ZI_Dn5 zDH%OnzBzCsXiT^hs}SsHPP74}Mo;Ss!gX(6HWd|{P}`-H;P?dW(ek$RZYsWONpr+D^o{LT++Ox$4(=yS}2hqrr(P6SRdL5_PEqJ4D2RKXF{Bm!YO&*!^}rt zlX{A53E78S8Pnuas%CNn(>?0Vub7+ zSea!nXZrH=#%XlH%0xjEz(fDU*ILptNm=>~pP|>r)p#Yv^=?YKnhe!F~D5?kFssV~6dd6)-4PeQ*LD5((<5Zg1u;pl{RW$!wH%uKK) zCDQLt?+!^2El6;CT<6|FB8WB>PfM48T zCi{HUUCNHE+?Z4RWWbS*e|AH=+#?uzC<7QWrI2Z^YdR%BAQ;AOUi$IFLHoK8pqwQ5 zUY!uWh&c*+=F-r-q#AcYEm#eGA@jzcQl?lC(Pf2hH>N4iha4~}X>d-=HzUh~!7%V? zyKKrhYUutPz?3!O64Zz|D+c@ZS0ggf;MKfVO1Htu2*xf*cVj>7zjhwyz5Mx6U@MW@ zN;%yryoheW3$MM;BI$k)!1xidM02gR@Xh4=zH@70yBMfi=HI{D+;Q8+Z^5{6VI65B zc+1^LjFGV0Mqn{!1%_hc<4!a?n81o*EpDLfSK$6TwY}*beNXGf9wPT~xE3k|Lx5bT zHMvp2S#N_jqd9IZ7e%j4BkC`Vn$Q(<#MpwXQV=>s$#_qYb|K;B;G>ye-xe9G(Js!q zF4IfL>%L0s5I2s5y1O6hd|0yb=~s^g{*O#pHNcjO6C){q@?V6Yg<=@gOh-{1yc$i@4-0j7$g-u;6gc2!D>8=nAy~~1uK!__;khv>$C!6lMp$J)3WHS&vX` z!a=yAo?qkZIj!+60u21!Q>-F&krEU22l+Pf!B1Mt%y;>jJyHjfoFJpJ|B|cWWMrar z6z1ah>2K#xu6@LA9o7K3G8yCQK3?Atu9iC5ot|_F4w-uJ@)v6eXcIRMGWy}I1kc}p z(zrP-aT)f#PI1k?(Sa;Jl$si~Qqz((gt#B!IY@yy7ws!lN? ztVKGD{Gx09Y80KB{WvRHT9(0?Kf}J9Pk1FVo+613kLMufuCCM^6q8D*$j%L~MQxb> z0h#C3=%02L`or+JqYlt`H@2`Q9~>zrF3;1&{hH-H!|A^f-xx8u1SbST?N50t0Zl#s zw&+g4hO}#*W%n^JKhn_#HU#?3b*5Fy^EA(o+{(Y zLVmPdnYL=*s2gZ?8v?j5nton>)0d3_U3;i`e;mymKHd;)%ofG;n9Iff?#OQwC_LB1 zA1B}HY|Rz-zub9a=kBwgZLy;(>X@dMaIq~o74k`w`Dm0?`?X#Wz&}jfJ$W)MBpvrT zX7ZlC;-TEid$j3C23QqT4?h2Jrr+y11OYeoLR3n+myK8lb4t}=!)1LkYcVLk1*Gmw z#bA?j`L)qk7V=WER&!5kS=3cr<_t1)WlPpx60klM5AK@mm*0_NWdy_`8+O>8j^?p~^vUPg*680=;-R^vaC zMeMRR6|d6_&IW8B08JSJ`AQ96Uw(EQXq0!CC#0}b$t*Kx%gtu-9(5LCFg18IWZZ6i#L&QEG?X;@L&s!{Qp`G zd}$;3kJrT7jZY(h_b?ztDRU#~I+_?ueHT|MGsK6nu0VW%)-b>c(0lu^z@+a17u7L& zW$I(!j}!{ow{=gjv#O<*Ka3ckow)2%gh80OBJ|xdq%FJ|oOMg5Hb}O?UnD7vU}A%e zM9nvnR*;^?dv@b3FxE+Jy7La=uE`~*MggoP%muD)n(Qmt=j^Dv3)Ewk?q3!7$w6xg zA?R8=Tyfs*d!`x&g|3fN4fMQ4&&SpzPruQJ!yFXlVwN!lC3WoxOmNrjGm?~XtPvWq zZTfBm(Eq%Vr!2SAP(pPQ;)M4^SNTc?w0g^MdQ>9X)LpK|7faVVY}kyzTQXD?`9oY; zyVrT7>*t@&Dd3Wv$p#pF0TEL|I(BLbiHCM-f z)!Gz0Gq)cz6$PTn3zAZ+207!6_VoZ(W}I}|6O2=BM!kG{=t#rDvhlsS`?u!%x;$6u zy_m~$mDFwjn$;AcSWJbTUx(L`yZT7F&3F5wy{=XMP3A+K5UH>yIf$43@>W&Rp54Z( zOtf3(5jQWj%FeqaV3_ARfhd{{4>f1Eo=w0ll$sV7aOU_-gnksx zZFAGfHrvnEkm0$IWr|k&qT#;#8$-QPO&%lTl`-O}^GuO{71gSPT6&_U@oP`uqb|3L zX8PSyt&xZd?&%EIpO;jN(Po@ldG*PFYs@~!nk!r$v3(IzmS;$1UC!g3JG~R0YrLa7 z`3-8WMd?QlS$zda4R4l;Akqq{O|zTo>8}JS63-rq^k|@|bs-zc6o>Ab z?|iGP@+n;auZNiJ5d0IpW-O9YwZLZd9(+SL`|lCpUn!XaI@UD(U^hZURe#Cs-_P<7 zqr&nK*!R$ z`nj#>5UVBXj5~#B(&qpIHxI-beBBvmSY3Q|K%)dncSvH99l}lJC_!g|XZTF*o9kTd zA5TLHKQ#|8TU!&y9qaTOte~eR6N4f&T3>AGaL3x&*Pa72I70rtgnS8N()^(wENNi& z42B*i7|TJ&kC#?M`uD}n5A9GR=#uBadQ$kogS7HG}W8TX_Nbn?@wDYTuQ`C%oaIWD!Pd?WUBNBQ>LwI$L~AAUf+M>eV_r4o0j9wq#tK9 za<>i0;10*VTEG^>X1F&1Bs%ODK0eyo5DUjn`Uxe#>?koW%=9_;@1v?cm(+5wN_8Pu z7sEh(H|DpA&?(S1j-ztRb2>8UE12GEhyr|5|&O*n&>0r0Rx=IdI&a}?#A-gkZ-)`aW61VNTA&hE;WQl)|*tmb;sEU7O z$`Nn|NmSb!w!XhN%=0O+q*CBQJz;>%)4msG=WiAy#$QKU+xrI@G{DDzRHa4RlnA=FiRp(gBHbkfl?+gq7@7|#m$&A3 z3DrYBNIGEYP*{ujr?^~a{ncymeWUIJc`X@W@tT9=On*bL%-x5Jc{?eJbUC+^W5aHd zRuUN1D>#Z>^*X-lQ||z-VC#@@ac*I#>F7I`d<2EG5D$5p8HN3Q#A{*QgzjjKn}e`U zheS#4At3$m&`N99>z^U}@R+-|0?37wwlCf)0$!rmUeU0qW3q66d>`~`Zx|kYUl7No z#+;UC?B`6QcoYQWYCV5~<;_CM>hn$Vj~^)V(0i{&^Tv#r=OdlJvAVFZr52%C;LCbm zsKYTyjz)U1r-s>mqPAUX<3@=5$1a?!P+BxW*9My9 zROynKo~1fU0S8!J>{iVO?EsW5_6ac0y6VR6Fg%bk$`{@GmnMJt_M+vkiblx#*CxD7 zng5-T)UvX!{z|zxm5&*u-m*t83X5G^h&G=RZ!&Sltu}VggkXMDM~`6EGKrg&2tSn~S1}<1TXVQ7k;yP1xAB*DP+_JrewcxW9yCj zNS`u-zT((!B3`FwINh@S@oG7}1BU)k6+5Q6`D5+@YO^g*cf3hMm)P7j`PaZZpCZb8 zXW|?_(H|B;$dj=f3$O2UJ;~UzZrNO!ZeO2RB_CJ(oND|EdDGFCm@Dg$ft^mTjF;zD z{$|seE1&lc7k>*QTHl%LnO~PpOp|R)ty?DP+b3F=R5SQJK5si?_eSP>@suRQdp@xH zjz57=9{1%3dheYu><4$#wbGZY?=u>})WLV&UzZ(Tj9;%8I8ytJVcjpIdT&fKh{mNu zVD-niZ(Z_6_;slRrKdBLF}%eJp1o~Zw|8tL6kpGoSH)muq_0 z%kd6>9N7g9Cf{5<{)~}BVrF_V6mGcSOC)aL1ZGTU6&E@B5j{ZL`w`VM0Cmx_4Rcjt z@K{23eH;Rk0YEp4ayua{b70(G6=Ek8Ho<_S9yxIm-QRJn_|JI|-b_`l)M=MIQGYL7 zfvq9lod!?t1aGa@S+8Oi=s|MyUXXbMqW&v##{ltxlFgn=I$cfKOmEd$wp8sza5JO~ z+I;bmx~{tIiNrSD2Gk8S8(INdCu~eZYa@g92dj7XDnN%Y82Sp|eQ&E~uhyKLryObS zEfDST3F~LSUS6=mwh}sa#M{cX;4v9b^~#CP+z&Ir3$nt%Bpd%8ayUywhc81A^0+PM z7BP+Z6yYc9>T~CI8k^CL7O9ngn8q-981Y=tP9PTg6-P%(Mu4#>@Br&B$V#vG~NO!Rq zqjuCAc>cz*qkRzrK(Tk8J+Xty#9JNCxo8mhrJ}?Vq_dLn{;4~c79^mHAw=}TdN-OG zB&E87mZ3ba8P*>~|8t+E+`|>iS_r{}#RSLf3&+4wYSR6F;3u}A%8XlZv9(Pg!ief@*vq@!SJammXr>5c3VBt5i$MW!>gRQy2~n$tw0m-AntxtA{$*ab%z zz`e6axUx?wbAN4gP7O+SJesCs->hSGJP;KP0V`|0zHP~|<+4O^#`jmf3i*Dtc=o5Y z|B6kD*Df+%2zS#0uez4<%~_1(bT*VkHSI&hEa;q@9W^>ZDP`wO`Sdm+g8LRSQ3?dg^p~-*Faij)qy+L75QTtA9o20fnnPRUufhvOe#lQq` zth@Dm?+*4Z>UeH&^ei7%tLtp^Sm->ooP0S8)BQcMfW;s7O@c?27^XFyFgNCepyHxG zZVaxdpgaTUn5`&YfpuA;E%!*E2gDG9Um8zHEjrM+dQI~u9|Xt#ZwL~dIW%OS{! zX1q0#8%>>5JxEQ z_|ERD237fZ6>;E_MV@q&<{9Ih_hFWOaje9#3S_P73@R8ySfD2bxSLkrG`S?j#G76| z;F#^(kSZ%Or@n6;Ei_lWLI{PuS%W&0 zG18Dz!oa|g(#U&(NY`;BxectqI~ahfvx`TK5+M@4B#tBLuY3biLB#(OX#O4AK@S>G zB3>Ae;8QPBN!WSo6%=b4AW`~v$eT1V6!dNKoY>Rly2Fc?)aCSFKHbSNFwtoqLc)>T z($tAVuCe!Sv5P&q{S;Kxp2W&gVBh^KNJB%i*~UQEuY zfNSv&o@p`xo$kU>kwvm5!*O)$S&@FL-f_gx{kCfzW8DltdCU5P3YDO4kpg=;rIDZ& zS3ku*^bmuj4(Pbpy772E?$BfS$Cud=L>p*8I7*`RbQ}K6_Cj={ z1-?ewZ(}6t3V&wV&(MfayDge%L4p2de&EKY#p1^0t|!?B*SBBqIQ~)IxTU(&oBWsMge)gk5tmdw%EPc z|NH9xOckye_M-58H+3_ z^#GcR3(bhSx+MCu-jQU-fXehw#2d_N8x+YiY5^59m)AZRw?iN3>8Gk1BmcEqRESFN zVb4SIyl6*hrG3F7Rr5D}qJ1Uk8jLw-y0`qMLimt2l8>$z?c?DL@uyMXQu_=jt@dFa z{rcz+#$yW0g9C|PCEK2uG7}4Nz7cg7iS>57y)C{^{*Mt!1{@OGOPbjG`&$Yc@#;{! z>5Zb9*Zgf2CP+>anMeHH_L@o4_=DBX1#9JyW(qRJ_1D=Iu0lZQfZu1)wc0>}CL z$3Ib4d%1wh2u>a)Y;$yU9v~`^Hi9G;^EKWjF2TActLJbpS!6XV>x-toXI1Ad^X+xq zGP>jMav0%@5Ky7mE0b{Qxqh*bnN3mzdL-laoN`!eP2K{_f2%2yQIQ8=03lP7i}I)i z2ofKAyAcJPK}mt9;fEsOC!VB_+U04v0nRSal=a9|mvJ9Q?KSl3v)?iTt<@m9m=n#B zDe+*Q2`-$2T8Vn7@=m?&6X+z5p8 zq}T3&>|Rny?;P0Ovgf`8Fqs<*yKrySIY+zxLA%1at~FajmNu0Lp9iEdtUjQ%Te5ww z{2ifur}?i21n=r%MP%27_i~)(7Aph2%6md?S+3@6X2C#(+)mRB319|V2(7H1>AsMe zXRr}_LZk7*LKg@es$e6<(n`(-ORUKz);di#b`|vn;kAm`-xv0cE)7dcAb~*YU}w1+ z)~$+$H?AQ79I30y_>#U|Eq|;8NeDxyv(OcJwyH(0@LQ&ecgSLDwtt|rg(&M!@sbUi_qeQp8eZaYE!DDvDO>PGPE0p z9i~a7XpkYSx@v9})7hom8#GM{cki~Wj7gZfpILb2J?p{*Vhnb5nu_a<2(S+}A8~Mn-SGct}1GDh^XC=i;`cg_j=EF-{ zbh(}$?p5%9izI}+{AOcmxVAp$790BN3}?X~U5w zHCEwGQMD@OQ{>Ix2)5{-%G6+y4Sytv`{An+cUGVD$=S?v!d5s@M`^Lc*4vR}54|-V znY3f629UyEF@!Re3%V#f94D?7ao-{;Xl%O=^CJs&<^N8XgDqOcNL_;a$c@H%TY8}i zTHpg4kIA20X?`ndWk(6&^&y?5qeeIhRR?^WYQ%wZRl^>?;Gb=vjztuhb#>8$Qw}W~ zKcI_f=-Ne}_U^VDFSPGOf$vH$DuPwL#}3E%A7el%ZPR3THN0dfe1LbJz58tDhWpJ6 z5OYi{d|M&b8=y_9s4i9c5rFR!Rf_yeKPQ$LdEK#~ARQ9pozx6}%w*zpSL9$Nfb?CT zEmq2#0%^;arOTCQn9yvS81-*0sUUVy+-ij@;P@k9LcH)<=fw?Kz4C$?_x=weg>kP? zI_C+H5n`Qwe%QfChK2Y&IoqQ8@1CGQU;VNvVBsZg#mdzujdV@G`-&WqAQBY@68Xf8 z)w0}3<6jE?gTWHa4!&~)56f7S0G%Y@JwwfGk&dStwtwz0nJ>uua7%+Q8-e%$O3Dz( z$P&L)EpD+EiKZdxqH(~xQwF39PW7CQyo##}RfuzMJ82uqeNGf$# z7RQ5~!K5{{ZjLEv(EY-r*xyG`L%lN|!o6DT-8qv?$KC~)ZYx!14Dz{;N|zDWkqoxG z)B@aH52K&eC1>g|KyCCUrji(W5Wa=a+$+_)`uD6qLU+a4#vP?IA1JAG2y%tsyi{zHk|1D`G!wf6|g z=(>cZ7LRi#&--9LI)07qKkG7}F}1n2(l<)K^g_?8|(XFtq|l88I-sl0wkMAD>tCUCflI%PrM04GWm?VF1Zz+54vR$Ty=Kpu1S5Hh`cv%HHmHGxt*d)aKZ!E&JI zgl31~yTPCYXE$m}wP&NA5o;#`FU!l>?&xv`HWG<7s5W8j)b0)qt2+SPC{)U`CS*$+ z0;MDD*U^L>ebGYhpVxHgbzkCx0)Z&}kW3DSeTluofmPTWNZ(Z*SQ9+@OMoTCuLW`h zp7`8KjBUu!Tukj&DkHvFb<%|Q(D2G9QdP`FzY#iZ89@%C#S2H18#^G^*HEq#hlZeI zf4rr~N7skv3zJvz!gy12M=;4~+ z%$P|a={9bb|M=0m_grN0hv!(n+CYM(Pp0wwl?LuW1(3(QSoqZ0vg;KTuw11QO>XT3 z^=^_(&8kdDrBaju59l|vI0mSpUtZ;X>~(tlv3H!Zt39GjDaqvRo@!X;lvkn`2d}fn467WeZ5ugKGmH`W5Uv%+K*aNq1u}5uu;GEu zS?6@^cRqg9+mbA?=RZIUS{7uXgzR~Z{pTm-nB({H%I|^S43>tdLh)d+foI7psTyQ; zfG6b=F;2p6sFzCW(+-=UPnjGh57byYIV{wml~qm9n)OuOpvPOKZH5;74)>%U7p1C; zzwZUfjhlI)ALTbD)RNv{mIY2z%iMAj&9KD=0XoHn8?6p>7U)WMqb#kjY#{nL`tGF) zGI?GNh}$XQ%W&Na0 z0W9#QsPAUgYm-$_x&t zE#55B(z_$8F>`G{ENQj_ioY-KxbY9$(n!;+89H=*S(5duIHP*F`%@Y# zSIMo0I#3(3@OV&Z4VY)oHJK#*ZPtb19?2S}jhF}~SVWe>VUWvmTpr*N6Yp@^nkdI^ z(Ezv(+KlOFcw5-T#oxK-TLFbNwM;>rErlq9*_tzt_@#97MTVsD76_91(!@(!4Uw%r zsw={a_T@ENUT+6C_z;)H0|&f(&s8jb^z(tq;vP|V=^#Q_ zyQXY^dBg(WCHV!KUJz#j2DmE1gCUIRAzui$@KJ=^@>_*{*Nm+^+9Hf1Q8^?*kAcaG1It9gjN&Epi|!T8f5t(H2TBS zIZWmGm`HzB=!P?d39XmS%~5@HcqR!?55C8=4Txq}z69eIxbfYg8%J<0+QyMDVR*gH zu7n+&HL0+8>BQ^B+cnwwE%lv@Mm z!Nf=^BD5HhA*OlKjy3qxf(d(b)!v_7kDd)kAy^Cu;|*a8Mxi9liWybM zPRkhBe&~D)`24h*5x|I40uUGWj97aGt)6GbI3NzxP|^!-cB+APM)z^USkP&vKu_ui zEAndouohOeY!0q=f{RYzI~K6~Fm5+3IKLbj^DRqrTt!w*(f3tff4O5^p;G}zZ%*&6 z?2G=iG+<_68mLDqZ^I0oJnl9yR+WmsW&{_!fMP8j%H0sZBL5#+=*&i;N2}+q=c7#e z4+x(N7h1os;{Q5wSjPpH3UpV)v!)!Q1p`#hfD=?#)TGQ`9O6L|Wa;^7>C#GWA=hly zW=b;F%0GcCx6M{zdI5aUTFh9Enu>2pT{Ph>L!oH?zv;lvjxRoAxgu2E2l^> z@EEABUmHUAn@q%<<18{uzr_QD5cszi(ffVo!FF1X|6Wk^5a#~;; zlq34b6zk5LPE$Hj#k}!XGPW-%O0|8wduEiExYk5=N6Y{gfLe1H>zvrWHMPhmj!NC`&)@B>%}hS+i`rl82Fo~1p*QZ zKb_h|Xb%yMQwz^7?4SpzL6KM?%A`*ReNi@uRC#My1J2^}ve>~%>DxJ3To&t|l)JW0!oH$42X(Lm2Ndi6ajM;DCoi7Z+y zGFRe1F>gm&9Lffo`QZj8LmyBQevP=}+ZaF*_gid@-KW{T@HCG&IWT_c*+)ESrU}~+ z2q!Hl>y5Ufymikv7cvtp!*Wu{SAphEPqh|DP_qo!lNMp_hKVLC`+);~|K`wn1y63+ zsp9o4$8~ZZgF=R3)#$5KI{!0FVx<%q%d- zutw_>i1+l$3G^0yT;MJbC%`lopN@_Y2-el{J$F!$_R2W`}B- z1t5bNYTqIh#QTO9ga#o0_STeXg^maEK?%vGQffdj^U6ZO)1M%U)^^sxAGjn_7AJa} z*|bsO3}~st_rd0-)hOAk28IT3tDfp-0fQ?=BSEXOkMIg#S=A4$qF1Fejmand9XntA zu9L~P^?F~75t!CY+6F1UlZ+HNuu2ZuJ9LeKUTBcz3Ozp*06;GH761Sx)bP657I0#nQWw6l6B@;M9SSaC_!v#r7wfQUwTSEo z^R*}j2xz8hJdoQS=LY}lwR1&3R3&tMtcctxvZCBJo0~{SN^)oFqy$k!vL)~SZ)X%$ z+%)gA0jdkV%>kS7IjH_Tv%GRVTjMLOD|nEWGdOhgr*v-$Rf4CDyH#zl?HZVt|47EO zJbxo|GdE=tV(0-8?na`V(nsUn!fU6aug5g@Dfd~6l0kun&FPZ5aMtVg##dA}#zD9z z;l-W1eo>o)WNyr^Xc8hIQLaF!j!t4c9hhg)doB4aLS7U-UmwMB0%(rnKL~K(kPjMpbch=iV%F@c++8Tou{qy| zXr^3_)lsAN^k_Ly-*~*OkYC*UQ1OjL{kk$>ISP@uo7%#C^lF+&JHprK z-b^e!m_d}y(H{`f@&gXCIOoX{hMBn>9Q?GN+}Vs@A2qh$-H$A83fW-s22Q7}P$<-} zUyJ`Xld2R*0zK5d zRy)=RUoZ$#=-Hkv>|IAgoWw)vwL`HAnE<-b6P1&~_L+mapfZaW zOnF@uH%PX-uE#uqeyh_GNZH@1tnFOk?Ey&{!D>?Ty01U>cQpUx+BB%@i`lZrYEQp_#P*QVYQNgr&iVN;g2Cx8F}g2i#zZNr z2-%|2aHzu9Ia%h^CLZac*C-97ji<0$DBNermW|PC>&k0j&e^xZbMbAsIhxWDcbQt|aDE4hPUO(e*k~x*88Uk!5lkM9egJ*}l_|A&VsQ>rw&;kNddnm(9KFl?-PrcX z4Sy2O2TaZ#a83^Pu5V%?4X{@jCae%k2OP{>hHyfeC!mycDVjiM z+fpi#(U&&yit|rv&jkaTX)FY)%8Fl=^)Bj+xx>1-z<}q#$YM2jI{7lhN+pN?`_&f# z6BP~pVcn)56;oJ4*TdDLgv`87@TK0ZWrJPE4CmQG6CXu-yl0PR=SP`07NKrEeZOoF z+Cc~j(lWSld*ZWvp0vLE&traD>j7&m1cGzPxy1{I3}ZtVU|WdC`4ZXa5%1}({HElX z@+s9AO_6zi@d@yttl;7va}fa$OFa>W*B-TZ0Db+F-P$-gjW(}@ySZG!%LhE2>T9o! zG6dw&!?Cs>c?TS~6D+#rwgYJHyKQUAGJAbSQ2Y&SvDt!BeeR{E9r9U<*Etd$!MmGcbh z5KO_!7l(HOg{y+8K}85Gytqe3rjU&|N!(ScTwxhWyja)Z5FeAhe4JYzGF+n06f9%0 z1=A@};7s9GIcX?Z2-@k9_^DsD6lM_DOvta$_G1HhGz9|rWyr113fq%nQQ=LG+_Tbq z*6_f>61NV+7gC@j;j%_{^eef2Dn%wO0&0QWXK)ybe*YLvNf56_I!edMmB3z4keq0D*XTa9_#@1=Sm6<|nk{z8sAJFh0)|^Q0VZ#0NmB%3f%3mF((< z{yVC!4J|)+W?tYqgjtAnDkn)1DX!*Zzu(3ec_GUc2rD6B^jO*?cdkTa>ecn;#(B&) zv$%C(SLm0yVW3{fuNzv`Y&ES0CB7-CfD}lvdlf}HKYJNcp-uj=6^HglNwu%(!37N>lh_4p`L z&O281A0HJC+OtopKUh-x%QQ$!>L+D6qY#p0mJUqXlqW-NLNi(w^ewF>uz!;Jud4tN zVB5_ZAm>oHsL8~30vw*^xgo$Jbc`+x(8N^C%`Rg9-k>;NO9N}sxJgDLn?y;^eIS|8 zG^yrNHR9j0qImvC0FWAQ19Yi4#~m1sSb0z z_=MWWPx;PrpUEvDImo79;s8nvIROcRi>?hKlfWc@<-}8DIfsBB4I~OVh;h}u6tNMr zwo#<|D#$~kQfMxWHLsbjya4=dd7`1GAU zZnXo6MFq{hstxc}nHU)sONc8<`i&Br`~5VY6aOC8-Py0~5T92-GbA4~Y6et3*QjSwdQC(E)DM4V-H}VC9{mbMjP zR9Ch10MZy5)Ecer;eB9AGU6)z@Ic8LkoZSXMpgLhdc=qG=Up`{aocIq~M+z03< zfTn?1x+$NE^Q}0 zO!i{3181Y1R7rKe+oJjZ2OaGsV-J`QcEdRkL~0a^z854)U08@|!Sj8BVFaqw#qSm- zu_9$+uHKHr2v)wNT!%9FC&|_J$tYKXsKj91IjfR$!S=&ePQ^GZptixF(y%p(CAk1+ z^H7;VPMh?!>oo>&-W6V60Onycc610PDiZyG*X8EnQw()+x1rct9~`4M3@95;WwxQ zJ$(17USk06AZpbe4W7G_rt&5HI04Mqiy9`9Nl~wq%1I=WNnY_V`WJZ!#&iKDN$2U5 z6^4uu$|VGd&G#-^yZv}Cd&5&8Fh@hXWb6;~b<*dr{0IR2t#ye_j3lv?JO$KYAL8La zZ2@y1?bpx&bDXb4bi%l)<6wpRA<4pQUYEhZvfZv#2rzqqamGkJdUG?TJaZ=dC|OW! z*qgsUc{fWbZc~JZkz6K0a;Ix~@S%X?de=Nbba-G}Tj@;kwPJ zF0;({TepF+EoP^mm4E45w3=lCisF`g4{txiYQTZ@v(&hHdw0Y(i84ShA)#A z>1uk)Ats@`>(uT<4(Xj+7|HmGPO?cP>WQ1KbJver)*5KG$uw7C$iix)?0InfbGcBW zi)uK^zYNQ>6jm8OeKwO==5bb~<_r>kc!7;75PM!H5Vb7G#Omzj4EZML+CRx9+gxnW zV%#QhLH>B6;v+j(H-w2n3F;nXR_R@w!`4_Xl2_THx%Za$bNT5a!+UUXw#T^xHWCN;KdQ-BXrNIj^l+*#jeF@E)z3AqQ3eX@J3v45xa|+=3-#0_ zd_vT!S;>r()}pMRD!Zi(4Ak;}#+{nqolA>jThDG#j%)kjVb7{8{~S~v`$=wAvOz8* zOL=Wej}co#tcHp=!9(*OTvb}ku3yFcB43w=zyk4YY(Il#lDm;lDcJ8oFF9V6!d*KA zFkvj~_bRW+O66k#0phX(rL?~NzT)&x5H`lKBt@E*Xm7D zEB0XXO>Qz3J0Q;|I$nM_9cD{^KuDoJ#M_e_ zI;LT88WlKC%4N-Oxg_Wl<#vA458g==eS;0!e0Kq%dK|Tz295A$#@-9R$^5Dqw93Z# zR9T^|@W86A9m7S9Qnt4IbVo(mwGtRB478l`^d$dzJ7NGlSMg=h#@zXH$*r6b>;$lk=KEaOdI<17TGfk1ngf|s0;@Py;t08CeRmn)58FSa3>Izy7 zx_4*49NB`i-_=mps#NY@FMIgF9x}R>z`=1xvw4w0F+Mwx=pq{l$eg5S8W>>6PGfj-e>}ZvP8BEj-e9;Rc&xT45O;F;yIL*S9*9FJ zeCvyXoyj9$S5fv|Q>T)|k|{Zm%0f-eQOWxx*Abhh)iKcOIWo8M(6uC)_THrBZgYs zd@TAx)+xeEaIb3Eez;By?u$fAGEoG-51A?CZ zJC<&fqd`mCj{B$-K52XeRkPR3CKzc}KriLI?)Cf};;h`jv5LfAc1nY?KQ)|(yhw0) zb*y1=HLgh%8T0c-AK1u?QLkeN&=8?aJ_7A*DzVl_0eN=Q=e&C=txT#1W8niOe=n>h z$35yQ2dGumci?N-7CbuL<~U}U^P%#FQU1pr?+9-}O*En(x$pa3)Y<5}MO4er-`_oH zg4L7ezx#nR_c8Nu70@S(r$<>kC6CURp5iZ^?7N^U>z5u92G6gsloeX#gSZsLo@wq$ zJ8{{wdV;S`LssTr9Z89)S(LmKNxwv>ld5qetK+zPFoWY~DPi0uj% zoJF*FTP8|wr*xOMtf5q~gIW$VH`{eSoKigQWP0d`{McoZKWoN9Sw7v5tT<$n8Gntw z;yjU;dq;R*XARfJEfGO_+2EH%WkWI8tnWafzxBlR4$8o*b$UTXV#wEJ4RHQb@}S-C z(LoCtjpz^6EsLEV%PEO1PT(1J;*TA2a26eHT&LRmA@vWC`q?)x4niBD<))m^c7~jL zVY$7?wmO9T7W|=tO=NyB|1duWDxZy(PezrJR>vg`8`T7=Ec?o(5nS0D&iip zy-KPEG&e$)6+RzVBDIw=(Q!s5^Kc5hOYL9OyQFEHDER~&B;x!>pdczp4w~PQOiI5+ z8%iXEkt50DOznSHSydt11c)_Rh>QgxPKZ^R6Cu+irANYvWr$FQ$XV%IkX=Y=hP(5+J=AsU~FAFm%Xl=9@~hEFGv8<|9+pUREVLc z=DF9|)M8HSocFfr+H@@4(s^OM5`v|0rrPOAWg-xxl>5&J9ixpblD2UepPz0>0(-vE z-hT8nOCKx4L)t%=(X%U41f)Y=w>#h3+cUZ4N_H0@k)PYZuh)7gY-sVX=;3t~8XX%x z34PY)F51J-j>YQqGJlSBbqw>ZmmT)EirkRXa+&ROh9w*kNpxJGjl*zp*QP;5b1Y1>y(^-HV2M!BVQkhj2oD2CPs3QQ>h>@}1finSzi8zyudfh*LaFOKW5 z2LEoO11SUiHNN&*Oem3KHZ(VE<8)IVK4Mm!%$7rbuk4eq$mmJ6DRciu9edPt%OdGm z?X^)*;weZy90Z;kXb{AF1Ia3xNa>2A3-GVNKXg|zVgE8Ie?sPEQ#+y$L1hwU)O@0Kb6dhgB78c&rbMJ^lj8TM`2}eqOXgT*;gk>%J=3h3NUL{P zZcojZOl&d%Q(jo8ba?c&$_fP4T}zwoT%_<7px0F$E_wO^n;2RxGwT6!dTV29Ab-=l zrflH@`L|M|hZ$>sjKfe^`>||;%%Lw#`+dHC?qUA0w4d{r=g2z)=Y{OV z`AFa_6k-{sH=qO()&ReOll9yq z&_lOwAHI%XE3~Pr)%f#PsXL?&vL#nhs_-bqGZHd2g?3F?=)~MKcxTCrOWYB<*Y-E<9KFk;%)Mb#P<01~4bVb^p(f{4zXsJSbh=zax5vU}m=8(%`ZJpB zTkoc0)+8(A%sgJT*-#o|aefdgNz%O4At32npNE>vQ+6+`;Q0L6YZ!pDg+k427(QpV z_#5qdEf*;l5>KB`uUvfy@77zKgI#wGem!PUiYx|{2y&>LF3$p>>P_ho0R0@K5dy;%p5u71!($%UZxn#4T z_#^61)Qkpp$2tW|zl${P6JCm+6FV!@c*<9%qvswYV5*)fS ztgOiZQ~=|!9;`mP-#pv)i4H~wgth*vrOW+&pMFl}Mtef6HVmxIP6OP$MF0WzkVF6i|Pz(W59`-jN4ZO0vrDIY3x*BryZE3{}|rVaKN*G6e* za8tRlbbR!64RO4%;tYkAqR(FKH&3a`C?%=v)y&*$8H^=T9Gi-C7GN*6S#$h=ia&fS7+4W4UTMtBnhO!c-}pS+pO~bmo`5oF(I^=6dZ7U7HzxDW&mhTeQp3C4Doo9dkUu7C+; zA;+oipxxfNq7aXbL$&x{_6f%fkrrmBqYD!Fi%K2$dQ!R|y%mmzL{S~8st?Pr_gByH zE#LoMs6ozH2;NH-9oV6m=; znpo{QY@e34B8|A7n}iq)4d@Yr(Nog`9G$K3khTk7i;%Ua?yl3zy74trmR87|0#Q)) zytW`|I}`DzP$%q8JL`>hzM`%|rPmJuJvg1Wj&lj3N=ZCASI>LHejV@%tYR$Jbb8}6 zAgy8=&+dsTtkz$Rt%p8jhR~~sO1`5yB;S`g->QjD`XC`3Q`L0@P(ye?r*byyip%*D z%F0)ME#3FW0Y0^0sL$s=_Nrl_fAUj75J}@e*>viw11fc@Z_lkp<_6T3q=s;UN3Wn8 zk&!jyy-4K1KA1_81zZZSWUMLRs&42z3>MUm@$fFpU~DE*Y8fCSlm)a4B=8-2fLKer zQ09|vUhgPVZiMaK1o!!_+-m;s94>UjHIbW`m{RrubdBSUu9{(uY$<3mW1ZNfUEY@F zK0p%?RvQk8LhQ_yEyCM)GlF8f#4Y3$dlGg-3vFDQE~sk-t?@uC4J-08*~jG>AI(?8 zWNYF2Q|9*l%+=>vkJi%D7rQ-5uuJs_+$50t0gO}4^)YUDcqS}T-!U-Rn%ly>C{8= zWz74Ifv$XTfOw`OU&h(A1dFRJXW0#tzrWN?_ahfS;(RW_sbG_%$%^86cHB=trsX6# zvXvkkHytk3%aWyl?&?^JdISrf_1LHE?+zlgx&L&h%tD`XD|`1teszd%Y5Ngi4ZY`@ zoTAaI7f83f(a`)A51OuKI)_Q)mwwryPyam)UUs(l9KEbZP5U*rDASXHZoNqN`F1mx zA{y13jX-qM$h

pZIvChf*A?RScPRiMV_FUgN@;DZ~`hDR0yx#n{UPy?`wor5^2$ z`KFDnuly`)DLcmlUwsmGA-Np(V&V`$@`vGOR!&Ov_n1{;K#WMr{Dnx3oi`KpbOokS zo-A2lTi4iwdoh$wtBRh*xYl=lJo=!u&*7*e*c(W9_L%K{$Ejzje^nePM%HljzL&6M z{L@dq_By0wDUBx8{ozk+%?^8MPFQ44GYPh05wBZu_85r5ILd}AvTBi#QLwOA%TT)f z`qf?5J!)O}K?P<)v5UsxUvVqU=DKSzXe=r27l8sQ*xYye_`h#|$G}}VZmZ%;=-V{K zYaUIl-Ik0!{vXs2Uo2Mj(sdVFb0mGjG%!%cESa1RhW_mfs-FHgduc5&OQYc-@SkQJ zv-%JEePV0i>t+zuTUXU+H%I-8yo?4&Bs44Zx4%;+gPE!gF4%ofxhE!NrW~+Y%S~)w z2Vu4>buh_b9P{tcnL9{gTpn%Kbj$S(BZU|-DXB{=oVN62^?U4c{x6W^iWRJ)r zngcXonk!FBd+8_Q!w~d`FWzE#e?BU3MrfF~;kB^EdirPT&9$8n7TGBcr&{N;B?$|7 zG=2O1+2wDXjZZy7pu^hN5o3Hs+weVtKj=Z6Jz62GLS3pGcO0M79HcVT`7}x~yadv} ItfPPb*$(HuqW}N^ literal 0 HcmV?d00001 diff --git a/res/pyinstaller/create_application.py b/res/pyinstaller/create_application.py index 9eb4c5df..0c01fef3 100644 --- a/res/pyinstaller/create_application.py +++ b/res/pyinstaller/create_application.py @@ -2,7 +2,6 @@ import platform import PySide2 as RefMod import PyInstaller.__main__ -from PyInstaller.utils.hooks import collect_data_files here = os.path.dirname(__file__) @@ -11,7 +10,7 @@ run_command = [ '../../src/mapclient/application.py', '-n', 'MAP-Client', - # '--debug', 'noarchive', + '--debug', 'noarchive', '--windowed', '--noconfirm', '--hidden-import', 'scipy', @@ -37,11 +36,19 @@ rel_rcc_exe = os.path.relpath(rcc_exe, here) # os.path.join(here, 'dist', 'MAPClient')) rel_uic_exe = os.path.relpath(uic_exe, here) # os.path.join(here, 'dist', 'MAPClient')) + macos_icon = os.path.join('..', 'macos', 'MAP-Client.icns') + run_command.append(f'--icon={macos_icon}') + run_command.append(f'--add-binary={rel_rcc_exe}:PySide2/') run_command.append(f'--add-binary={rel_uic_exe}:PySide2/') elif platform.system() == "Windows": win_icon = os.path.join('..', 'win', 'MAP-Client.ico') run_command.append(f'--icon={win_icon}') +internal_workflow_zip = os.path.abspath(os.path.join('..', '..', 'src', 'internal_workflow.zip')) +if os.path.isfile(internal_workflow_zip): + data = os.pathsep.join([internal_workflow_zip, '.']) + run_command.append(f'--add-data={data}') + print('Running command: ', run_command) PyInstaller.__main__.run(run_command) diff --git a/res/pyinstaller/hooks/hook-mapclientplugins.py b/res/pyinstaller/hooks/hook-mapclientplugins.py index 33e939e8..6b79b2d4 100644 --- a/res/pyinstaller/hooks/hook-mapclientplugins.py +++ b/res/pyinstaller/hooks/hook-mapclientplugins.py @@ -1,17 +1,9 @@ -import os -from PyInstaller.utils.hooks import collect_data_files, collect_submodules, get_package_paths +from pkgutil import walk_packages import mapclientplugins -print("==================================") -print(mapclientplugins.__path__) -# hidden = [] -# for p in mapclientplugins.__path__: -# d = os.path.dirname(p) -# print(collect_submodules('mapclientplugins')) -# print(get_package_paths('mapclientplugins')) -# print(collect_data_files('mapclientplugins', include_py_files=True, excludes=['__pycache__'])) -print("==================================") -datas = collect_data_files('mapclientplugins', include_py_files=True, excludes=['__pycache__']) -# hiddenimports = ['imghdr', 'mapclientplugins', 'mapclientplugins.datatrimmerstep'] -# hiddenimports = (['mapclientplugins']) + +# I don't think this will work if the plugin is zipped in an archive. +hiddenimports = ['mapclientplugins'] +for module_loader, name, ispkg in walk_packages(mapclientplugins.__path__, 'mapclientplugins.'): + hiddenimports.append(name) diff --git a/src/mapclient/tools/pluginwizard/skeletonstrings.py b/src/mapclient/tools/pluginwizard/skeletonstrings.py index e5334723..e038922b 100644 --- a/src/mapclient/tools/pluginwizard/skeletonstrings.py +++ b/src/mapclient/tools/pluginwizard/skeletonstrings.py @@ -342,6 +342,7 @@ def validate(self): # List all of your Python package dependencies in the # requirements.txt file + def readfile(filename, split=False): with io.open(filename, encoding="utf-8") as stream: if split: @@ -365,25 +366,26 @@ def run(self): subprocess.call(['pip', 'install', '-r', os.path.join(SETUP_DIR, 'requirements.txt')]) -setup(name=%(name)r, - version=%(version)r, - description=%(description)r, - long_description='\\n'.join(readme) + source_license, - long_description_content_type='text/x-rst', - classifiers=[ - "Development Status :: 3 - Alpha", - "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python", - ], - cmdclass={'install': InstallCommand,}, - author=%(author)r, - author_email=%(author_email)r, - url=%(url)r, - packages=find_packages(exclude=['ez_setup',]), - namespace_packages=%(namespace_packages)r, - include_package_data=True, - zip_safe=False, - install_requires=requires, +setup( + name=%(name)r, + version=%(version)r, + description=%(description)r, + long_description='\\n'.join(readme) + source_license, + long_description_content_type='text/x-rst', + classifiers=[ + "Development Status :: 3 - Alpha", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python", + ], + cmdclass={'install': InstallCommand,}, + author=%(author)r, + author_email=%(author_email)r, + url=%(url)r, + packages=find_packages(exclude=['ez_setup',]), + namespace_packages=%(namespace_packages)r, + include_package_data=True, + zip_safe=False, + install_requires=requires, ) """ @@ -394,193 +396,6 @@ def run(self): APACHE_LICENSE = """\ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{{}}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. Copyright {yyyy} {name_of_copyright_owner} diff --git a/src/setup.plugins.py b/src/setup.plugins.py new file mode 100644 index 00000000..bd40fffa --- /dev/null +++ b/src/setup.plugins.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +import codecs +import os +import re + +from setuptools import setup +from setuptools import find_packages + + +here = os.path.abspath(os.path.dirname(__file__)) + + +def read(*parts): + with codecs.open(os.path.join(here, *parts), 'r') as fp: + return fp.read() + + +def find_version(*file_paths): + version_file = read(*file_paths) + version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", + version_file, re.M) + if version_match: + return version_match.group(1) + raise RuntimeError("Unable to find version string.") + + +# Define the list of requirements +install_requires = [ + 'PySide2', +] + + +setup( + name='mapclientplugins.builtin', + version=find_version("mapclient", "settings", "version.py"), + description='Builtin plugins for MAP Client.', + author='MAP Client Developers', + author_email='mapclient-devs@physiomeproject.org', + url='https://github.com/MusculoskeletalAtlasProject/mapclient', + namespace_packages=['mapclientplugins', ], + zip_safe=False, + packages=find_packages(exclude=['tests', 'tests.*', 'mapclient', 'mapclient.*', 'utils', 'utils.*' ]), + install_requires=install_requires, +) From 3864d568de434d7693cc32d25a24c6023a380d7f Mon Sep 17 00:00:00 2001 From: hsorby Date: Fri, 28 May 2021 08:57:53 +1200 Subject: [PATCH 14/15] Add name variant to macOS create installer script. --- res/macos/create_installer.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/res/macos/create_installer.sh b/res/macos/create_installer.sh index 9877ba70..0c046d1e 100755 --- a/res/macos/create_installer.sh +++ b/res/macos/create_installer.sh @@ -1,9 +1,14 @@ #!/bin/sh version=0.15.0 -test -f MAP-Client-$version.dmg && rm MAP-Client-$version.dmg +variant=-mapping-tools + +app_name=MAP-Client$variant-$version +dmg_name=$app_name.dmg +test -f $dmg_name && rm $dmg_name # --volicon "application_icon.icns" \ create-dmg \ - --volname "MAP-Client-$version" \ + --volname $app_name \ + --volicon "MAP-Client.icns" \ --background "map-client-dmg-background.png" \ --window-pos 200 120 \ --window-size 800 400 \ @@ -11,6 +16,6 @@ create-dmg \ --icon "MAP-Client.app" 200 190 \ --hide-extension "MAP-Client.app" \ --app-drop-link 600 185 \ - "MAP-Client-$version.dmg" \ + $dmg_name \ "../pyinstaller/dist/" From 1a7311bcfc8e783fbe16991a5e43478676f356f8 Mon Sep 17 00:00:00 2001 From: hsorby Date: Fri, 28 May 2021 09:11:28 +1200 Subject: [PATCH 15/15] Allow for setting a variant name of MAP-Client in macOS installers and app building. --- res/macos/create_installer.sh | 13 +++++++------ res/pyinstaller/create_application.py | 3 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/res/macos/create_installer.sh b/res/macos/create_installer.sh index 0c046d1e..5a33f794 100755 --- a/res/macos/create_installer.sh +++ b/res/macos/create_installer.sh @@ -2,20 +2,21 @@ version=0.15.0 variant=-mapping-tools -app_name=MAP-Client$variant-$version -dmg_name=$app_name.dmg +app_name=MAP-Client$variant +app_name_with_version=MAP-Client$variant-$version +dmg_name=$app_name_with_version.dmg test -f $dmg_name && rm $dmg_name # --volicon "application_icon.icns" \ create-dmg \ - --volname $app_name \ + --volname "$app_name_with_version" \ --volicon "MAP-Client.icns" \ --background "map-client-dmg-background.png" \ --window-pos 200 120 \ --window-size 800 400 \ --icon-size 100 \ - --icon "MAP-Client.app" 200 190 \ - --hide-extension "MAP-Client.app" \ + --icon "$app_name.app" 200 190 \ + --hide-extension "$app_name.app" \ --app-drop-link 600 185 \ - $dmg_name \ + "$dmg_name" \ "../pyinstaller/dist/" diff --git a/res/pyinstaller/create_application.py b/res/pyinstaller/create_application.py index 0c01fef3..d9fa60b0 100644 --- a/res/pyinstaller/create_application.py +++ b/res/pyinstaller/create_application.py @@ -3,13 +3,14 @@ import PySide2 as RefMod import PyInstaller.__main__ +variant = '-mapping-tools' here = os.path.dirname(__file__) hooks_dir = os.path.join('..', 'res', 'pyinstaller', 'hooks') run_command = [ '../../src/mapclient/application.py', - '-n', 'MAP-Client', + '-n', f'MAP-Client{variant}', '--debug', 'noarchive', '--windowed', '--noconfirm',