From 7f39d43e1759250507482c21854ab7b74ddf1318 Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Tue, 6 Feb 2024 16:35:38 +0600 Subject: [PATCH 01/75] pkp/plagiarism#52 iThenticate API update and plugin update --- .gitignore | 2 +- IThenticate.inc.php | 431 +++++++++++++++++++ PlagiarismPlugin.inc.php | 383 ++++++++++------ PlagiarismSettingsForm.inc.php | 42 +- README.md | 22 +- TestIThenticate.inc.php | 262 +++++++++++ composer.json | 19 - composer.lock | 177 -------- controllers/PlagiarismWebhookHandler.inc.php | 57 +++ exclusions.txt | 9 - index.php | 4 +- lib/phpxmlrpc-datetime.diff | 11 - locale/en_US/locale.po | 16 +- templates/settingsForm.tpl | 14 +- version.xml | 4 +- 15 files changed, 1053 insertions(+), 400 deletions(-) create mode 100644 IThenticate.inc.php create mode 100644 TestIThenticate.inc.php delete mode 100644 composer.json delete mode 100644 composer.lock create mode 100644 controllers/PlagiarismWebhookHandler.inc.php delete mode 100644 lib/phpxmlrpc-datetime.diff diff --git a/.gitignore b/.gitignore index 61ead86..e43b0f9 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -/vendor +.DS_Store diff --git a/IThenticate.inc.php b/IThenticate.inc.php new file mode 100644 index 0000000..625d886 --- /dev/null +++ b/IThenticate.inc.php @@ -0,0 +1,431 @@ +apiUrl = rtrim(trim($apiUrl), '/\\'); + $this->apiKey = $apiKey; + $this->integrationName = $integrationName; + $this->integrationVersion = $integrationVersion; + $this->eulaVersion = $eulaVersion; + } + + /** + * Confirm the EUAL on the user's behalf for given version + * @see https://developers.turnitin.com/docs/tca#accept-eula-version + * + * @param User $user + * @param Context $context + * @param string $version + * + * @return bool + */ + public function confirmEula($user, $context, $version = self::DEFAULT_EULA_VERSION) { + + // Validate the EULA version + if (!$this->validateEulaVersion($this->eulaVersion ?? $version)) { + return false; + } + + // if user has already accepted/confirm this EULA, no need to go further to reconfirm + if ($this->verifyUserEulaAcceptance($user, $this->getApplicationEulaVersion())) { + return true; + } + + $response = Application::get()->getHttpClient()->request( + 'POST', + $this->getApiPath("eula/{$this->getApplicationEulaVersion()}/accept"), + [ + 'headers' => array_merge($this->getRequiredHeaders(), [ + 'Content-Type' => 'application/json' + ]), + 'json' => [ + 'user_id' => $user->getId(), + 'accepted_timestamp' => \Carbon\Carbon::now()->toIso8601String(), + 'language' => $this->getEualConfirmationLocale($context->getPrimaryLocale()), + ], + 'verify' => false, + 'exceptions' => false, + ] + ); + + return $response->getStatusCode() === 200; + } + + /** + * Create a new submission at service's end + * @see https://developers.turnitin.com/docs/tca#create-a-submission + * + * @param Submission $submission + * @param User $user + * @param Author|null $author + * + * @return string|null if succeed, it will return the created submission UUID at service's end and + * at failure, will return null + */ + public function submitSubmission($submission, $user, $author = null) { + + $publication = $submission->getCurrentPublication(); /** @var Publication $publication */ + $author ??= $publication->getPrimaryAuthor(); + + $response = Application::get()->getHttpClient()->request( + 'POST', + $this->getApiPath("submissions"), + [ + 'headers' => array_merge($this->getRequiredHeaders(), [ + 'Content-Type' => 'application/json' + ]), + 'json' => [ + 'owner' => $author->getId(), + 'title' => $publication->getLocalizedTitle($publication->getData('locale')), + 'submitter' => $user->getId(), + 'metadata' => [ + 'owners' => [ + [ + 'id' => $author->getId(), + 'given_name' => $author->getLocalizedGivenName(), + 'family_name' => $author->getLocalizedFamilyName(), + 'email' => $author->getEmail(), + ] + ], + 'submitter' => [ + 'id' => $user->getId(), + 'given_name' => $user->getLocalizedGivenName(), + 'family_name' => $user->getLocalizedFamilyName(), + 'email' => $user->getEmail(), + ], + 'original_submitted_time' => \Carbon\Carbon::now()->toIso8601String(), + ], + + ], + 'verify' => false, + 'exceptions' => false, + ] + ); + + if ($response->getStatusCode() === 201) { + $result = json_decode($response->getBody()->getContents()); + return $result->id; + } + + return null; + } + + /** + * Upload all submission files to the service's end + * + * @param string $submissionTacId The submission UUID return back from service + * @param Submission $submission + * + * @return bool If all submission files uploaded successfully, only then it will + * return TRUE and return FALSE on a single failure + */ + public function uploadSubmissionFile($submissionTacId, $submission) + { + $submissionFiles = Services::get('submissionFile')->getMany([ + 'submissionIds' => [$submission->getId()], + ]); + + $publication = $submission->getCurrentPublication(); /** @var Publication $publication */ + + foreach($submissionFiles as $submissionFile) { + $file = Services::get('file')->get($submissionFile->getData('fileId')); + $uploadStatus = $this->uploadFile( + $submissionTacId, + $submissionFile->getData("name", $publication->getData("locale")), + Services::get('file')->fs->read($file->path), + ); + + if (!$uploadStatus) { + return false; + } + } + + return true; + } + + /** + * Upload single submission file to the service's end + * @see https://developers.turnitin.com/docs/tca#upload-submission-file-contents + * + * @param string $submissionTacId The submission UUID return back from service + * @param string $fileName + * @param mixed fileContent + * + * @return bool + */ + public function uploadFile($submissionTacId, $fileName, $fileContent) { + + $response = Application::get()->getHttpClient()->request( + 'PUT', + $this->getApiPath("submissions/{$submissionTacId}/original"), + [ + 'headers' => array_merge($this->getRequiredHeaders(), [ + 'Content-Type' => 'binary/octet-stream', + 'Content-Disposition' => urlencode('inline; filename="'.$fileName.'"'), + ]), + 'body' => $fileContent, + 'verify' => false, + 'exceptions' => true, + ] + ); + + return $response->getStatusCode() === 202; + } + + /** + * Verify if user has already confirmed the given EUAL version + * @see https://developers.turnitin.com/docs/tca#get-eula-acceptance-info + * + * @param Author|User $user + * @param string $version + * + * @return bool + */ + public function verifyUserEulaAcceptance($user, $version) + { + $response = Application::get()->getHttpClient()->request( + 'GET', + $this->getApiPath("eula/{$version}/accept/{$user->getId()}"), + [ + 'headers' => $this->getRequiredHeaders(), + 'exceptions' => false, + ] + ); + + return $response->getStatusCode() === 200; + } + + /** + * Validate/Retrieve the given EUAL version + * @see https://developers.turnitin.com/docs/tca#get-eula-version-info + * + * @param string $version + * @return bool + */ + public function validateEulaVersion($version) { + + $response = Application::get()->getHttpClient()->request( + 'GET', + $this->getApiPath("eula/{$version}"), + [ + 'headers' => $this->getRequiredHeaders(), + 'exceptions' => false, + ] + ); + + if ($response->getStatusCode() === 200) { + $this->eualVersionDetails = json_decode($response->getBody()->getContents(), true); + + if (!$this->eulaVersion) { + $this->eulaVersion = $this->eualVersionDetails['version']; + } + + return true; + } + + return false; + } + + /** + * Register webhook end point + * @see https://developers.turnitin.com/docs/tca#create-webhook + * + * @param string $signingSecret + * @param string $url + * @param array $events + * + * @return string|null The UUID of register webhook if succeed or null if failed + */ + public function registerWebhook($signingSecret, $url, $events = self::DEFAULT_WEBHOOK_EVENTS) { + + $response = Application::get()->getHttpClient()->request( + 'POST', + $this->getApiPath('webhooks'), + [ + 'headers' => array_merge($this->getRequiredHeaders(), [ + 'Content-Type' => ' application/json', + ]), + 'json' => [ + 'signing_secret' => base64_encode($signingSecret), + 'url' => $url, + 'event_types' => $events, + 'allow_insecure' => true, + ], + 'verify' => false, + 'exceptions' => false, + ] + ); + + if ($response->getStatusCode() === 201) { + $result = json_decode($response->getBody()->getContents()); + return $result->id; + } + + return null; + } + + /** + * Get the stored EULA details + * + * @return array|null + */ + public function getEualDetails() { + return $this->eualVersionDetails; + } + + /** + * Get the applicable EULA version + * + * @return string + * @throws \Exception + */ + public function getApplicationEulaVersion() { + if (!$this->eulaVersion) { + throw new \Exception('No EULA version set yet'); + } + + return $this->eulaVersion; + } + + /** + * Convert given submission/context locale to service compatible and acceptable locale format + * @see https://developers.turnitin.com/docs/tca#eula + * + * @param string $locale + * @return string + */ + protected function getEualConfirmationLocale($locale) { + if (!$this->getEualDetails()) { + return static::DEFAULT_EULA_LANGUAGE; + } + + $euleLangs = $this->getEualDetails()['available_languages']; + $locale = str_replace("_", "-", substr($locale, 0, 5)); + + return in_array($locale, $euleLangs) ? $locale : static::DEFAULT_EULA_LANGUAGE; + } + + /** + * Get the required headers that need to be sent with every request at service's end + * @see https://developers.turnitin.com/docs/tca#required-headers + * + * @return array + */ + protected function getRequiredHeaders(){ + return [ + 'X-Turnitin-Integration-Name' => $this->integrationName, + 'X-Turnitin-Integration-Version' => $this->integrationVersion, + 'Authorization' => 'Bearer ' . $this->apiKey, + ]; + } + + /** + * Generate and return the final API end point to make request + * + * @return string + */ + protected function getApiPath($apiPathSegment) { + return str_replace('API_URL', $this->apiUrl, $this->apiBasePath) . $apiPathSegment; + } +} diff --git a/PlagiarismPlugin.inc.php b/PlagiarismPlugin.inc.php index a1616ba..5101554 100644 --- a/PlagiarismPlugin.inc.php +++ b/PlagiarismPlugin.inc.php @@ -3,8 +3,8 @@ /** * @file PlagiarismPlugin.inc.php * - * Copyright (c) 2003-2021 Simon Fraser University - * Copyright (c) 2003-2021 John Willinsky + * Copyright (c) 2003-2024 Simon Fraser University + * Copyright (c) 2003-2024 John Willinsky * Distributed under the GNU GPL v3. For full terms see the file LICENSE. * * @brief Plagiarism plugin @@ -13,16 +13,31 @@ import('lib.pkp.classes.plugins.GenericPlugin'); class PlagiarismPlugin extends GenericPlugin { + + public const PLUGIN_INTEGRATION_NAME = 'Plagiarism plugin for OJS/OMP/OPS'; + /** * @copydoc Plugin::register() */ public function register($category, $path, $mainContextId = null) { $success = parent::register($category, $path, $mainContextId); - $this->addLocaleData(); - if ($success && $this->getEnabled()) { - HookRegistry::register('submissionsubmitstep4form::execute', array($this, 'callback')); + $this->addLocaleData(); + + if (!($success || $this->getEnabled())) { + return false; } + + HookRegistry::register('submissionsubmitstep4form::execute', [$this, 'submitForPlagiarismCheck']); + + $submissionDao = DAORegistry::getDAO('SubmissionDAO'); /** @var SubmissionDAO $submissionDao */ + HookRegistry::register("Schema::get::{$submissionDao->schemaName}", [$this, 'addPlagiarismCheckDataToSubmissionSchema']); + + $schemaName = $this->hasForcedCredentials() ? SCHEMA_SITE : Application::get()->getContextDAO()->schemaName; + HookRegistry::register("Schema::get::{$schemaName}", [$this, 'addPlagiarismCheckWebhookDataToSchema']); + + HookRegistry::register('LoadComponentHandler', [$this, 'setupWebhookHandler']); + return $success; } @@ -43,169 +58,292 @@ public function getDescription() { /** * @copydoc LazyLoadPlugin::getCanEnable() */ - function getCanEnable($contextId = null) { + public function getCanEnable($contextId = null) { return !Config::getVar('ithenticate', 'ithenticate'); } /** * @copydoc LazyLoadPlugin::getCanDisable() */ - function getCanDisable($contextId = null) { + public function getCanDisable($contextId = null) { return !Config::getVar('ithenticate', 'ithenticate'); } /** * @copydoc LazyLoadPlugin::getEnabled() */ - function getEnabled($contextId = null) { + public function getEnabled($contextId = null) { return parent::getEnabled($contextId) || Config::getVar('ithenticate', 'ithenticate'); } + /** + * Add properties for this type of public identifier to the submission entity's list for + * storage in the database. + * + * @param string $hookName `Schema::get::submission` + * @param array $params + * + * @return void + */ + public function addPlagiarismCheckDataToSubmissionSchema($hookName, $params) { + $schema =& $params[0]; + + $schema->properties->ithenticate_id = (object) [ + 'type' => 'string', + 'description' => 'The iThenticate service submission uuid that return back after a submission has been successful submitted', + 'apiSummary' => true, + 'validation' => ['nullable'], + ]; + } + + /** + * Add properties for this type of public identifier to the site/context entity's list for + * storage in the database. + * + * @param string $hookName `Schema::get::context` or `Schema::get::site` + * @param array $params + * + * @return void + */ + public function addPlagiarismCheckWebhookDataToSchema($hookName, $params) { + $schema =& $params[0]; + + $schema->properties->ithenticate_webhook_signing_secret = (object) [ + 'type' => 'string', + 'description' => 'The iThenticate service webook registration signing secret', + 'apiSummary' => true, + 'validation' => ['nullable'], + ]; + + $schema->properties->ithenticate_webhook_id = (object) [ + 'type' => 'string', + 'description' => 'The iThenticate service webook id that return back after successful webhook registration', + 'apiSummary' => true, + 'validation' => ['nullable'], + ]; + } + /** * Fetch credentials from config.inc.php, if available - * @return array username and password, or null(s) - **/ - function getForcedCredentials() { - $request = Application::get()->getRequest(); - $context = $request->getContext(); - $contextPath = $context->getPath(); - $username = Config::getVar('ithenticate', 'username[' . $contextPath . ']', - Config::getVar('ithenticate', 'username')); - $password = Config::getVar('ithenticate', 'password[' . $contextPath . ']', - Config::getVar('ithenticate', 'password')); - return [$username, $password]; + * + * @return array api url and api key, or null(s) + */ + public function getForcedCredentials() { + $request = Application::get()->getRequest(); /** @var Request $request */ + $context = $request->getContext(); /** @var Context $context */ + $contextPath = $context?->getPath(); + + $apiUrl = Config::getVar( + 'ithenticate', + 'api_url[' . $contextPath . ']', + Config::getVar('ithenticate', 'api_url') + ); + + $apiKey = Config::getVar( + 'ithenticate', + 'api_key[' . $contextPath . ']', + Config::getVar('ithenticate', 'api_key') + ); + + return [$apiUrl, $apiKey]; + } + + /** + * Check and determine if plagiarism checking service creds has been set forced in config.inc.php + * + * @return bool + */ + public function hasForcedCredentials() { + list($apiUrl, $apiKey) = $this->getForcedCredentials(); + return !empty($apiUrl) && !empty($apiKey); } /** * Send the editor an error message - * @param $submissionid int - * @param $message string + * + * @param int $submissionid + * @param string $message + * * @return void - **/ - public function sendErrorMessage($submissionid, $message) { - $request = Application::get()->getRequest(); - $context = $request->getContext(); + */ + public function sendErrorMessage($submissionId, $message) { + $request = Application::get()->getRequest(); /** @var Request $request */ + $context = $request->getContext(); /** @var Context $context */ + import('classes.notification.NotificationManager'); $notificationManager = new NotificationManager(); - $roleDao = DAORegistry::getDAO('RoleDAO'); /* @var $roleDao RoleDAO */ + $roleDao = DAORegistry::getDAO('RoleDAO'); /** @var RoleDAO $roleDao */ + // Get the managers. - $managers = $roleDao->getUsersByRoleId(ROLE_ID_MANAGER, $context->getId()); + $managers = $roleDao->getUsersByRoleId(ROLE_ID_MANAGER, $context->getId()); /** @var DAOResultFactory $managers */ while ($manager = $managers->next()) { - $notificationManager->createTrivialNotification($manager->getId(), NOTIFICATION_TYPE_ERROR, array('contents' => __('plugins.generic.plagiarism.errorMessage', array('submissionId' => $submissionid, 'errorMessage' => $message)))); + $notificationManager->createTrivialNotification( + $manager->getId(), + NOTIFICATION_TYPE_ERROR, + ['contents' => __( + 'plugins.generic.plagiarism.errorMessage', [ + 'submissionId' => $submissionId, + 'errorMessage' => $message + ] + )] + ); } - error_log('iThenticate submission '.$submissionid.' failed: '.$message); + + error_log("iThenticate submission {$submissionId} failed: {$message}"); } /** - * Send submission files to iThenticate. - * @param $hookName string - * @param $args array + * Setup the handler for webhook request + * + * @param string $hookName + * @param array $args + * + * @return bool */ - public function callback($hookName, $args) { - $request = Application::get()->getRequest(); - $context = $request->getContext(); - $contextPath = $context->getPath(); - $submissionDao = DAORegistry::getDAO('SubmissionDAO'); /* @var $submissionDao SubmissionDAO */ - $submission = $submissionDao->getById($request->getUserVar('submissionId')); - $publication = $submission->getCurrentPublication(); + public function setupWebhookHandler($hookName, $params) { + $component =& $params[0]; - require_once(dirname(__FILE__) . '/vendor/autoload.php'); + if ($component == 'plugins.generic.plagiarism.controllers.PlagiarismWebhookHandler') { + import($component); + PlagiarismWebhookHandler::setPlugin($this); + return true; + } + + return false; + } + + /** + * Confirm EULA, create submission and upload submission files to iThenticate service + * + * @param string $hookName + * @param array $args + * + * @return bool + */ + public function submitForPlagiarismCheck($hookName, $args) { + $request = Application::get()->getRequest(); /** @var Request $request */ + $context = $request->getContext(); /** @var Context $context */ + $siteDao = DAORegistry::getDAO('SiteDAO'); /** @var SiteDAO $siteDao */ + $submissionDao = DAORegistry::getDAO('SubmissionDAO'); /** @var SubmissionDAO $submissionDao */ + $submission = $submissionDao->getById($request->getUserVar('submissionId')); /** @var Submission $submission */ + $publication = $submission->getCurrentPublication(); /** @var Publication $publication */ + $author = $publication->getPrimaryAuthor(); /** @var Author $author */ // try to get credentials for current context otherwise use default config - $contextId = $context->getId(); - list($username, $password) = $this->getForcedCredentials(); - if (empty($username) || empty($password)) { - $username = $this->getSetting($contextId, 'ithenticateUser'); - $password = $this->getSetting($contextId, 'ithenticatePass'); - } + list($apiUrl, $apiKey) = $this->hasForcedCredentials() + ? $this->getForcedCredentials() + : [ + $this->getSetting($context->getId(), 'ithenticateApiUrl'), + $this->getSetting($context->getId(), 'ithenticateApiKey') + ]; + + import("plugins.generic.plagiarism.IThenticate"); - $ithenticate = null; - try { - $ithenticate = new \bsobbe\ithenticate\Ithenticate($username, $password); - } catch (Exception $e) { - $this->sendErrorMessage($submission->getId(), $e->getMessage()); + /** @var \IThenticate $ithenticate */ + $ithenticate = new IThenticate( + $apiUrl, + $apiKey, + static::PLUGIN_INTEGRATION_NAME, + $this->getCurrentVersion()->getData('current') + ); + + // Try to validate and confirm the EULA on user's behalf + if (!$ithenticate->confirmEula($request->getUser(), $context)) { + $this->sendErrorMessage($submission->getId(), 'Could not confirm EULA at iThenticate.'); return false; } - // Make sure there's a group list for this context, creating if necessary. - $groupList = $ithenticate->fetchGroupList(); - $contextName = $context->getLocalizedName($context->getPrimaryLocale()); - if (!($groupId = array_search($contextName, $groupList))) { - // No folder group found for the context; create one. - $groupId = $ithenticate->createGroup($contextName); - if (!$groupId) { - $this->sendErrorMessage($submission->getId(), 'Could not create folder group for context ' . $contextName . ' on iThenticate.'); - return false; - } + + // Create the submission at iThenticate's end + $submissionUuid = $ithenticate->submitSubmission($submission, $request->getUser(), $author); + + if (!$submissionUuid) { + $this->sendErrorMessage($submission->getId(), 'Could not submit the submission at iThenticate.'); + return false; } - // Create a folder for this submission. - if (!($folderId = $ithenticate->createFolder( - 'Submission_' . $submission->getId(), - 'Submission_' . $submission->getId() . ': ' . $publication->getLocalizedTitle($publication->getData('locale')), - $groupId, - true, - true - ))) { - $this->sendErrorMessage($submission->getId(), 'Could not create folder for submission ID ' . $submission->getId() . ' on iThenticate.'); + // $submission->setData('ithenticate_id', $submissionUuid); + // $submissionDao->updateObject($submission); + Services::get("submission")->edit($submission, [ + 'ithenticate_id' => $submissionUuid, + ], $request); + + // Upload submission files for successfully created submission at iThenticate's end + if (!$ithenticate->uploadSubmissionFile($submissionUuid, $submission)) { + $this->sendErrorMessage($submission->getId(), 'Could not complete the file upload at iThenticate.'); return false; } - $submissionFiles = Services::get('submissionFile')->getMany([ - 'submissionIds' => [$submission->getId()], - ]); - - $authors = $publication->getData('authors'); - $author = array_shift($authors); - foreach ($submissionFiles as $submissionFile) { - $file = Services::get('file')->get($submissionFile->getData('fileId')); - if (!$ithenticate->submitDocument( - $submissionFile->getLocalizedData('name'), - $author->getLocalizedGivenName(), - $author->getLocalizedFamilyName(), - $submissionFile->getLocalizedData('name'), - Services::get('file')->fs->read($file->path), - $folderId - )) { - $this->sendErrorMessage($submission->getId(), 'Could not submit "' . $submissionFile->getData('path') . '" to iThenticate.'); + // If no webhook previously registered for this Site/Context, register it + $webhookStorable = $this->hasForcedCredentials() ? $request->getSite() : $context; /** @var Site|Context $webhookStorable */ + + if (!$webhookStorable->getData('ithenticate_webhook_id')) { + $signingSecret = \Illuminate\Support\Str::random(12); + + // http://ojs-stable-3_3_0.test/index.php/test-01/$$$call$$$/plugins/generic/plagiarism/controllers/plagiarism-webhook/handle + $webhookUrl = $request->getDispatcher()->url( + $request, + ROUTE_COMPONENT, + $context->getData('urlPath'), + 'plugins.generic.plagiarism.controllers.PlagiarismWebhookHandler', + 'handle' + ); + + if ($webhookId = $ithenticate->registerWebhook($signingSecret, $webhookUrl)) { + $webhookStorable->setData('ithenticate_webhook_signing_secret', $signingSecret); + $webhookStorable->setData('ithenticate_webhook_id', $webhookId); + $this->hasForcedCredentials() + ? $siteDao->updateObject($webhookStorable) + : Application::get()->getContextDAO()->updateObject($webhookStorable); + } else { + error_log("unable to complete the iThenticate webhook registration during the submission process of ID : {$submission->getId()}"); } } - return false; + return true; } /** * @copydoc Plugin::getActions() */ - function getActions($request, $verb) { + public function getActions($request, $verb) { $router = $request->getRouter(); - import('lib.pkp.classes.linkAction.request.AjaxModal'); - return array_merge( - $this->getEnabled() ? array( - new LinkAction( - 'settings', - new AjaxModal( - $router->url($request, null, null, 'manage', null, array('verb' => 'settings', 'plugin' => $this->getName(), 'category' => 'generic')), - $this->getDisplayName() - ), - __('manager.plugins.settings'), - null - ), - ) : array(), - parent::getActions($request, $verb) + import('lib.pkp.classes.linkAction.request.AjaxModal'); + + return array_merge( + $this->getEnabled() + ? [ + new LinkAction( + 'settings', + new AjaxModal( + $router->url( + $request, + null, + null, + 'manage', + null, + ['verb' => 'settings', 'plugin' => $this->getName(), 'category' => 'generic'] + ), + $this->getDisplayName() + ), + __('manager.plugins.settings'), + null + ), + ] : [], + parent::getActions($request, $verb) ); } /** * @copydoc Plugin::manage() */ - function manage($args, $request) { + public function manage($args, $request) { switch ($request->getUserVar('verb')) { case 'settings': - $context = $request->getContext(); + $context = $request->getContext(); /** @var Context $context */ AppLocale::requireComponents(LOCALE_COMPONENT_APP_COMMON, LOCALE_COMPONENT_PKP_MANAGER); - $templateMgr = TemplateManager::getManager($request); - $templateMgr->registerPlugin('function', 'plugin_url', array($this, 'smartyPluginUrl')); + $templateMgr = TemplateManager::getManager($request); /** @var TemplateManager $templateMgr */ + $templateMgr->registerPlugin('function', 'plugin_url', [$this, 'smartyPluginUrl']); $this->import('PlagiarismSettingsForm'); $form = new PlagiarismSettingsForm($this, $context->getId()); @@ -224,34 +362,3 @@ function manage($args, $request) { return parent::manage($args, $request); } } - -/** - * Low-budget mock class for \bsobbe\ithenticate\Ithenticate -- Replace the - * constructor above with this class name to log API usage instead of - * interacting with the iThenticate service. - */ -class TestIthenticate { - public function __construct($username, $password) { - error_log("Constructing iThenticate: $username $password"); - } - - public function fetchGroupList() { - error_log('Fetching iThenticate group list'); - return array(); - } - - public function createGroup($group_name) { - error_log("Creating group named \"$group_name\""); - return 1; - } - - public function createFolder($folder_name, $folder_description, $group_id, $exclude_quotes) { - error_log("Creating folder:\n\t$folder_name\n\t$folder_description\n\t$group_id\n\t$exclude_quotes"); - return true; - } - - public function submitDocument($essay_title, $author_firstname, $author_lastname, $filename, $document_content, $folder_number) { - error_log("Submitting document:\n\t$essay_title\n\t$author_firstname\n\t$author_lastname\n\t$filename\n\t" . strlen($document_content) . " bytes of content\n\t$folder_number"); - return true; - } -} diff --git a/PlagiarismSettingsForm.inc.php b/PlagiarismSettingsForm.inc.php index 2284d98..fc8bd60 100644 --- a/PlagiarismSettingsForm.inc.php +++ b/PlagiarismSettingsForm.inc.php @@ -1,13 +1,22 @@ getTemplateResource('settingsForm.tpl')); - $this->addCheck(new FormValidator($this, 'ithenticateUser', 'required', 'plugins.generic.plagiarism.manager.settings.usernameRequired')); - $this->addCheck(new FormValidator($this, 'ithenticatePass', 'required', 'plugins.generic.plagiarism.manager.settings.passwordRequired')); + $this->addCheck(new FormValidator($this, 'ithenticateApiUrl', 'required', 'plugins.generic.plagiarism.manager.settings.apiUrlRequired')); + $this->addCheck(new FormValidator($this, 'ithenticateApiKey', 'required', 'plugins.generic.plagiarism.manager.settings.apiKeyRequired')); $this->addCheck(new FormValidatorPost($this)); $this->addCheck(new FormValidatorCSRF($this)); @@ -31,26 +40,25 @@ function __construct($plugin, $contextId) { /** * Initialize form data. */ - function initData() { - list($username, $password) = $this->_plugin->getForcedCredentials(); - $this->_data = array( - 'ithenticateUser' => $this->_plugin->getSetting($this->_contextId, 'ithenticateUser'), - 'ithenticatePass' => $this->_plugin->getSetting($this->_contextId, 'ithenticatePass'), - 'ithenticateForced' => !empty($username) && !empty($password) - ); + public function initData() { + $this->_data = [ + 'ithenticateApiUrl' => $this->_plugin->getSetting($this->_contextId, 'ithenticateApiUrl'), + 'ithenticateApiKey' => $this->_plugin->getSetting($this->_contextId, 'ithenticateApiKey'), + 'ithenticateForced' => $this->_plugin->hasForcedCredentials(), + ]; } /** * Assign form data to user-submitted data. */ - function readInputData() { - $this->readUserVars(array('ithenticateUser', 'ithenticatePass')); + public function readInputData() { + $this->readUserVars(['ithenticateApiUrl', 'ithenticateApiKey']); } /** * @copydoc Form::fetch() */ - function fetch($request, $template = null, $display = false) { + public function fetch($request, $template = null, $display = false) { $templateMgr = TemplateManager::getManager($request); $templateMgr->assign('pluginName', $this->_plugin->getName()); return parent::fetch($request, $template, $display); @@ -59,9 +67,9 @@ function fetch($request, $template = null, $display = false) { /** * @copydoc Form::execute() */ - function execute(...$functionArgs) { - $this->_plugin->updateSetting($this->_contextId, 'ithenticateUser', trim($this->getData('ithenticateUser'), "\"\';"), 'string'); - $this->_plugin->updateSetting($this->_contextId, 'ithenticatePass', trim($this->getData('ithenticatePass'), "\"\';"), 'string'); + public function execute(...$functionArgs) { + $this->_plugin->updateSetting($this->_contextId, 'ithenticateApiUrl', trim($this->getData('ithenticateApiUrl'), "\"\';"), 'string'); + $this->_plugin->updateSetting($this->_contextId, 'ithenticateApiKey', trim($this->getData('ithenticateApiKey'), "\"\';"), 'string'); parent::execute(...$functionArgs); } } diff --git a/README.md b/README.md index 10adbd7..daf19f4 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This plugin permits automatic submission of uploaded manuscripts to the [iThenti 2. Install the plugin via the Plugin Gallery in the Dashboard 3. Configure the plugin (see below) * Enable the plugin via config.inc.php or in a specific journal/press/preprint context - * Configure the plugin with the username and password you get from ithenticate.com + * Configure the plugin with the **API URL** and **API KEY** you get from ithenticate.com * ![Example Settings configuration](ithenticate-settings.png) 4. The author logs in and makes a submission * The submission files will be sent to iThenticate in Step 4 of the submission process @@ -36,19 +36,19 @@ The config.inc.php settings format is: [ithenticate] ; Enable iThenticate to submit manuscripts after submit step 4 -;ithenticate = On +; ithenticate = On ; Credentials can be set by context : specify journal path -; The username to access the API (usually an email address) -;username[MyJournal_path] = "user@email.com" -; The password to access the API -;password[MyJournal_path] = "password" +; Unique turnitin api url +; api_url[MyJournal_path] = "" +; The API key to authorize the api calls +; api_key[MyJournal_path] = "" -; default credentials -; The username to access the API (usually an email address) -;username = "user@email.com" +; Unique ithenticate api url +; Make sure to provice the schema(http:// or https://) with the url and no trailing slash +; api_url = "https://some-ithenticate-account.com" -; The password to access the API -;password = "password" +; The API key to authorize the api calls +; api_key = "YOUR_API_KEY" ``` diff --git a/TestIThenticate.inc.php b/TestIThenticate.inc.php new file mode 100644 index 0000000..810b3ff --- /dev/null +++ b/TestIThenticate.inc.php @@ -0,0 +1,262 @@ +getId()} with language ".$this->getEualConfirmationLocale($context->getPrimaryLocale())." for version {$this->getApplicationEulaVersion()}"); + return true; + } + + /** + * Create a new submission at service's end + * @see https://developers.turnitin.com/docs/tca#create-a-submission + * + * @param Submission $submission + * @param User $user + * @param Author|null $author + * + * @return string|null if succeed, it will return the created submission UUID at service's end and + * at failure, will return null + */ + public function submitSubmission($submission, $user, $author = null) { + error_log("Creating a new submission with id {$submission->getId()} by submitter {$user->getId()} for owner {$author->getId()}"); + return \Illuminate\Support\Str::uuid()->__toString(); + } + + /** + * Upload all submission files to the service's end + * + * @param string $submissionTacId The submission UUID return back from service + * @param Submission $submission + * + * @return bool If all submission files uploaded successfully, only then it will + * return TRUE and return FALSE on a single failure + */ + public function uploadSubmissionFile($submissionTacId, $submission) + { + error_log("Preparing to start process of uploading file for submission {$submission->getId()} with iThenticate submission UUID {$submissionTacId}"); + + $submissionFiles = Services::get('submissionFile')->getMany([ + 'submissionIds' => [$submission->getId()], + ]); + + $publication = $submission->getCurrentPublication(); /** @var Publication $publication */ + + foreach($submissionFiles as $submissionFile) { + $this->uploadFile( + $submissionTacId, + $submissionFile->getData("name", $publication->getData("locale")), + '', + ); + } + + return true; + } + + /** + * Upload single submission file to the service's end + * @see https://developers.turnitin.com/docs/tca#upload-submission-file-contents + * + * @param string $submissionTacId The submission UUID return back from service + * @param string $fileName + * @param mixed fileContent + * + * @return bool + */ + public function uploadFile($submissionTacId, $fileName, $fileContent) { + error_log("Uploading submission file named {$fileName} for submission UUID {$submissionTacId}"); + return true; + } + + /** + * Verify if user has already confirmed the given EUAL version + * @see https://developers.turnitin.com/docs/tca#get-eula-acceptance-info + * + * @param Author|User $user + * @param string $version + * + * @return bool + */ + public function verifyUserEulaAcceptance($user, $version) { + error_log("Verifying if user with id {$user->getId()} has already confirmed the given EUAL version {$version}"); + return true; + } + + /** + * Validate/Retrieve the given EUAL version + * @see https://developers.turnitin.com/docs/tca#get-eula-version-info + * + * @param string $version + * @return bool + */ + public function validateEulaVersion($version) { + error_log("Validating/Retrieving the given EUAL version {$version}"); + return true; + } + + /** + * Register webhook end point + * @see https://developers.turnitin.com/docs/tca#create-webhook + * + * @param string $signingSecret + * @param string $url + * @param array $events + * + * @return string|null The UUID of register webhook if succeed or null if failed + */ + public function registerWebhook($signingSecret, $url, $events = self::DEFAULT_WEBHOOK_EVENTS) { + error_log( + sprintf( + "Register webhook end point with singing secret : %s, url : %s and events : [%s]", + $signingSecret, + $url, + implode(', ',$events) + ) + ); + return \Illuminate\Support\Str::uuid()->__toString(); + } + + /** + * Get the stored EULA details + * + * @return array|null + */ + public function getEualDetails() { + return [ + "version" => "v1beta", + "valid_from" => "2018-04-30T17:00:00Z", + "valid_until" => null, + "url" => "https://static.turnitin.com/eula/v1beta/en-us/eula.html", + "available_languages" => [ + "sv-SE", + "zh-CN", + "ja-JP", + "ko-KR", + "es-MX", + "nl-NL", + "ru-RU", + "zh-TW", + "ar-SA", + "pt-BR", + "de-DE", + "el-GR", + "nb-NO", + "cs-CZ", + "da-DK", + "tr-TR", + "pl-PL", + "fi-FI", + "it-IT", + "vi-VN", + "fr-FR", + "en-US", + "ro-RO", + ], + ]; + } + + /** + * Get the applicable EULA version + * + * @return string + * @throws \Exception + */ + public function getApplicationEulaVersion() { + return $this->eulaVersion; + } + + /** + * Convert given submission/context locale to service compatible and acceptable locale format + * @see https://developers.turnitin.com/docs/tca#eula + * + * @param string $locale + * @return string + */ + protected function getEualConfirmationLocale($locale) { + if (!$this->getEualDetails()) { + return static::DEFAULT_EULA_LANGUAGE; + } + + $euleLangs = $this->getEualDetails()['available_languages']; + $locale = str_replace("_", "-", substr($locale, 0, 5)); + + return in_array($locale, $euleLangs) ? $locale : static::DEFAULT_EULA_LANGUAGE; + } +} \ No newline at end of file diff --git a/composer.json b/composer.json deleted file mode 100644 index 37f1a3a..0000000 --- a/composer.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "require": { - "bsobbe/ithenticate": "dev-dependabot/composer/phpxmlrpc/phpxmlrpc-4.9.2", - "phpxmlrpc/phpxmlrpc": "^4.9", - "cweagans/composer-patches": "^1.7" - }, - "extra": { - "patches": { - "phpxmlrpc/phpxmlrpc": { - "Allow other datetime possibility": "lib/phpxmlrpc-datetime.diff" - } - } - }, - "config": { - "allow-plugins": { - "cweagans/composer-patches": true - } - } -} diff --git a/composer.lock b/composer.lock deleted file mode 100644 index e4d8331..0000000 --- a/composer.lock +++ /dev/null @@ -1,177 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "1841d3e30deba0c3223aa19c5a18c7b8", - "packages": [ - { - "name": "bsobbe/ithenticate", - "version": "dev-dependabot/composer/phpxmlrpc/phpxmlrpc-4.9.2", - "source": { - "type": "git", - "url": "https://github.com/bsobbe/iThenticate.git", - "reference": "1266a0435143bc7a627be3a7dda98b690ba6bb47" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/bsobbe/iThenticate/zipball/1266a0435143bc7a627be3a7dda98b690ba6bb47", - "reference": "1266a0435143bc7a627be3a7dda98b690ba6bb47", - "shasum": "" - }, - "require": { - "phpxmlrpc/phpxmlrpc": "4.9.2" - }, - "type": "php-library", - "autoload": { - "psr-4": { - "bsobbe\\ithenticate\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Sobhan Bagheri (A.K.A sobbe)", - "email": "b.sobhanbagheri@gmail.com" - } - ], - "description": "A library to use Ithenticate API easier and faster, to check and prevent plagiarism", - "keywords": [ - "api", - "crossref", - "ithenticate", - "library", - "php", - "plagiarism", - "plagiarism-prevention" - ], - "support": { - "issues": "https://github.com/bsobbe/iThenticate/issues", - "source": "https://github.com/bsobbe/iThenticate/tree/dependabot/composer/phpxmlrpc/phpxmlrpc-4.9.2" - }, - "time": "2023-01-11T23:51:36+00:00" - }, - { - "name": "cweagans/composer-patches", - "version": "1.7.3", - "source": { - "type": "git", - "url": "https://github.com/cweagans/composer-patches.git", - "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/cweagans/composer-patches/zipball/e190d4466fe2b103a55467dfa83fc2fecfcaf2db", - "reference": "e190d4466fe2b103a55467dfa83fc2fecfcaf2db", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^1.0 || ^2.0", - "php": ">=5.3.0" - }, - "require-dev": { - "composer/composer": "~1.0 || ~2.0", - "phpunit/phpunit": "~4.6" - }, - "type": "composer-plugin", - "extra": { - "class": "cweagans\\Composer\\Patches" - }, - "autoload": { - "psr-4": { - "cweagans\\Composer\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Cameron Eagans", - "email": "me@cweagans.net" - } - ], - "description": "Provides a way to patch Composer packages.", - "support": { - "issues": "https://github.com/cweagans/composer-patches/issues", - "source": "https://github.com/cweagans/composer-patches/tree/1.7.3" - }, - "time": "2022-12-20T22:53:13+00:00" - }, - { - "name": "phpxmlrpc/phpxmlrpc", - "version": "4.9.2", - "source": { - "type": "git", - "url": "https://github.com/gggeek/phpxmlrpc.git", - "reference": "805d727670b7a7c08c9f129327482f13a4c1ea11" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/gggeek/phpxmlrpc/zipball/805d727670b7a7c08c9f129327482f13a4c1ea11", - "reference": "805d727670b7a7c08c9f129327482f13a4c1ea11", - "shasum": "" - }, - "require": { - "ext-xml": "*", - "php": "^5.3.0 || ^7.0 || ^8.0" - }, - "conflict": { - "phpxmlrpc/extras": "<= 0.6.3" - }, - "require-dev": { - "ext-curl": "*", - "ext-dom": "*", - "ext-mbstring": "*", - "phpunit/phpunit": "^4.8 || ^5.0 || ^8.5.14", - "phpunit/phpunit-selenium": "*", - "yoast/phpunit-polyfills": "*" - }, - "suggest": { - "ext-curl": "Needed for HTTPS and HTTP 1.1 support, NTLM Auth etc...", - "ext-mbstring": "Needed to allow reception of requests/responses in character sets other than ASCII,LATIN-1,UTF-8", - "ext-zlib": "Needed for sending compressed requests and receiving compressed responses, if cURL is not available", - "phpxmlrpc/extras": "Adds more featured Server classes and other useful bits", - "phpxmlrpc/jsonrpc": "Adds support for the JSON-RPC protocol" - }, - "type": "library", - "autoload": { - "psr-4": { - "PhpXmlRpc\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "A php library for building xmlrpc clients and servers", - "homepage": "https://gggeek.github.io/phpxmlrpc/", - "keywords": [ - "webservices", - "xml-rpc", - "xmlrpc" - ], - "support": { - "issues": "https://github.com/gggeek/phpxmlrpc/issues", - "source": "https://github.com/gggeek/phpxmlrpc/tree/4.9.2" - }, - "time": "2022-12-18T21:47:48+00:00" - } - ], - "packages-dev": [], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": { - "bsobbe/ithenticate": 20 - }, - "prefer-stable": false, - "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "2.3.0" -} diff --git a/controllers/PlagiarismWebhookHandler.inc.php b/controllers/PlagiarismWebhookHandler.inc.php new file mode 100644 index 0000000..e6de97c --- /dev/null +++ b/controllers/PlagiarismWebhookHandler.inc.php @@ -0,0 +1,57 @@ +_xh['value'] = $this->_xh['ac']; - } elseif ($name == 'DATETIME.ISO8601') { -- if (!preg_match('/^[0-9]{8}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/', $this->_xh['ac'])) { -+ if (!preg_match('/^[0-9]{8}T[0-9]{2}:[0-9]{2}:[0-9]{2}$/', $this->_xh['ac']) && !preg_match('/^[0-9\-]{10}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$/', $this->_xh['ac'])) { - Logger::instance()->errorLog('XML-RPC: ' . __METHOD__ . ': invalid value received in DATETIME: ' . $this->_xh['ac']); - } - $this->_xh['vt'] = Value::$xmlrpcDateTime; diff --git a/locale/en_US/locale.po b/locale/en_US/locale.po index edf9d1f..ff7c179 100644 --- a/locale/en_US/locale.po +++ b/locale/en_US/locale.po @@ -26,17 +26,17 @@ msgstr "" "Settings for the account used to upload submissions to iThenticate. Contact " "your iThenticate administrator for details." -msgid "plugins.generic.plagiarism.manager.settings.username" -msgstr "iThenticate Usename" +msgid "plugins.generic.plagiarism.manager.settings.apiUrl" +msgstr "iThenticate API URL" -msgid "plugins.generic.plagiarism.manager.settings.password" -msgstr "iThenticate Password" +msgid "plugins.generic.plagiarism.manager.settings.apiKey" +msgstr "iThenticate API KEY" -msgid "plugins.generic.plagiarism.manager.settings.usernameRequired" -msgstr "iThenticate Usename is required" +msgid "plugins.generic.plagiarism.manager.settings.apiUrlRequired" +msgstr "iThenticate API URL is required" -msgid "plugins.generic.plagiarism.manager.settings.passwordRequired" -msgstr "iThenticate Password is required" +msgid "plugins.generic.plagiarism.manager.settings.apiKeyRequired" +msgstr "iThenticate API KEY is required" msgid "plugins.generic.plagiarism.manager.settings.areForced" msgstr "iThenticate settings were found in config.inc.php and the settings here will not be used." diff --git a/templates/settingsForm.tpl b/templates/settingsForm.tpl index 5b212e2..10966c2 100644 --- a/templates/settingsForm.tpl +++ b/templates/settingsForm.tpl @@ -9,15 +9,19 @@ {csrf} {include file="controllers/notification/inPlaceNotification.tpl" notificationId="plagiarismSettingsFormNotification"} -
{translate key="plugins.generic.plagiarism.manager.settings.description"}
+
+ {translate key="plugins.generic.plagiarism.manager.settings.description"} +
+ {if $ithenticateForced} -
{translate key="plugins.generic.plagiarism.manager.settings.areForced"}
+
+ {translate key="plugins.generic.plagiarism.manager.settings.areForced"} +
{/if} {fbvFormArea id="webFeedSettingsFormArea"} - {fbvElement type="text" id="ithenticateUser" value=$ithenticateUser label="plugins.generic.plagiarism.manager.settings.username"} - {fbvElement type="text" id="ithenticatePass" value=$ithenticatePass label="plugins.generic.plagiarism.manager.settings.password" password=true} - + {fbvElement type="text" id="ithenticateApiUrl" value=$ithenticateApiUrl label="plugins.generic.plagiarism.manager.settings.apiUrl"} + {fbvElement type="text" id="ithenticateApiKey" value=$ithenticateApiKey label="plugins.generic.plagiarism.manager.settings.apiKey"} {/fbvFormArea} {fbvFormButtons} diff --git a/version.xml b/version.xml index ef8f420..5950b4c 100644 --- a/version.xml +++ b/version.xml @@ -4,8 +4,8 @@ =Rp)%E65`-!^>9g`W#sdN zPEm+6MMOX!8(km97=RxPg{Rz|3`-ZJOJR9zbr9IWMU5GNzC!^Y9+08V$wpo0FNu^L zkwfqd^&No$Za?HME>aY8#-C`$D$9q1M88uDjMp;U-H~hzT@L)NBF;oF=1Qacv6mS`4yDLP5lXUc=XV$ zw%p{B7@bVP)GiI~`6ZPVMg}tk+Tg95Q+Yjny>l@<*H0bgaddN~U4NY5rQ2`E zU;d1VFG%}aM=gtQ*h?`5<49GuySQ(P{ZUapbRjH+PftS+Y?qLv?AOJQ1(~js`#xj z@@fy;E%fw>m;7v3)Y8CUeUr8M03GmbgWAw^6g75<x}i`3POoB~XcI11s1? zR!Pnk(6hn!fcp~~zw4_5ad|e{1&K=#Zw|f~29~%qK{%sv$O3hFIDEHMV7vnjoUG_n zygUv3cdE~(bR6W2(&`k)@ys%)SJ+Mn{INg9mcD2F^)0}DM1Bk~WG16o2V?dpvWh~hv=>bzlr)?#uSS*qTPYF5Yst=GdwDSINUp8 zwAXD*!Wcb5l7qJC2T<0L2J}1r%V%x5B?SSgX2~OpHtOT}vcF_I2u=c8pIIn1;@!W; z{b2o`9q-Ku!SRk1p^c>~kT3f9%O;;og+*C_q3sLwA8PLSbji_QWBKZ;$Hnx&-HR(+ zTwH8io?ZHnWL)-+z8sxQ^Ordr>^?}=|uaaep_!dgPp<~*f4#m!W7&k38DJ`A~` zy&-}iLWCiLdZA|ydRgVl?y+`Bc5P?0tN30x!rsEMYm#loZAfj471E9RruHVdLyY@TLS@f2ElNA+X=4 zpQm3|DhzY-?_{`nqV*TM+JWNH;^l>jg<-xvk95bROH317Y!d-C&k>(J)jhvG?!7Qd zJPAGtNeMjE-^5Oqe{~Xa=_u)_5;zjt=rj~Ssnzm53fJ-}89b?L+&!bZBmLE6$lM?~Cfw^W9_vmeAvFRsEeitpnXtR8!*Ls^+$WKc&!4bM$h|J0QYgy18t$EWb2qPN#Ia)Z3QC_J{3fo4cizx?fAx zwl%gIi}ed`%UX*uRT-8V*6zbu#^d$)%N123W^Z#{la#ZY-eGWIMX_|TLIcJF+5>`$ zE=7h#jEb|08b2e(Z1#orQOEH0l=1EHtK^b~VKruE2fl7Kch&h47^SYW9abJ0&97S6 zku*>>Xg56dr1hADrl8mpyc!3uhTmWgOaCOgTwGliUiZy-I{h9>EgkofaFOeZ6&)WP zES)rftJG{ByiYPNHJ+khu1{4FqtDw)xMtGYac_6|y0d*uegFIV@TTs1^hWR8JJYr| z)|~ZQ_8s*@2xRn9@Z^4NeV}8)zvC?%$_~mCss)%8>qJ6JRA)QWBbp)Vw~;LR6@!U^ z)51Ca!-7C6xi0B5MK6yeLACG>;y_x$@ZzW^<`LNkbYTKW^6_|PpDkKXH&xG2_fj`% zPeRXp$a+*|#NUYGn1k4x*q@k-B%i_~W3|a#GtIlOFRVOP^L?eqiB^deq7(BMMU?? zMzmn9(}d75D>P@GB$mqC$xg}*%KVn~%pgi`ruxcl*W0MIJ@zZ@m+TbLwCo|{;qtV1 ze^{J>a65I6U_RIO63hVNG~LfM3m$g=t?#m42@eTqrdS+mobG0RI|G*`kHT85rMFtE zz;eTwjV3n9#?K3kNH}E}!h>id`rlu;=-JH86pQ#Ybt%t&IM5!`usY{E@$R;dMh!22 zpHIn7?`R0njn{IJv0@las8_82DP-%^GV)dZgPOu+cD2{%1|jWsJum|u0}*n}#^y`w zlx3nQnf~!#AI%vvH(x-uR%iDN`poroHxB)9%e3zuBh6 zjEtqPatyeQ1@ee{6=a0?@*0xvQ z&if3!Eo55cWjs$7?Un=Qw8|5kCU4JAj{|*yedhiIj}p7+zH-$mwam9#&5neQX)cR( zyIsTX`ccRRq9D)UTt1eN1V9&xEXWG^9=LFA51|u;<(097reIo6l1b=@jXoOhiE)YaeSXx3qI@?WnmA)`ITlC+&^&HcBR$I;+WTBW=4+ouJ)z za}l#w7hC_E*JS7uXjhTtx7JsRZ9^?#Rgt##7O|BaD|u@h5iW?boSNu#mqF-T^>*d$ z<{#>Q>148BWO@#@=bD#QS>Lpr=P!S5qwCPst$^6idXwg=%53TLm9k#Bx8|{n_=;jP z(S&>-qTkXa%oojx#~y!{h@AVrZrHDNklI{ZmUL`*=U(Qm_Z8l$oJzC88VLCDpIlXF zcxa62#k4K?F+VQF923rew2Tgmo-Lv(1X-xsV1IG!!!DucRuax4JBvPOeXx11iQTW>Z`1qbPw-sz z8ZsS~{f6>*?Q`FF7MpUF;_J`sX9lqvu&$VA7QPg|U&CoV^wqf=yICE(Ke;ag75I5f z3Eom4n(Wf=D=B2>i>x0q9ULcI?moZf1K^0$Gf_JY1OYikP@Rnk9dI~{*=tBTA)6SKapT3_S=5FS75uLMHXl2R+QZ>UEgl?@K<#C+lhUs)4dNg`2CilU19V$ zmR}9@%_F89adsTvHys{knzG*%6aXLIbp!w`6czybU4wcT02C1b_Fp;x@EMBuzq%?E z!@q5S06>@}0OsE|+VAB*hs^u=-umAqFbDV_3#gkM=>O;d&VNjGZbuB>3q%JQEoT4# z8T+3T3XuMj;N63knYo zHgU3aaIv(vqxi?Kk+Hq2i!c?{KY{*x{Lgi|SbqE8NOsQuPU}5E)_;CsWoKby{jcx$ zrb7SJ3Me^Qn!QK<$3KW&=wFuqU){gs2(kVX{Qq3c|77~F+V@mJNJ6at?KTjSd^f!o z0KknUD=GHH1L`yrK0xo&?7;ZhH#JI9aU~#KA_7rl&J9)M6pBJ55)^GX1|yXr09oM= zQgIFyUL+DypbIw+?yZiN?wQe^z~x;2BwcjRqMRQ*gV?&Tt4P zEXThE?+1{XISGhx@gwfyH?#D}9RA}{*l#2Qni|H#J=uoyeHwi?a8*uZ0@41c}nv>dC}bj`T-^!2#TFtNQRyGfyz zN&YN4fg$QJYF+=VMnhIf**D>2t-?SldRT9_CU@%!Gs86Ce*_U$JH#`p-1+scakT02 zn|1T9IuqGb3+{D#X}J<>jTt0uG~1rXw-EPQr_}DRsP)1#_1v`yc}=^Hol#q|K|7F5 z1?30PpN2*8iXT+#|4GCY$%PuWvUHcl|F{qTbX1PDrl}~)%yk&Os`-1*sMp;MSH2 zWS+g>$ec@Ym4wV(iOUSCdiO_5N`LWIX6Y|2#ySjW)88DL@HiLNtvDszKHm}YY{VnZ zIWL-7Bi(+SU@{%{|KB^)90t@}SbFBUuDD;!@IJM6rB>%8=2$ox2JDy(FE^i+sY8UE)QxI75x;w9M;hCyiHB5o^ zx_2=M{qf(swK2!p?K794w1g7;7}+!8bHg_kHx57H&de+;cPp7thVInrDOyw5B zklPvv8LHj)@oe7t^tDvGKF)E?p1OIh7hCuA7;U{dAGN+w7I$yQS^LuaS&ijRJ+~^z zy>?Db%{l4$T!e#g0(GUUbuFasJ{iKC7S$JG9yoKC*rQiaksiIt3?%$1VQh2 z1s)kxP0QxopNf_(>rGU>mLdDjo%z|T)!F*kjR`5B&xBrUC7X+!CvV$1!nyWg6cV+E zkJvFn_boW^$0{n63!2WN%qyP@I%MQSDYJI~0HX^HEblf)OM_wee037 z%Z&Af6=Ac?^Lp#P(Q=KclTod2)z$lCUg5aM(Ubjmesgkxtzvf9IloD6=RV5$Cc`|n z&KorJ6Wi5>BKzCa_sg^$)8)qg?9F5?@$IA)sq-r-)5g3hyK)BOHFL&8e(NK!FoR=n z2YL8(!{HO$>rr>;KaOlD88v9MGx15jWHM*$$(^gM;N6lnJ_}%3WRA|0ff8vYpO%Mf zDjiqZH@Zp$9kmyDTlwj&|oKNhH>s4r1L>jNBlEUb5Do7SWjsi*zTo|7PXQ*HdNNMyS$omm^gbZJJC=Tq=qztHGLH}O~WJgbKz`OR_h z$K9#;?t&9t%c>h$^tK~Rw#_i<+G7{bws~3I4I)=(RKC-$Fti&v@>39VQIT1be}zOX z?6diBAFmvqn7wV`CjS(0|87ZB5&De*o|)Y5!H8JErTAL3S30YJg1kX6H`hQ843wFVGHkaW|S}V%=Q7;j!ID`BbnA2VZKKQVQ~oOD!24yL@gY) z{cMrwihD_xD`J@zj?A?rN3GQB?PrE2Cpa}Fu(V^#{FKZiGny_u?8S38qyM|%k2B-8 z@WXS}0GT!Cdg5lShIH>QXVEUNav`Y1ur-)HCkxE&(8k(Ps4x$pSp>BR_$mAv;l&bN zWb2{s&^$@uIP%KzWqJK|?=dAwPJkKz5UkVGE_0q-f?2q4WnPbfx`VHc{blvlQiFJy_{Ky`H|Gdq z5A@lY-(1r>=XDjLAV}A=T)`rF9eq4ry5B$c{ud0-$X!HoDwiANQB>+b=>sd_0O0 zfL7Fn_S3Csz51+U`77yUoBYiq11#p1h^XnVIIRt(|%U{S@W^_RRfxjzs!c12wi~k3{d|@SDs+@VGab_F~4g? zg+j#jcNw6F3%WRHaI|Aqi?GeOi=NAAzb&(0{7_Q5)ot5@%3C|`cUR-*zw=#s36*zc zBM|gU+Kb#p#>n}t!vAHMrR_#FEORf;r*7yIq{TJHtLathtUdefd4DYIhOiY;3C2GN z`VqmBcncJQ>xgjEgC;m~h&NAxe0%3rA5i#n931Y=OGh66FH`ARmH_Y-n z`n`tc0o1n$@<)<{%||nY0r9SRP{-9joway-3E)fmEq$-w9T0h~vTc9dyQ5U-?i6E> zj!%wg6wQBsmn?Y2IHBrJNs~Y%Z z^~3*hHzgBv^TML7V|Mm=8DYh0wJfRExt4z~pg8U_sv1zrZ$Davtt2!VD}1N9&ve!3 zM2>Jw)EU^8OdNZx!Lhm-S-5JTa9)xQ3Wq3Lf%9btLV?4YqdSwsHq;{{zk3i0C3Hv`|8 zO&+hCBW`OywV{U?-c`#s+BitmtNmG37_NWQGR+qs_f{@brnAO@J>jR)+rkPR%Dy_( z4U3y7){bx1q&I3UyZV;+LsgaCBsou~4cTSo;|r&a+p%tIp8Lz`*5#Hxp{O-AG?JFB>S}`*0<$1y9mZ>3KON|O0MI=Et_F_DcQROK zbtIvycm<*l-&{wZcadAjcB($E-M5?L>$!Yag8VZGR{zk(@VxDdygBMaEBW0Zy5wZ% zvX1vc$1x2tcL!d)-gm55?21f;R_~zd4^Y`B(#jGDd%4t&=Y6cqU3MN9-ZzQ!IEn@B z^7oT_9&(mSKyX2nu?8FH=siI&TU}|FI1h$=7u201(fC(AN;~w*p|5awM(7H88;YW- zJxmv@H<27Qb%ThnhOY?vlraWs&LM@-rw8O$SOLyggY<%{IR+P89$@!Q3jdk9Ic@8v zO274|HS_(S&aq6NqZJ^jAaamTV~?04kgjqHKw^P!5@NnI9@i8MDu@9i!}Zn8>mR>N zD6bnzlQ;%5g?0v)GpsSTb>hC}tyLD~9`bfPDm=Xp(oH^Cn=56|65b=&_kB)%BmpRx zv`*7^Wp^S7{KyW-3&Y3B0&$b$NkUULz+;p2MMCx<&;RkbYGhT_;^w?UIm7R=VP(1XsbsrW%av^(x101vTPHV zho&ZX9$~lhmGDVLhSM^e{i=)HN7YRw-H82{Jm@i{+eL2rlDeXJ8robLrDe`#xPp22A;v(D8oIY56>1$Rc zWhV_CFJ#kns^R{~d)=m*k zryIfNp$(X@dx6e`TIP?q9@M~>PZ?=64XbWC`|uWW-Z`f=Q+H_?mh`^RZHoN6IKANegV0<410(RqIrV54tkGzBVmh<*y0)uGip}tnfms|hJFfy;d`*5vbf{&V2 zJ7Nb@kBDH&vasSup$CxHCD3m9f z5P}99DJql&djK=G-5=xJ6HzPjyot_|bI2Q=8H5g62-!jRyMQKVVjv`tm`D)Fy%#tx z-M*%AeyH%fWx99D)n%{Xe6^qtT`X@ovl4+!#{Gm3&nHiH_kVj@Z=o7(9C&|&B~VY;v27Y*#_E?m-`*yiS1q;8FwTT7t5#I2OH|?YT~{P1Ed?H3_KOi)!VQhFRI%_$wDA znSArqx=mytTmOfgg2$(drZpStLBqPfQ1qHd);5c4?)Fq?A&Y=E>f%i@_x%@tR+|RS zs8O^RKO+;xkA6OL#l?rRe*tib8bfNogb|-kZ#a5ciZkV~LoFm0p(9KvvIuv?H3!t}lX>G! zPy!pRez-uy8ti?xiL+>|b00R~MT%cYuG`j4Y1NG^r#=?sJk-!#ZQV>O-Ft6wZ#-wc zkI4%v)?2&x5!0vV{?+4rFT>tVTTK+{$2M!<_;43`S4*wQ+si$x%(SFVGzouo`~@?Y zEKc@AFMTTr^$JKN9bc^`6aJ7-*DaovZUs7^0jpa$vDEHtT&D9y`Q9xKcp^4pq4iBG ziJV$u8T$!lGgBm7Vx^w1V8hU=G@Z*LsU9*T&C5u!WjH=a%Y zdJz_qi0Yp_!4Q~T;3F`0(VB?RVUE&WquN{2O50^1^ZoYfA~Lvm9KSZjQ98cwoQo>9 zowk?n7c*9*BBxf{m~=r9uSxvHboOg){Kf4hJm|QrC2Q|`KhuELMF`y%jp)-;7x7w{ zJ%VaI5;N?huy5h+UvZ>Jkpa!bZWWnSPZIx}WxJNsy=x`Oz-z<=#S3ZAm`G6D6W@AZ zLaXnZy2HbPw8+t^k*B#ERoG2*>LgXb-LG~|bovIKgiJM(f5ai23vs)sCo3Gwyo z-k(THGKe1v;&Cq+D|uF3)bCfRf}O5^!YYV-4-zFNJ3 zuZD4}m8ou1^UEWn_N++1HHN!fLkBAsa}bA@gF1x&_Q#f&-hbhWb~?MuemXAU-Mpic z{u6T%UB~11{BV^1aj7l1XuyO&&vR2;OmJ6=)I!+%)&&(s)1t6(b`ij3THOA zj4!{=1alLrt0h;qrwzXfEiNQx`Df)H#p|w^&}1cynkVfv5gLDoFco|ehrOXankBJp z8MekK4eakavKvFq`u{A%{Q9)J@^TGwnSCk1r&^27q560l_rN!4UBj&Y=iEL zyD3c}Td=qAD+m*)a^!MqLA^92D^q#df$BSm`nf3gwa8h$*8!hC<=B-XdsOJNuswtU zGPP8JXd+9PzQ=@XJtC8=6Q{-0an*7DC)xv0*4V6Y)3*fCv&euoeYXA=N8uudHXE~5Re-_p(@Gz^SAjF>t;Pw}i^|-sx z#w;cV^;`8uezT)8yfi_bnosPTLTw#5?0li(1?Y89=lw^agRdEF>?pG(La+)akz$T!1kk7(wb(TX)ah- z)YS(iiQ84J2Rzd6@h!$Hnm}NbP`FT7t!tsOy5&A}9XjI!^53>TYcT>q1{*yjM~gGSIL688#;mUC^2rBfl;_a?!9}Q^_U5v@(?5PuqJW5n!vf3dIPsU7!x* zpG#R}`mMpO5_Pp!F?2C|GOIP4=>u_0A`ggwZ5#yqhchX%MYdK0Ck>g*!x3y{l!PUi zU#~x#S%zSU2t$0%D6nB3Hpei&CCjueWUZsS|RA7C{<%0tfWpD z3>gc$q?TOmj2mP)Dw;mjB=EZ089a+E&~;XGcFm(_MG28Zr0m5N08d_P<)Jcm>V0Zcd8 z93^7U9?1z@*M3%#BC(Zz5S zsL}IDW(sl2dd9b7JiwtP1rO;XZQ;2C;C1^L*e3wWUP1{))`39JB|ZLYMdP^~%&sg_khVf34hecSByKqE?OZ4|8} z4oyEd(w7lzcE4PO+DxxBIfp^)PRf3N>sdcUzi7UTe8nSa#DH_g0q&!G`G$}=$4!I4 z=~f0wLK+LZZ`1l5X_K>mgi0Vkln>Q9tbOm086DM{ei*n^stfR)XazEAw8DvV+qW?P zk;YbD*mx;f=0$@PAUnG?y3?|4!c!}g6)L2GYv=XLY@8@F;o7f;{Cz5`&%DQl-F5tZ z8}R5p)liR2)P4BLo%5SIHK2}d4verPhDa}*S7 z3E-LI?qF0aY`h0p<64Jy(jeFzNp`}w5ymqx&q%-Z3D5yk!M)mi_s7v%1M?1pVYg_C zJ4N;z*mK7iuQp#`cp)h-xI4M!E?6+xIk2{7fT9HALzsq>nQ|~R90Uf9#p1eje$rhY z#^Q~^VCM0CBfbcWZcCH-3OsY>j<-?AhLCtyMAdUrZkt7OAaK9gEa|{5Q0QF zU1(ec#7Wo1wVN9EZw2<3c2u7cKQ>N@oFI!0N-`Rv3iR`|N|IybxL@cdnvcUdY|&#YFMUYeA*{F&<{Bu0^RFx%a*oD6%0ti7&$=YT#Gsi`coQWb%9{z`tTaJK z1fqXJNSz2}A0+68NXkILGvO;?w!)H5Lvm=Jdy+iE*`qFu{U{}$a`9ilqO@%DRUNQv z#-%k;nRVXcL(|dc2)*#E(z;DAntK}~LOtmMF8zV9XdckeUeW;|_VK)lO6dqcDpr@R ztVfJ(fHkqlM1W_wqpa{oq8DKJs=^b=a_Ue7gu@|bBB+H)g-2!7C1awW)--H12ZYTgakqbkcEW(FedA3dmPUx^vt6H#ZW(-YlO&Uf6QLSmU zI7JmDyw4#M4B=^9J^KX)nx>}>Pi|S&WAJMMs=S|kAc7kl&O-q4XAE@$m(WlI*kBrB zv*Mr_n~iQ$X%HO(4(mam6mufU%Gz@(#X>L~=tNf<(d36&JO@8^;GXWVty-Liz(WwL zFRXAtm`*x4b{0-?BAsVqT{HfM5xa73jTFu|hDiWIzcM?44l>RAe0dq>{)qnaspakV zq{D|3uQprgk!RgQR_Ai3a~T1()aax0!RI&5&21{W_uhcd$|nK(R<~*})LbxbBkKo+ zHBB|xu$eJNviAlnF5=f|!8fx>5nf*q_~Low(R4{8d^s4CR3aTg)fRDW?~e?|50KzL zKsu*L^_aya0~$DpvC~h$-%#G>=~CcqFnSQs#)Af&r1-WiBj+oX@4zwD0c^iW89W&h z6QM-*01r@RxMtA0g!YW+9K4f$M`jX~F5jYmWJB^_qD3BfV8(g0;qqB61f9u-5pHC6 zij+1~vJRnvt-~Jq*%<9GOCnY`#eXiv2=~Mtp5w1FS?x(*BC1DMLPaAkF|Ju12vQQk zbOxaEc0xmu{|Zgb(+VD8M^e2qsA5}+QE*k!*<$@&}T zoP95X^KDMxJ5Yy7!3Oost3tws<(30++R?Iz6@i?N;i@p*pcc%$ z>M0?rMve_LzN2u>jF93)#3u3ZBbkGCoB^fO-qIO4&Q`q1CZm@K9R)y_W8oiTgG{Qo zhf4Pq&S{A!K%8?c&uvsB`tGZU`E|mGS8tmT#31I(%&a;8mOr% z5y=arT}j@^D9n`%Tdq>qnR<@ys3jjV!;p-wBaqm=(H`&ol|Ai8Z{H*`b#(#rEFt44 zf9xPOd@gP~R>Md)HcLFu6e}kIRgg!R*^_esCuGkH){AoxmkbJwlDmev9XQ|iXnC$v5 zyJ*CSl>?RBM@ zz;6~?)dl2X2Q~>#Bi3Ej!ZU?rBF%9`-wnYj#v0PU7O*uHf#}dmh4mN3jzb7Ng^_b( zf8q1F{(4RPF2-u;3Y>-g28Hi83pG8)Sxc$(IbYkBVL;8(+YDOW`w>6<0*EzSIb|+{ z=z($}YS>maHvrKgY=8|g_$X`kJmsf!E>`}tA=)8*%-5{ivSg*mbLe9DVrsuu*Zhnz zqg&}*t&w!K$n|@}v%Ic%<+g;3N~rY(&Hb)&sE!|GH(j?T?w>Bzi~ZU|-Jb`hi+9n>h!;Dj6{|qn zu?K8_iEsbhk&g&p>Zmtlfv8JHm#hH67Yc5-`@ZvV*8F|GsaHhU$w=Teqn@_`4wq2J zw}JFlNpAXS|A?d5X!*jUd3sTsg2@s!qcvb;{%Ex?YwsA_9I2|gF40r8QQ&W?P8Ua86p9vhwkSgR zR`q{7yl>`_sL zm`?7skX`|4vItY;OF(vW_jNU4T=P0sP;)zle#y{Q$WAhqp5^J|#QN>oDDHo# zK+pbpfNYaYN+^(;y)ze?bL(tb^$%Rlc?5G92Ls=H333Uh!lRaZwZg9}S2i0uo}O)Y zbYks+<*COz1A62ATlCr0d!xK{&F^%Vt|f$dozLQWB_+ZZ8L(c;R0jWt$O8s?JYXEz z%TSC@SvSRa?Uw3Sq~W%@%~8!afnp2ixj%?BRDNG8i*UqIZ%M6@NfspH|laY z!1$h1PqiqQ!JqnkRW@h3S^MgI){{8Q2p*e!kwlmO{9-w7ejO?)9XKzqY6e5dz-z1X z)`}lAH!~Z*n0kGxoHxp}=Jkm}d$od$faW9&c1Vhyd_Brk%yjzvGlptJ?ImKL|KWN~ zkio8%MRcGvJg<VEia81?aXv2o)ToJ;5HP$)*;X!&sLtNwPy zM50O2RZe=OTQ!mtXOOGp&``>~q<13ldjN6-E%$N@@>W_o;ST1%83PJC>lJpsF~Ew; zTqv>_SZ|l;?Zy?l6dpo_X*>qt8u*^bFaGV3mVB@xG{A_)a4>J@pVs%Px{{r`v9|hd zFWYog$KT#KFrWx@cgW!OPHy{kACzma0j%)8jAULf*q|1^{MA+7d1RA@^EQ?|_}Hun z#iE&Etfm2l)VS{gQ(Z*&cn4yoFM{Ya zH%!>F%YDrum6S3+RQ1TOMxkc-`xihw1%t(~J-)A@;Zgnrc<`seBPeT|$U!Lo_2N(g zG%2@{frv?>Uou{aX9Mycp-+RR)414X@{uNUEbv#3uusJn=w?1rs89)QEYA1I-b&t! zsCHBsz8sv?xk=LmW|Qn?V8UF%p_2K$!}kEjEoe9GZ2Zr!1+Js^s-j1jDP0M{IPR(O{fH&=8KU*bto&Tl`zOZ{&vX7mK z^X;0Vg8Nf7emp)4k_V_TQ8GV9lqq1nxz#BCgfIWlJF|d>^z?Shk#k!cNbfwkvBbsbV z3X{Cxxj6?k)0>0W2tVu!r2*xjV2z!2i`V3CRU(VB{f0y|T4F$kU7H*vwOxpY@=GMn z!@-J#Xrr6)sAyE1Cue-Mq0ry?dZD{IBLaL9NE!se(2|u5{H}2ohmI3Sw@&R3EG;Kn zfuRZO;R7*fHo8+Y(xUP4W4VHjY1`M$BxEjwv?+Y@XnvakcZ6SuatHZMM+>B|GKX;Vu(6Z&r!zkf?4kijHaPfZ0DJ}9tuq03 z`GwA#M+rGv-&NPc<@U=(YL4LPRx1=*LbFbhWVwi&uZVhbkf=DpHuL5L`4%4li8g8+ z$ypiMArLfyrE7r=ujQ+lOyaV0!&T~$tjt%P>gFg;B1c5x(hXK8!RP@?Okg$MaEEdC zb#ag^^lmauV8%gfC}wPLFf0v=@&3eDdIJXan34J3U~clSb%c${e!oC);7_Hs72*1u zYl38G+psv(--yw{;-qZ8^UvH;nW!e(J*q=t^u;2O#jb64PFy_K9W*07Cu*qG<@7W!!wjNz|&_a#?&yYdr4hp}^0=4PLXM zMDgy?&4kBy0FsgBV`S6y9v;?3NN{;iydgt@Bo3B&c*3-9@}Ddm|dn)QoaMf93*na zbsU$sAbAoz>ldNn3CNB(w!9;>$eCBWmtZE>poB3S28)Vdi>h}c53)>Aje`Q-4tRgk zYi${2d;!L)_^ZuJtk=FcKNl6su49+{)$9ERzBPC*+m6<}=D+^pSCMc;VxM_=c1mMXJBqw3 z5|sq>MAak7ka%A#C_;@=t-+urZWb@uHZ0HSEn3IwPcv(M{QYvbJYFUgTfalY1RMyd z9*o&`tb$Y)R}Jyyxl9$v+Vwd<(-3zN5qm=fnsERPYYs_rjZamHKlSe>g3urPSz_t? zu{*0W11-Vj%USP_aklRB6&2p-z{r8hy*MLVp8h;OFhe$Bh3 zFV0oi7lPt#0wLCCS%TFI82kYPwX{j=?*EP-(M+~YfO39o;9Cfg7+bSE9Zd<=|K zuE5ST9rapVAPGfYgbg36lq3FS^bXS9JC{Vnacc%so$X?1V#ZA%h$%g~6!8UOiYW@% zoiDs7wB!kSggA8ygEJ2j#Rg?IZ)fM5EbzOd)llcP%t`T88!Isz>3=!|GD%?5$zNb& zfIs=vW;<17DGKIr4#RF>d0;7JPNd%63)*$$H;turiY!9rwU7-^+CWAlr<|~_O%v7WWIek7`)ppNOo4pUCw`}EStxq1N&!Qn&Urjp zT2?3y*M$upOyM>x&zFjE0{4Y}nESzh8W%xqt;FKNie-k`h)u6}L%Qk#mF55H$vS?l zJJV7I^684JW>_#; zPI%2>aM)pkGK!`)_Sh*b&Gz0AC_1te=UFN#0j4@T;VG&~( z5=Vr~V*K>2CJMtrDn1qMV$Ly*qSXoeVde&|I~KzjH3J5E zWuOJJ3+NrO)@$4%Mcjqij1&*q2X|Tq#0g!=d|gmW<{|NW*wn{kg}%wkuc<*qSW&+6 zuw(on&F37KCy~8Xmt!|~qyou1?;>8n3?R0=fI7bGHOnQ#(H5F-Wwg7T5S~wGd}r$; zP=*-_-_EG{s$mm1Ej-r_ka;&MBN`3WRaJ4^@Nd7oBSbYp=vfp|K7zF=tAwnn|uG4drIYv z`m}cg!k`4YaBZ{7@jK$|ENwpmXMWxXK zOU;5eANRA*iCa8iQNeLVQ0~HfRnuAbJD7IbPj2p9;wbOT9KP#6^Is6J1%KIC#4N5} zB5YY;bM^x~1{ip& zu~LITMrTXszm?{b7F@-LN%u~-yY`_FsIbfmp8t~lH?0!W4uNI^LsMdxj56?RgxM&k zID0TxOKlZfR}hoB!OS48P;vGH0s{uZ*SYVQd@vi%v~?K=aR*|5zCZdEUXK;NqW zw~2P)b2Kmf6?u{2q`Q3jeCEYbAD2wO>=fa8^V_E-nT7Ffm*aMR15Ln)cZ)R6i#imj zw=QtmADNGDW35klTQMG#Ul=yC!(HO>wd2|ihnzGHckW>{-g~d+v#-#qzcrD~WsCPb zXzbXqVAI6q#@9vss{C($*?Fxt{nd%eUGtf4KE3zXTd(SMcg2fB;yEZ?wWJ=@8uUkXgubl<;A{wVCE+4-g6aIv&S z)v|q4!{d(L*V^&++wGig-E9VCvzJ#gFV~R%u`FEw!Y}n#-G5vrn}0fPeEo!X)GwJ- z<$J=P=O1-y%vq=}w&}SSs7JZ0nMpBa7xT4Ae2c@PvybY(e0%aosXgnxdx{tTZZJLq z*#%TSmC1W?sD#+tLqcuak}kUc+z~I8xnV=@`JdMAK*P%W{4B$P9c~CbAmj_O;NsoM z6Hmi;v%HXD-Q@6IW^U0s#J(ccS)gi(D0TnY*Bd&X;JPb63AEA7)78&qol`;+0INWW A8vpc+XsFNcCr|ZT007oE za|sD$SqTYhWd~amb1P#2KqfRn9i*W;K$xlZN!H94O$NO+l$O^g9``FUQn6oA!0Q<0 zZ}Mm?&Q6*rGix6;8aP$)1YqO`o(A+QPdC;%5$-XI`LJ=I3Q(V+V3071h@gs*>^`yCR=l@l zN?Q7({Y3s$`Hcym85uxLf@_LS;P)aV4XHy8nah<1(8E#GknxpC)sVAC%7K`=hkHsu z+CQn-J`vUSph5QIs`w%rAf<0-$PqAZ9q9HYmKt=rE8;h+!xArpG|ufOAVa;4Nu%fo z)p*}&#G8p(jaQfS9)|bLd0IVP(0gNybaUs-5w)73(u*co7Qe>h@%*Wl=Sd6WGyy0= zuAdjWrGmbHZ-8yPsSx$WkhDi+dpV64<4cQu9Kc6{H+esJFN>PQIs-3&@*zus z_f=*gBQ#Ml+weZK3(dJ7Xp}v6_1TlJ17WWZ7XxWOKywovTRj}a7XhP*j)L<|-#uL0 z_3AxKx!6Ga+{^r}2QD6@GeA80RJ+xd{k#I}8lOzhs6*q-KsEY774Dl#TrMTpF*HF|^*RWzJ4B@iEtlIS2(*R-#qtR1*!Hcp zZ}&B8pT(oZn@0zusiU)WjmZ9Zb;DmBfyB~Jl`|r6a1db+>fehDUiXcm;M$O1#A;mA z9S4KJL7A;NiKUTR8Sf5OHU*PA)p=*;RTi0+b%=D1-xGfS&|VSEFkRMJ z;sBCvyBK>Y85N(E_O=Xt+k>NDShX=r@|R;8pfSr?_VQgcg~~=J?|G3oHa1jlH<}TA zD)YD&U3pPlk>Axi-8%V@=Zu9P_LHE5pV+0ws#*I79h;H;s=8Rux-3d}a5ZF67zR-G zR^_QIRv&(}Md^avec-1$+7dI@(_2|%Z{7t1?yayJn)bs-PhNRYbX=Y6ZM`Uf$>eoU zfnRu#?RHWaW3c+Zweur!1yJDv#Ki=NvDd|3$pG;TGJ5TVhdMuV;0*%{vdLM2rJX`m z=vFB2Iw`BDczn871+EFwfkd5Zc4QS$8lye&Srp)-e;iycB%3PLn!Fhiqd640^>149LzD5o5 z#3*A!2P?iWL2CL_8WhvWPkTej7zbU;8s-QLOSQ(>N6rpW){6AkhhH{65 zhmwW3hmQ0(uS6=`_!#;2QlUSl$&S{LYg1h zXw+j|Vxxbs$7aR2GvDI7hl$ch(dNq+vKCn7@u;vV3o*5R2A0tA#-vJ)6pZG5`E*dk zSnN_%>Ez^O<#g}Vw=d(gz5jXt@1$V4qu!42NX)kQ#srty$N5+DIA6IB84d|D6kW1| z$0zp!&*{%eZ_#gsZ{O(z9ogw*Rw%nf*(BJs9?>rmx#0`D3r8(Wwtj2HXa%|voj0E| z-{RbAd$v7VJ+M4T+|FFMV-cg$VXtFhU=fo2ywoVe)+rqcZg}cHp%91bu*deN zZLe+K?O+;02>}U72}0~*G6(a1t+*Tp8V1@puDDhPbp?^+8u@O8Gx?-6zT{=z?h)`^vV}5tYjW!!)*r1d z=NIb>=4-5Lt<~p#%{nh=&P7(InX6m63}t>B`$e=+SuJY(G~M}|W@^nn7&W*siXjRD z{|5gGf2ZhFs9(seIHjnb9y)5Z1KGhICDKtQvL&jPOBg~?|1$+wTW{{H_art*Ug6lQ z+BcY4GP5CXpl$ftaMzvEZ5Wh?t&G&=hmkBB!rHHFP98Tm4(P6m&-Tvi&qmI5 zj@>h?d!kI)O|mZOt^;pJPTu{!T3&&-k9)U2Wg*!hxgxc^$c%Czrzfqq{?jd%Cg!!8 zD5i${hKbwEF@|MUD49x|;-0#PPm;JscoQ9-5;rtA;`(x*k_9YGe4BVMmeFgC)7?ee zJ=ithh20(3JrlSRUKQFOS`@h(bsm-ea*q5%NLbWY%I_Jbop=Zf=u)1i^cd+9sY1A7 zgf7tobsxPHL&JhhGycYx$=k^OmK%^MmUT@dO>CxB?NGXt=Af1%m zW8Pbsbngp}))Q`{>wcHVvoVhhN1tR!Pch@;^j?pZb&I=>!!dfrrONGM?6nC$DZLTa zgq2-rF1@JGk6dlykZk-o%Z!0vjw?KXGprl?z{AL4YOGi&prK83^uvz+;5EBro&*0@ z+erA(LhMXZR%&~Lk9Lfvos0$3NZc>QU+EBQhn8WrFD$AGCs{Ra9~&TF+jM-H7??;g zBUjfRU=y-88K+(<$|`EVTZ)-g!SdY63>nT|%|quOCbRIR@t*{MSv1MNxhCDVVJTOp z_9oUTk;9{@OI&d0Q9nTnN4lM(bm@#F{^N#MS3d~oD|ZSmT_AuYB-Q*DBFs zVQ+o(?6^uJT*suxTp)C1``WVWm{RrEs>$8;!wtOGuh-O@_(oz2>?v21RQL8mv)P`+ zKE-LSeyelHrGi641-8C6$ob|#z4}W+xm&B-#6CBHE%aB*RSEzESB$FO#ikuGFmAaW@s%Xwhp&$ z-F1j;wV8?zfr>yu8TETGh}t2@>>sm?UfbeuU!-vDbd)Gvx~9`z(lSC?Be<|$=9@~+R| z6$%taW#B+OuOpsPBuwW_$wqI|OGS@8A6IRc+bOKh%uCx>-E&TIS9*V5svJtQqv#2F z3I08;REMgM>O{8Ad%eAxk31lmQR5Hb&s-jEzd8N#yL@@U@fi0gerc**%YN)$_u_c8 z{aEd$C~6Vh;{Eu3-G2d$0?rcs1i789UgdnS@5L)+ zcoW}OKL$>QXFXxvoOxU|9z`XcCV6_l^)kM-fLm71ycIqXzFNkI?Rjclj-D@#Uj4l) z6v_93PQ1II+cVr^+)+}<$`f7Ld$W5Gcd~W=m5OU=OU(0d2SE=1~RL>mKd@Vc~l zz2~|56(U4*yC^7KNlTPV+~mo1qA@hvyKKpL3#xMK5IzN0ze`Kp!`b*06rp- z{ZIdd#PlDV7XU!8IRN=THea9j|7vwxBO;=dM1=h?vj>Hz6~Ow|j+l%IF# zb~2id001W5KQAOeYC7?=2Tk+O8crGt@_Foo4&-y>j?6lPXGI6pLrqxhTrk1dEFs9~Z<6+~V6~UmUriM5enFxK7 zl={!<&!2>8&77R9ux3!`E$FIRR+wV@ow6y;O`rr2Nema?({J%&xj{h0f^8nfZIl|7# z#=-tS-_NH){%I9baxgc3j{J{*5l+azEdPIP|A_-(|0nqW>CC@J`mfgKp^9KY*#9?e zA{g>rjG6#|7(iC?{bwlBVFpM)Vd|no=@m7N)f|(mm~w1M_Lui6oxWcQ@U;#yz11x# zD56THO3J5&EVL{$$`^#R4s=(=dc$aGYp&4VA-_OhdAc7Ra@Eb0MWY#B1iBvI9SK}5 zIv%@Bw;s1>hWbf{kpDlKEfI`qRa2!3js8E495`0?7_Glhuq?E^8v=LOg6b^1@Jr9g z1HN}1VCPi)L|CC=Yq>A=ciT$ash-iwkuAPHEoK=pGB)-c3MFkmb*6CHez@h6@Pw;P zH7_%4wLadi7ZtsQx3*oEXjRe*bveNm=5H@&hJvrBcibcn+_em-WVm5-nqBRw0C;=b z#uq$mbr9&B6zpf}WSP?{^sqE8lmaVZY1^MJW$|KH&u}iPWt-J-q|Kk%E3(m|srY^Y zKPy#*AJ_~YvoJde85-`@lv!!ls&%NLlnh4v`0;9uot?ds#cZZUUMBdms4w8m4KJ7A z6GS1uv2pfRD`TMPi?@?cNf=$3I>r2(5>=9AUdw42=SxB&T$YA62^ant5hSn*^-A5Q zi1JWTfS(t^4=r@R3~%=z04Q<1FXq_mHhTiT_#T*WZU0CiXI z_$gDdv%%7YkB&b@pYG2X&|U^rwm&uxr}D~~3@6jzG04ZLJJXbuW9qUc1*NKzaJWttBy= zYFvrb8^ALGSJ!p@usxE-NFn5;Q5uotnA*yQisx~Cy%8N*k>Nbgyrc&oYPgDY8&!uB zEXQqMWSh>_7@u~6sQPEC4UKQl_db38{2H5#ukHjzodIW}XvcLmx6)^F_0Todcwah| z(ITDR@>63m-ZXgciZ31YNH~i}X~+HY?;MxIrVNRw7fdJ5jFjKTNs=D`F2io?n{z$AlSM-7dHw`Tmnn z>5N{-=XS?V4u{Z(g}Xf-yW=gG?kwR}m(U_`400B6f=qI`on|{YoWgxLW(@U5#okP_ zZHx7OIMAy(Zo5l$B%DCSu}!k=SU73B=D#^laxa{Lqd)i_?fxmA{CX{(zDz}cZE;;- zWE?V7**U`NZQw~)@wa=(O>lQYC6>3KSm+N>X_lyBZL-qq;?11vPDa6VAB%4!ri10)wf#$Cclk<*OdzY%w-7#!Lq847dA3*i9C$(w@?oxd~a-*FOc6ml`9}Mu>%S zB1uJ4T8G`WUMHUvBX^IK%1)3$siFjt!VQOk@$TI4cfv256h)GwC)ilfV7dkoqVjz(&Q<9Ez z3O3te~p)&c@Ja3U|&Aa|v_vW*kx z#w)K09A#x?Y7iwfn}mI%FEVcB@v?!-X;+y$m+AOi0H;mZ`giUJhH;rZor&(trprsS zH<5Jjdc7&LpTkd2w2D~&97?!AB3~wgAA6p7-5+~D#l81OP2nil{2mGga?$8plk z6=WZp*|4$l2dEuILUts?tM zek-C2lgnjUyVUey{JNr{v*B#Te4T7jK=BXAN~HMY7A86Rr}M!pVu>lh)ZHDhEXISPR!v#!9M5eNE$ys{prPw-q7;h z-?zff`!wN1?1}9Uhq?qED1;vm78)vD)u3bmte(`qJR{nph7~W9jExM>%Q;g%&YbTJ zOU|{wo^EH_Q&&3>9kpFQOi#t})@G1^s2WtB9cI8|YdD1qPr-7Nqp7ORDr75O^^f0* z+SfX(_nbh;HGA827xL7y`|(@o7!EXSTvi7vNrk{Y89tb)wC!CTOVaaVW}5g?{xv0G zu}Fn3&wk(sea({d!az8Cn^_pf*Ts!|(N&WgZo*MV%CC@ws}=8+>z1d-yEMPN_V{j$ z!W9uE>KBX4u)^VOQCfdMz5iD2_r*zjK z<>BfZeh(Xdy5A8s3FwdmQFfJ9G=EeSeQ=WNx@)=JFCF2?6Q&gR5yWJl|7C4?H7tq@ zHpE$#?O;E8=e*ApPRPa;o^g6}bMpmNq;@zUJAggH{&>0dE&FCUy;T?3mW=LjNA#&_ zIOE;SHokV4=GVvePVB0`#EDK~a5MDGz2X^szfR}D^?3An_J(5~7L z&S7r2w*7}S8fRqVMtP7<1eK#nk2{^wethws>&T)X9FeqxTJRn@^5zqJL#D72F=!YZ z$4&Y+U-Uf5H2g99T)j-2#vc`@<`x<;E@l+ldLiM&sGE8qEU=bHiraerD8l4vB%V8m~RP>|#!ridZOD?b>ekO-Vf9boU z#_mkh%(q5lH7}&YPJ9?6KwN$BnZ5Uvv5NSCUWj{yRp$3;%{}`-qVqV{u``*K7-PhX z`B<%E3!}iM0EjP9oj+DEjuGw{Z%y(e7plwB_oUxAqN{jL&_BR*N#|I-e43UH*>fLP zpmz=dd&=YT^HYYeP~+=+k!(X^OS5&?9uk_|eyBeg^*nU1AZhRek&e+A!-MZtzl9O; zVbgFvJC3%?@$}N|$1Esn$1zuo!yi+dY|QL9KJJ^N>yp#fOT2i^yfO*U;l$S?k_lOb zIaa|OwM-uC*f&?$2Q(vO({Z1$zndf_43&)v=b!_O(bjO#5Ll3|&%`GH9&48UuuUqrdV8n;2Qve-D2R7_--jZuA4V|wuc~KsV0rN$eonTx9h}aO& zI}G4pCU&w7MqlgLv|sf#ML=Mq)OS6dEdhkLUj5k;RzFm2dqQ6Fg}&66hhU*o8m+Dc zQ~lzp$jPcAmcpaqgc$;SgcS!2ZCunUSoA^BhF!1}Ow24uP@7*3$@@I-X zUT-+en->l|KkO{Q!h?s^aLU?S5%eZsqKE`Ch5UzWxG0|&XEBo5cBlBu$0L{aTFx9{ zN_k2PEKa*qK&IoUV4p1_M|-U)dgG-uxdE6GOl}A~#HNW0?t`mEoKE|$w1 zAQyjB6N7)W+#R(XlD-d9?ywUl@i=y0k&7-Sm>s4Xp39388r%*U)52%i=+HLM?RXQw zxKR%?Yl@FgOn!M+oAoe!-B;`SoLMa-Pf*;BE`F<6@qT*vX@vVD1z?Li%|zdogdoZm z?jzEd@3OoKG20m7U#@FrBI--27Q1!}2za z6ch#4kPo^G^F$I?W$pp-@b+~^LOAO291~Rz}p4}s0x#U^iN3M^d7(MZRTj7O1! z9v_aq)5^L-1+Q2A%cJ{op?+%tScS*^61!rV+#s);A-#EWgdj58;5gB)_%D588dH0z zHPPDuk#5kg<7%^=YtDeduHoo7q0kF4LVfM`qK;F>Kv$ZTrb;fe-j6v>kv76A8g(9O z4ihU<^bRLv1BS;6)jWsUp6Zut#&zAHEQ3xep4WKwUtUoJIHi6a40UGvJ*t(8;VW5A z*fJfOx+^L78EO9E`;1Ofkyw=_!Ti8;?&99Ez44q}DpGnN-nXcu#22mCSc*KJCbhpV z>G-QF5faLhr~Z}D+@Thu7?)B1 zxMYG}t{=1S7f*q5s`ImKf1Ho29~g=dHA4ARp69>KVT)PU8+gy4k7tJV>q-{QM+MI_-ht&$WWUalO{zUayFYl2TD=4f}+q~eh+-+t`uzG zu$vRiz!FoIj=_E>@?84j5tM`~nsnz8HWhT^Azm~~rH$KyE@tB}*&3-;)~sbq#^V?> zpIP6bg{Xt{#X$OW z0*kk9v_E|?xhnCPFg~Q+06ua@1I+Zv0ows%#)V0?+cYpN-(S$j&rMofV~5dR=Xsmq zoO-j@rP67;ZShV7I&5-IPti-I4ocB2V}{#20FetRYp>F-x}8*~zRN$VN?TmmkSjz` z6O|vSPoLpLGL;1+zgCUpwFN$LJ3HvWC(@?NsdL@D}LYS6vr=i1XbH?v;Y@O8%3? zqp5;2Xq?;U+^ldkCGc^mQS|9%%v@83@Sg#R}Y?W-isXO|%JjtE}WUEZ3+sCIT4Moa8s!4R%<=h4s zqIWPJO@&swQ@v@?jE)ux%m37I*N17Fs;AB-kll)Z@bKHyg{kzcoc9y+s}ZcXM1!}j z-f=-wk>5jjk@XMP)^_u`N?&1q0l`@%Sl@}a0d4}`kRwjN6!W4o)y|yOnT?gRv$7N5 ze!)4w9#bPRr)*Y~uWdWeiR%W7LUj6CttqT(PpcBEg^=u&snG5cN^>AED^?eA?Idl7 z&8Hy6(eEQnC{BKrvB)cpybWnsKo+`cWqJn*c?dRSfFA*$Q>Er@%{*tNcT z?`s2BpghZ}zj=$4&WH$Q!lwKk%9v@kjGM^_3mAj)A+XpZ1Ur+l#&O?4Kpm5{rb-*& z{YwQapIfLDKvE!CPEwr2wog9N+Z`t)KuC9-pg&Fe=0G#4Xmcp0tH8@ zE4Siijt6$$pNDRO$;>yg|BR!zD3b^zk5R44e}@zZt=0NN^h(b?3W1#){ymZawAh#P zjQJ8~Y08O7zHEFbNaInjXytn(7zvs3r z-g(M>R1lcJdBK!E&SVK)7xOfe7=M)*@RONTgcfVpDLdY5==jE&95Ni>t^xmKxzwe_ zM1`M`ge2;{3bO*aqhmliN6!<`Q{?dT=avy!7hlj@80;;JA<$3X){>d(4C zAd+UEqCgnNN+PRqW?%kdm{ht*lwnE$~4mZ;>LM4N7o2RH?~tOcKt)-}R$_ zG9K0N`0#XuJO{_}n)vma2J4h@)_sj2Nfh2zw}bZCjx~35N>)IarVtE~i@BA!vO>Fm zGtV8iD!o>f-!cDgjM8Cn2Yj)X13bg>4-(WVX&+u&K%(TviGS}~9ns@fDaFBBHcB4E zMupkd>h*Bz`g5_{HEcbQ@Ho5yZ`57Mu#CGiOLT%Wo?;aa;5~&vutk|Mh3k4-{fAK6 zU0m0%JXC`PH&5rXB=l?~HNO#e$gyw0az*-39oHH+qPc^ExwZ!E20x9N`?#=z5Vf*d z{=~;Q>pyYMJJqwU^55#hWFosp%}IJ0%pJwl_^A0~n|wCv(=M*Bzr6YUNp^1nr})(* zh5uX9YryAEH2n@Q3<&)<0sd95yMz6rYHjvcjT?75+f;;QDHVl=zM{(`SKW#)lG4g* zWup;H_qYmlNV`{jt|~!1D&t_`T7E>MX8@$>DU-{KWX(cY$Aq8K6F@||s9>f#<)BAa z-I`f5TB=p|zF`vc+w4hD@_?c@VAn7M+pVyOtL?PpO*xKduc3({THVVO{qB@EdAS51 zrWxZ=4r*4j6(Andb~%{gnIa{4KTwf_&mx3hKwBk|G;GCZKSf{gAA>xA(opcq!*aX1 z{&mROG~c}#TJ17?p4YScn=u7?bP_22#N-gu=lI_0Wi*-xlt~iIfyOaToOgp#{M~_X zM4ws=2r=-g=KR!c`b!Zt`ov9hL&}b}C=`QwbM58U2|k7Rt*k#EGMO0VH4F>Pe2=;d z?xVU!=$?FSO=s&Qe$d!Je3l4iSS<#5?E`2;j!1~EvKv>l#YB@q!`N6lFq%xkz9<=x zE=`)pY-wjQr}{~=wgK1UDCTWPdfph?TyHp`7Eh?XK?SWxZS4@UTMCYyCLp?V;HNAc z^i+h&LFjeJ(=D-GFWrkM%8uO$3VA`vHo-oZ5 zt=-9NeN$*I87hMUIe+|=cxf`0X?(GEBk8HQ%9%DA!X+3vj!F%m-RZ3LU!SH&a#xIb zKOXs9KO^+t9DHvwz*=nqUOO?{ye+_9@zhm~;u`h@7{>4#n&npZtLNqqbM^`KP((31 zAkj^1VUOhw+2ta&-;CH=>2`VF0@!Xtut1{jri(rjsGQrw=JUPd5>Xt#02_D{N~9R% zZnKbqixc^lvmL?$%=Ag#vkpvP$82HlWv;{eFIYM~$?M5Vm zxlHYF5mu>&b|*}8btodp!fQq==EIT(>v-#Q>A@45z5p z4roI_-WP((9|c2+gGhH&`mkVBWNr_iU>Kc`NT+%Lj~}o(#S9IFRgXb14u{fVZ1z3l znjle-$0QX#eO%Vc+q3KrDr6SNU_KH(hSSP5Wq%Yy}|hchf&x6`sT)A61Xk5r`)G;T!P(I}{sGBx$9P3cBg#&jEccxgC z5i|DP6DN-H=CDgdw~qTEOC%{D*P4QN(azHFcg`gi5B!F<4oSTq_ZS~^WWF(hu6rSGDS@tgq|ky5~v z2s;0M36Ty4f?S;+48r>SG@MU(X7Vg947V{#O~X8j#L2nt$4yRenXoK zzq2a?`WG?^mmF2yv`jcZMySx}>#;n_h@Itb<$PDy3g0S7CYN8QgrqzNt4T!2a7|)W zR5Y%O@u3hY0}5W&(uVwtEWqX@(JgUMD@@mTWn4+LWFdIaF4)yT@1-PST*6p4DkCT2 zLq__aFx>B}f_1+e$c%kJK=dxv1~}m2ZB8l`O=d|1nK%d-%sW|*!gbfL zZFmHHPOvkPMk-~<122e);HEM|B3)d=c!SrqWQkfcyx%($1TUF-)JO-0Dzk3)^cg7Q zaWC!#G4=*nTPob`Udmcd2-NfU4{;Z!JZ)X93=wDSQ{?vhmW=!IhZ-D4y;Aw~oo>2h z464F_RnAQa;eKQdyeMoTA%Q<%8Ngi%o1o}!K4nh2(GI@)bLC}!c$H~#LGzV{`|X)XZG_t3H6YGKbScxO zc}ve#j3isgI`FznBzSM_y9tSH8kfPH0Yyc(n{Hw5Y06E?6^+g5HD*F%lDZ$us>a7l zf5!aIgFti3`hr$~q45^W5T?D_mRl{$c?qt@!Vt&omO^6Kgyp;TU-6Idlete)v=c7{ zmE8q!32wh|Oy{5w>Dr>?&se^GA#1vNj z2v-_nWbs_@FPnevj`ZloUC~5750q?E?a#_^%|Y{u@}sTHL+W36^KDc44xIPg+B3lL zi5A570))G|^>CXjq%ehCfh!Hg7EZaE%CUExLHF)TkR1xTWG|!AHT{Km+~9#D3HBVK z%9AnJ>>%t#g0RF3RxWOSkY+-nu8)3d$#;8nacooj1-r!8K8j6LFNE<}HVike3NOMc zDdu6UD~o3=D!Nm$WH`Eg$K35R30a!U$8Sp1HJf*SdoKr|BeuClO{*G26CV=ihGP5P z{dScwF!9ca8f>EgulxzNMX>j%X?l)1LL^1A7mm5l9z@R4PXC0VbWru*hP`DJG`<1kVSRyrSGpABPH(!r0Lx#BX{4g&*- zf`bD5NYj^{jiK6W_SvEB?iBY?;fB(JWxHR6gTo}G@39TeQBd~k)<}gs$B~z4#QZ0_ z@8(+Bj3F78%b_?vGm}jW86tuLk&2>wFvra9Kq%eoK5P*D`dyp(*cf9rYb7o!Xm#gf z0PN=>?%+Y%%!WeHW1G7YkcbCLwz^I#wCkNbO7oiBXydrx%3)N3{eXu96_Mpq=vV~? zEd%mZgCQU)=_BDKI7d&`oL;3~TAOO2`k$Ya@HQzNNu19qKs40=#=<^(7qKKrd2=8zfc*{)z*u2@j#*h^Ka02CT*C&z8x)b=2C{svUz1+ zuh!5=x#`CMI?adAZ=$j{dBk9rqq?GN0eJEQCl)%2BV8?<0yEWmQ3+lTcbY5NWWAEa zDH8SqCkXZS+k_1Njy?51d7ig?&!8U(hrSO5%r_~_VSQ8Jv;uZI$Wy5dOHb_$)qzbU z(St_S5O_Dcm{3N=WTv-Yf5l8HiRvg}|1}9q$E$}{iVnsYrmdmW+3%A=m96Rmziqtc z(mjkgm3mq88NkjACpk~=N4ZAg(srB%GJbUE14>hGyv@`0yl3j>oInsm(o3WSbCK#4 z1QAH*8*O(-wQ;@5+3Dp+i~*dFbrKoRn7JlNlwLtwmIY`j-QzOr=^mbo89{fhpB!^^ zUm(0a1fueY5eXevTJ={-uRyoya|z2N54J~AR8-pN5mvO?l$4IDHc{kgSoEoh`qKwC z77OV2{YQ@N!~&g!6rwW}*qSzfNY3QOfu+5Yi~N+%nPjz&J_n{0<;r|cp=W`WN3q=I zE3JqOBy$?Rx{!~124fgi3~XFW%Hp0A+;_h>Wbg?3zo;iT=MD}ImaHpOG_GU3Dg6lf zO~;KVyZ}+z`k@V73k)R%CKggQtWD9q!y~wr3de9AQVrB!DG9(6mg4@+U5#htYKX89p9+xXH+S!$*LGRTm#gQpME-pE zP7*s(GNEd#7?e`vr+98Q5^!6RT*jVX`l-gDWH!P}tu8cZqMY&}$k|K<%*V`>Yzu8H zw6;_69$gf4F3*IWywXM-`+_JrQdj*aE2U!BCMEo>$e&kZ|E$(HSlGQLC8@H!&PP?q z{f(R_7l}zmG-0k6>1(un?>dchHIAjA&CL$rO)SIS4y5EwE#frXixA#ApZzU~-6|Q) zU+;cf>i*(ysuM3u1S$)sZBbsIWG<>)ZkWh#)gddJJwfz6$lz_GqYfEO(Bk)>|Kg-w zvw=QSf2F15%beP3?i;z;bU&_d$RHXKI_mHR9^wl|?QfP@LUxj6cv3T z8R}8$m8d}xcNXax1f!aB(5-Y7r5?cXk4Q`CLR_IdpHkeo_cKy`NUQ)+fSJH7c5SE2 zQUW)FaVRW)qg?lEu0k6|(i*BlP?l>*`M+d|yb4?`gFa?wICh}VIHJB=^UTE(iCX;^ z8n+1TI|(AQ;W*9`SzmI~NcX}U%@VNBwbs}mcZ7WB9sMis3>~leAh*#S_3p@wHJ2in zahY)Aqdc6j`*9wz)@_Yr#|9A-C1zJl+YFGsJ_{DT zfBz45uXWmV(zo*SWU_5iKf!WN`txqRRfnMq9cVfUxR0GmU9MhPp?2|I&Zg_T?Sy9V zhwN9mj2`ku=Xud0TqyS2DW<7iAI$hI{`A}3q%!$s*s*j`(g!+#I{aT5O)g54>e2@& zBq#pr@a4>=T^zi%?{dzgs>tR*g=H9ru{Y@2xRoc>l(pWCI_zc(cSwvsA3YDhx1&fy z2nS*3SjAJXVxWBG#h_toRmqCr%0mMBkMm$4Cgj)?kSy@C$2neg_UN~U1CwX+okO3Q2}@W&@pUGnL`m4wV`SHr<5VY{x9)VuSjPKkZpSJVS)0{y9LMKd zFB-5&0*ylVM#JE`lj>q~E7>rLQzCT4W|&GZ2?X*)Luw|b>x;$}@*d73(uH=0sleeq z2L`i(@n)WdS!?2ALv*`tZVYC8218DsaaM-sr_ zb*i`j49LE*n}_2fE}4Tne;3FRv0-b!Z+dm=blcs`FX{_amMpWKRNpny1H=OHF+QRJ z3*w|e0N9^r-pi6#kkn@&3M$nJ-&~#aQ>eCBJF|saa$WT4m=$P#!O!<;V z;F*rX>fq;qoxp3@>xB%0nMS z7x>f9Btr$kQ^$%Sww6W2qRW%#CysV8Cu?o~PZax``R(cz8YwsfxyooG67aleVHQV| zF;1mVGu`Eo^X!N>FJN*|`)BMv#X&+dr|g93xcPu>;k7g}Qb7<>HSrQrn#!T9@38z5vh z5DY+EZ74x(!qPl;jk&1?Q-6gDR9U?bcyXHo_Nho&xUV96$fg_;WJSsDnS=D32rn(@ zLl|;98AND#akPVjUON$0${&X9Fxn9Zog*!t7xKOLP}R03J)E8C_r2Kkc>`=a@lh#4 zQ+>K25+`1ZT9s^C)p@269&Niijww1ojl2Sh__*Qfz!`qN4!}kIhbPC(&pNQ^K{mPCa$hIs^|q8sMh)Lq4Ujl!Q1iP+j{rb zGNlH~1;wuovaX#re-N!sbDsnchHE$1!`b=h{TcglY~qD{xcn949fL0^jE+4o`BKr| z8(vqv$wG)&jx(vlbf$|tBc;PT{W;%ft8JZKfMiXWzc^??vCNI|WqF_Y$V5wqvjihl7j0;1m6fJ0(&|d5e6-PCkqmEv|akn4(?>6b+6hX2T?6<)JHl zrpW#hec_dx&WR7$CWjcNAnA|36xO#fkl{=`{|%qVnEDZ2G;TQ{2Dg#I`J4n)dl`{p z%yJsV@)2x~ITSEMkbpkfgkxU3+gu|=uqKwWHg!750 zZVcv!qrK<@=~|)DM6+~#aE)h|A`K&_{^4W#Q0e_JgvBLSwn=Bj2&>2+{Hp70;$0G! z$92E(RTrzt){>6&4o^_In_NtV2BPD0%Rgcld1Y)o8)igl@T(w)98fvNYdjMe&h@7t zQ%@ZwIw>d9zv0m7N9LS}c^weiLW48JbVqIB!x%1Zx|DKp^SA8tQW(O`ZI-D0(wV87 z*E{D^c}Or#`RXZO(HQUQ-t+w&y3>}!){~|QcNG(c%OM9o)@XO~8i$Zp4X<6rU-7ky zD$33BxBr9yDyk@F6tfCdquj(o;@k`Q{{|<~xAVO}AGe$|`%e;`1}wA1YcmC=+iJg2 zvajlHhAC)PY?dg95wLujMm?BelHvQU_NAi61TmpWB;8c|CWAhFf4!tA1G_8u?OD07 zx(eQcmD}gtg}>u{Q6HYuaw}FGtC)#74M{aW{(S!D8T*(}WAREofixnJWvinPyD2Hq zi={x{a+DPl$$CU5q)z&uTs{LBP=4YtbT(WXWjvV_u*?ymql2NmN|RY037$H>=k|AK(r_ZQ3qrM)rv|SeyquEEm=e9)^Yg zE}ehz;rxM#tD__pnYM|0?=-Go@Eb)w{-JA??c`@gU{|@)oXzv|82xm2eXb#AQgF8e z1-cwE6;mg1z2bCLQfe^f6w+kr`L3}lHsZFsU+_wwo%AHLKc3`=gQxv^ zR7DsSr$hNg+osHOcYoa|CUdIB{{QmJO zVPS7AA+}cRz`nO6_sY}Wd(aq+Y1KJ1o|)JFZVE5W!Q^L@g1lN;JC0Y&3 z0sU~wB^m8av42bXn%Kyja|g|&Px}|2Nv73plagxk`QQm!(4mi?4UHn%i16Qx6c`5$ zB!1A(XZYVrj+hZ1^ErNL=$EskUX!MBv}{4~|9af)NF4SZ$9lAcL0r+$i#E~XPEar@*W!`%qx3n9% zux~yoR!64B&pFfU%$qq~YtNctOZNQxT4@o3_|k%-L?jUGdQD#mi7IeCt^dCs&ODk8 z>~G_p=}b*2rc-Ty_Lf?MwDzT>Q?&~tG#UhLZ4snJs`ge#JF2CW7=ln+MJ0AcL{%-3 zS{h3T5gnq$+7QGNubJt*|KD@&Id}Qq=lR^{-sJCulV4hVAuon zge!DdIllPOPFNI$KnOpX3AN}p;F;#3&e=!oVLr?2E#1NpZYU`w0(_ru%2$yK_`Qs3 z*1CC_d`MCFz`-^Wwl@Aj!XgS6Am1vJa9=vSlRbo+s}$l0^K0#^{=RB3;8A>|V*#Y7I&_P-J^jPoSY<)HW=Xwd3XCY202AO3k2zBdATUeOn~K~G=^`J_qy??&*Ze(pu7E~{i@;zcH#2@z z&PVqe4>K7Z8#6&5KJwX=KxL-1_dqw^ul*N(57!pFHZ%oTO-&<~e#BhoI6=sknYcx# z>t>1gHCw2JZFfa#y2d_i^0fezfdICmbdv97Rou$wcd69OSE!ZiUhhS>7^E2o_fA2} z%9BqE`C`C%$fvP=9EfB*-C29nf6K1@HOhy_&8V&o>XiXB&SE7W+nGRX_rFKNSkRfI zgNRZIqDDi*b~#Jht1nH-E^A`{aNUgEe~#04wS4`s!J}JUI!dBz{?C-*uQ~Nsx-Gh2 z-5&|euB3aZ@83U6DH7PO5_S)zP^)pqo}T+_cG;KWt49+3uSHn~WXw@1wZ3a96E?Lw zJevQpXCrm4b$b$eQbS2low#o`NLprW7CBECy8oqRn3BHJ#Pgx&!;2k>gsxB3Fa2!} zSf;?(25Oe8zgF7r;}x|>V9d$06%5cEom749s75Sq?`yT=Yp2S_UMf*8WmX!FAufk2~a?xQK2 zQG1MPf{W8Usugcpj3zJPBX67GfFigiYcto*xUouN@1<5ZN?1o3^)h(3J06q{u#8a@ z(ys&p9b>`DtkCozR-j4KHsS1SVSKzIbGHujwKmK4KrXn_&T-*S@o4YgWk%|oNQSZ1 zG4~fv)@%{rkhB-tw_hpm$ld)myAFq&OgyhDKW}fpb}5(NwqEAv6F|uAt>0BFdwt6`(>ojU zvus`1g~y_FG(75pAVG!A&--LrJ)2 z3%lfBZ67=BOIgVSFttDqhd3FmEXR8waaJSKSaV$o(3tYZ6LR6@h|X3uqCcq+@SzsMkX_eNOI7Q zSm$%%@ULkk^zLtwi=3M~_ugNVVvoE`D6!C9Dm)q58?romR%N5HC}uTMU~X;m^&R0a ztACE@ccTLj!T7S5NIeB)<$w+=%Q{F6;zZdv~o2zf{t^}Z!+tPbWyoL(+Ptt zQmzK9^Wmjr*WP@S#;h)>SD?3!u4;cmRG%+?=_NYKs`|??;bJXprKSV^7H=}srNvtF2IpN12@IotV z-B< z8?8*+qUtKzR}9rfZ~$2}72_DXfa}-plD%=G&h{8DKoKlGnx!S{mOM+(T#(YowfZE= z3>M`DmCf*4^B5IM@1ox3v&}E~6T3o}evP(vmtEv1XHj_KWMu=;PDB1+#gqM|;W5u` zod~DG9xc(5FDc8#@MPs0)Ych4dx^zAnEdqKED&P@c>Pode69S{W&(3_DeRr>IMVfh{`|LGomvqFUrm+Pt)Uw z5@~HwO=yc8Hl+txMors~rtW&#pG2^(WH!o?UM-Fp;3A4;3epmsQ)4VQSw$5m#)_ha zUBR{1l-uU+l=p0iAv#~;nVgDqydZiZYJivC78^zh@o==&-KiQHNNE(jp*b_T4M+{8 zWT-WBS;~gF!{Y@oZk12qla}_9<*9gIs*)4X(5`iymTX+c-6B8j;tP1gfbPUn*7*h zR>nS0yiI-Jd7e@$c8)R)h^F-CIWH22iHM7j%n=?tA5{7CNj8DHZ!of}WN5Qs`yvuQ z!S1G>-Cud(I6%H`+Xc+TfS6u6`5=4SFK5eZJk`fkm{`%qlFn*KRnRx!404;tlhwftk`STu`vYu>Epv;IVNEviO?lrR+lNZm;Sx$sCZT(@a6c$AXWoj6r;G ze)?IP!7R6a5&|fB=j)L6{VPJ0aq`2Do^>8M26*5>>zx9bxQPl#-G*9Z5a(7CYHW&D zQ7e^r@|(&&FXmI8U_qdtP{p4{+WJyVw`@Zfm!-a6MIbS`&+~PAvi92cU{Z}pyB|h> z;C(NO>;ELXeBbWS2sbDC>xugg4B(&@^rlC`yQ980d1|%7KIJQuD}zxc2*%roqi}_= z@Up0ui+>hHe*FyIo&t@SguB0Qh4aM4)8(sF(gF5hd(X=wBXDPHoi^j*V;hrGe7dY_gv z5D7bXo-zh`q%U#Jk49%q((6LKeRBT;WqSgb2@nENJ)ykTyqkBh2F0Rv=!dfk)sHGl>_EZjHk@i*p~8 znm?`b?ZiLrioRFza@=bk|iZpDW?u=Qh_`s3wGJV)r6yOVi(Yt-X;k+&N6*l@D56+GfEN)%Oy; zXCPwvPj{T1j12))k%?#YZ_ofBq@Q-xQO(@b$}PK!HD+HNtonI?$afIg4b2de>JET1 zm{$hXPvR*L2WRd{tg*agv2v2&b%UPBrfu1O(BC2ayCkIl@Tw~hR;p?zB2rT9q)1VZ zUXAGV3H~4xaCa5!r@g9!9j!sSWD{Woq83{-;F#J`rP=_Jmw}KvghsYAOKi7)jaE!n z`Y&QbJET2{WDLQ%{p0E%XrcRACF3?ow))pg1Q`XA9}E_U&g$_E{gIyNdl=a})wX9pLb#)N6f2Z_cc>;4^j_=idT z@^^cy_QGM<%YGt?c;JDo%vt#vKehDr-cRMnGM0~4<#^O)6ttBL1WsP?EiPE=&>jg; kfF}KaJm|HSkU)O#SG|vq@3b5J{p*a4g~K(%RqurV1Lh0Ze*gdg literal 18282 zcmXtg19T?A*6kPDw!YZO#I|j7Voq$^nAo;$+nLy!iEY08_ujWxukK#mwW>~^I^DHu z*FGJgC@+Bkiwg??01%`kMU?>n(C<@#A~fXp-rjN=_T{kH7A3UF&oDLnvZJTqdy>|`IhSljrtoo~iQ6gyN#B34+lwxh7!O2C*V20S)}Jplj}tNjRBBB? zAqxlFu+tL8rEZ#xN=nHO>^T@VYWwXZ;$i;>@1*ErLdT#|EGNY2vdytF0Em!~U||wo z!mBGq(f|J#fvOMYwjcn2+)6wUMup(zzfJb-#`(X9^03i&;LZW@K>Y*$5B+Q6jEoX+ z;EGR|VjI0gY_xEE*rGhYz{mIcOk2r@M~qL_&_<8v)9?|C($Wl^r@2A>OHRUJg9O%q zUj44wF=>NrYbR;W-2WSq$5*%2iyz#kNusdvhNZ)tZohO zdcf@0u_xba{}*r5!rJ3Y03xWS=8W}P_OO{j z*Dl0=wF~msL+ZwARUwsGzg`Je+&f-U96v!#61lu(4fYoo~q z`Co1C+~BE+=)0>8w22pZh5`;=y%$d~hV_>0vc8av=_oHD_Gw?YjW zF<0r88&r@A9})yp1i;lZ3rt`H{T&mP*`winIfx=Ok^w{h+n)i8Y(Jtq!Wq|98R;Hg5mZ_yP z=>9cuzycw#8Ju8oDJAC9E4|ppz&;giVWxtwZ3t$7ATkx>03LfvZw`uf@IvA(_t|fS z(B3X^1Iag+ZCiR-DJh)Dn=$za%tsaFzhB)^H<@U+DawT5@7u!w;s#>~Knk@={P`p9 zs52ioq$VBal$q0!Lds7YcD&ZjUvPe(ce#$7_!b%JWYyz#5}@}}Q>-)!1PJ~N&OjL1 z-u%a2CMQ;?;*md3=VoiMWSSR<=MC~q*cA9HktabL*Y`0`%x6ih<@TSy;ncIn-O{-S z-&&4rPI=J{n9q6)hW1bqrr5P}IMP5aR6s&zb9%xaId~Pm)E&)J%IDUajB)7SkjTaz zg-c^y=7rBSyHkdI2Q7`iTuv99EO>URwn9oyB>!S-yIqOoKF0X|?wTdkSNG|N$0rZ$ z6Sk_ngumE8Oou+(>5VPu&t)mB{17l#fy?*MY9`Ir7kNEs$jMZ(&|VY5WYCwfgjUve zHFBtpZL{f}I!V?46FKv1pBx^@|GxXr*bY*@O|0_eT4e{u$ z{mVYr>1z^c?%uq6h+9iX9nEqz>=A*WG*y(|c={Bc8}VFWpDUkEP0FA%<&dG9tKk=a zrwoK^7@8Iw8hluU?Q-fTb(s4r&u=URRh8KPZ!g&i{l-J6OEad)VoEF*&C6G z=FJ~n4_A8V$$npWFm)|px23&SSQ$Mt<*#r})Jns+qimG`_#yL!L!%7jxPa3p4ZMqFn^07ab;- zwgR)1V{cUl5T|t`;>CO?6edgy^aVattPw$r#j$0eIJiOMdOA+bJboa05H!QC^z3?E zHj_QZ>_vuCx0Z6TM9xIEw?#8J0z2$M1Lr+NAZ`}Ru4XfZPJT*&>_Bg)Yx0vdf(vVH z6zXna_87NeDP-%`I*L~SiJlfN;uz~~e9na+b2_xrUP| zqX(0s6fH}>3GL90=Jd~m^-$;A3+T&IqMcSR6 zu}pW5ADi9JI7m%ygd5)FL*;X%SH$HXYrIqcnKKr+&7eTab%mlJs7;Vc|Di$SZ1bSr zsoDr=_m!Yfz!vdwf;mg|oh+F$PSknY-G_rTV%QnXN;OMLXv(yu=ebSAqueJRx>fj; z^5lolVv5nHN3-580vfq=L^NvGvtJGsv)1mXH{<9omFhPqp*OTt8P9iIK%0||7`QXj zCl+v=jBC$I7*tc%Ogg+$zEMe?$~=vjd2h3z=Yz3GENa|tof14xOJxaIvgj$B%uPNu ze&)$Ksjw4OGyMG9Y%)j6?@bc%iYaMu&s_Olk&_;#AoXv^*kBI6e8(@0ys^+FE)TLQ=+d1RY?ceFvhNE}=dwWwTzJbT$ zJI$8TCIVFym*FPIyDPz=` zC0?EyOmuy=LW($JYwZ&1{zQ#lxS|pLGkaaaa$FO5M8jFkFSwBLpUAjMS+tv@Ivtig zoVXEYouyQ@nlcH2PZH>gi4`H)ytpBepQ##w!UKG6jN?DOKx&OUMkqTB9v5`;7z za|BTPWPFW2?b)Eh5)wD=nG#y=VEex!=%^A#p?K`PaD&VYEOKaEA(vTwx| zTuI>ywL2E;l1$05KNe}fh9zx0aUT`Wl3H)Lq@VGKGq?(JQJ;SRS6P;TY`8ZTTkQSu zVTY~*Dng+zx-!CiX!{jgyKIVFKeFic2i=n+200phUbPRt;2v=0_l!aQi?@(cu2@6_ zE3d(4T6-V&huK4eJr&2&zk*7J`~(8%)cVs-#?_AAEKl1`X0vC*#O!(b6@#?lH^$yE zn)xKMldbmSNU1-p*5|tXam74$Wh++18nVYqodq}Gq-npITAnp+1Z{NT8CvneSWg-G zq0@?ybu?y89+pjhoU-PWe=N`}oSo}@(eHf53!U{G;Be&8Q=k~0EldNQ?T7v{_K@d} z$o4p+%IWH3`o2RtVG@!#ec4gyv;2Nd`1Rg@u$U&a%gya=|#S};@;S$&o>}|2V*0G3~{blE}e;e!ql;)#=>4( z2X*}9D3P}~$U{1(EsZ6NxrSnVr?Zfhf&@~Cyt^)Rz~aeahII`ID{E4RLwQ@T-B!X6ZPhg>X6RlQ+PbX&(eC`qhG5A zG|A9REfJQ%l{yUzHP&5Dm;RK@EShwgWS8&RPh%xltr#!(L-WW?dw22RU}O}(i08{} zuc0$qL|78ln|?C4NCd4T;qbiGR_nOya^YlCI&`e*S4DSK65+MVpkgWzX1^_F)2-q0@KzuhgI~Od89Sc{aLiHEH?cq_j{j& z1B9r;OaT;)nODVNE52T`N`0(2zZN}JzfB%2ej5Fk%kb}ZuMA!r-G83&laL-6f2wFi z&bIu9BO%>?8O=rSiKJ1LW*y$C=}>!DtqNECly}_v9T$n8i!6O9&U~kU6qVghxJS)P z1IsIf!Z3#1+RNEn(f!^ex#{q9wjVBmQVhire#Y3Qb|@N*e55mEC?2)at4SXF8zQ(y zjqyS0X7`W8aKAE1Q=LSS-$$bRdlJ1cv|5$-oi?+dxg<0SYVG!e{}@f|b~^4l31Np@ z%{3eeZ0juA3jb{a75wS`*fQg=DDv4|FtT>f^WD)?#C{&~@ClsQ*Es9&dX;ki^RHn6 zGei{HU-H+W@1Yj`$~TwUXhW579Fc=BITar-JVRTpybLTdqy@ZQ-@`*>saQI)Fuoqy zuJVnZXAN=!>dgrn>u~BuWH7SO&GeTZ<+f(K0+lezPOnd+WX6s75s!{kkz&ymKaf;7 zoZjgQ+0DC4;yZ{Ex%|*}im>2N=rED=pEQ*6mSrDj48$Xv!+3?M_#F-XV&{U9p?W>V zrq;6bJZ3Z$wkTS#z=Nq~kyqq!$UfU?WXhxkZ9M%_+qoQMg;2Z zL@*P7w)3l4cnW&|`Zv6Pa9=14tw;AZ%4gi)VvI7S2drtc4}d-ve!guSN>C;ln#V9+ zB_N7q5rZ}mYT?u^fJRwoyzG7prhFHc*lbmPQJv{Bn+2jYmTkrrIym z2@A(FV?@_iL-XMI8!<`rA^RMHeD-$}xV_=63XOs((bypBQ62eaxff;p*|I-zvE*cj zIqTCSCz_nM+IS4%IC^F+)@CLa^+fa?YggVZvB{Y&hHwmx~hT*Cj71Dq8inYjktp+8K<@U%wkMIb`dE8MU8B8f*I^s_U~N zK}r`4jb4kXF#Va&ay3Pc6cP5<9ERlGc)O4zl8g2+!oOD*pIev8nIt$dmBjU*XGo3L zkk^VH6(%7ans9Oy5|M|p=?e|ZeAF=6VlC9>$IPubI%c*<0=|vzsbpd%Go8_n{+U8j?K*w z0!P&Sdmc2#B}%KFZz`weo6!3Nx}InG7{p$>K<^B5?kuIg=Lz}ErqgUhU|`_HM@LN* zm($r_tl+8j>M(k@>hDoW?$IYws7ds&4rd_{R5 zDuxr1BnFNDVrxaau>&RUvRhC^kk;P}BRz$USV5Nb`Yh>gMsTA^*%2hmIJv-OFp6C| zMz8@J&Bj!?&OA zAcobOLH?Q!n;+xycn=v(#3PW)tKi(tc7d@m3|pSche!a`LzHY#Xe`XSOGPxuW;wy7 zi+h5Ngz62e$}3q;Sb?Lpf4O_}5;^B6n|#a@vne*Erg65mWnuj1B04>2R3sh>12!Nj zV3NoyDq^fx0}I$_UziL14@;&c>n4c7V?5za$2_L%InNdg{rtq?34{)?Y0Im<7Q_+v zxnj&|bh0fn0EqSO1|s4vHo}UH^Sxh+?C0xIq|VNAB5DOs2Hx&q!&?jmAu>X7awfXn z_>XUs<1?GWE9HI#DubHFNh;-7))H#TR#r^eQv?D`&LgV0!x<6w%TbvOE)AaM$g;aV zb}Wk{h$TW`fqQnypPv~-sw9jnWguDd)#XM7R`$CW;x9&GgH0m#pM{; z9OekqPSL_kk@nO2a#5m);3Z$)7{lv2se7rY(Q_-w9iu@idW0PDi)=pGM|TFVdmqnZ z9{0aJTJK&j@}z<@{X~w=L{ciLp=|l&g=kN8mFV$?V>=Xcy(S`cK&Cu<4(Sj5`@G!g zuuK+P2fV4Y6V^*ehRV`E7tD0y&X;rOtaC*h7F9WmnV7O?tARu*)x}Kbd18|zX#gp9 zlbYr7v6RT-31P~fBjnHrDG_#_W40R>MB8=QazF$VT8ToTV{}AOiqDDL0blghB5cxO z-qmwII%Wt6Op=XIO5eVf_-Xx;jjTX4J$a1yji5K0Hj&nNhOO4>8C$7TAlE7FuvNcl zVBiOyWY4kZI&iISxOKO|`mNr|iGeu3qtkII4PCt*_i!USUc400wI=@(M+#XReJ6eGH0>lMCYST zZs^LEcNGqkoEiq`Px;x2&6S6styuW8m;YSLk9hqfN|_=SPpn`|HfXuqf*$G`w4);5 zQf*d;MXOHRl!|M}wVE;&$u?*ZM`Dp;T++YY*P8o>Gl>+lGtnY~LOQGk#uLu8$h7Wk zKn~VC_b@E;^zot|>7AfswdcH|8k?tHwg1CLpf1}_07K<(OfZImMtjzfo(XFSG zo30JqfOpjF#mbab(5^Y--gN~I_`H<~a1u@+{UR2KI+E!fq8CG^z%$t(&!;6_-=$$u ziHhV(%bt9H;VR3B-87-29tf^IWMW1zInys_s6Ty%m2rIF{M?mY&5B6&oB%|4M$9D1 zn!{i-M{JmH$rPq(zgg>*vUFD<{|G3ue1`pKGmd>)$J{?SQ_^9j4DPe3MuiOC&AP5O zav`6yA9%RWbRhpqbA++p=#ewACt2%cXZF*lsDS)+H4i-VM{c82yAXnAl0vQcOSzIP zXfy0vIV|R#)vSI26Un-K`>C-ZB`r6U+L?VjbW*A|a%bKnen4OOvOC@@*gDzfq3s8> zS~lQ3uCGSM<(Q?zq6377(y(i18%G*{RT+gy1+PW8T- z867)c4@M5&PiQ{eX5+`sxO&eMQoFBznX;V+zL0D&J;RCM2?e0|Flr+~W?rbpKZgZz zh1pHY=^6!7fImPkB({eP@a#>;dkKwNOpyIL?Lc9gqkqv}EnO9_9u8?++8hfbV&qf7 zW<{Jd0M^XP&;2UaP2%50cy1V9Q)I)y$D#@U@UPp$3LV|I&y^e9D^}8H0->RTg6ZY0 z(v+=G9;>ouIlR1o$U8UqUGT5B^5nG8#3iyINwBhLy%$5F%rlcC9pj{5#&>l4~{-9Y-hJ^uWBe`)&+DiuV5CAqzwSxu>~K>%Q2 z&`Fu&!(0dQ+j2f`O%Dxm&(>j=29@b|Se%guxLzzsUUCPH|07@Fd@Dm{<0+I@QWJ)O zoV(8mGhGuMO)+aBxKCWBF5kbnzV2@{VE#PPILWXoba07Z8^&Nq^%p<}J#X6@Z?c>V zCt+nEc~EW5tE5tNi;XNpS=tVk>frJHS#7huaMILZ#xU8ocj{yhsFp*J>@H z=@m9rSKGu3rCqACg}SsY|o`(?eqYNcdB;&sH1BkQEggXbt?2`?dr0UJuaiK5;9!`9G~%A z?A1M$OZ{uI?9X5PW*T6j@;w<0^gV|+wH(aH%PsRv)!akPXR?oh@SMF|c}b1tV7BX< z!#DhA!FzgazyCb?v{m@nWA?c7WH!9AbeR0+illKGDk`IBY>PmFKVCFzqzbs$G&NUV-QT&nis9D<@`!hs1pF791 z*$^2d4KI7`w6X&eN%-9c&MZ@_M5vq9&ANRv6QKvyv}WSPqHJ}}~aa{^_`?z~GqL&mQq0;cUs*ssILD+aWN z$I@qywzemnT6E(TukE>j#-A*mY_dK{(q2LisZr8B=IJLUhW40LM2}JL7Eio;^zNaP zEo{>@l)@;Z`EkY^@V7GeD1F7R;3w$$Q zdye6j7cwr9?+1Bxv25&x{-jVb#uJ|x8Uj9Q{LqmG(*Daoq5_c}yI|Nm3yynf$fk(B z_e;bauM4@680^vOntx6vZ);PYmrUJ@n}^9f?PepQ8O}r!J8}w+J9l1|<||To93lO3 zcuWH?WN|%~KR3gr?oZutY%8*!G)LB#S|xOJw=xSa`qk<;dSg=#p>lkV0|nS@R_6;0_&FaK_i4*k8B)V>w=*8r~D; zVYP1$*VOx2%b~0l)`1E%Rqx+7JDr;6b-qG_$DPM{k%S~M|25sw!hOP%PjuD$Vh^jm zKF*gFN4SFuAU_tGcSc6t9%z6iX*}hs^8P2(VA6qtHbuVb2x=K&c*37H=Tm#_yQU~w z9=4ieX_0|Qfv}d-SMu{JkwmIWH@lx6Ngx)>npdn1McJ>Q4 z!gnta+bsxuc!a&>o^gNaRh>}nmnoO7Vv-c78tDJ81ptC{V)YI_dDtlv5V92Y=&n@# zy=^!9hj4fVrQfH^8_HZL&iZlc*!4W(^!}$E0!Qc3aWdO2L3J=*7x^)zP}SN%yDU0S zo7~|nHMb)27{kVt#-xrw?q zG=gN2`4{Ar?-2w8A#1|j+tc2woxts%1HV#*w^ww`HypMDg{CqJ1WldCk(>SQslU(% zl=@R`GPV1|D>;V_Ve*GpYlGL;_9a^MA^Gt?grT0UPb9d4o!FJ;%(#;>M)s3CuK$7P zv>(*3-CL$k)eFbqtjHDz+|gNqRH++N$Q3*nr$TQ!Aw4P;*14QP`Va0IP9#%TY1V@- zQm3S@UbuQbo@<#Hm|ksL*aYabI;^T%slc&4`}Vzab8e-60x6IT#RaB7q{?t(dzxlSZx;2<{7>#t9mvDGYrV zm37U+NEy%fCu$sw&`LzMf{tShw}~PjDLH_H(VaQwmL^Bh^`#*E}l~Z4S=3W>o|Q@?2EH;GEN{l zyhBxWwqf8f;|p9fi<>#KG~(SR#w-oFZ&z@vdK;9zv>-ozGIAU-O!=+~HM(pyi(#rG z_Pmbl48>cBAazpzC4}(yjhV~1E)x1^``FOlu`Rq_M^NJi3gess>X(?0MFUu;7-&8! zv}l}~eNG4J03I}na{w^2p2wta>2@U#+~-*YHf^fS*rYy9@EE0wP(V|!En8i1@ZU{= zg<;EDgrj=07Tm!D#C$M}ge*LJBaB`Izev;~f!<(E2=x;rG6h_HJ@Xi99_@1=4MXYy z_|7w~uK{-FVubFQUKF^`F(#I4BRb#g0eL~D!$=1*3PdKEHbXx6%`@3*Hn)sHd)&~Z zL8%`YK`-OFy3zo+ngdq>HxW6yAS(~e?S~I?hj1TJI3jwYY!y$6^c`OQ{@tr08MKFNNrdhjl=LzL8Y3DN<_{6!>eKljD{?HM~P9Z7Btj{ zp`&3^`HdYBCF(sYv^8Q5RHqMp3SwaWoZ<#~EnIty?z&?u??e{sYcSwq}~ zK0&yTX#KH^6cTRDGKZ})0%PNgTdK{#vq7y0CbBchdQ6A=4!!1H1Y8rs`~we zx#PRf?>NR6>iV-b|>T2+=XHwkQH1~5eMUn3X zJdC6@{Tmyrg3uu7HEAHSPh6z{(cFz!7ga{=xH0AO5$7ANJ6lYm*ComQ0GuXcdvFoQ zj%Z{=x$EbA6jLsMsB$2+t0=HQ@Hsz~9HPdd;5e^>puyU=9}z=E4A zOXl?VtNXng+ZzEebg)WZFu}h~x7;owl>S5{?0Cef`Fb~5&q70#{N%X7I#e#>vPjGb zcl(mQZ1W@k;&?)t;p3o!goONuYvsxwVrdE8ce5J=e7~@Fpdsr`A`TRizUoe$qpdZ} zW{(+KF&IsbcUZXl9{XHM07a4QUrt6n3&fGbRSiDFsorYmB4dua&$reiyI(ve%n({% z!~YIFge7Yr-ye>6V*04L_4(u!XK~Mp4MghxlHpel46lkdmSc^SMUf zersoLU;ar7o>ys=;=e115+De^&gf+WlOme_PNNLW0sg1zL3q#g5r1haLn+v-#G2`S zhwy5()8uyH&Zp05aH32&w-G*DDdc^#Db~~7pZL8R2LBSb!cz=M+!5XWYkr~qbo$T# zWLJbMf6B+Kmv^)I@Q#ucuJt|0NBPJmksmIxu)@&sqH?n3ertK%pKU#^^zQfULDF5U ze^j02y2BEmq8w*EnA;itAFd_(_#KFs8T6o|3FWT0+?1B9K*C=iG|;JNB0p)E+|I)f zQgrGNaf8|D5l*lyj;*;txj*Aj(wF~h1V{g&E1J{8(vYqXo2MhQrxMEPeBpeMF!2wB zahs9#cGi-^LltvZ$UjQ})ixcj-(KkdUoAzXqKsNn1e~(n$oa5d+Ww{{ccZ%jxc}3J zJt>L+kVUiMq4h+&|9&f&-W8DV-xMDVDDErw0R0YInn$HUH6bwIztQkfzI-b(6g-zb1{u)kU0q7S-%bN2I5B`(C&QXMvdgvY)4)(?mI8- zMq2stKt_B?C<0oW(nMjH#*2n{m~#6nCQfbMok*LP$43b@knYk$y}+2H+#_Ym-NeQ9 z%t(*Kg4qU9&*NnEK=KM8B+!?xAuYbUS(N(cuv-+DE_%LNZT|h$CO8)b%Fdqc)SD-x zwlSPI0-kIj+4@T={%T)?ivS77`N*o#mVqw$%#@x=r=)KR&xNhI5& z(E-uW2b);v)H>I3;|5;&*JxakH&3P1(h82$qo`iWTu5ijTBB-=DSrD|&z^TPuI<7H zqcN(HCrg+f6YqxymPj_*k5Gj?y$ZNLsJ`zv*p}7Vbb3u841?l}H9}&lJkx`Z2yfxm zr)C=!F{1m6*aCLM^%!8~`mSk=n7(l?IZ8ft06U1NLN0cd^2_C>Y6Hx_Xf&X?Qq5jnt7Vp4pF$G*mtOkceYG@sjR%y`e z*qA+rF^Si6)Rg6hj+vsT)#|;YYAG6l=k|kss4ljdhMyChHam(HDSE&W`T84Z-=iBn zn=)~&L{?68=Tw9dw3EoKFs6+1uC)li6c^A>6zf3!<#~=ckvMxWAVntSDt0iKIcaux zF#`}`%#!zNar$}_0OS$qj#S%U7G6C^9p~Ba?ybpyP|a%35PY?U*N{=NG?;r;wUq7E z*)Si_Zub|?G8U?hQuyaS5qhLGPz0s3RB^!(wxxFK3(_7;cbexn^XHZiZq%Jzm~&c` zzocg^bfNk1xESu1jYpr)gDyFRn_v0{Li&t4&L0zcKiqfQjNO3wVs_tx)_S)D#Day* z{piu=)I>4dl3=`@UpIlzZ~(Dwe&GFhltw33en*S@xKLXNmE8{{seU<5fLhfm+TUr7 zPE}84GCM7X7pP@(L`-i0JM%E=_oa~U%-Z`{-%lo=6Sm2C!XvYRh8ft`AI@jw+tJK*E=g;=t-)A ziD4L|rYvTYBo~n`OID0DYl%ET|EoEa)6(MP3BMgp_Zh+7=SnIn|EQS_{Hd}8fRiv( zkwYEi`%}1g?a8t>Wy)~A1L>wrbFqL6;6`x)#frX=NSqYf2q=u8r2#m%)M!t&MN!WG zU`~1L7DrBPPaqRqUcX9rA5?3q{ML(XFchT;acI?f-f3Qc{;KgjX3yX@9m=P-iQ&l& z*uq6gU5`Ks%Cgzfh}7?hiZ)ASZLl`MhmmVHT*nxbo<&#WNbvE`O zWVEa;J6MyibKs7O>$-o7V@bE;4WGIp^}YUU`uEjht^pxt6R`>tZz7-IoaeOIcai;v zTm%S+nU`1-cmAUB-;n6jdDzNI{zAswv2~126k%cE$X8XBryGw)kLZ(mTytfoktf?3 zB(1gPocJO7LW#v{50-IyPgWCmK6Z06k?QL@0*^Mc@g8b0V$tM_J_eNk`u$fDda{n zDZ}RC_)aG{2|fzk)=N=o8`V|XGv*|?*P^{}%c)=#tU3FA=!~Iu$uri(KMRFap*U+? z3fa{D2lTR&No(H=&Q#PtmsW_BUV|bdWvyn} zH3#EW&`E~1Snn(7PP(2h%(d$mt*=5DuRpA5ZAw&7$6-iA&c*prV_C+OOlrUsXVroi#&#<%vD94%+-g`{4A+<{c0*}V(rw!MJP<89ltFk8me0 zDn!xhCmIMC14N>(5B}i>yr?fKf!|Hykhid~ma82VsJKPVz|PmOEb!;J+v(EWnpQ5r| za%Y@MHJ10WcPs~CjXuCDqb{ncp`pX2k%C>2+dm}HV+jPb9c>iBLLK=Gc3bh@p2hYK zgK4Ut^mtsFPEGM3)%!G0CmA#MQTB%mE$zJTPqQ9-`BC3gf3aRzfUeIXd0S<%25*ew zf?J^lSp66>ca~7jH*@pTt;I_2aumwQ=8ur{cmVwmnNHkb{nGcP`DEhaViL&)ku~N9 zTdAS8zRePPs8oW`emM}TvDbvZ^pIf0lr4J&XIDj|BTw#s&$7FGRfrDTN_5>1g5Wp# zQYi&?BxmtFRS|wAiY|Yehz|HeByZx=+2R={79YP_5tQu&^K{59N z^+Ald4Mj|L0(7+>70TKKVAiS{T>2})JvV1Af^daz2yb&fKnNtQ=Yv}j(OL6VXaHI~ zEhdEOZ19sT_}U*NcxYia&&_=PsIj`tr48Hi=n#+YRvLryx_)1a@NcIce`_WWOFqqj zLQ5~gs*AXICZm3ErGEg}LIDWypPHO#+)UO3uy#I&M6$>D5>)xLNntKP-IO@>`2e{5 zy@#-Q{~5H;p~x^IGx=rcjNxD^)l7$%?^jG<&q|&58r>;2hCKfqpl3ccQ1Jp|9e8Lq z_~JA=>am|x&Fd?rP;>rC7RUREYvR>PeC5F2&Dayt0>jtVwE;@#aRDaY@~h5EgZUD& znKA}KIuBheDuuRwoTGFbaK2$i>?Gag)vj+Wt(#$ z)o*%^mMA|T!GbHGJkwye+%58Ccj9PtQ-70<4MJfA>D_C|cOhei%xe;*M3)I-cF)$k z$pVjF=g01D%SSXm2RJaMt`wT>lq&}E6QBQMpH+J_M62f>z`^f;m4^azsE)nMcGNPN zxGM}f_sqb!}GhwVl zI2_^&8Y6ei4J|i(5cj9-&Cml!IFYNv3BYS(o|mxuOq?raXozi1RaJ|7S!9~@n7ABP;cGVR10Z&WGpPBIE4WU8EAUhatRV<5^kmw5+t!=epM2qI5}cw_KH`HK*GpL z@8dBbTUi`B6`6mKdn$q+jPgEAQapNGw77>7N>5#=O>c?L^Y`Lw3UMY8G z{30st&~mPc%8We|&r)zoii&}evckV$5u?DZ!Uy)1Nh@NPFeH9?!3ya6^hYwlu`o`2d;@53oq$5j9*faFUi@`A#xz#FFkhd z)0Sd<^B&_;qXPJ*`-x{OAE3#$z!iJVcFWpA%v6Wrl`PLb(_;Og&}R9@`1mxr*{iX|RNp=C#0Q#$|tDPWC) zvfM(eWu|N((f%@HmyoYBP($@@H@+C%_dEkp>BiuzgahA*KaU@4t=sdF^fIn zWZR9?EOno20hDHlpa~}#>4M&*EI$@t#UE1TOm@lX3^9nXWb~r%8TrkPCN9TFR!V5G ztqw2~0az|yhxlKEozi#o0g7r92Hq$xJN&5no-j!~r;@OVI9Scp0P-xK`QMSZ&W6E`0@e18K!vM8dm8u`mvu*ufFUh zM7x4LPep|9?;fL^ipRB^h$)BlJhjF;lOv{{DYZ`B0;SL9u@#`D0vLH%M~YoWl;n7B z$_+n}eB(SL8zIDUdncDG1xOtd7lU#0d3^*Xa4=p|NvXIzlc#ZBz-eWPBAtG%{>nqY zuz@qkDb#hllbO=;dZsfN`*ziC+^7}?0H_7&8>*zc%fumY3-PU9j_v$vj`p*s4o9rW zkp51a!sh1(4b}X7knY(`mr#t+H`!Q;@-VX|L{WokM}b1pAKXQ!6kdUr`0+!H1UnMB z9G1f$Hv$=+wyZ*&swxkxV86?dD)3hZS-LvOb(&4fB9DL*J=ANr0Oa{OXjF%-<-f{UOGM9KqE#pgltQKBu5 zGsKyy#5Gh!Nq^7gH(*2@JE2w(GxvuqD$hrU$TOi+AV)g1T>c-Uw;MO0^__)yIR^sx zd8Qt`;`Pc7@bK`CKQlffOP%8z#@)iA`Ip^_>EM?VN)NnyMmWGRnccl?9zNe_N~7=O zx#yeK*Nr=*XGjI+67_1Bl?hcvvcN@s%JLUC{eHe?4CE za#zqO>^?vBJXPqEmrG-45yK4ujF5DK=;)zgkEym;;2#4ZO)c?H#sQx!z-pQB(}e{zzSPvrLa zz2n72`Sf(zef7jzA(PhQfcJvJq2krChRO8u-k<4l)^0l`fE(CB#aNX!QN>T43al8LwzLXBfAXw;vI(8`42K_%`cT2qi6O|r4q zvq=@=fOk0lXU6ZG8I$9RAd>WcRg*pCOF4ib&V~m^m-Bov`y6Iur@zw>G|u>&#aWVr zif4ciiGPgl$!P!UMMd3Qo7aIfp+aKxuGH^~U@`V=7vW}=FG-V$BI?VNE7$Q%8s|p~ z8Gr2vKn`r++|vV!qgN-6B8ZpmsdTE7A!_+skXJzE=fl7ScCDw;KwvVG2eyZ$-`DEn zb%u1l9u~6#CtkHaL1ynGEizQ_oCNl+5|YVrl{-PZn3R5ZsE_LTWMmfS{;eB>>z%}t z%dOc;PdECvZP|MJcdJl}jb7PF4xVHVAqdve@r}TVYJ)e@C-ZaaCVsdF=`l&bkn;%d zZ-b!?@0u%GW^GD!SjNkAGP5clM`n3s!X-#tS=Lbmf=N2wGoro5r;{Ub_^A-prsUH{<@45B%yX)2*)` z*F?Z8bt2en`;aINA(P#c8 zIIAuWX%r<40D??N*TtbZ5FkD4o+R~2cCutDJX$J8EI8P}Jk$1H;v`mHAbG}E6MV-6 z>_EAm`{U(a)#|gv!uHw7n+FGT#U1%0)APrVqkm)|qfM5nE69@JPHvAv_F(X1eO9oj zHMeM6DuNyf2=w+8C5wUD;YT+5!tTgW{6&XFV9a*k944o;5dhLNi@<{Px&cfVBH1Qf z`YDfmO6~&1qL*l+o z^i+5YkOEa%IgLG!6>*VRRck2GZzJY7TO_xRC~O)bW;#A`Y%VrpRr$iSG(!@6{*+s? zW%c1v!Xm@)Xmy4&nzkKGRSEs*?I;jjFnrbTMiLLB(QzhA>iJmdy;4Jk!w7V~TE|g7 z*LU0mS4M`@uKgtA_poiN^WSn6Ip;CC5{8^3#d%xf zW6a{xvoc%Bfo$lG&!03Vg4{!qK|7lV6-oW} zW}LNg1tjSY=+2B98|!y&FNXRNR$ts{N!0>?lN@FqkSP1d)ZmvAgaK`Q7BAc+3Ci}Y z;N=K(Bi`HQJmtAR$}m6*6-3@Tu?&+V!qvi&x?V8H=kvhj;~L`$VUxu-HAeOV-d?Db za;YDcTKeG_ILnu|4vH0E78Om&BsNBWF>oAvUCshIGn<$21x7smAj#379Nz~8P~8zz4npXB{E@i8K!u4Y^n7?cX+YSt(bV)xB zA8aCISwy2@-tz`yNq`k0QsBcMhS6h&G56J%$XQmz&vW8&+f0mxGX8eSYwQs^IIrQo z+{AAV)Uv35@=5$_)*u1bLl2>+rndgVL_%1fZs$ms*N~)>v||}vZp{LlAY<`#j`dp0 z5gb@_B|EePEfgS9Be5)<%*{(UIrU#Tbf*K6)sgHER^iF$PyC>bl%(BD&7L*nEL~1> z-eVkgzX*8fa(FqN`n7$#;?#kId23P`*Z*o0_yt3!jNtY0-4R$w1lbLB{ATTQym>sH z{D%jUmgZu?s3ayV+RV7?vXL%5w$agwLWQ4bO9J5O-JKiC-XMF)X&xJzh&LP}=+0#4 zyc9;x-O7%6IoPC*FBry|-j9#+N*SK_Ja`0?$Bbmtyb*NxVO5+~6h&z>UzzEbQXaA_ zEBDxm&j<#CBs!gBW~5`bQT4vMHEU>IwhRE*^Uvd&JsYm_GxJejBNfe25^V72_jj@S zNIHL5JeqIYt|)yzY8NgfxN#!_aJ6D)FX)ob$nBymkX!bWpe>CJrV=tHi&@_!imy7CPkmi6Ns|_pZ zcor{4=sLc|i)oxY7vXf`y#4kzd;h;g;PX$(TDcduOQ$|AnZ1h!ee2*KEiJ{nbSa^& zTakb}KR?#sNV$L&jZhbg@Ria9!CKZo`#KMoS`dLX|2TocYVcPSMQMKmq?Edl7#GX{ z0J-6Cn4`yz6SXX|v$F7b+IHHwe(hSC7A=ZRn{U_Khx{JP7xF_mS}U z;|Rca*IhJh+H{3$_Wor;g@x2ko{S6zF@_8wdFM_w_$!K{DBla3CNNs|`3dOujR}Ad z0;ki702&*8?GXj;1q*PlTL(bn{P}oStRQssXxsm;HsasCo7$Uh!YV1jcH3>F?AnFV zwd>UmOHmX>QCdaQG)#N!=_m_&UUcErnGlbrX*k-keQ#o39~Vupr+=`HDBKY zPzdxr`~8`k8k`9U?V1DtL<$ROc=S<%FTRK*_Gp5cmxq1gM9gm8Fw)Wx9#6Z*@O9Ri zGlYtZX~@eXvTq+6;8?Z{&+_Ha&euax6h%?m!_-!ucE!N6A_AamJ#Xc(7ijNV=6K|6Pc708-Ps{ z;cy^L6XG1P*W%(JE*|0>$hdgWv@cup3IRfVq(MrAl+e(C_~aABf&Fmk5b~ps zV%Md2Z^A2AA+8;Yu$!0P+(=OrMNzIYm(wXd9Xy4H4j1N{4)fU8AHsL>Wq*LCqbG{q z2#11y6TK1xo~D7WqlH4)PMyMDScvVNT^R4ad#+ePYjTkDPe`8kSpwKhunAtCB6rn6%|EM6yH)UXRT>5RG!7lo*nhyFyj0-z3jBTz%d!!R%|HkP zDGk7|zz9ldi+~ZaEF)rBMp#OF)QalJmK*<;M90wekf~__Q`dtI2pQnz+F>=!m>%KQ zpF{!o zYy2$|!nV1Lx4-1!8YTC2{VZal8-!1;{o6-)5IxtDS5hK8YgvA@wsv&2b8`EHu=-l| zl-&OtGauf6^Jw_>u=C|+)f`M_`)mf^ zfcMaGl-!(Kl|0)r->#T2^(JiQcFRB;#I@H*s41BlB!rybEi^Ux`vb(pq>dugPkhqM z@872SKRXDYlTbeZ~o^n=pX;)rrJnGsVt`d>E}N!o=EjyS1et@=#RHh z&{R%J>;~ii-$RM0pSXFmeRQI#45Byuxt~JY1;|!`UHND_i=PsOcNl5esEhv5nCcUs z2WQv77sxtJG}rgF2HYf813&on{2`myw%4jyH!H@Q@ypU>$j=-wSC{R1`>kvDhal`+ zZbe6H8m9{Qc~Q?*@@(K4^I)}x%QveOjL0Y4j!Uzp*Y$7}6paFIXA+EIFs;K@wauNPID_Dww3a0+W~HUVB_gg}cWxfu-^r}v zL&33_qlYR?RaHek*>r`~vw0AA2iQ&xYRm6zTGnkf1Ez`JG`sRRI05>c{H9Hu zn|Ev3&KEjo16a#d@lB)x&x-wZB#@}f)274eozxG%)^|JyygkANYS$bR-7yX8KhkQQ ze3qDIhgAe;XO~#RiW}zPZ?F;P>AD9#M`B zLfXZMnasdzypm8^EgK4?2<^XR?IxH!KBIM=A9FH=2;~pcJidmks!=kSL67y^q!kI& zfbWjTqC0TtGN$FO!*U3zI_ME(OAhGBe8MJ#`&4Qk1`i(P_94ul|sn( z7A*`S;Jl|6oruR>k$ADj}qQZ{e8 z9**h3xDap)ao3eUL)o<(yoL)zi|rRH;;40M$>p#8fBn|v*;27nS`vIt^r=s{z)?=M zegac`KtrphxxJ2`<4HVmf>|{`yRq+C66!p6zh>8WH_bgCS*&I7rkXrj;-r3nr_VUh z3BWhv8$`?!3QOlGcy|c1Z3`Px09l*GwAamUJGzc$+P$fSD6sq5M{qj{a8j&nXY2WW z#aNo|v)y9>nZnH*`Pidr8g(RSx%Mf-1s@<+oN&P;uKoutCZaF%zhrXj9E_H=bNzxW zVdp3^YwPu{T8!;mpa#2DBsN%=Ipg1rwCDoy(e`A@Q zZyh8CTV?GvuWM1>5!}+s3W%0D`s>A#3yPZ()`_}yOt=6~d$mpYORAF9>(-6=LiLGO$856~6WaVxd-lO>-DYx3PMY;nG_W8UZx z`I;8wtP{MIsTOtRn>|ml3P`S|i|83rfM!T;=C}V8F&bY)18&*7b%jepsh-?s?c_IWhO_Xq zo@|&v2FJOmUKhH#KvS^Cysk%+wy?ZRKd(gFHsg=o9A&CqOYW_Jmb;$en3kxv*H}u| z(uZ_TYyu2i++#R%4d-*9sc8FGPel>KFU6|{@mk!^ysCfKGl@rCT~LZVenLXTLh>Yj z?y3LY_I82 z>CVrbsGj2uF<3E~ugI`zDM#|M0&^XXu; zg=zQ#JxeW8X2L~(6vcX7YST^fX&MO+N4LVE*fkN0GF;+*vWZh1! z=qv7Pg$gIdJ@BF(;OdO4RllDPS^x2uzyqKvwgoJ)1MyliWtms9ezD1~J z$|CVDY509p7qH@5Gx1^cFej7a3;(#mLdDfaETN+8$7w}fsJZh-d z<$k7YHWLjQWjf^(;&UDiPvv2`PrXJV>L<4OBm`*V~|`AlNZmO(g`^#F%X|QwM@{_Rk9`?AecYA<^`t$bo5Hs zS3&Plgy43zLlNa+W~mOysn2uu0+3qUiiI4+8r19kno@V{zKgI!`5fE4DV&f-`j@WJ z3aVel%w|s(>})#$-Z)ZL>?z`|4(aJ$-c%N~FmKeiP!C}}Xou}C&g?R&w@!iH&61I2eYiyPr81_Z1j#0bOc1wuBMNnb@HG~`U{sfaWP@51i&G3*Iz_mI(fBpkY znb}2OTfhp9C+&aF#2)+yf#2M(ZQrTX$KA<*+xW!txiQww6|#(pAFClI3_tL<3(r=w zudWS?U4)ZBTg^oE`$qV!F2z@`I6J#(5qp6LI}mKB##W+%P0Eu(_2WzDb+%frP6>XD zNp*K!?LkK6!n8!h6hkm@$1jG?H$?B4cu$#m&W_fAQ#O~PTXYhy9?WlrIA7+n&6q+8 z?gbZJ|M-IRTgXftart{x`6_r-vYWF*p%T?aHU|fK%zTjp?Vfshe$7T2 zOW~?|8H?-BvG6T<`Zd=2Hrk8I7IMDjyi+QEx4YmTyCo{|xxot@2=%8nT=7|m9mQPE z!;u%UKT946+P~yuDQ?KkL372834pIpxpi?-E7i={X8OJjiB&pnwtclXuf^1rdqh^4 z1Rh+P;->j+lsDEJoE)dNH`QJOUL@nuE!5^%KSO7gwy zi6?}$a|@u}A*KNfNiPk`(`=6GTSjV+Z%n-lpn9u>A}k6j%`5bIH}nV#-M!x|u$iX~ z$~Q8^)ot~2Gu(!iX8+x6%M-Sc{gfRg4X@#@rV(o06AH8A7VTSUj%H_>L3es5~$C^Rr~rtJ8_R7gCqUOIpch zz(F=BGXB2dkk#rX;%zZh3u`}asS}=1KE>q z4I4m<6U@I$SV`kD7uCMrBZXX(=#FmALt!3v#<%?&4>WxIQ^FNWyD!h`{z9oNjX`XA|#gKsqM1m9x6_Fseb=I{6V!TW!9 zy4a()#AcjZ<2MOT40}R&r~+H_w}C_AToLwo`@^!@L$aB*hfbW=B|f!Bck8CnoDcfX zu125wz%X=rE5|wK{2z%JOL*IfO;s)Z-#%umj8v1dO?P=!IU$CGEuB{&0bl6-$IF>5 z6ZEE3ZXY(u`HGU`;!CHV+Z^)y1rYpp^vR49>f+;FztJ4lgr#uf1@|a)nqz;dl``AE z07E0AnL#*sG=E@J$*<^ZZj54ZY~?-F+Pyhe^11J?=J?66+L?pI%Ovv*_ubMiAB%Ug zz>FbA#NmtL^ypzwJ^3*}w95f9i|r`Iolbmzch-<0IuwQPI3xJiDYc>0@oXkd630^$ zjfqQtT3Q0-Y#H$clf88KiU}J3irB8_8(xu30vWR~ABSOimB{?r( zi`=2Ko72Ds*>I%H-oYSjJ_2h>Hh<0HdoW~>89Jj$>d9b4`4x!vJILu)#1c%r=cJgg zhTtZRRE6_8&H1=MI7e+nL;_{b>`@LoQKe<1?D;9dVM*IP&YEAd5q^hOxJqgIz}l=~ z8K62+NVt`3we%+4znL+BcD?7%EGRS5!9t*?9(yTsKR^+JzLesgBgne#TBClA`t;-1 zpaNGy6xd$^{CP8k`lNnqyxqfjZSC*&VBSX7$hHjw05mKjXG=Pn(@v=}4Kp0;dyq&5 zY3nC3H1>N-*Zg9ErB8S4nPXy1V6)HGIZ>y;q;-;-JcZL5H%=*P?XK78j66wqTuqby zn+XvFHlj@pgbu0fPnQ&N&n~H%`Php|=7PET!zh5#QvSU#WA4_kZTnm@>)rNy->%wr z5y_|RiS?DKTJW8<^!bY;SWTHceb_d`eLr!7l4n`*l-_1&B@;a`m}QaB*H z<`Rbwk5j%w1>wyUr*9g4RmTkg%4Jn~4N4$&d6sGZxC0XJ(Q$TvRq57qwin6UUzCdR zthAPFadP89f=?gfhng=GKqjM3jVCLid{VWt=Xqxk1+$|CbaG#0;)o=VzC+$g5O#F(#}cO5Y9;F3 z+o{`~1NH*g{s`5OvDeVFPlvcnGewWF`a1a-d-qjz2W+4U&M2O1MFu1Xo&kio)H^he z`JVcnW7aUykr)0Pzmgx|F1E`0cPt+b2q9z+^EK3D9%N7HYPdW#$FmV`^BZS-@zGQM zKZNYwBCtl8?Vlg-GhU&o{y29VsxI(oO}%ICW{dM)3Ekc_Wn*kb`W+UE2vA088XcN+ z-<`aHR#0N@5V^%Mk2=Q)4gk&!@lStH_X(vF9OB{E;)z>hgta|d!G72&Vi@+xVS#PX zsp*)?k{`Q{;;;PsXsO$Gz2be@4Y=jq0WjP^N~euruV+H;u9D)<3d zXAu3C<3>59VitoEDzG9uTWs;``%U&9Oh5nk+JO(lj-+B*AvVHikl2c(ZAX10QRuwv zQs|w?oH70@sqEvk_P-qf?KyJ$$$(UX*H^(n}K?;cRh3|QC4Z5J4MRt5L5B}8JYzMHwe0&%0Rc2#yiF9A- z#(uN9t9MJj!zjPh!joD5&kSa-eW63jZ#h`!ssRMNp7) z(5nz@mc7z=g98BL@|jprze$(;$zldl!_ze9NiW(Vwn{ zE|<=eJMh4`%jsqmDVXS#Nwy-z)*sIqD0+5fT|&MxwtxmohKcIQ1pTn#v}UhV{l4Yf zjqTtH)<8aG{MUJDynGzP>id5!_(P1WV#uBMu_>^SB~FVIi%FA1NlT_D=;UXEiUtZ^UPPv=Ai=ePh%gZz>ym!4jwQ9$KnfJo9_;zX~ot=TLc*S_Q18rW2hin^ zmHCR(UFvh3yKT4Z*!^M~ggj#XSZ^+c!vZda#3C(Cqm#eHW*)>!zzclsxEo%WqF=G^ z5+f;rH$RS7Gw}Ep3c=UN>jQT$W6h*KLBty)%uTPoac?&A6%=IMWA&$NwJhlqo3=V@ zaH^X1V9(fSfGcGNJx!aVJsjk+`aH*N@Gac)NrVV=iG%Niy>Lvx2P1i7?a|1yeoyvD z(x#<$CY~!EbV5N1MU}|&F^KiLk~=ni5_>BEcqn7JhJLoR%_sEgU^VqaQHrTlDbX4o z^tsmd&KIXMHI^~1jj{O+lHtAZkWj_D7vM(l^OASU7iOLn-==bW&C_8boSjR!UjBKL z^RsZ;yqa=303^Hq+%ocfgC(`ebkGfF^BtMFJ$IVCO*YqsR;9h)p@TQYZHIdr!JqnWh zZ={fGI*reit7~{}t#fu~PislKr5M)?@<5cI>8jg5&K}5mN15EkLq2UGW!A7U6oYFn zrp`>gwfF1Zb20A5@0$*X*AG%DsqWKq`@-TQ^9=A$d2~6_VfwOOY;KhtKq2Mh=Y%xIqbiNERc@RB_~#O-X+7 zGeXFvy1|*U_u0l^TAT9uM>(^M%Zm}k3vJ&|5aApuP9H^P2cyZ$?-bW23orMhsHbJ@ zURXwocTmW9m<&2L&)^It-4mz*cEw{mi#9ILLz&w0hRU+GD)6W*hqp5kCZYJWy#4$^ zuu6q46Y8}0U}718V>l`)M>)3NlS^phRZ z^4W5kR6}J|$=DWpChMDWdGiArYu8k~*h~6~)TM!ZSzErrHcRoSSMDnc^C++Grw?zL4Z1O{OM)JEOJTyIl zxlWj-)MvMal0RRkBxMZ?x5!x%B?1>%vQ5Cu9FRq&L*Bjs7)h*T)@9$WUY?cSq(&MR{ z0t{W=s)Jc>>QWAG2W+z0lJ5;%!qnajc=iW-I<^*kzOD^QrIy~>69sbv#CMPj-`;S$ zyedx!mEsmYXD|-Smr~ElP zD#{+sbtfM+8M*hWKn?|4hf*lxm<@)h1EP#K`F!o@R@42DH0AEGa#-XdGYByF zbf-aC%IJopsSl4utZWHcGzEWpa%PRoUE8aqRb5J-FdaaaLzP->`)bUSHYB-yNn9g( zA2hZS>!~bSIT=e2m~Su#d$g#iN3y@ll|Q1taWAz*ty1-s?w<}8zfIeB>6=<%kq&Ra zo=*R@x~)HyZQ@5O`Lm>tsj2$61?LDf6*9pFqfv;Oh%c_a21!zFYG*1QV7>UMxXSqC ze1h6G=fDYgekf_#(N@0ov3DhK&EYOP{k9yVyKZ%dq=}|-qqC=>cFLQ*CV1(w(2!$w zbFe49l4Nk*z9LTV3~jNHRy2z5mzkGLr5xh!`#dxWmg_itC^;m^<+s`vAFS?B7x1PBr#?lu^WAVTex zZ14b=_KIlP-Fma=Q&UF7Z{Y~?5Nx;5_vkKWzckCpLX?^Sq$>rRVr|j#y{Z6$&7C)D z*!TmQT4OIg9+1e1yc`~z(gb15o z7h1d6!}qo-CTKCOzKY&Pa@o&>SrpHtN8{O5%44Tz%E-6(K|cBN2yZu7(Y;oPY!tgU zKfpfl5t}mS9_&)l!hg-$-%z2%i%OWP{c(?l4LtGIO=O(^0U=Bkq5Gu6Xs!0M_y?do zX>t|4>H3@TCs-VO2W%~+!E#Tw<9=4)Kv?`+F8v!XQ`LV5-KbLcPxH4DwwTd$)b-+2 zU}gT^Qpga@JSXiybDhdprDO@A`b+Sxv{*>Ry&DW8_x_j+Evvt4Ts!Jj%$ zP_M~SlzmfPsl=`9V-b-}D9hM>f7osJXl?3;?BO$*EJB}Agq7Pi?vznhB1ih7d}KtZ zO~u#xgDzWEoUjhtIa~`0oz}?DVuTVkz<=_$ubv5b&KJe`=Uri=p5`zM-2n=x1Cf5O zN)os*g|my-e5~Zs19qkuRu@ZWH&zvXzt08lX`4O$&9D>kHte(cyTas0?~F~{2}Q!j z-D&aliB}(Aba0cHDuSDspt|BUB&SR!i(PrbR_BfQI;SI%AX2v71f_9{oaHu&L8m!? zGQ{U`n>Z=I!jRavvNwxmRf7RI37ZDFeTlrvYEv4Mj?MDMXQm{?_IC6 zAE;S46N;Qrx{pepn_L)wzh~ycVC-P>*qq_erbgV@YRj9p>0y?RTc+zG$NqjJQMs(Y zwTFMP?8VyRzV$Cga(Q(L6W>ys(lCwSu~eCFf_j%(Y55WfV)9*nm}~(46W>GF+;02k zWvU%?@W_*7IMee_4Tvl@RfKxx3nFT}g(d^0#}NwYqBv#2Y`u)( zZiFnu)0D9i(gSo^soUcki!ZT~)>usj+0owPhqMvWQm>dC5u;B}o2$R`4ZUMZV|^%c zIt0#QWAwee&oFoW1bZ9Uh0Yti`KlotrD(NYRMxL9Da`4>p>%fUPW$mYi=0vEZVuZ} zj_i=VKx|0PLiK_yv5EH@|7p+lKvSz*+(>G$IOKq$iN^QAMSSuB0d;UvkiC=uaUS>H zvXWcFQ}m-AfNbr=Ll)Q??btGOeI9}2&aeuob*J;sz53&vP!6EZj>kZRWSxP+$u&jc zx`8NU)YjprN?k*1PQ%(8BsPLtIL`G&1jV+NdL3JBkG!int}i)modWTb@ge@1X&1=v zIwqF~StN-t&7v54PJK`))@4MJ=rO?@4mgj5Q!-z?*tN^?3_>d>`G>cB8b-R^H^stZ z_TTgQ+G}E>Er1AGXu>N&`hkj2e*>@EvKkVXf$?+{Ps%xOL{g{)uAF#(TYLPKr4W}B z4H3}YN2ysjHAo%4l0;UfC?!Nu`Lh$ZXJc|KdFc_5h2_ne33!OwTPhMcEW?II@n zlVW{mZbCYcfFGQ#iNWhF`=9HI^QicwFCo^(zdJHN4}^+CYv^s69QPwa8UiXaXrGo1 zOGF`Y@Jf3qT-}}@)!F-p&ymk7_#THo5r`Y1<8zjt>v*1_Ez8dW)t@|Sz$9FjuqbN? z@xtjHfQq!XDIe$sw7PvdxO3B?_YV)4iy1oQhF*8BI?3x5$vej4mUgug)Fv}~M}9Q7A3_gf9nq`%{nHO++0DVo1DE6|L1<&;rC1|X z^u)7EQ_tz+^_B$K`Q)(q6MoT}5m7EM)DWO-X4qTOck;{xnQHIQI}NqVFB`|V*90j$ zVg$;a=~6I~I-ZQ=Nx$291PfUNNerH+7Z(&^?qDlmq#x}K}6DK@q|n)I_OW~cQ# z1%=2I%$80#!}D-{8@gv$m33>03Qu0+wqEuvEpyM&>5gzFz=?@pErnN4qQJN!2f&S$ z4Qs()d|6Hli)tw}uJ}-UN@1IjLY@b{>3sd9NqZM+h)$?l4Dv4>8PY$9s?w-&Nq7Fj zN0k_4EV^`o)mWxt_X) zOlB^_Ml*}PKQ_*IbNUyp56y_qNrM zjl_UV@3JO*t~5@F(S<%~(1hnkCgoRZr&ON9t2elP4h7g=dvzXjIM$x`+>6?v*`-5} z+Zx%_o=$=H`lvK)z950@n{$gHc}ol)IX(<}N=wNuW8+$Gp6@A`=^P{36s6(k4Ej*k z>e47~iZFU}th0ZCV)d!!X|-b}wD z(<2y4y0`mdb-p>^TmLkIm_xCio6~OEi4HbBA@l75D2^@I_3C5WTwaYFpWjr zD5~<(VM+JA_$92)CbPZiE$t)U6%y<1KK}WykblTtMgTEI>Sx2jwHnuhMLCQcvmGX% zN+SvQV&*LAY`cz{q%69bluK;=kKUVMW#*pns_AozmRh0XG9)sjzu~o#u=8-9&8w}Q5_6>?r}s(GS0$hD-Zp5;Qx?*01@dANXr%5;NG{;|7S;&|8zKU8Kb`O zPfUMZ18)QSMsT1&eKBE+M1R+y%=OhMoYVYj=$)W<4Di`9tqE-**?mPOCO=xWBHRkVW z8-{Da!G2(w{bPmiO10C%cZ??YC8Ivnt6H-TOmtMC*L!-|i!uIYpkK0#zYbc)AQY=^ zqN+NTeMaaOt&==&sTqZo=R1Ev`p_LYe9P^NZXNSh(U{b8EzGeyDsnag#*EzI0EiU;?NSR*6ufrz z4W8d2@=KkU2{|N=Ufd(DW^KWw-h?s*c3yLIqrbz!G20fJg|Px6@q;FHoS&PTXr8{Le@?`=zUmPUCsf zgOE_gT)JOq$^V~jB~Ym=ZT>^n1Dv;M!+Qfv-q{!KS+bq|U29p`^;wnn?6v^Z-uR^) z8qJ^TnwI~(Zp}y}aLv6}Qo}!7%h&k*#-n#2P2r+*?M9Vk6C>wibjT_u+Yhais)S3n zj8cjYQURHWu3NkTwbu?F{A1`$wKwPwQ(w1d;u^GSJHe+!p)RQPKh@&Mjn}t2fjCF^6T;=N3ZW z`V_J^TvpKi8Ql;&HX@=vBN0I4YybGlhMRXdgsHe zCrV0Cu+~kSiFJ(b5xif%wXO^&ueY;P(bi`D-H}eOs`uIK$nr3tpLEur{FEJA_bySd zSipeJL-VIu+nAu;I4Q11yNr^Wii@=Vqk!X>2kOfo>2(V&yAZg^@ zQh*snNI*n&obuVwb1~zhqUgchN1JrI`VT#$V3qL|MyVh7YU(ExGObox*)E-j7lh40 zg~D0JUK^$6ueJeR8Y7Nrg%xAYo`5gn0`BmWOZ z%thVyJ?3_YCZyGQk$GduW}N`hUVLDy3d5T}ICKe8xGJ)hDU2rL-QR9J+wo<%M@T{W zK`djpm+tmK`kfEWoe#{P93&ZkRAQs`U=s)I@GfUwY(`eTaQf1y^?UJ7@i6#;%VoP2RzF)jVX$a{5VcAe!KqPvlhDMRhmMyHA*iWD2@%Rn7bPs@5BD za!x`hJ0OmWtZ1*<4`vgc%X66oGVkJF&ND(5y~$;DncQ^tw{~-^reA9F;OPl~H$ON) zNnV}*(K~D;)S@;m`2?4aW?}PBn1bclNEFyQlqNM{KBt{%sg0iz;c2aB zLhsM`epP2*btyuIQJW^a%B;Xck$)|$=1rijAcaX63B~7 z0^el97Hqd7y<5L8tTB^5huY9VZdis(p7^!hQMB^zdc&}oqIds+<&-l4EW(?MayWG- zc#Uarwlr;uPub=Ci3X&%%e8_NMk?8(!KDNsVysNyoPt=mb?UA-P+)87TSg$%56z1> zBmW@{XVoS$BP|OW2);s^%BlB-5z*US-`Oco;;;CtW=d%+!6OCp`_{+z|JTG2%&&t{ zAebEKyZxa~=*KYeU0N3}fc0`O1Xfs7s=PWU%t|(g5P}SQETM@y*?<@LC|Esv1GR=9 zE)J+mo*8j1Js4Jj{o`7Or<-Z_qBpOG8rBp9H~xVSI|S}U14N?k)xY3;`31xkQF4%t zbu-4}H-|TuXLK3fulsZFCI~wV)GWt-CKD*uWfSaR_1=m>P$4AeIBvgEubRR2=EB%1 zKM7E#9yreUmel1Nx`?F6}R)d5`ph&p`Wbijh)fgj_;z((&70jsS|DluiDQ5RQR@Kzq0iK95_?Ki&Bk zy)O|iO=!Nz1U-E>IW{bjDbVxJ>fBhSTtIBt5`$8)S zkmx+oIrJ1xlp9JF#J0ojsYKjcxH2!F)Z7VCf5q`hOR|H4)rkO-@W@YvU;UvMeVQF6 z0JWB|J&|z9lO<=kKu0>kKxg$Eo=|E0yJ(; z>H7St{(tOZhyNtylQ_V_K_jyMF<1vo{ps7?>6e~!K}n>^3~I`sLN>q0srUSLmF&M1 zdeKC{4@8B%mNkeUaMoQ94(lE?V4&S3l#3>@KBMMNw2o?}OSG(lK_cb~ouOQQwxTtB zWz8f^%PEgo=?;amPt(o>D(gzA=g1}0eoqm@mCBo~>IkOJqXb|{CP^(X$kc4^dM5Nxl{^)q7D zFkA2v<19La1%f+>FL~%Y4XxUqJMIww(b*XYG-5lLVE>HH_w@6IG&@Gl@F%seJI>zP zGTx~yH^tXZVr&b-R}@PEk4=WFK8W5Ethc}61zh(DTN-}a3+p5e>)UQ07 z?KQi^Ek6thLPu0l3X?DoWFJil^8 zr=G)g9j@V)g&YeaywpC;skL2x+*Y*SLogeM9I0&rp!_ z292qj&#%kOn&CeOhCNyxS$+zn13Cm^d1F}com5S48~Ve4lw<#yXw_DK1InV*mw7$C zM$Z4_D$s zfK_b|(_zDNXmxH-3HpspG-b|bn9|(m%8Z~KL_!_{>cfQK^{uUrB{LOym9+hLL|vL6 z*l5vRu14#^r&hJytJe4LBdDX{Lj7rzi=2^m*b#KB*gs|4f4(0fl3i_jVid^9Osk|O zceqUEVu}eo=6jB!X|Imeoy&Rw7-G~)<-F7^aN&5<6J8TTbR1_UY{8^aOoLO@EC{(5 zV##CEX4KD3_p3ld(?!8{Omi2fmc&KNi7GIyCdW%;C}?3=fXo8p@SHy6l$W4X{h1mP z!&dHt?=hPx5a8H*b;D)GS$9{Ivh?t9{wPoGeH)j!IhocJx29`(Iwz z=RW^QKhh7)oUkm%|8D+YX@uVkuJ0=OTc*gBU-Y=RQQP9=e0cs$Z#+>) z6S57nF%g*)wPCjVsaO49HPU<>)lhvJDJK|(vG%NtI8ABP@s(Cj-@vi9&B7TF7D&0x zEa5z{(&RugPT)?TpMPE6CORt6lIWV^kx`13(edfp{ucahQJr0K=IZ&u*m-;k+tf~%@YT*`U4!S; zqEoBuqDvZ*Y9Rj)OH45R9x`J8X1)yU#z3&tzlr%GoxH>w)9`)|Fmvszzy>6Awh7vq z#i49`3EZsW@zjc|+PU!Y{9*|EK$MvnAa~9>K3vAA64Z-yuG{UWi9da|{ZH&hi|R*^ zOvUERKNu#vm-JCb*SJyRhfeJ=xp(bEzo7S7U#=lP2+^}S`6A5}>wGc>e?a-3gWuR1 z{9HvoF~ithB>>3l<8my(EgB_r3@q=$o42PjVD(EZvjkU<{?#_^@MeJ6TxK>Ml1BRc z_YRuI8-6KVYxc&B``2KKLyz&M(o?ycSkNniK;rmD78R=? zt~cX01M5F%V0ggd8a)AU&+|tO^J6%b?Ir85Uj>B-KtUeuu*CPPkNwFUvgXW1`v85m zDtmQOKXt25VANw`soJN!I>_jJPhBS(%+HFE!>|dCbW|NDq--?w=t-V@s)r<)TIcG_ zdFftyAqly?f{&+b1aqcv87nI})Gub%*rtcxr_Kvs?v6JbhAAYejLurf{qR4}+CbvH zbn5|dV#wv^ijAM;x^v`u2?HPFE;vwdjm%2q`}D$`J^H8uWV=Z6?qGUqKCa0gju+;_H>Zhbu0q1)H1!f-6CG@M0HrBUldItG^lD-Hmi~wixYhgGklY?G?NUA*1`932F8f|?Oa2C#+<<%Zt zEMA0gcyph%sfF}v(l#>#b}P&^;g5L;t626dO{-0rg~0vJ*~*f=(10??V!IA7*MerL zCYpIB(ljQKFyNiQ#|js$N66JN@SZY8(zsMs+m3(2#<^*ebRKdxurH5aPaFF z-u;rR%Oe#Eoy@MP9dY6y`RIU;5CtbR-#OHW@jE>ms9j-nc$qJ`;1Aq5A^*65CMr9Z zs_IY$wZ4*udwbMlbO>tf*#!)$Wu}j_CtM3YE}Fz?gPcIWS~T4!ye}o3<6V3cZl)Z_ z)5wTgGYJTrc!qOg`4M6ed-Cr(9kgGZmI_qS*rJ1Bc>(7Mv$BO`=G6}A^eks>&s{oT zF_bHco;^X9Hsn94gPl_5*EEUanj{g0BK^mjaAj6T*gC)D+jJN@J5hx$)RU@A&EU$css&hR^3&yc=88}d)Z`f#^;pAYL?y}Kg_ zoT#Y3Ab52qRf}PKD=c4d*F9&W$75AqZ7)Gj~XFve60_p*T2Vo#JTlF zoRQATy!HpiGk`_3vu%bq$mt8+p@B<`@XRkSmw_zl4P#bl>?nx~PWS-|->{1bY%2Sq z&iaGEX-YoWDiHRTwl2CK5WX=QkTpngzIBCftQC}y?krKmb5X_2j#S= znf(wXoUAkOTg977%?mra-JQm_xV@AE&k$q!KEOMNW@aelYOj}A*0R+%;CR9Gl_^K? zuyC(H9JG`6)fb;NT@((tuR61PiB~}^Uh`XLug=YI>0s>UO7h5|xx&VflA#WQgy9AC zwb;&!#GZvnvZ1zRkLIte@o@@1gugD)AYiGXy$!JAy?x z3ssSpzL=ztTpKa)o+5DS^VO+7N;@-?9^~^uvHO96_^*S|l5CUV@=bZR(>FatGT)Gc zx=YNE!_ToY7go#yho5q5+jnc=F!g$;8cgEspA-=-fxTb3Pbp~3{*$1`NB~0Nq#v@~ zX$9QPm9s9iXI?f+0(_+0yl-|}{$+GvFO8K|8HMY)pDP~|6iz;Pf(8;C8IhoC$U|2j z9)`&|=hl8x-AK@s{t&*0kBRpA?!B&JmU`l_TOAkuLcIH1Gwm<;aRaV>A#T=#EYjRX zZA8*f-RX!3LN?29Id_s^|8fL<*HzXPJo{Y{an_GK#{T=y2s)C%b~>E|F?B5McP~bh zdnLl0xArQl8u+=c(^iKzeJ2eQpT9h+s{5x-R9d=5%KViNMw`*CWyG`JD~JO39$Uzz zI4_7O*{9(HsHM0)S6(=>y_4Rda)Qg>SK;KMtqWC1`K$r>EYi+)=cT8|C4PW?PkUWa zvp|RwK02m(>glGba!*z7t4rIa?X?_DJ`7=wrHzBUsZvUKxR2vELsTCw@tK|Uyex*4 zHaRb0<30K%Wz~se2?+LO>RRPri}2-;P_yJ2J3MEaLu_zacNF@BpyUvnI$KTOgCY|< zHG|+se*jyE$jRbGkf4uw)z#%0#g99CbNEJa&uW5r)=kgESLcY2oor38TCO`w>|c3# z*JIun|J}r!AZE?{6QCYWOe-MYWIaRa6DKo;B*>xGF+7q@dhj7vLbBL4QzWYCpGavZ zhwZ`+=eMcnm=PR${Qq%v)=^Qs@xP~$5L8-XQIzhEWkC@TDN$KKx}>CQfrTLilDCj%jhqmWRYkR7XIx))m9%h1DN^?C^=wNW9ENd%IGiUYLqAz7zIxA*6c55JmbQPeL~tJ0oPdw@UQzi5^{m z(Q?~L1jO%)%n3eDa4M30*#KjsT^Y60j7L|zHkU#Znpr$_89G<- z4LhcZ08dB)1iDB=;>WQKUW@sNqUTyFMT@YZIn!O)k%uQa^wKp4??bo3deTY#%9=RO z$;mwKmZ_SmgO1hZ-h8D$HLNyyD&EGp+eQ?>Po-n`3N+tF+(l{Kw2MHV@>AoCrNXI73(7zIKjlC>45A>z&M?H{t+jzpcCXOr&8``6g1HLF`@dkMi&yR^*d{ zTL^KpQuI2y7kt4A^7WVj65TAC#MFOiVCURqiX2MK$c|iTIsf- z5!VoQVz2)t;L!HIsoV4D_vt+uz!UcQ@&IviU+ic?r-)yaREC4MqC-XIt0w^}!{(f8 zws00hFyX18<{Fv4{(&#m@ha9g*L+}^EG^-@HDbdReQygnLl+@DEytk8(XQUbmK<&# zodT)D(M!I(6<1x7d-e+9)w~0j_u^e59bONo=i~V}2ywbn+sge7tIaU^*gk+~jgiaSGF?e53SUz52`}s0O$=@*6zVrCL+DAN!+4+WA z=%QF^0p0XAJNL#W-Dqn|UgGsCN6Ww{MSV+rw`MC?_or9G*_)LblYxdmH0L5dK%Z%{W)+YCWudRP#Jr$-fjxw77)boJ5r%rmg3%qv z-B4LUnl2Mu^3V(Z|7jT^x3;$PZQElf*=T&ZdmRkK?9nu+-z# z-KZrMN=~O{2>i& z#hu3wu$d*}XZj14Q*yrtmaO^(mZh7Y&IfGkrp(~MMDI0umK3lpqK9blUklss+cscw zOWPEtaPo`>`!a$!AHVQVD`8E?FL2FQ3*UnIL;WkCb6(LXZtFIAc)Z4(dVraAyspdU zDblv-m=$H>bKf166ah<=e(x6b%uH@9m+ba?N|bbb-JKp5MYF$wcgYkoGyCOufNb@T zX!XS}?G1U5mwS}1UMug60O)5AHXvDw>g6z_`er&ud=-R_dNs@SZ7pzFnP7GpXkZN-C@9czwu& zn3@v^EsOi2_=`D;ot&X=ma=rsK(Q^(@7nuym1N5Uezm0%>>Z)f9*z0}7gl+nKGNAU z*OHga%=-H%i>7elZ&g_yD*){Rs|8MMSG4_N@(-Dw0rL#}y|^^y3~|~3h5!d2uH0Pk z8k+)3V@wG79Y@+(kmDXc=%i=fV?X8CUxbZi4hFFqK3sjVrPZEZamE|#2P`x?xBMz&1p}>@);}oL0&CVng zF>&~0(!%vWZiMHPlGp=$$RB`Cv{C<`M_LX0T2IP|FAfOsHURov}O2}K=* z{rhf|px%(#TGK&maQ3sJMw%rp1L?$_3f#Lxr6i!+cU?`Me!N5YXp4$w;Z~g8`^~2kZal^{t1?dqlf_eLUy#B2HH|S^Oz9v_v4JjD zQh>+q-s5oCo2T8xrZ+?frEC7>s?6?z?cv`A)CRsC;>5)(N~KsKO_HWEpec1$~DGrvZ5-Jq?GiPE#IpK3$aYJH$Vx@C(w=q}}8; z+YWI&-jYatSF6-SC7Sj7ZwSBf_nj?8l*oUopQ|THKT6}gN`z;@vdRNf1=e|hQ4%8bly`~lSTt>_zdO0NIkuaXfnUQo1A09qAq)DSW5prNsC&8b!*ZWa!8CHqqkA%CIzU~R7? zftt?lC&sWe4gVNa-}nTrgj5X_;q*p-sBmWD8X#Y5&m%ck?q0Soku)4-$sahI`He#&tP+O`qJ0hfrI)dUJDwt=7}##P^5eb;3O6^!QC!!0gWbsc2R2%PId{NEuJks^ zw$u%gl(Dr~f6WXg6LwdwhlR_ZlN=9+BorRR93Bh>7AHpw$atTPxP+qsla_CR;WM^< z#6_1rnBMF5Hk=l6S9PcE8Y7&lCmwDo2Y3&O{gy>$lnT+t=c^&%!+2+_;u`2zGYAJV z0NNSp!b|>jx5dY7tK^it5usu~19cMbAEfOyN4Jv~glBxmfDrn!mX&twwu6IDRX>n8 ze-obNA`DMNbnFqi!2*C08yTz?`qe+u;$}ZwXzZ`1oK$TetehgBl%}u~vrSEVEW^gS z1Hg;(s(kcZ<1)!dS}p{e2n(f$^3$I&3*rCGMR{#X4=G5yhEaXt#9aAX2c8Lm8f!05 z-pp{4x{cvE_%;?9f3>WFbXb|PTs~I|-{8kGUV3m*4V%Ti!98kjw_F)1?ZCPob=at_}!tXOtb{Z?qoK34< zZ4X6U(2Gw`#)ARHjyD7qk80V;WvF_uAf=c3QshVcRqxcuA@6L(Bf4^-nXT5hZ+9t! z05rwS(7D0_SaC)fy-x?zjQae@HMcnGC$LSj&9~D=JgjodEzn5a>{W^trcV`HGT)>o zRn@SmPZiduW#|%-+W)vj8=f@kku(u7%zvwQTzQCQpyjel3`F;?O!pqYsjtr4PMf@3 zWHaxpFxczEJtUqD;gi_+(t{3%GDO{n}@U;?m4nQ$i6vNEtm{K*?YTNpVLqtyw zNOl-tsI=&yl`_Tyv(b8U`)aY~p3=i?4_P(rSKR6qvAM!Rs2lHf?dm=U z14>d#Q?*`08?HtnxAlPSg;*P88{$FL4aWbUAPmATrv@}5R0<~wE0|lg)EZ|$<{Iq z=e9hxcx_v!%RAn#|Id!NHghx(#Bo2YObeCw+Se|Mryc(SO4f&er2?iEFRjux51{pCH|j&80SNdSXwXrS$0X&rfOe2YY;ng=STq5 z;Aiz&CYR6%5fggR15lsO^nk(5&HiLZ__}U1-oz&zzVB4pJ2r>fnq*ScqUxzgag`L; zb{9QuRoc|a(+bm>gZj9pg0(hmJNaYXL!0FNT@U|lEmNDpb$TrgWEgJIJkmE6i6!5c zrA-DEsb(_0m>AKh7`Mfp|B0${o(F)+5=tkpg^BB@2XjJV5!&B`sCAC)c1rcb^@ne* zuP0&`oD-c3hV)5&J!XwdZOZ?qF8ocdd0m|FYlizq<%@-=2_=oNg}r_ea`Z}Yez`H=L_wNXcG zCH~h9zYusP`GRHp_vNqPf^&PlAGRxtkJmpsjhCaN|GVeIC?~q`GvC9Cpc1p9iQuq& zWb8|?24soI&Z zojhbYvi$H@FL|S79}KA@FK~F}NY-?~158M=QMIbeNx)~781--RJ;&8Hd&yG?t1QsL z+(_vD$`XQmlCOrZx#a4q(y^&x?;jp4h6B!3+^S(8TNP^Chd5OD1i;m=f&-UxgE(f@ zi|2E*3Py62@X?@%3={Q97K>jj)S@PAPF`ax)l@o=vbs}QmjVO9MTODm@ z5XaTJU3?|4qlH4A1ExpLE4?uq?XlEJT`6YTt7d`p;HrL6yf)AstS_g>THET;&1vR> z3mP)0IFEaZ766NoXh>G=f0jNP8MxbTgFz#j+6%j+b`p~27%+J- z8o#7I{oq|1H)--cyHTKtplGH|)8Qcjlg|^!TpIToK$!Iyjn@=sp;)SFJSlQ(2(Y_} zuvp`{{QNV&AvJvl8E3K0NvAbHE~TJ4+>haWA@~y$%vB=bfa0)!amVufb8QUAZxn@w zAezG1w;!^URB!$azxXpImsCAfD!aC|#ppMpG5nJ7GLbp(p-kzXgp(>rrm6v7P0aN# z#oQhz07kPk$Wla4C?2j@qg@K5$8fyqXl;Y(^E|kEJWR~< z)6H~MuF=pD^>c97_9uB-eJA#Jq@SiUW$S@Iq&kp~9eh~%#B^L^9!sa3weKjY`Bw7| zs@9OTv7tZ9idzMI3b^>{xT7pXsaDq}Zb4+GExL+`Z2j?yv1c;b;@!yq(dvdm! z=U+zug5lGUT(Wa9u{6ab7I7Kd$C`cP7@TNT2yqkfZ z-dA5&)t|vX7p~^d{;hS5xK+(o;f*Q!)V!(2OLk(Qj;erH9DI z^Mg%g%i(*wjs$$te(0SXAme`)@E{BS(^DOP4R~e2ase8lne%t=p_9gop{`5X13h)! zmsYF9zq2;{3)YBg7_rqSzU{W!qcp+XbiJ30Gz`t!_U9>bw1frYe#*5Hxg9^Pj(@u|ZH@2&^$vgpq&~&}tJq zeQ#>mL@NvTaLEW-;JuS7`Gf=h*tC=0%?=vDQ`iK`XN)Rcn7m^r#MBcC-vUY|2UQk08wg7 z@ZH{*u|U|#J<3rmgU@ET?=9qP*0JtBsKthln1r!Xr*J>GMTd5yZZ`OBJO4fo1VvJ< z=)so!=l&(x&U@Z$>+hopknwAjJ3TCE$({kO-0l8dvQ4O|iEMKkGw#bT*#e&nK$S=5 zE8(j9A&oE-9dNzlaSlvH8lEb{-ux zp8GM`ev(Pmz*<#NNnittcdgqw_oWVooi^uy5>hoh!~eMiCsQeb>dHr7&i0~i^YFO@ zzVyGX5rz)`<`ViframO$@W|y)=@B}#&BBunIqDaPJ~L4TnG1*+y-lokW1*yoO2uB+)bb)AAv3+ks7T)DN%pDb-mVDDM@tX_aPBoi?U-an@oTmE^V~<^=p4GEB zlcp~7q;?0Z)c)1v+1J?IouOb9ae8`jITGJEM(=uUKQ~9&pdGeuZ4925?3}xo$;WC! z_{!?gt1XM}^5J9i^1hi+D~D```0ml*nYS!aiH-weELWY>M#>PMz_pGe{L1j^Vf-A{+ zvbIB*OZzF`l`lArDra3MUNF3CB9%>8;?;EDU$`A`y?oC|Lq*7b)aAWzTgyhb^2%zM zBB=Ckb{!IbVHCA_Hfuac+$9XCfudbXh<{(36ST3f7?tgc%)?e7Aw_T=_u;b5FG;5x z#2v$dA9jro&NAAsMAwG`UvKj?9DktH0=;AJ3(#&P#f@8f-+jZDn;f+?4%IJ`2Us`y zL1faMT_!_K=wxIM8nBdQr=*v-e@}t_<*$)WD)T#BfoaC;BPd!11aOQf5xu1J6dImS z*ttBIF%iFHxL(9RnaNd3&e=A8nP93SxjP17?pc+m26<9{p}9l*bR|Fs2cp;R@L7x@ zNKUOYLyGx`;jUG2IFK*?(D22vp%ZiCy=;1e_BCe%eN}H4CyVQLM$%knESTt)lsDU8 zJ&hx*G; z_K6h>PQUpe17FQ`wZ~boq`@6f;>=a>_+Nh+nTOCm8FAM)fn~>@cS_7!!Xbh4=#W(( zSJjSj)PTdJj;C@H8bV;U(D8;}v5CQbBg0eaH`+W~+5sf4gB19VEU>@Jw!IZTbsL0u zQX8|4!sMATXqwp1Uld=yM7$8#MN<`Dqeg=p!T%DB`EQR$Rrk{lzOlTpZ9V8K>sU!x zbVm^fEv$+mx&%~!0-`(b#voku>9yPN#}*jSe2@RW#KmVBz5w;3lM|4sEu*tY&jzD7=efX{H(a~|giduyFo zo9{>NJ;06TjU}D0A=2bLNbONj&Yb1@tF2{^>L2Kp?@vF-2N&YyTpl%y^M#>(`dos#jhN z+2XeRJK}SbZb<4_FQo$-Ygx! zsGqU1+@mXd4?KNU4NY?8qvgM%N$vxvnP5ByYQ2#A;K+*g`eBe5E#5(rD;^k~&jXGB z5NO?JcfSkL7b5k#;T#{~a zw+qW{+^fI!s9N7p>9=FAa1z%Z+YxOGT#uL7dTb-hN_rsgNf#x@n(EKi_3gZRYY`Fh z=YZRs(X*cyt0D~OKuBPWzC&gMIKd=^B|rVVVdHslwnlRCN~kvHG1HJ->KTo|mw%eF zs>5$cN2QJ#QY{2%RvOxv=8cRWHet?Z4p&RdP*-fyukF4GM0wx7VcAdA#n3wlejRUa z%lSpV3k(hAvNL`ZQSj9Er2pG}ia6yvHt_MOrqJ7m7=|FjM?|UGb71UpJU*QmNKUVT zA+_BgHkld?6*2wdjSU(CBsj(IfC_%jZt6PdG3)ro*jn+^=U6_1>34!Zrk-XK2N(C2 zqYrt2l0~`EWqIP4{g7~P`c_T^QBwsad-yTbC+10f{D%TKtc~$cN+ndOIY!_T6PTqK z`2H{0i03*+IH&9T15&x#GiC7*W~95c=j9B7UQcZYarV{z!*A<_#EP$h&ADNg9AI-;iw7lJE%NatG6rPJbNASHgt0}I4FR}5Wd7gKe&bdL?k zSx0#Ow?-<<8%RsA&eNd z+93IkV9Q|m_&Q>W^V^1&@l^ozmGnG6oY0k7$%_KSUR+eQ%&y8IV*Wa%$8I4y-uBzcA;F0bJc6!}nTLiKSBO4ctb^oGgo}rrV#Q z`SSwyiLf4Srk`*<&l906dv8*8jmpIOXxn+BR2n=go*Y*cwo+V&t93qPlmU(%9lld; zKfjXa&IyN!c^~OH`IdW)gk2v;GTl~GL@o>hdq>lhW>sTi44*0tlLj$t;-DKTr3l=JA19iGXO( z3ZBYt#-oB1W_q$*>>eFtJtnhLpt1F?+OanhJfN1HAxkjz4u|}6(E!_X=Ofq@){3D4 z9cD4iz+>n|89JtxJ^Y$2?)6emzVIQP=V8JRnNw)CIX4rb@>Zc=BTN&i2o0JcIWQhq zPZM=_HK&iU|L7S+brSfXQgYRR2LK}ij{}Q{7A;o*%hQZqy%k!Sp4P%@HWr8)V0yo5&{(^%L$q%pBXyP|to#sRcl7uO| zk-W^8uCYYNuUQb0$`~P@o;>t6a&5O)y9-64#vOvF1MK#TnAK2RUvwD>z+LTl;U~px zzc1ZrS#r8r6{WrVWfr@vxCkK1dgLk4%6ry@e>wXt0FU1gONfBqtD%jQZsOl=8E)6P z1FyE{`O%-iq9`|bWL6wctU(lf>tm|;Oqr1;pAof`v}Y%#LBa&|D>C&r`z!j(Lg_26 zIPXKm9scRyp<$WiOT;BL;6%Jk3OZi0L63iVJJ*sv4BD71Avq8*p$@#&^ob884vrpl zDYoa7NR-o}oWFxw(yi2Z0gt+>HCRXmFIcm> zv8qmHGYKGnpqw8#yDK93D({Jp$){1K*SujHCg}}1lMO385KAehG|b}JBlJdbEW8un zZCEcL*~*c0J;nR{$qmg-2bIv%tk*`b-ft4Jem9cA#cjbljrz^V zcp8B9r1T9_snI8L0C>%*_UJj5+N<`b6fb@@JyqmnWj(k)6F9q>cimsAIpcByV-HGt zxS0L-^W`l0tnkwOW{v)z(=bVyzffKC-ikIOwcb)V@4LmH+&-649^_}fL|#a!!M<%v zJMLd;y(Stz|5u-4?qmJxMBWS|A-gG-uR9)aPH1&TssTRn2pusV%x?r1uLam8x#UF1 zsEY-eo;)QcNgdilHV1kHFoOfDcD~#F4oNw6rxP6Sdq>JJ^rbg@l!`;GljqEwyEB?1 zGD7GCm%C|a6_U95G=l1&ZQ z2kG22vMMMnNozNT0-YHrs8kQ@BIM?7bI|MaCBnvIr?9DIlp9=2?lvm6M&SK=a9r~# z(PbnC@5N<@eO8)F78;UEziVF7Xf2pHYIrux2b_#)?C}-A-L`04o%(522qUr<`+uKJ?I&EmH^MH+`!Ppg`CuT8>zw8saM-XzAf zi8G5o`0KUY2b%BGR@aQKmGPpqD!4&*UUqL5ItX50Lb@J!?AUElsT9p&hTH5o(a$kh zo8U7Z$1OM9^raKd6z*XwE(z4nJkgm}o<-N9`~I9<`>PaZR839&?Nv<~>Q;vU-PDRa z0R>+lSbYGTHwL%*A_8wA6^^@ol!_%Jdq#q*S=jDcwV)BusRgWLKnODczUDQRcH5|$ zOWFoL^G*&h%_|>sE)@@6Bef_Zwl!UoaaWwn!VM5F{X}nCzQq++MZRmO|7BQ{LNCtJ z*z}|erG_<$L!iUlT+5%3PcQ-aR-6h?g5BK8ne~{}^(l2s+2qZ?`@v`4Ppteh#G}pT zoQw(lbv5)rW$$BL0g6Gs@hVejF)tUht9OV=G5nn*Vy4!5RQn}#Zp~>38+Ca(;`{vW zvMXr5PFYL+^qP1Sik!bf{pQ*q>aYB>Y>Vy+d6`%17jj-mdaZ`4t}y}?A0}2v?E}ta z4KC8u^A=Xlu3t*k6C(+@>rLn>~nJf`Yp2+%*)p_J`_23X`rX#wTM%IGReBQf_gZ203&*Qmiu) zu634JcEz{#=Ix$Exwr#*Iak+>g->G|+68CZwG8*0Jl1ZG#NfYpwp5vcG z@mlauxBHLbjA@QN{m$E24e-28y{bPOoyYlkrvVU6f4-5BGoyY~OcG1obbt_d=Hanf zb#U9%p*i6hq%Hz_5(*Vkgm%x=rzd`*V9I%}&f6P5L&krOZLWE`ZJ$+i9^aoc0RBYt zk-jICBV<5$r$b*UOfuAGmZ+qsu z7%MsE05G|(+c6kquakl(exS303C;BcJ#EPLq;r~(=cZb*fJzBa!VXH`f-ZHG?~FX>5i*^Ay7bl6+ck|DF+;~!np*)*A(7<;kjvq4VfQXo z$kp`VgqBO#x*fS6lZ?Y{>b@|acgD)kD;*h$Nd^|TFvdeJHoQ-6UcEAAP|4kbm01BZ z9J~PMsD;rDq$X#Id$G*Vy~^F-t;YGi1mIzpCC;SKuEKq}pyY@w=dg$~;?(0hrsnjb zMcFGnko%xzG&wDfk5JFtKg=uJwpf~8|GVq2G)Tb0m`}8L?4*mpToW1`Qcyk~;EayU z7M`x14OIzngx;2RF=%(?vAPz1=P4gW#@DaDqJiYZu z9`h4W!k5|wwmzoiXXPw1t3Lfr`<`dbEX55mAn(R-`KT#^+>$O@m=$M zYy6@dS75?CwY`$fb4jlul)Dv@$Z^7Y6k*vo!# zP%V#2fxG0`e=C=HZua%FaXAJk zvCCJXxVx$|gP!May^4FINmMp2F}4c%-ldH7HE_IbEXWdm%`+)hD3*AFN+j|KWz zR`eqnw9NeLUR!zkHu~p{9|c~BSd(;-^bs;I*~#UmoUZlU-85BM;v@7r#RjHhUz=lAi(meIwv zyBFZ-kGCEfp3t#hp$)uJ5)yU1u4yPqlnWYyUE~Sh1V~&>+o{#-m;V|+9>C|awioTC zBPnW(U9$&C*f_KvvW#)ZT!S521JhF21qa1|^<;6*xR4=_b%_P7b^n^ClOkK)>VbET zq9wXyukyS!l^vg~rvbOC`gbS#ELGK}5*VzU==m4BZ z@P5r9#2G~e98#H{hyG~uzQ^A<^plvb!4C`XOg^`~jb@^mN?8>=I7RnAi(H7QZ-J0R zjHDf~%_yk^*6Nnx$-vgtCcVQ8DSYm%94Wi2 zHiMpxh1=bQcO>VOzoU-O!@;hiezduX=}Fc8**lp`fuqRM3T0AydiGM#9*ir*AOdc1>4kX8WYrsCSqfR}ye-MK^!5=Q=s<)|q^rLKx9lu#RDY zY8HWbowtEhyw3eVDx4n<-thFxA3b>!PM<)c;eCWod(=90xP3qW1Jgtd17$tv!}Sm> zU~rppemyC=1S>MlLmCJ zb)x4aMAS}`7kET$pNXE(XEodb%DP1tn_yn1cj(--fx|{dASHwat;9<;!Di7GABX6_ z_JfmNjmAudkFzJmu3XbmHD&imCYNOtt9-F!oNfWSF~{^k!hdji%*!HR*IggZ&+zvE0-V6~^T1$#td=Z}n-D*p(#R^xWsg8DK2 zb@JiMyB()bYioe$zk2`?MT}je>m9Og@JInPUWL60@4D~NsrOB-DDYmQO~ooY!IZM8 zNAM9-Q1F*=ai5o-*?TTHR_isj>3_f4gOFp)mObzH=|O@!VB=D9yXRVezD6Gc@2S8 z6{xQz>T$Mh`Cs82;1LAA69{lHM!9(XYJ9MRV~53lldkB*y@IAeNHt)oILfDGff!sZ z^&31-r}29%;~5C9Hz>U%M@A=UE6X+hR`tt@VwoDyRUvKaGI#Z8z2Tu*E+LASXFoNX ze*F{I8e!oVxrGUR*@?MbSI0ckU6>Mg_a!o8i-qy=AKs|C{YH=B$U!m8y2mcrh$)BQ+A4NL){BVta_`U; zXcuY8J)f)hU=Y_mdZtor>vt9*)nm-S#s_iKpX=U2SCiA|g(oQ)G(64^ydFa&!*F05 z_7hqjDa)_4LT>#)*9KK5xAD49Rdxq&cPOJJk;eM)O&+&Rpj?-AfK=Di_a{z(%L0xW z9b>mmvVj~1t|$pVqlU^5cfZ8^VHi7E^B($f>LrgSY`j2EXxb}qw_xW_8%criKCDY( zV4u-ke(0;K0%Ne$nQx1(%XH59Khd7V(ac;$A6;MIx(g`8z?xsUxmg(BdvY^mR%hXB z@+z{_1wE<}IIzo=n9EzuNONHb@zV`v0WT3$VrPIBxoq7OchNJ%u$!zMnQLG0zWrRo zH%7Xmisw;TiWx}f@OBqV0pvPsUl}bcwL!tMmm;+R3%=yRD~g>J8EK2#0ARA=Y`)GHc(ZoT3sAIK<-{Pv8DSzKbi^_# zeu{5_$wAjbQ@xosU*XGOVa&=n9G+C@8a?7%Mow)Re9QJx<7y@+X*KK?U2WZ%ImrnB z7nZIf21A#KKl)@lx!~?QbxA0P_#6DtEjzlo4-HZZn5Ess)`|rF)jsa=^+fGifC_Jq z0l-V#ZRwV$kdaVQ!e%FmULsh);WYdmj)@C5nKU{OXxpKJ2{$$`ZT~Vo%?}!JIq2NJ zU!FCZaN>^Ht)A*UtXs<&XP~YJ2SpDK@x4i=Uhh@oWlWA57hB07dDPAerW09DzLvVa zCG}_F#lRwMR`3v;REcipjG$+>#&Ws_D%Ktcq{Mma;??uQT^o;5tnd{QPY-vu*7W60 zd2FtzC>TE{c3NyVEp~26Hcz|vJda6+}vfwe;Q9`HfcArG{w&+<0&q{K?0we zN+VsM?u!A%tMy6)D=m+mHZd5OotiBDci%Lobw^F+dTFe8g3jF8$_n4&qY8^1NfPvP zMJV$itW&`9dbh$p2E%q~yc$0$-a`Ym;Yt_+qG$4`Gtc!}8k_O#F!qfNS-HDi2Ksy) zYq8id8FVpSEWpfF9!6##?nD7CAC7KVIz{8blbO|2`X}xjQ-l#(boIA4t1MD^i-QA% zxkdCONKKprQ>8#@RsLI-!o7y+hIK!%BU3QO2@dmkd;tCdCTHOWc>^x&ok5n=UT6-` z|BSWaB0wY!02dA}DW=J+WG*~GYN~e-u=()Pbu>HkviG|342rba^0D8wS^cqXRE^SCKv5@a^7D@Cds<)T{K@vOj9~v%3o+9!@I(u`O<-r z!IiJtrEAfGj3JBmEl5lxJXzFY(HjMl_EjIFb`zl)^Cbr5NiqzvMwPwv|~&Sd{QC_f!gweep;q>7vLh1yjyD zrbmx(zH}V{6+Fqp(|fnbSS6er4=KZa+}g)(zZ+Zriu_LZBYEfpA-t7BZ!vcR+)R|s zb`Zmf5R97n&yL25XJT;1UEQ4ihnS|`ek7@01mAY?&eBU<;5(d{n_laj)&D*^9lHZ% z6W7!nR6AbiD)DcOr%m%UnNod8cb9+xCH@~6!4&1S2kCq77gH<}Wr6z|wd0gB*22(_rEI-8LZxiJPs7i4o{m0i zA^*Ndz}*1I>gQl*tTQOXS9-21|IlsW)2=%Iz?sX)N~PDUtMgTJh!TmBIq14yNdPR3 za2)6xqM{pNd1QN8lU#@)iW{dk1hl@DW_mxTv)KEeEPnm(hIOJW)^I~CY5!-mk!I{%+KR?&BZCqD4eJI*;w9BOgT&emX_E zHqFqx&#o|NgnwN`V!re4!gS{eK00=2)TNWK#3Bl74eP(3IM`EWTBUphoInV>`qbQ< zoIVg?VXT9?bX%HTn?7FLQul2H$;+F(`U3suD^d5oGqg~0PjEu7u&NDj(gS?C+F=u} z+CYZW#q?_b6a%&Gd^Fi~abj|_P^52qYqw=SZ9l?5zkI&Cb3v8V_qq9D_aF(@LAQ$J z&0{5!7EwYhF+f6A|9XT9*tREK@77v5A>e9;)ZrRl8p-2JGVVqe$t$`Pf^SQ+n7b$9 z3|?QBAVqI~^$ZplF*b7-8^|v9M~;$7Gt3-+SC#aM>F`T|29xZMPY>^a6p{qapX-bI zQtnqzE0Zx6HcZT%lr_m8yG#c#Hg|LPqCtk5#*gTBpMDIc4kp|OE z1fQ-Ppw*E4hN+7%;ibE>U2<#90hWO$JPGG!_<}{-e}5M3Vam zLb}qC;b!saDZNUhkCF6}{Uf?u54neSUw!$GaoBz7R6_i`+rA5g!5;k|uHHNzs`!8V zw}fP?lqHNxQ3+YHk0C{6YqKRrA;j2sW{#z(EMrNslTh|$>^o)Ohla6@Y-1VgFpTX! zKA-RX_}$;%-{avijx+NmA{;?PvR4*oP8a(ku#MfQ*~Ot{n^yfe#o)u@ug=es=eZH zH*hV|T(Tjf(aK2_dU$qh8C^~T!DLU-J(0ST63PK6nb!-U zD({xLkM~1;V37cXRvu#8B$;KITKpn{yGasx)zCtRyRPduZwULPR_yNg>zDruFWjmW zk>0$G6eNjU2ruQ`j%`=j#reUGaH}PKupG5`Olgg z-dx_5B6f$D4HW}YinAT@*I5oPvyk|n``N~@4ZvNC<{!nxcrV9I=+wASwHV|3Eam@a z$_1EN>t|86Eb{duNj<>VD689Cfi%m5Z!I1E8oZ>~HMQw1u&vyy9raA-&VVkfSV2GV zhF-bY5F>?qy|<3iclJqm#9_BS%UA@*7Z2)91xEty1J?qDjHn_S%uyNaq^{By?diJ%T zh3X6WcYjsz)cx7CE|X+2gtYUpf_Y?{h(861&i9^=K2d4% z)DhTS8H4LG(ztC1r_aQek zOQnYvK1>ZQ+UCyGJHjX5P&yld+mo}~wON9;hEP9-HYm~ifzUy3Y;X93!4|2#>C85@ z(l#~@uV-28{?ghZf|ZvKiDQrAscG52?7s>6Ro;wYT-rg{WVi8_CzhOS6w&(GVjoxh zc4$P>QapSW)h|IMLZ^SlNU|N04f&>F^7ys=B&vr!GO&p~12{}FodC!ZelpXUk6wOeiv_d}nr ze0R+$o@O}*u=TLF`me@<(`60|7%p=i*C^0rel>jlo3Fx5j)S|sGIF{qK-}ad_ z75=y3eN9Q5pN@CE@LxXE<2P2y(PeP6w2+2xy@mhxnhcAch*4m&x^Jv)6@?eB1Ogi( z6^^eS3~FVQ=)L6Z1;c8$U4$BGZvU?NzV=qZMdJn#oUJD@ywmTMdGyS^;B$%bp$XQ5 z*DYeblQ?#$?06x4ekt0${EJ<~+C6qG_A$&>S>&#i znrE)IyIN7-`^FYi$X;1%;cnHnzZBUqGJhi=_E8#Lp7uP5Yw{!!LpU%J*2mwGAU~SF zI0aA*8*l`Cr)QnfzBc=GTjOzHR?Y?)Fv1-?yn*0F>^?3n06Hh%$$ z1z%79#gVD!dj@p-ZLDoZ2t;H%tm_f!BLw~r)vgY4iC<&4x{V|yi0^*iP6*4~!Ju*N zuPgT>%X{~aytf&AERqzrN^IR!C9D_8B3|{E93Z>DLPTJOt}4NNoD=5zX5eewj@1ucFV_5ft4BYe?oA90b!okqEnWp|4!M&yuqhTV ze}up)1M1E6^aKRibW9h%D6D2VaS)L=G37ziR?X`>=-P)UGD$al#%~REB1>C&=#WU2a~Au(Hg6-~&!=O-mq< z;1crrf=qKzA-d^P-e6omyBT%P{@x7aG)gbGFNgwq3NR5$(epnE!37?J27T&!deF#C zLI&-)2#LlvB#B;d$W0^d&qrw{v8z6(p|})5c_d$_G|sdK_%rl@o4EWw_0Q&z8h!T+ zhH&P6x!vyLeY$bMY(1x6%1HJYA@&#Ktbec*t2{~%IY%s^GPm7UH zW{>6Xr~WDeKLR4+FL)&DLbtU@<}(ep*3tR!g|z&dRYj5_r8L1s77xzBqXt&Mqz9+N zUB{uT{BHikd!Y3kRt2hlW9%=X>Fm~%o>R!>SK@Bk@(ZEH%u1r&IXX@*Gkg=3Ud7Qf z_mkBr-PTaol8p)30`&e~qhNo8>ul1Nm42a0H6Se6^0tgkgwq(`8y#estoC+6wJ{CW zOK}nBNg4Q9ygS;*hn_k#n`_ZRN%kK($=4HClGGQzkE#uXZ1qANOF-8fm!Rcm@x~xi zLDKi@@EUfC``^?clWFP41-&_?CQb2DwH_DO1%y7N)RNWtnD~o;7UPDcD1A%9V{wI_ zK>RrG!@b@eEYm`N2R#%qL%%Zx97l^PZdV0yOUlUOvN9Zye&dahJqZ8~zmDE*0auz9!<0{*6 zaehw*jWW{1T)8a!g_OJ0Is4T~&A_6=y?L1fB|`l^Jm4>xl0Qaj18EI+b2o*7I*{E=eHl+VrN9COlJR(T;e_wgJV5 zuVD9LR>DH}J_}Y4^u@sssfMw7;)@Lvyzu)K(!wz1e;kfnH|B#kRMEYffbeFRg!0VQ z-RG&=gP@!Hp1`i#J;7;Hzm7jKa*&PIjy@E%bV*3TQr8wfHh-b&eq5QA^K{sYxoKw9 ztg1(A{L12w@+6>LcYwP#@*K2V`D>Q60{T39B}(Bk&2_-qHoDL`!;#k!v0StFNbYc* zrJ2+8j<8pYv@!kRbGa=^!1W?xCyk0K-PUStZE7O)>gkNF&n+9aUfqmXoz?>Ut8!o< zTJGt_S(O~86T^k#EzrjB_W?I^QT;f7Tk_cNM5V|V4T**EsYPMGd9D328H~aXt?2XG zKQ&45@`4MQdFdEL#Y8!~qE$D)hMm6sdDpbSb8Z6E>V*{FuTKHzgxa8|0#6Q(C=Cs) zmn}-|M@ziTRKN||7w0#>!QRfIPrd=oW8l#xr2)dw>ply#Mg=JR`zUnl^11htZ&(Y{ z0?sM!&BlnFU`RKb&yG&`42#0`HMI8svo2PUzD=ZEh(w-{%)EwnPY7l%$NN)&OUIwM z7b-!$ML^xrcA-Ry0;)z*Q^5Vjz(IeA$_v`hJ|6#gCQmUL6nUKG`Jp2>;pRdf(2Qdh z_;#?@2h>9bA|)=Jv`vV>k6UqC?5tzbDH~ymXXB*TZD=7VfoomqlJi7nZRI0xFd=IQ zi`8E*z0yV6(*Ox0SYT6$&ac`?JP*m?y`Js zdnY;>ogL%O-9qo4SuhKe>mL+#(fl2~o-<0$O%m1ffClBiBHSG8I^YI%st)h|Lmb1rk9~>-g*N=B2;p)Ty6Tg@?iP? z0^yB|GPslIbWQ;aYvz&^UR2JSKXo#5ZKl*y>a+?whGv9hPH1vpumCo3@`bYR1qL{r z+;L^nErnlxk|-XZ;EM+WEGAD31!D0(msPD1mwcs;!MvUP==XuM=5?Uzm9kR3Trih6 zAOw^0n%qh;bk&0OG>Date4h`M^aBepOcX8ULV_+DLA+<9F6Ir0kvdqQTfvZ-X|U$U zXyDn-Nf``X<_USXb>iSJIvaXuTUPoukD(mwhjkT3`vJ2;p@k>Zx=g-Vt5se-wKMzo zju)d<71-g8T%)DT?Dl`TLqkB!SkWw^Hk{U5Go(B91RR(d;|Ky?<~?7*$=|tSYr9#b zHrxCCtm(Jcesk)*qi*$HqVS&%S24NgG3$$~nJgQflh9^|lKa2wd6JVMwxMiNZKtFU zo3H@g4ZU;y#rrqEUAOZ~5ZdhVuI|$1AN-4_Y9EnDYJX#W!8_>PF}OgQIs0ecF{u1q`z6K+sQ|?`bNO~EdHE3Ni2mCTs#$KF$s{V ziy*)jPU$F2oC6Zn;vpU*W7(iAp9yq2!&suHl8!J8I@q`7XYzGg7ePrAiijy)HHnmh zg8yI9Ly#+K>C;Hdq@5UJ=g0rT8*%sU1Snc&_rwoFtEY2$S8Q2M-8#Oh=iQ0n{qR_> zMG6t|8XuTn?bu{unkX3$IrvvqZYg7}G+~>aoP`)Rnd{-vGjX~ztRY-d~%T{WK=%PwFt;x5W&|_Rl?M$>5%I z+><9(f7`LUc^GHgV6RIl(&A!8$+8R2<&Ts%KItXNw!NgxPSTMdFQWx*bl>3vyB_aj z11lD1cD%-wIeb@&+sH%D^~CC`PV5CP!MLOajDlx}t!ozGjzBMGov`^tNgR7JZBQiG zw)N7`yVYVL*|R`V>_)t7i1M&tKV6b7%QevnxC!p!J>3Y!FHD z`iEh#24Zo6>CKL`4~HGs40TKhig&qt)QiAA9-Xnkbjwlxc^RLLkkEzM5J;Upd)2zh z6G<3K>`qcD3!>=`BD7#|fvZ->r18b>k>#t*o;j{N4|^$fVrdBz3VEBvnXe`e`kNUw zVm7x@E|#Zdw(2C9ML!_#Uk|CZ#0NfjfaN;<1wcKdAZq&j?9}$jvO1nau$>VLZsJ2n z^pLIE^3b;(bNfYB8(PhcXlDntC5+gUoIC~@tkU>2`yWk{Je|}c3g@lV1B)q4oVOO5 z$ZxLHGuHi7zR50N^}m?}6nMZ+}Bo6~w^v#q?TH*Z-V$Hv%q7Bw^y6AKdfseszemG@Ko~pO^0| z`dsPqq_hoVzCmD5`ta9d&Xo1{FPVRtTWgt`9A9?J%wNr`_0NrSYzlX*H6uOyIi@bH zT-I{I3{wM^?{vc^i?uS7=ab%Dd<*E?;M#8W?Ns<6_dR${`aXum12luUD+Hq6DhqRX zHPQ=v9&{-gU{9#*%aZRky$w9YjBnajX@xSFRxf%}AvBO=l`j)JHV`lsMwrzv^wB5XAhevBdN*+fhS?wjIBYq~wY4PI z-uM+Ts=igSak}HPKqHvCL)=1qKv3E{dG3ETIBr$(|2m=M4^w7Ut2x}g)Ft3C{yHVg zR0>%vY6bQQg%x8;9N0_SA9$|g_{V=RjFs(k)vuJlgVDfws{x89V2C#SGCJMvm1Chv zLzM8YAY`vPf{3LaG*DVHPky)1!Tv=6MsAiU*~r~E{2gjaQ*D{utV>hW zQViAv8P@yO2ty8OYM#4s|A2cOv}ZC1Wzu`dg~h25B+++;1W8nm$bIG8+-%8+Cd$DK zj67Uc^Pb~?R>~ow8lpBT*;$*KjXUq5PVU>Kb)oandZ`KrY^&?RyZ!HsBCm&fbDT;+ z*-ny<>Qn(b`GHe*Lp8Q`wF)gxvCzhiT-)l=ogz5^`*_oxYIT;O}+tnwg(ja$+dL=J&AJBTV=w2DK z&SvSiLR!jw_a$F;6@b-23^OnZ1T{LyvK1X19~Qv<<+;IWl3w74 zAzT*xGU8@M?4-xn&fSiM5r3KL>}1qS#4p$PVNXFes+`rXjjz}TG+d)IcIyp4BGdI} z64W>?-t#%8hroEslhxS7_$w>EKzm?wHvXys+!rHMu@hW#;PcMa3R89w%%p! zk`LKfVckpj$<5sz;-BUWQloz3LUEZVK$e#ZpaZ?8y=794G~)Ur_<8W*Te*2IFn_cKO8Dpz$#Fr`U=rCeEbV7 z<`i3emur=4lLp-bZ?X;y6N*|ONon+ z!}e|->C*5xXHw*Q$*MUq2V*p}F2f2U;6(_1>Eyf6QN7%~$bsket^LW_?=gSg>^p97 zKBMYpCFbmAB`%}sl(^HrN^n*+FsM=%Lvzzbc*-nd{^jmqn`$_~LS7eR6Y+UKfxgSk zu<#!=Gb=znm}MDg&R^cEmdd1B&oe|n;lW+9$+E6BwRTDJH75V(YmW&U%2Q|bpZ zW3Bx12Zy!gJN%RSuisCXX{v8Wgr@yD)2Dmh;_4lFkg;GVHFLeOz181K(slBNTrP!l ze6Zt}*u>qRZWW^8%Rh7H&RL8NHi8DiYnXeNybXu0H;~{@rG&$xf!Oa9#IwJUc|t!YFY%|D;|!bit-OFYNOEI;6u zVC}o>X7=$G)`uz7;hSq`4}N7=k>o3yv>erwqnwqO43)}GhQLuq zDOxWBocz9b1(t3DEWCU@@Q1sf$yGtsu|(*7@PlyCiFCBT3LgxHAsHlcc+7Rf{NWgS zUJHuSYLNxQ%KSCH4=EGwB`pnm^H3FU)#EqPz&Nlx=IUx_{s327`T;hx^_OdX=DFZz zVeQ5cWy7s4oVct!%VIx%UP~bIqryA3-n7PPZ0W}cm#B)_T((iGOoSSkz&ZZ-Q z-=_30Z`DkhzR;j_OE>%tn?3#oJmR63)_NF!UpU|Y-kqjMeDM5>T0&2eS6I`xL@yE& z2z0s3TG!Yr{*_xXf6`$aaL{KIM@aD)5Fo$qWI@`TFYwdw2i!9-^_u>s?Isa51?H}9 z&*UXNJ;e&;uYp3I5(Yehl}loFy@pCOViGs@4TA-b`a`rP#LxW9PkjDYMRS8g^GIC*fGSz@=hoBoe&ipTxqz?H{S$KeNh0{H35v2r z>G(2=aE@t23(}x~b!EIOC;Mw{85*|_BOE>8b97ogz$&*W&0wlq9j(#hzS$MnX(1)Gu8w_mO~NN-Bh4=9cta3|+6;F@ zW#D7L?AH2e|HBN1Ep0e4#ji;@!3{mZvze(kFK61qx350$b>TiOuxBa$?QP-8v#88s zS>3>Qm1Y)~D@Lv=t#Sq1e~>-FbsGTf0jNQi>d3ZCuhP(mDS=!Tvlkg`H!DtG*Hq?F zk|Ev@DC)YwQAqq2*Ltg#$W+ys?nyc!m`$tw>P%WoMB>@7B@oXuD7;g$_euV@$x6K(9jhm+Nh<81QRpQrhc%{z zdDQ-XOO^dH^l-;z)iSwkfpy7B(lGCFY|p>q><<#b0M}{YHYedng!1C+WaC3E0Za&q zYz0L-#Y#rnnm{5$bjwM;3M`D#4Z@fK!#*^MwP~h{>k?Zj3(VrBMjfe{A%7vGaAbjF ze{$xLL~tS)?QuDq#7EqkvClDIxBkn+vCOgNi@$=asCzLPX)txXn5olBD(>$zA31tP zX(@>vSOvQFt3x*whW6`wpDYZl&ef%fIescT>Km+s==l`Oa&@gO_a%rR>*{L@D~zfO z$7Z@a1$U6e3LkXgsYeMGsE)NQsz-?Xe#x}a&E>YTHWJqM`DC6X$+->8tt>~My4AR( zL|%p;XCX30iJ*C z-bPEP;%a0v#QK|H6~Wm^SYob}A3$@+^)G1Ay9LVx%5{gNN-aWW_y1J=3ia4sakkFH z{WyA4ds_ocIPm^8U8(PjGYe}i$~$Ygp*IzLtHswlSBk6DX~>i{SeavuJGY{GujObK zK>gZz8_TvuJu-Vt;mKxHul=+8fg4G5rXHjiq^5dMsYq{lVRl`XZNQgftl8AxXENL~ z76B^;&ILP&$NN_G5`WY?sniZWP^>FhJ_+fV4#$|g<4pv{W7+Ua{ediR#)C0nY6IwhT}4q$iQysbb8GNoCGkIfMZM1s#0<)f zP&S3S`@f`@6+?UTYF|(2H}U?hQe5SpaV_>!?!A>5Ygid{*;1eSk&C#kw9SRc9*+M| zIC88Pl-lDbKF6`33!m#XZ?JQj3a({aGkl;|Xp>~NhI_wrH=V<-nPLQ9g1OknK$2ENi~&tAg5ve zF#8hk0kc3`z{7nP=S`oXe@>qW4hD&#WiX&yuv~MezJ4{dn{MQ_LVd7Ivz-$|YXlv0 z_!o*h^0&0wz0_3ahsnkWvFm8#U9Ew~#s#6nl#9Mr^_D7Mw3cSuuL$PHR@_29swqep zO0HH{tfE{;z$Moj{^diA1d!iyB`I>GY|{5(DlN6P)9A>$SaIDtHq(JBxr{R6LIRum zJ|fq5FDXncU2*5KbNwdBn;umSt(z5*IOGu6>tJzM4dUdT#p4#oR z+)xzcYj!f>ho4uWc;s5UIJ}0^(?qzbH9@E<+-#~fV1MRmq&FH^I~N)Pfh)=*72Td2 zP^6bQHiBiooJ5tYZwL6?|Mtio09CDIzoQ|E3Zb{4?*_HMuTwrrodj3bqqPFswcbj= zyVYBVpnv#hvYjWY_Tm3Hd2otN)BqUuD!*xoYb*~L}%*)mUs16xdI#tQOV`j!vHB35BJv(uhM$o1G%9i!)b_v!4Wy@j8LK~vG z;N*z;vcJ9AiG-IY_3VX~KwJb>+AjhTu%=}Y$v6A2LsDkmRW8Ftjni1%S>xoEw4BlF-@odeb8D6)y0w z)1s^Rj;Y@DN*{D>Jg4FDjLs(|RT%O<$L+rjRm~R<@83GGtr5)q{+gdp#};P(>bc0F zzHmN@`lNj(70fAKJ8!hk{ZM1LLgvWc1Xj_7mjNppl{pqJbc@>B6yb$wO@6anYYJ2z*QM}E6^fxl zDqk*PiM|tO37>DVlpf!iV(g`duW5ZmqoL{scTP?fSu0mPOUU z^km-!|HbDVO;OzRHzu}LQN`s1g|(IS7WUL^62K~Bk?8X)(H9YjiQ0$gRUJS?Yz^1J zM}ex|v{`#_g6HdIDx$09C+6w}1|}i0*kJvXi9;~u7mIChd*H1-2lI%_ksf&FORPkn2T+qJ>a#D$+y^Stamrseg8RK_H>y3v;(>vIjoC=j?cnz=3z}-X|_zt7hkW zC!>l$-jb66ctT%>$QkiA%m}P~s|EYcbB3!_J33a_wcLN+5SnwcpdA3fqO!ZAl$-lp z-qv%@tMTIs1C!GgB1um7#`O2i1fJL%cGCVv31d1|({OUN(`@dIx#g=)Axba$Jz9CK zhiG%yW4MyqaVii7RfAZChcD|b6v*f5(8v{wn3FPd_tQBO4CqS&ilQI2j;9qjj(%oD z`^z^T&1wtF0_2vDB#vnfI3=WWhu>~#QovsGPp+kr0Kjm zfN3eVA01a~WG&i|F<=jJZxl1*zu#T-Z>#{V4rjPGaQz?#$lv(R5~eWP_#dSTNliW8 zOI5tHBU@3gQ)btlx<9_aHE|+@yPL0$TBn+_cSQU!m0-H6be|ik9EGlr<~=HdN7N+y z{?udNfX*Mbec|W7b#RiEbC<^iIW(OZUq8vN&))%Mt+ZFllbc^FZdC7HkVyiL_O2_< zn6CgTyGTS zjID4-zYOvs$g-3;8p0aRkU{;cl>G*bO3Vo53Q2Bk)a6m&vul#~Rv?VMZuPi9x-h7| z)iPb1RO?+fmf@Kz&S11%XUzgXx3@6TLL8)na zZV0d-Ozempv@$5WSES~otFkv+0&fjc>3^*>Z_n!;1z)n2-U>yPye5CvCHw)B%IJv% zFU-aUnDDCbIJGF^v+|+X>5u5xKUHVj8uEPH9#K+0h2*7_mmmNV>4I*d9k4gIu<28+ zSn*3p=f)C0WTa;5VsOh3fIL%Gl_Tir-DM&SM=%wXc5oSR$?ZPVINs2N_wai3d@H%@ zhPEf`t6uMukN5Olt+F0902IFlrCGFupE#%rO3&MTRzU4Ue0=kQZXRqLre0lFuXs$OD{7>4V&_SlbPSrMr^LIt-rm`(#= zh^7~@WtZ*ox~NoHk=Ki|2n|bWrUcTqdaGASFL5hbHe25dm|g}MwR0HW$<8tBRAd&~ z>$gx=kE))Y^2Tr5#P)nxLsFYzwt~N{FRL6PU<5fMJB%2!??Zy8z0T?o+Ju7~Y?tE;ZhpTIW^`#-(&%V9}G# z@F z*snEdCtfKm0b@Q^c-Bc!fx({CXJeV5M72Mz7sZdaB14od@%-T5H1jX$c74CiNpxt~ z!&Ml|wQ{liNKRc55n=aOyyp=poah6{T|BNq_AaXDq25@5<+NQ5v{jTBLu26+S2GU& z{w)me)RLa7(QxX?M+ti(J#N`QaD3UXgd7MplR@;__;gFQT@bXK4BN(#$TCnR1fGAY zHe#s-tQuQcJW&sqwj5DgiT@F^Y<;zjlx3_{CcrINPBNE~K{dbt#m*D5#_UUV7DJlD zGEg!LMp9TkDzz#GCWizozMje)q^A~o{SjR{0>y)2H;|L_?K^@$+}KyyxcX*(164&! zkQ}Ak+~Vn4{vo?T%*aLtB@3PV0;GbP*v!2JFcC4n)SyVFV_Pg|k;#N}_z~#s>?J86 z%G3?dKM7zIT0r$MTg)hRtdQve3!_Wa5&Q8jsI<3{iG}FZF-vN`A03Mqn`yXktb+R&=H)VuttAIh^F4J^t z%C}Upez7AHb6G^dw||RZjgEdf4KOc?WR3i#;MKh0x}^mK?0FCZm<$pk>{2IQGyOoz z|ND5Ui=JKH9Pcr7rcjJOOYCEgOyVa^)xNMYX9Vrj4mJ+r&#AynZxh3d_|yde?7GE* z6{ncibA8ly1L(G`UcNV$u5vLe(cz^>zkJ#--9U7)LV)%9l3_#j;EI3M6kXB3iOP66 zQnB+iub@mj_tfC-UGDB0t^+Pod-bgo!}zPV>qY;no+qADw_!QF%P49Dt5Gq~rOk!p zK32Lhb=d1EB4={^wygODxbLzov#aRJ>00W{=^lRE@vcOtKQd?kBnII+h@FCjhmBFOJ_R8}Bwhm@QC#(p-;?LG;DmPwCcv2Oc|@L$?*shal9r|^=^RL#s4TR{?{!Pu z%v-s!w2pT{(aCK#9=BHf``JpGLQMIp)5K~%O!i2n(!~27d?*kI%~sj|wYBDxu2wF_ zBesX12*A>H;BCJ%kw^LWw@ePb2d)aadfmJO!B_Pl9H1v|F_W#P14)2%VE{_S(hcGF zR6~0KJ|$PazInzcA@%Xkorr?IubDO;>G?ccd}{JAwl+Ll;l3uFhv9+$hK-sAX^_Wo zd*$PRxBE&~&J<;Uy#y{nbGhMd!e2i!3O~Wp7R1XZ4SLRFr*OWfA)-im302k~Qm?KNOhO%w38?oHi z(%Z0SDi$*rmhfw02`vP7%}r&ACntSwYhx{fWoWPJo!psznBwbKow^5IOe~rTiOY3Q z{r-*Vrtdutwx?5BxfD~nLFTwNn0-~{i1)gaKwRVJc55|FPUE@i<||^9QI;Y@4=f+R z!kPTq%8f^gR^5a*&e^&YYT$P&RI`5Zq^%r}rw-y)(Qcg`hcQI#v9R_f= z-PBVeHdJPXQ-`h+UP<3A@tp!=#=lg zT$kTY>4S}}_vN4iPorC!Ijt{d2WWT!c1o|e&Dbou2c{qSLjFhw5=Z`7(VcU}v8QMtUbD`0CR2;bnUvzvy-sO{_352#3@lvc8SW+1{q{Ch5{ zVyQppD?S!0Tdnn#y1PwFYD|JJEX$&*!ZqB~_UXR1KZ9ZAEVvRjJG%TXyz+gY*Eb;K z<@V=*c2zwl;`BRp!>Xh2amCTr1xKsk3Dv0lXv~R|XeHhv$7NSo>M;Op-x%Nhr&Y7= zvoE68;G1wl837kNbkcNry)illKcu~J_vNit3gtAruDSIM7)y@*I@fr|$U{BvYCeYD zw&s!l)1sQQA0^$UvUO&)-`2KPW~PW{SYN!<*cQpy()wDI({g&C;J(+&#`LLKjxo2s zeq-;K4=Oa>hvA~ihh?QeGY{jx7vsx8QV~r#>p#jvFRu4;iUfK1zK}isuFOOVkyQ=S zUT>oHT4-GjF{MQcnMmldQ1hA@*y&8xKGSS=ZjZb6CCU+Of(6yQB+hsBJvv64R^S2b>9MQt71FHGnvo}E< zd@>^4iX6n9S|whRp7Z!#>)7U9(RTCh5gfXo`(R2?30_yaS-?>_3o^*884P%V1OIU? zJC?ppRq{}sH(^3m&CBe-tlZvM!Np<@sj^F*c_-o@Hn_0jmYyqND}?A|ipl`o{vj*n zAbYKQ6L;6JM1ZqS=518CPiy!7yCaUNP5M|lT>hodFuny+@@)&+c6~^ruSZ;msFbv9 ztJ;&-w=tsMFrh0%|@MEWeht&22lO!RzasRv;N zh0I_Wx1n)aS$^?$U;QneYpA+^Jxv^`=T#Ze3;WbDMJn*r)yW(*@jL z={GknIypWlXy7OA^w5BC9mw{>_P=%csDN-l-~#$4gEBP(;$$@|Zp+S|qQ7}XjCdcb z8^dj$FIDICI0EvA`9`$TBzVV;#<-p|Dt*XNvPuGAe3Mz9q^=?-A43$lx^zt=L7Rn~7$=46}TGkdkevi*YNs}c2 zZH2oogjs0H?^M&kbq<)VVJ~8F}S<67x>fgIg%!d&b%S*L^3~_PieX8*c4ANAwaU}`q)P@0$*RSzw1tI)&MLYHI*m!QLm34$Yjkl)At&GESr@jGO9vR*A z7S$jz-0-qytK~cP(~T>{D2YpELv6Xm4dDD@ObySfUplsfW9M;f1@O@Hw$-DN9BXcE z1tRH!4|DC8D(;^_s3SglFFL2xE3bv#g%pyEvf-<~{V7s4FOFU_O%(sMc+P;Hck^8< znZ5651`wCE8V-ec4mo7bUk6|ms_3`x+^uPKFuBp~^cr3AbDGDV81>1zN%G+jrdd*y z7~h#Mnkuo9|2aj!s3L7-I*)SU$8TMJPp{c4u`E|KHo~wezL+SKL+F4iJC8k!O3rPvv84cgaeYNY$ksi_^=uh z@7#dx@AV1uP5QO`YuY#1FUzLH(tbF>nVClkNTUJ z2=l&!3KL`co&o?pSibv=&s0mE#$@n-b&f zN8#+>O*VkBt0MI`A*+zeF1Q9U4!m;gew+)}Rh}GTB<^v}@=UGV8DQA#<6#8Z6|mN` zdaTL{QMnT;Qo~dAkXII=^`@{A7N|@+BQTp#ob4Luj0DI+qD@lC8EvhD-y*X&qW@~N za+tbb6{6a{TEBsKH9X*GQDHx-p>xFd^_7A(CXCrTk^y-y*TVy!)SM{U=-L`nOAPU* z85BnOs*a5W%WYoeJd7z!k(zlgTs3e`s^fqaT6tI-RG4bZnHp$X10mmVk)xE^si_Kg zXc`_53@2UV)G)_(S==6O>z9PvsL|*gtC(TUoSTg?)>TnW zkXYgT?utI&TEp#xUqKb!5`uh8#;agm9>X6^FLBS!?s(H{=Xv zbM>f^43cI(sx37hHZh4lt&@I{ac#u|6WzdOIuNr;YiivvqAeA!Oy*|uTgo`PPa!j) z*L&zUg}Ht1fH6fF7xV4i=o(#sWHk)T=N03d!)-^r!M8*ib=MZ}nV}i6 zuMtl>!5$_&zv46@%b{SCTdOe7o}s7t6=8SoeF$Or9#UNPTVJ%1@qUkZ#WAGDEK0WT{>vhH=pjZorVcVQu8;g&xYQRROH#UW<5D3BzzI4SEy= zgByNWWxRgjf~bCo*C8^M{ixH1b(wWd z{UiglYZ2LKMVBXvZj~N?PCJX1rWO})r(rG z5*!o#MCWK--h?L2776(l-^zd?obGyTM_e3=VQRR5-5>3N#^IjNLs%EPw8mOCXDJ9f zQA|I>CV_QduGUaO`EkfvKZ_%@fjD-Z26+fZwSwhKSLXsSpF;ku4lv-)6h1O++Jr&j zCDi>tyR2r!OtHPtVKu6DJ#tiROTj?`aut3RQI40L>0a8HSockcLcL?>V z;t+H?;f|Wdom@Zddi}*p=DYuiz5YK+Bk-m19`kLl4$}c18L#0r2u8y3@JihV>Pw?w%&B14zep8s zsowmH39908ZMyksZrhn}vI|w%3l7B!JCclI6mh6W;ZP%e=I#T-_gZyCGYy}MN89FT zT()7Xq$o)~h^HZQ_oaSy?q^ST%%_UGQTkKaqA_b-T_%0NLTpsM)c)j_uYMV}qN;ik zl}9B<_CB*xAGd2cbkB$3F2u)(R^CE5O;JRBU-?pz)eF=3==!UzOL*}hyG|pqk*3d2 zwlXai{N`@(!nd~XT5z(Op*|5ND7Iep=T})82U9_w(Xw5GBBb_}P*_S9A*V3)Q?jBH z{jWG*+$>Nv-#GoaZ$zJOz6O_)x!aLA-!wR+Cg2Ww7h26gu4f>kR z54)Ca+gZ9hQ)8LnC~AtMC2#6l@_yY_xlryypi+A(j$l2aJL~jJNhCTY2xBUD0y1@V zdK=r77+cuexw)arRZp|Zvd=5mmQf4(xAQH`lfwE1H8DIrWX)r;D_3`ps6<1%Ef>V6 zbkl^?spp%1@nD=XBO-y+N&Gd1TV8I*X=?7(?)5kpa0<<`IS-~t5mYYM@t`^bYk+T{ zyL<47wLy)ok|CVzS<7Lb-J|BztFWNW4`&EWbR)hiW!h6Wo3(Oa+juUw{fa(xj?LL+ zEddUII46ASbwR5o)~@+Q%+Vu`EAE4a@2R|d=P7%Xk zos_adox%;KJEE@SfEh7W#{Rp4sms{cZBg72yEN>+?$=H|OnxQ(F+CAI@T>2UKbXpb ziK=P|R9^P00rlJTIiI?@%2=}_XQ+ID%G7(OHC0PeNE~KH#k=>r5H}$Rh+GO-AHc?H z>c_;PST}edXll`L8b+SQYYlKrMTGD5IUX-4qaWDp32tLiHrtdfzcD5I%4tdD!WRMB zs{o{;1>1eHe(hi&ePcUYAC$O!Oqn`{^GeH4D)(6`2TIoaWL0{g^>^At;@e3ikse%yVyk~=) z=fe`A=PDr6<8PHqgxoaGKi0Qpu{-y)?#%nu8{Y{{?bnX?c~rybQy&BO?s7kC=JbWK zm}1u28g<+2x}!Ikk!-!%6fxs`Dz*2(ZI=CXgd5!O(rrRnB0&Gv8!ZUQ1u2-`31fB2 zWw;9FhU^$BaW7N5KEq*z&HO1>^-7sVn(FRX_V6o?>7!fcs}#*b#0>vpA1h*-P4JIW z2_KHmwjtLu4_!R+{bsH`S+UjsFbAAz*tn>ORQiRT$$n*w>g>3+qrB~+uVSC={xgE+ zACA9}3`UtyV5~5k;};wuj$7_pr)IXjW2btV*;Daf zG$#vCO%lPau-xkbWq7q;AwL*jqjpMD^Gkn2Kpg;grJTLNz4eQ9Z<6nvy##yk;PZ!~ zCe{YdwFXZw^eC9n6iD|ZJ<9B!&g;EdD*Dz+%-`7nh;>;&IY+WaHVs28vUL!LTd;=Q zFWd!>2(Lt~ou)_Yc3j!HJ~U?J>N95qu~S*26nAOxRv&qc&wTb|Tn6D&Hpw#|vQRc% zOZ^2Y%pV}uDW%IphB)KbPak{p7nfF(+rBi3Le{@api~9?YQaEJ!A^53^+X}mnN2EX zj02LAdxVM8H(WjVMX0f*4bK)zc;#TK!GYGuAtv{viMI#!pxAi&lc5B_f*=#p`=SJi|sAm?>2n|fcu;h>tO!UB{uv2(Dt5zaJ28+uuh^SA*@c+ zL|HAm)k$;_y+;osS}c}Pf+SY&(W6GM38IVDdkdm>BH9u*$~%6~`}^Pb^Xd8UzR%ZX zX0DmJ=DN=FIM3rac=zZ*Juh}9^cI29df-dzB27t5mOw zS-?8RcO&{-F)Y<-Yg7#(R6hHF$=;TB8o2%gRJeJaW_fHOiRlq>`!OnLbmA*W|A1Dw zM#w?%^gtFe%l#NsJ3AXKxLP*J$aHN4PEINY@e!hPOLpvZ_2|dGVT2yt%>tjUsVvT> zWKLyUz_n-B9GLIbnELi~^mfG#QJWZZwZNZ)7v16XTdWOR-w?+Uj7loj)*}j?=_1s5 zqk8*Vu7aXaBva~kc-5ddfEs^5kQG9a~0ISq$vKh0}ahDVvr0!W@^5+M>jR^m) z@>+vP4#28e)@(9k$QQPFC1fSH95^E!_jbdp+LG}HK-Elbi98vHd>29fueDGp=0R5J zcGjE2wU53VRB6_~)^;hRUjWmG5!4tpWz-$$(Ey<}qseFK#xm*6zJ*KIee;vZQ~|HY zd^->|nWL4}iOHllXo~ddU(LQp6PcdpWrOThVlVSjs^APh z1|%Cki+}G{&CLloEEApFy2iMJ6s4)0qJ&?%S(xW1S;32MW?Xh-lYF;QN7mY^ZaW;X zl|_?qupWa{u)L#*&9mzb*Q)}YegIPlJeuJzXbbuhE4|rS@6fp>pIj>bd{s8n#)>f5 zsw?;DPO%2|XP1}poPQj!F9YW07DSlT-5w$Fak~Z561;)tU9%DmZp)~TqknIxmxM>| zx8FS0kgsK6{0oYLeM+bB5nv-@EFedROZEO-TeOMS=+pil!|#hm*4RU$#Wzwo;!V^w z!D?ZLf(aulb`Kt3=3&9G1Kl;`B^mDt4L2b>aV8I>N8PyLkVWkrZWq&Y2A0PSdbdbj z;R@S=0R0(B3NAuO871EW`|B7^Hu|_JW^Tqp-0w&f_$xX|?LKK?nT`&z<|J;+kwFcl z$BGziU2t2R_x0{WG5&{d2?%-L<@)XW4Ex=_zHv#5WDwu#Pg_72tmyiAt~J?}4oe*m zjConxlk^5J3wx*wm2O?C>?x=wDk)l8fgxOkX zNgajV><1DhA9Er@8ftz^?CNK0p#p4*8NMjZ;(TcFsC~n@h24z$c2#Yw!suhe0B{Wb zZmJoa8y1~4dDUQx-`bZa4tUI;ZC89j<^;qt5t1d<2?$1QBKFdIXPwH-tfR_h-?>PF zUQ?5{d@e$Xr-42KDR?BQ;w9JEJ;x%EZWFh}Dk@9F5 zZsxhHq!fLb6V93C?k;X{ij)Qd`b`!D8xB4ZbGDwHLqB{uf5AA$)F{8{@w&DpZhUm` zigpf<+;jMcKPaX8aurzZRWZg;4Kj^bRX@04McKCiyU~!0+Z+swtzh2F^o;h9zonpdx9cRQ$1tzFWA6!;FphwOACx4yeL_ zPlIypGt~uZzc#GG8T4JY2*u+P&$}`!Tep6KR>{1yHj1w{ZZC31dSjH!(U1y6t*~UL z_lV9B@`|!%HA^q44Y)}DNlL)KO#1t#YomAm<2~u6t3MS*nd2|ufwwf<|HI6c1qB>E zIH3WD5l$;KVw(C5?_bE{ph@q+4?>ts4dRbWETq4Yu;v%EN$%C^im%B#01%?E6hT3U z{*UhSYv6J$e%jfs`31DqSxNMmv02r4mOqQ>WD2nGp8-Ikm#QNf>};v`rj6}m_L*g6 z*)NEPOxrfG`;Euyip4h$ifFK{( zp!9kLb*qI*x`TXm7B>K^P?0gcGmP$P1|i!WI6{GeSgvhhGx}P3;*q9f`>Qn^#{Ov| zgjJ5vutfzft1^bL8ICgvuD_lv1nAPqRIY9$uRWQ{-R|%UZv6p`b3gEL7DZik-1x#h z14T{MH8+%?zB;{64wzF^pdLXw)+D_HM$cS}w8WA>y}JXMpeG*#%iKVQ`7X zZeE&zI(vi|Cu*@~qa z?DLpT&rv}6av4O#Y)Wm4AM>t6tioW{^3Qud?U_$A+&&xzUi02PuWQK z=_x#j#tfF<;v4<#Q<`=-{PL-#T%g{EIf9qn4BkAfR?JZnJ4GM4kT|wn4qp;O27y5 z^eP!2w%-36>8I1sO9T;>BWC4j<8KH$<)W*cQ*Ku}nthj^;O34ksIC0jY3(O{FWm;EV$kVBYB{+t7j*j9xM|W)2xU%Kz9{0I;dow#4;9H+o~tmhHwz^dT2Dr zCcbk1w)aJE`l2r-uJDvb<>($_%+FB{YjrS{b7?&3&B48xWVaqM?#)uOL)ie&Uejv7 zHf<;B5f91t$CXkCEDD+_RiaFT8i96DKTX$=(=+nd!e;`J!^)XEI zOhgmh%1pHjTYP5zL`n_V-x0sg!&h}6+!E%*0c}=B`bma2XlT6~`Yl9_N=k>}1&w%wygSX}$F;w`oisOkPU-`3TsGbDBkdR#n zCjTZry8GbA<@R4zI>yW&LbBe#jDq#>5c})rZ#Frga@5R!k;#4tY~PM3taa4XS!~AP zM1V6JjgxDS?(dnnABA{#)_x2-AyP_qmV)NRK1**~vZ`HwEKML*{WSp6Dpg?anS>{` zHK6M3Bw22Y%*x$pE?}x(Tlx$2l2Kb+gId6HgQxqsFtO{#$F?-aq7W)z1c>k%Yg`VwTC*a<<0{n? z6$AKt?d&B;ue1YY05F;&ntBU|{L^t3-G z@OZWu)>j&Zu0#$CgHeh}& zBp@b15VwMoeQBLhH=VlKJnJAr*t+8;1~TgjYw_FOV`hd<*hy1zf&L=o|=-X2?6 z(<)%k>Y3AlIg?*k zVg8iQ=RQzx1^+@nDOo%Qn(OqNq)OAd1pbEDeKj+_x%o^TU9rwe}7Ol;eO0sP5gT6qKp49Zf?1%h$qy~&5${X+g z9{6?^a4&1LoTs1P@#!J_-Ck|mzf)DFB7tLd_NIEYc83#C5X4;1Ns`NoN4$*IBFejS z??VEcEKxI&p*CEW>jBXNhAJ$asdq12wGcZs)UrxCjyS4!gU9d^AH02#ai{S%TMix$ zwmdT%p8V9~aJFrG63SWmZ;;j1n!9ph;QrvkVAGPzNyp}&TQ~X@|Gc9s<(PUs z02vRJK%Yq5OE#S?5)-^_>hY~DJllOEziEHOJtc88kp760UtXARRLvUid@I!Zos?Bq zyqny&C0mB?x?MqdNMXD7{T|lnT3lg938~uB-X8YX0NgUNv!+*%#@zn3fuWu3rKOy) zl&v(EwfYDntTsgCwM&2fMp)40Hn{1s=S>mtpSqVa13{@%x@Ejez3Bv!D?K(pUn0(1 z?wj{0w4fLX6+Jt9D6{ zRiKd&fUUcB%$SA=(#{}JEJ%& zz@1vXEpAySDwgxhpv2@Xac){He}+`bHOHIs%K5H*Uu0F^gzF+!e0Dz z&$tCO(1EM?kOx;0Z1ikA^=l_HtCJfgM0zxNTL!lG-};C!J#Qj@a{U6&ZT-p8$3%n( zNja^srrk%;x~p#bkI7qT(85}8rw3sJ3@p8`y>{LSx1qP%bfzfc@Jxu4M)V+%H=Lb6FA|wiGbGVZ z_PwXwFT@n}SjyBV1UrkfaQYhH$B`J@>N4*5>%TN~AF>-ZCA_oLnf?N)&1Ab3UOwO& zY{8vvUuJzZMiop#OIH&qAadEe-PIT>#UGlST^A=N@$405(iTxXG|Z* z#cD5^zTX)kuo2rXHtpNzTi~y<8etMreAopUfm`o?x-1p{P7{yR7()V&QCSv*Q-eOOb(A8U9pHN>YW!pZ@~jfotv zU~h}~&03Avu|3G<_7VaN&tjBSY^wNWJME&Q+`9xFQuB5<@k2u2zVA{j$T&Du^tQR1 z(z7I=VfwWCj!=qGQwpRuA{2+F_P$mUhv-E@^boNCBb7}Mx#w8g``#t{Diy}+%(V0L zW@sp^5rs$B*G6JSnUd1;ECWsK#hmq@oZXw(711G<6S*U4 z(@72u3Q)4(b)V=WM7EQq_Mi+c1>;qiMy8$L^>q6MlJprNwkSmG%+8;1_>O&bKFt-1 zLaI?c#1PVYh7g#xy$ev8&Zt%)@*kmT`Z3ZLA`nEfz_Q)?++Y0xVY*QY1XzkfoJhJT z6S!m#BI&4%Hz)yO9<(4Nw(HZAG_K9(gJH^&G@H%~OTi>44i^QBSy@;Fv)j(6j9TJ> zA0$PD(rrmFb_er&OoDj<47g-Sy#r;!*-&~E&Dq%39tG$I%}I{vk3h~7{$zmwIA>hr z2>wNzqKCq2N`qDmpVNAPJfTe>u|ca;dsHN?Ge2ehZEN7y0}A?)kVDla-;csB3>oXA zP{E08B?Fsa=ut|t)}_y1!=`HA2=W&K&&Et_HJ2vTBcGTNA?yokDE01 zM0`*$dPM8ce-7JQjWg+5?Jr)j6<_zfAARJjw!4imbvKqiZt9J1Xs8|7ABX*JFkbhg zWrB`#mvPp@e*0Xvt`h5Nac4e~%6CmIOy?V~d(v+ZJ(TAr@&Uv{Lo z@O#_GpPn)6)D2pp7oc^~yzZoDkh)k1?5WOgJe#&TT9@v1R@y!HrGWN7EM)K8{9E7W zlXTqgIC_vEC;Ky8UrGEO0M7Xcx*udx+f@LFJ_JJ? zE8}S5`pVV!x`E!jL^r(+_Ib_jYQB{}jWOYTFfF%C_-M+VvFUN$@{v%L4E=K{|7KOc z=7-bUI*4MGMjx8K5dAY%nWJ~f+m_sex4r4iF_kGwZ%#ESp;n9(GKRwO42(gE`owJY6ivfjU_e;HVB{Ry# z?3TnRJ;zo)*+R^BR<{;t&#~j-JN+h@h0n;DuT*p)XSukNDO^sAmIl$pnDCHSA`{O7 zXkdi)kDrSPN@dwRA~&AYNJqe0NLPZ$Xop$FNA7&zU7t{EY|+y)(DZg*HZUvBeN-k0 z3K78Bvk>Fbt*grEfcC4JLOrQW;xO5GLZ@~^3(1#F1|)Ax`|siev6Et#e|^2}0e^Rg z2oEPnmbnuCpwf`mFu2hihCI@SYVP5Rb2nG`U;k}+sKQKA+SN*)i~m2rF&{`M zWN+Kkj_@vA!ZS{^izxorm~M`!kiF~5)DjcH`r^Bl#pDkq9d9a?jQ+Vh&j&acBjPdygRRN4 zI~MWS$sFWVt;~^bT{6LaGU{~Gp&4SHp9cRKs&**W5a*TK@2Bw``P3GOst6$?QkRvs!$BO+uI|=oQKzS4rE2si^P|zpUImW!T?fZHpnuet_9W7VTH^I_h5?PAdVvjDeX02^WXTIOR?bGqIZM&m_E<;dNYx~m| zzn}dQKKk4x9mH~x7r_=OkNHK!zu!uDXyKEjXCXsM%nIy$;$4kbFD0GH?=6m+qQ+*n=sw&vXi+*cNNgfVebRW~ zI#QAiv9J;5zt1=J{*&*VP>^fM{R2I66epHP(zKo%S8TpSQO#$PtFiiL4QFf$OHNy^UL4=O$+UCqvI-`jW*>v*w4i)dp9gslg~tjkbBpLS zLfXflC{wtIj+)VEc$%9>edP|RCCOY*oMoZ$r9!-n-#4<6xGJbG+p?4?oDdP!ji(|k?PE~lV zEOFmflCICe|KE#+7oPFLA1hNUo6F(ri|EUZPB}t`gqs3|=iJ*lWQ|Cc%)|Hpv$*|d zsnb@@&L6-pemKKXpow7g%jggIphz-gjr^{`Y92 zl(O@K@E-`-57h!^K3(?>gadCltSO^P56X#1sXk){k9gg@sDty%|m&2IfBO z^T74xjcBLZZbfTAM;beZtc&L(!$0@K@GkIIRyd=t7%8MuomSw5qFP!}K4Ap6EZ)if zqKr%Js4_nCp1F-8+rO_Tn|&)NiGb?4VD*9B!$<>edEnnKI7rqBZ%;$c z81slEUI)XZWP0$UfBlZF!2CDUmt-ZB@j2}Gc0xrVl(i-M z-1f@7QFJv=uX#*qxZ3&f(D`vxF?@DiCpq-lq8g#JU)(62|8s-;E?OtG+|cBQW>VDd znIjvI%;u~{r)>iepZ&{r(CaX=<}qK46jW>77gJpfcik?A`!l)|EkRRZTD6aK8%2ll zmw~%34X?5m$02ul8_%z}cONwt`{!}>J3ODp%|&8Nzf zHEBV0=&_U1g%+pDA+d+vmPXhX3zV+b2em*+1&@UzG)=0v^1|FOC(gR5!J|aJA?ndb zeVwtwO@vwVX=9PiI(xR?8OT|QD-*inz z`oc)tVpO@=Oz@Ga{-Lu_xN)6YQ(2!y2|}jDcWgBIFDOM0M%J^1QqqZwJ2NJY`oKls zA9u=WU16z`BZQA0LJqE2Qn>c8tnjELGZXd4B30j0Pgu$5m7AV}L3#Bf7)Urd_vBvC zKQG&X*Bv$gp87&yUWPUsxhQ^98>gc*_oyNRSuB{fxoUg9UhUqfuGNUNVvj^wS&Q-2 z3<&DkX!vLlP$lupbo2Y2{z4!11JFOkV;qjL|IF(kS<72WSdxxyf!Nz1<-9Jd?B%q& zP^C>XDWjCwp${k{KX<73uiyv|hv9vob3u+m_!n^T8gVfBz(w+}uafzWAv4~`a-wB4 zbl~phtd4ieqnhMqTBt8gWU=$e2cY6m^JC(R!^HE4+5s6w=E*jFs(I?r;-_Cck8C+Q zN2#`zC7*N}Y{><%Qu@~K228T}KJhng>Kl&4E|)jxAO0*)7N~8T@oweQ<;#*;!i*y% zKj8DTx8&1_uzu!t6MbT*tIN+-wBG_H}E#8W=uvH5;}lCqczU#2PR!9`l@6A5|_ zltN;;Ca21gf5sDim>Y3E>>2Q7>v@H1v_q--Nr(~I-VS%Noasx6Lxu;?99L}PB#AR4jyiuXz^9-QZ<_TZuhi~q~ zx<)Dr*e5D-iw?Up7 z>d|{=gqc|Zm~Hf0yjB5cfpl!9&jyW$LNSnDxH59=cjro!rM&gZcU6Z*D|nMdQ~E8~ zoxwIA@OO`DvxKLDtLN?+S29l~<_V#cYo_u=Up$GF-OXP2^{0D;&(?3Sq>ct90=rjS z){{Mp;-DF8iN{AHA>_6f>^Sg4gEXogGv?SXT?sWZ{IVm(&Ki2^XuNp7-J)tZK=3~| z*4DwI?Pz&u@K%M%|9RutO2l}*M|b`$3XUHf1Ij#|f%PJ;0YYl6X^)+zNpRkhMBID3^)2UxO=jpzmD*GvYANr zJWJ=yQEfSE1CGu&vqTw5R1a0B!5D;X*5aZ-`P{vp#R4IvQ&t-8songDQ$ri3HCc8+ z$b_goGa~C1DERlj8!DgO+ZOkhkP*&&ISsgEfPUW5d7b1kQhOk6e;c%ARQ1>xr~(Uy znM@*1Bzz(cFgz&>?usUNW7|Z%Uw~+x-B7xt=kdm%P;?5CB*2N-^=>u4ENE29uv&Pr zczxyFpYGk*B1ttZX#oLVAA7y3Uy^Z5!zX}q;uKy8PJ`-=aDi z54zT>ff@~84lAlqw8|dfBgz-BMnMKaISr>d^nU#+na~s%SlJ)1q=SO+c8WjYtC5Z~ zw#kpd&VYkPS-*wz&HM)F&|~XW4OicI8fYtMq7Dp>G=jH1@VeuyUC68Z`+G;Q--F+L zhl5;USBrk|=;?oTy3Pv!<^J-iQCLVbA?f0zHc&YQijUxFC zYhE=PhAE;^ff#dUc*fC$u0=A*ERd*g@mnTY1o)IhG)7DQu1AllL234UcgvCi4m$<` zh`>GQRex95?!j_rRV9xl*F55Qa2wP_7GNa}aSS09d6I1Q#;9?pxMVC|ODgqM!$}ez zl_g$zu1d5fcWGsC-JdYJSC!S^q!Kg(3+G`JP3VUwmZt6Dgf4Z z&u+rZb5v;??5!>8-J~`OC#ADP(PfI7O>WbYTDuHBo>u?6-wHHtd~_P4u}`;BCP9sX zZQ{-!t(q)jA{it_+}8hqttgTVppA7>c=s*yCiNfHmgk_N(ahNamzAjtIE}VJu@i4v zVF&FFKs%q_XG_*1a2fzETgTrmvm(jKCuFV;$>Y1pI~lzubT-U7nNbikuSvZ~GU)28 zQ-zCLlM{D&{fk+!EHG$7^!vs;dKR2&gE8}gUi1#2y zH*xtaXqGY#y84pM{hFx-W||JOe}Q54MriwL4M>2cVY)D-e(~HY<~6A`h;o)hIq>HZL7d>9`M)2uwe{D{gDMfW>kvk8 zJ<9eetcP`~g<^*iI)GC30<=h464^d}*@KR|BU%K^?zc=ggMjeacLLr$Ea544!*s-6 zPH;J~hAo1!j<2L3&*1y~6Z}K`zC@-LFP1E&wtdNFYDpF1+q{-{N-AEtZ3kk10n?&X zw|wg5L*Heu&iV&S8gDaO+AF^wt7xa$2orNI5XUborM<=Wz2!u4$Kt=65(uPe6HyW* z)gPu*0_QKJDi2@0tK5FUQz=lBO2Pm9pmOPiMKD-4gJ;h#k}y!=iaYSnFV)gGe5oNI$YZ*vg) z^JgYRf4!9(-S(K(Mcx~kH=4W4$T-Vu{RBly01)qmWctEeUwXC#urf0t^F*g}-Qb7HG^Ch{o`k}?#F#BkPhru6V?iFBoc&_|RA3XFm~#K#uQ zWW~qAw|{*3V-C2jn62RLosXHrhzanZhVdJ=ugdHBtMv^7@Q=CVh7<4a;~XaYL5LwV zkUNlD@K*k}=p&Iv7Q)Wk;v>%p-Iv;}Lo(s-ZP?t{dm>Kp92|+)3)9_I-9q1QI!+Wl z9(?ktSuha!5QyzgWDh#E0XzkEmndgzRgWnz{ANU;qW<{Vggplg{ zHr)ZPABntYwmByGPX|}@zp}Q7DA~ifZzMcd@=+S503A#j&p>0&<*Qjo$am#I(Na&FF za2i=6sQU#pv**BWx4q)K3UVl%eg5V4cI|8i$OA|)*=9^s+CZiQRf%^|suU`vGwPhL~|j zg}^XG+68s?{dGR?67{|%FDCEyt^f5k060NyIG1sf2KGnpwR7+066=DS7_`0#uGMk7 z8ceAsH>#6-lL$>-UiE4$XWDV*tS~b&vXh+Ew=J_dLom6ra~|RT&u3*hdIR)U-TKQM z9VKF)7;kYu{Hvakq|rfY6A$$_<&#*ggKhU_ThPz>p&6PjT076fb^_R1pMFS-5q9W3 z7S?mCFi34lr{X==!^CUd$#CfNX-Ti&>N`I;uPzo71`+Z9ZXo~bO1zCdG5>n6L9+I& zcU&KPzqwY~{bx|wBLx1>L;SxwLg4?8hxq?tgus6iZ+q5C&xZ3lW8OnYCQN>Q z(#~`yo9aJv2z-~?coK>vqFAK&;y z^et+>(VK}2^wInF0D2P~HPRSHO9?)f#%!(fQn#ERJ2`HRusG&MPO0_t)F3r3-bAnw zZ+GyK5YMKt2L-qprJHL=TMRZ*B@3W^GYrZw9}x0BWe!TMm6r#;UHPJWpU37`S67>3 z2?sk4(E4viZgvGfyn)2;02|xD#}j#pzrP~JCk+x8*I2B8bjKl9#&U?j;ZeTg1d_5yR8JTM%YUIFunno!wa2UR}~ z4v*gd6&yW&-r@j%bXM(d-aux-2Xi1&^_y86uJD>pyfD~k?EqK@GbBYbJch*o19sG| zCG2u!krE-nn7BMR32}J9LztNC*ynhrs5bvHIk^zAMfsi8XDzqz=xIa+&-k&dK|g_n z50$Hw1>&$vc=^jMj#V)FdjjSv<%x^nQoIeGr>4=|CqHUk4ceT5ilj>}(8_ux-1k-S z>Y2Z-H1K?=M%7?A`LXa(HOZK{cUBT&8$>(P(V$$Y!0=}yeY`9<%^%P%T6C;ob%+;( z1xxH?_RU=P?Xfn0+FF?D`zTV<+f=R)vCT%ajPlq{0M`4SFw?pzO~3X!^Ik+)W;xH&XA zPjZ?cp8Il**8^*@Dq~<`Y0*PvA%z>HshGW89`#hvY3djH>d$^G*sI++c2|Xd7R>_e zA9RvGEvaZJrm^0`8eaodZPLa;+p!o;nM=<(hz!`(%_cGd@@yXZ^)Wua3qC{7DtJu$ zr;Zn$;q@FsZWaX?z2q$=m4JrQbWX&^LUOf}-7&p$9*@i99oMHe7r*Rf zgcRaQdUfWv6h|mnZ`_2!*PoIf0tb{C@L~r;q7t~`?i{;%Od-M|8qP-Ui_tsJ>jFE! z5Qj1L+ZVqXeIBtg;i4~yhqR!r7u7C}V0LqFX8R^TtrC#cvdq0PCNsC3X$2Up``C0F zxuOfnAN^@m)jFyUQ~uo_>td^U^KL7KwE~Xf-^xAF244R->!5A{Vn7+YcFVrfnvc{3WqPhW4GpkuW>)}<+0Y<&Ed_eo(e}bG#SEFsO|_)W zirh2_*C0gy)VXEgKIY&iXM?>SsKh8$6nZ{0cJJXF-i%if2RmQfdVS^Lpi~-=V2j{Huau zYb+d0iO@sdE#t6$-mj*OU|~e)n)c0LkK>#CM156ULNejI!!p;18%SX6^3P&c7%5#6 z0Xd^{qehy@AUa*l?S(H`R2h3zQu@Mi$KI+DG)eprPazmaLi1w%2Dafb?@?hyLwuYG zfOrlKL546ghDRr58tJsR;B*IEWniXxnny+zzn*Nd(AWN}osdZ#%>N3P>pE_88^YA+ z&YgL12}qvs#95<|z0)NM5fm2*4|PjPuZr)_k9gc_FwI^2H8T6bJf4I00t zRk;SzmIH)bD%%Od7`*1e)F}*G`JP0dWwyl`7(TV%J7;JF#AE$_6t;8 zj9yl`boCuiE43J%8pi{Ko=m*x=D=A z-;0$xH_5HXU|HRiae<65vI5Ma$JPS(=@t$M zoW9x!@Ig4ibiKM4n5I`^zQiTi8cYvK79fUVYu&M36B7BHCE*|{oHu$2CiYKm)L@Oh z=e;5U@KdRCN40_E0@k#e9;{=XTxHwz-Ce?zan}Kz16e-bpUK@^XS$px*+R!iaWzR{ z*OAzx!`1FNIXlo@M5rkfarBhV8p-=wg$b20J7k!r3B1;0Dn|Nfv}&Uyg50_wcJtV3 z=zQLZezCmEr5>p}0de>+Brkvd-oc0+&T&!*-cjpO;;5}-Bo@~FlBbGt&npZWwv0+y zQ^C(Td`)3*N2H=CysCpfXLy3J#|GAV&_S$Z!Vh<3H5AYnPRhw4g(#Giefe0Hu~qJl z64|o`E^VS<=n;hia<58)oC*|nUH*I=(ZQ4i z3UncFPzJ|oGw(X3t4&^KD0i8n!~f#@J2aRq&7JXQ7BNZ3mK=ak(xT=Io;NoD z6>qh(Fa)co8#gE@obxwQXsEJ_$ixfW(ltOROC6NuT^t8jEFYl<&<0@bo}^sBFKeb6 zr5kPDYNZdPOCZ3<-x<+G?K~RPwF6Gx$hu@Fjy2FST;&Sn2ECfAoiWU@uTmC?_-*Dr zpStd1Pkia!`qxZ|3M6P*Ko}upJ@OVJm&APa%vPnZT02jte%+9#HpCUkXInuY(_9#^ za*K1ejzO$yrV2P81$f$e6bTCTMM5L^8o69Rm&j1;+b!SrTl_E}Bhsb`%|gr{M(Dnk z2HI#&RnA&ROAin&Vc;O5P<8r(a-_Q>j5JK5ykUcO&JqC0OQ|eJQ(s#qn~c%is9T0+ zz~zZ!n#-4mm_z||cg1YzL3d>CJ7DD!D}NOIp9GO`b* z-;oTIKNMU4H18YD(dec*SHF*hV(9lN(^#yts@mJ-32>CJ@f%t>rNw$tkE|08Nkl*> zOl0+Kq(2B)iaNut4x`gz&%f7llHj5q1by*f7kjZr)Jgx-QS>-8Qm3)3^$KH06tK>1 zF$7#z1)qqf@r5(GT=iHZmLA(6-Prw>m8fUaJD=EOR?%3q1wHlvd8~yShqXEqM?Dp3 zI#r-yml2bN?{@x|UhvP@;3YI@#GTPd10*-{7K!{6E;NsnBRE5dK z#a`3xwJ}J!8n?JQO7;YawN!*cU^r7%FhUM_zr$KCo=O4c+Zo$^*deEYx&O&z0W}&A zMYqe2k_@_93gJO@gSfx_F7@ucdVwjL_=$$=tG|T`Wa8h?#KdwW&&Iqia8 z1#OnO?|Hr_Xqj99;(7~P2V5Ry(E}EjI|d@ql*N-1;Q?;k$1M^RK~nFJnO+ZW>ZFMu zH_VE*`l!1ct%dVmssgNw_aZBriY5ZCj^mv~7vLrt9EJUIM*$bBOw)XrekJ{MQ4|LT zVXNOy@zwGYB++Sq^IuU^i(txhPMFEk^|={lqQ##}Ax_ohwribrj+=Sf%Uu(|yAra5o!7$mnqBj5QGe zt^y`fu7GS^(~oHfrmUv-6L|^?!Y@@o8LCl+;~MKy^AoF6iAfk{G}@TP!cu9@|DfK6 zH8)AC`SC$NN`J4ildQ(K`tCDH(0!Ja_^6%DkMrdS#nHxdP&TA1-(X>_)Md3h`YYnZ zb|KvfEa=CXZ0gJ};SkH8Z6eP+~)<{6qn7REE&d3Rs0`>IElpt7-rAOj5Gwg|SEq?@)4g z()s5%E&P6Oc39!&j z);ZT3rB^sVnNGQ;m7E#*T%~^}B}5N6R*)EXoq1AHWygiM+_k7!56Nb)S+??Jm83K2 zGR-;g$ogx_YY{Y6t@BdYSk%zf0oQAd+ijeMu8AWWh98eGtQPjqy^_-xd4VJ^tu7pK zK(jYG^UVCn+b0^xMVx)M)iT}74k53WLZLxGi6O#%KWSS<#=dhDMefEgc>x@BmbD-t zCAO=dlbWsT5U*>iZV9>AMD~O$#>>s)ZRm?k+@9wZYQYI2Q?lHavN9pqY3_4F^4V$$nM-I|qB;$4%#;yHZEbgusE;j1Qaxvh)mD0I|J+Ip89()KW=w1`079kG>6KWJy+2``j%$Eh+;FJg^BVxjHpBN2nWr)TlkUly7H5#6NR-L4hyj1ca;pe~TNPAZf!tpAVtVx`S4pI*mu+1N z%%$#nY)%OXtXzaTH@(GMfsc&DzY%0y<3;rgT3XJV#6{X1!vp~Dda?)E;j?N?suq1C z`1`4$rs1==(wXsrNskgc%?0bV-Kl z1$MtX$5uviZfyfNf^FEt_pznwaXJ-33sc+@$$6(ZPz_tzg9P=FZsor~!CtLYl{8FB z2>P+LT|f&%n+Nc|@EsPc2m82K*1tB(C&WIIyVdz1)&3)5w(Gy zY$g$}1uNhY;iSqp&&1o!B6qeNzlx9yM~|`u94s~3{^IN|m{ckM-RrDinX7GC1Mikx zu#yO_!%2(cM?HD;hskSH6Nk?4)ZxdcbZPE48i7G5!=PmN=|>~U`WIHK%M#&j1brKy zcG=cG$ppPQwP@UBe{;k|2vq8Q)Cjy{{*^-d<(FO+P=75?J{!{BabGx0GE6K?%7DF= zdi4%#u=lH&=%9hHpqvkGZIhh-y@Z_!e+(%3vEb2N(RYzpCmEP9Ve4Ri_)I%$HBuH6 zGI(2kOBerabWuJ)J9;gqkTgonb7b7UR)O$VALYc?JQ}Alt#wN+MwA$Vr+DS)P3`lm z_q!i}vjF3Wk#+o=vFkWuyMD6If4F@_T8_~VGy!7Korkljs|n-Yh!jy*qOVpJRAn6k@C~7LGjfNY7^LwGMO?V5Ab% zCwf|Dd<6m>hQLx)?bV{Rbl%)p2=rmH_yw$rmpn}>?&#U1#(rX~y@1YQz-C5ZL-UK0 z3=+yXe{u6(5k?lLXXJc-FcAHzf0m70xQQO!+3aG0=D)jm?;G$a^*P9q$xkw5w0lSIEV%XKW1{I?UeD`r!|MXzzXT9u(toboQn& zj+hfwfz1+q!HltoEXJR_eY8gy;vK@%f5Eud&lXTFy^v2mGV(~HKlL*vm?LMNd1f(I znU@%nyxYb*QFuF;koYg-%;7S z%X-5c-eAKG(oc{2X&O4LUJr8^e>ta~daAXBxexyEVSMqPDp=xSWIYpZdRpc26$o?~ z0!=Tu&zbXLHbN%k3C7E*{qo}UOg`y7m!8d=+>9AB^Je#)Jtt1QFT1EmX3xb)n@D~! z06#5M7-JY31i9APK$w&mKX^VkDG@l0lg8`C2E*dTwZUQeDgw_Cix_1ae{a08ozz&2 zcuAOv&r9WOg!w%gTV$c(^v{!pj!BMj$HK&Bz-G)QfWgHgQFTSg0)`>Lle*TjB}WO$>~{e@A`6hQxwMyII_6H#p_@l^2Af@nKWnLp})pEUS_r`CrZvv(Myj5Q4}IDFs>4~Itjmhr+LFEH+? z8!RIP0-cJ0fBlkso}YOl)K5C+pMPndcn{{u(RG>=I7}8M@z9||vWt25ya=*6GP$cK z5wtx`u-?$9em%=Pcvo1QS-1$CAUVO|K`YZrM)_%14cVwHhcdrU`?%+8l@Cp;GUe-8 zruF&0teo%5h?fKJ6md<*W}$!#LRDXR`93b*-aI{@e~-gkPD`H8_i>e%pU@C`YD1Z? zUAkOvyEns#~D?CeSDZfpP&lMQ2L=+OF0jjfC;Xqk}E z^Wii@Ag+AUnzT$*i|1h}Io#E}%!pH!(}~Q>kxr5Wy?9g?G=wUCFH7{2eBTUV5lZ ze{`gYOE>5hCtq@)BS4ftS2;K73VqRr%-)Ey3$z8Tm_c)V8X$*MqslJciEaOFsF02vwNT z&iUw+%d2DEwS~5#diC;ocYt?jxN;c1_GtSR^#y6q ztEcH}TNCfJaJ9jeY~b_S_C?gbWFWvhM;I4+DP9K2lF_&D+sc{5=tr!N~a(p2olmM-6^ot2uOE}#FEk>-LRrGEJ#T&-L>>m zKfdq#{{EOd^O>2?XXf5J=iGCi=Q-0nh!azV^(^9psshO)nnxHI7$i!HavB&InDGzC zi3E5LtvyDj`_E@v#O#>yIoKFD4`(p{yY{eQ$Y{zcDLw2p&D|_5o!o7lJ>*uF+-mtq z3NSH+lcq?8uwDx#fk3qY6uGpAfgz2dBqyWgjk&jgpJV;@v(%9?KIXR3T7@Yl5vw{` zNE2KRmvS^5HzrR$=3U-Ba|1<8M0mufS5Jx6f0MuOB6pB8f1b)7iOb3OR=0rXZGqSQ zN&3=tN7mB9lJE6m4S0aA>2OiZeIrxAdL&c89dNhOx&ElM5RXR)5R-$Mc@<6LyRcZQ z(OAoDK_@b`SGmmttj{t?)J%1>=$k?oyRCgeu_2>|WDZC87jF)4(HwcxD<%XE28Saz zH@i+Jep|Rb?RV1|-GzQ12mJ+owkB$DQMn@(jf*X%Gi~oLoyzt$G&=`MPc!SDUnXx# z>a1>HKly$Vk`=WGl(HLC@bWicHLs@{M1J_8UZs7oZh1DTQ#H*TR9e+Q)3vT?FeS+Y z63G^z-E+8Ft=CyFfEnMn7fz(sBWmGwS10~X#|;SgNqn~9DFye*_V$5|!Ryk3dqBpW z{NDYTPiKbNu#u&z@b%n@;pLpDJA5H!;OXo}$S(zLqLN17@jv9@k~2~4j&u;RSL)98 zV%RyL(*U?Vv$A?hjEE6h{I}nZFkTQeaMqJ>S^^vSY!^}noD2)WTwlSV>nS>((}wQv z8;1qww7?_mmMU{q1H| =B)HUeiWiMveWf853SW*SlQkA4(mM-SS%1#zmjqNk72q z=)G9&ggWrUc;LFauzD5k)Uy3!U{&9~V$#U}Y?AVVL}-50@#mkXr5>BvzD|wXKQf*+ zmoF`#%YGf&y{DzYFXh&!b!u8B9v&6c93MGBNOjKH#1iQEjF|Xbid!Xad`R z3m3lISL$71`p#IUee^>mYOr}-&AK1|q4K)uxM&B`R);zN-6y#2oE;wZC9%RAt|)EL zYEeZYN*!%?wXtJj{V)%hyi|`e!~J@iiSgMBQ9LzMwD3BD&6yjrndz?DxZg16=~43M zV??Udnw3g<`}r)L(GQM;9@2KfDefj@kdvKV>6G&>lyv008KrrY`YTe3w>h|dyC-jT z+8EHhLa*}xdQgYK{_PEZ=zPsq+f9aZM|11ZFCwP8<6=?hnQsG^ zzVkT7*#m~2C~86YAGj|-H?xGaH$oC`k=ILASJc1FXm(Kq(tn{+*E5Kn+LU;}ubLZM znO~ZESa2B0;o?YlmHd2tXKh9zFPPSd&U+<-O`C=d=7%DVxJOsrzl?-J{Wry#&yKg~ z@2I_krPdwU3ij`>JMZVRyzUfLOH4RaR=@I`&7vmmkK=&(ET5f{lD}D=v$m7RBNi&F z5sft7W~Dm%5S{&P_Fk^ zJrR<*_L=D8UIr63?t#jdozep$lgpsq^z#sT)KTW|-04FIG@YuW zG}QE@s_wHri(;=IOm%du;wZjhvpvLddoWGKv|omQ5&dc=0_49XyKsMlxc4wY|4l26 z#$w2x2}@nnv(EZ>4V-p944?I0DxtmUyb&q@Jr0|?`{X-&J`67XMU}nyU?ZPl*L#~S zUhTU^^=jQ59R_XwcT9&}xaVwAS4xgiUZPnYc#U~=4zv1 z->}!1;0srS4rsPqFB}HEj?1AxuMYbNk-CI~TIf9g<(;jXSdPcvl+TRhH=c8j)3+msH>wwZcmjT2KQvf^kfgeEKJShYjqe|@v%gsIs=Dk;IQBlxXE36a?frEd zt{|Q_(7hA#=AiYk!>nQ;J`ah&K;pp8>xw3+xdMR2`@0LTi-BW@-!*7`@J(fN=5Z3DqMts0?VyAO zo&vD@D_A|SzMa8vcNA8CPmhWZo9K`15vcpmeC=T??|pVOVft(|c*2X53Yxxm51&z+ z@4mgs-0g<*oz=w^0_afH&OZ9e=3(I2{_$d4&A;WmA_cCQjZPjJQl*96tg-1BF`hi> z^!;Q6&2#w`%A&n*5(P2ebII> zB!DPK`yzZ7YgHs+i(Gm&1=q9F9ojk~zK88zbUIS^SBNr|iZ9!FlB{K6Qa8(I=-+IT z>etzjItAEa=lxv@zTb*(Sw+K6-yC>_eT&FHvcrZg-R?>D3|KTr>ffW)xqnE=Ho-ME zK0V7S0Uhc`?G8K)F^2c{w5M3{59;Bk>lKD zHAd)Qi$StK(EqvfI&h`~Otx>mmB9L_%OA%Yoh zkWP&Yp1WI1+eI+rvoECn&22nf=Ko6jurPSE6L(ybO;2TazuM*d0zgk27Sh0px&n`2 znx&uP?UN_CqUf#s*8kjGeJ1K#)`t%W7YAL6U2254Je`M>*oieA==#AIRq_|tl8SES z*g2GQzA~1jwvPF`9lglp;1;6v+fKTVg~c~Kk%*y*)l&wk>KGa1tK%gq5^V|7An9tSQw#~RZQ?y%0<(#ma7L8 zP^;s1vnqABS~_G^!sEZKEY{QAHF~E)+Bai5$*^PM*3a_!G0mxW%U+Fg8J{Tyds#uJ z2+lfjnO>z}`|ZAS6?Vk&=%J>j=I0|Yct_Ja^lLe>FjP_i{MbbR3ooZ(OK3#lnx}IQ zHOm@{!URCx(q4Z-s-?FIX)6S$EFwE>Xr(Z(2eT~&9qq~n!;XIg9$|1sS(L;<(`sqQ zm}_X3Kp2Aqvi@FYU4WPgKI+PUs$k@}TqnV{%@%A7xc`dIxEAWX8g`o7Z>T^QR#+5B zSPfpTejD9jK2l6O?jrk6QCyYfL3y}y*mg1kEG*p&FKN-eSz?Y{ww#bU{~7n0#~V(x zW04>uK)RKUs@qS3-B|2n`+Kc;sg{dg*QB+VU++wJi0(`$sg@-NtsIuAL9;eNik;#~Y^~Ob z;c9g;{z)`S_X{q!Bnt@&^mkqo=qvo5`PFL)Zk7XeCQTunBb=t+vo zJbj^m8G_HX&+mEazcm@AcNZ-ZU-RudfZ1)6*t=10Wu5bwAkOxM@)*0nmDblDFn@Al z3Y@aDE$<}*!rD{=4^PQIQa12unjS^4%jI&|w7BwXyuYR)OBlgv)x(va+vFG%;dmF% z!XSUs&0t3r2{J5N0(^rXgg>9B=osliN6+h;?^r+Z#oXD1d1~ZL>X_uyyg}Id0@BO) z_6;)W{g|E6FS~j467*gmVPj_OV8tF}I8$t~%WN;BJ^oCk`dUynPF#zU%LkRy3BFn- zv92!5o=BdW)V|QnW0?cIdcDZsO)gHX7~U=Cv%94U&+Pk6zrE}+cthoMdh|zeTUI=m zijGg3*|AFuybkjH*WDT%**(o*1r(E`y=6d>{G*jZ9mg>#PlLO*mIDpX+Ls`sLjS0! z7RItcen{-e_|e+QN9}z$_a1n0N4y(Wj+cDZ2+8X`yMl^%W|V+T%W)_z$NgHK+Sr7r zH?m-LmPP6|Uv0&MRPqve(0=IeoCP2EI_;~1O-xD+EKkVa*4^RlPV<=oXD^pmznRCD z)a6-UvMFEKS2Z_`3rmB+uV(h%zN10c-&PVfCw9JlYBqLRV7ud!3vSpV0d5i=pK!ws?<@1?d&@@_tFWL z*Z)XzME4hw9(5Sbbg@!_bwbneavBUpFUcu zri$+KZ&Wy#+Q0qUzWa|A)O7TT|1oqITlDqE9<{Ycu^kc*j;fpk7|0)3^ZAP)v$+`G zaSUY``_(4)JAaLKi$6a_)O2WT$QY`R7dggPI}WvKqZk|-)fnCz&H0P*%ksAeJMOrW zXiyHxC*!PV#v0;3s5#qk2vzU6TlfC@uXQt&a4^tQRN?89A6C-i@-n^4%d}Dw??@p= zRLW{lnUEVNB7f8|0QZ-@Wo`zO$SgSjD0@UfEc!rnT3~fWfZ{DHb}ei0?9dn|J}CMd zWmtp0UWr=jm6iWto`n_D+MbMw9tlPJqPrsv~twY^^J|Nc7jtLv8ps1R~Qp zjgI?OqykfbQ_a&jQm8eB2`Vv7%iQW_l-e!I>5Gi!b1zGmMYj{K&zX6fLXacPKV9qs zBS&g%l`ZH}>V;s1xfDKCi=8|MiznYNEirv)f}bAkbWuLbqKOB?C&nKJ`W}< zyztPyckx4G188iBD7Seqyg-1J-XoS+MB68*;m!=mVD^*0XjhOQ(`ypQ{moPqL)Fsl ziNn1=Je?LTEBobh4aBbfFG+{_53L(aUXc4 zx>?>j(vnY&5VhB_Wc3J*Ip!U#zIhI&Px`BY5remyj@4agEc#_d-3NMnWFdVS@L}Rg zlpJuePIfUl|QSn|)wT0g_ioRZsdu=KF9m z1z${WTRn|VKevrTQ^;L2AMGxfw~Ma6GG(t3%zI|rc{eJASL5dx!a$1s{@#YloDpvO zCWjQgo#==FU$iFl~AF4(ZkF0KKo)Tv`kbZ9!d?nfLSBe+;R@^}o; z#v?VVnP4D(Iq$-Y6Oh3e+(*YbHZFVZ2^sb6 zx%0gz*SKeO^lKmQQK~Iv3#EhT*TRk(Ften}jvrgPW4JYzb;BxS!BqQw_#JCwjmm>K zHo-v(fb!&*w1$1&dRf6Y=r7z2b#1E(Mo;io zVNXW6QE}!I472Zz(Q%de6)_&h=?#h=!OH8{5zORpoI$iObT50OXSCZNh%{eX4<@-nDxBLl==wSVKP_qVvOYSXRG8jaF>v z`IoZQ;y!-Tr9-tXcM3E;Y%3mfCP_I;)>qibf77YF{nm#m4I-}YZalNJqh5w?m%M9u@Vn+;B=1p~;f&p?vCFf=gB zLuU~+QIv%~&@eRsnvirdoC0`(jwjt2;-qgE0{ktLjxJ8Rl(@2xc4qK3e{#Q!G_*_4 z3@+fZCgI&)w8;Fet64b^;Xcd>1m*iXo7qA6%J0&!V7?h?))%7!_5$M$Cn!UKK^W3a zO%J92Ok10IcY4zO7sH`_xfyR$>>Cb$l0Mw4KYoO-ljfOKvx~1>it&hl0QJ!W&qup0R&p;YbuF&f5zsJ zIs~#cxvTt1qgyBb4z|`jn$DCO@68pzncH;Ws4${~;99dqcdoFvy$hlg8Cwf+_GY>A zr&;D&r*xs2ayOtC?+>m5jsMkd$n%=hb!SyOYB+n-t*wPv;c>`KwhC6udi3gs`hVeV z9K!NrA(nn?Ua%I~(s`n<)!v?O!_s$PjBmW2%AiA<5zc*{W8ezWdLD^Omp=0-Oh>H- zG(+zisD5rRXTAra+id!0;%FkC-%+qfrl4SSojU22O6hmbOw?~Zzkk-7VU1~W{)&jW zZb2>G=oQ?|q(jlvU>V1oFV#l0ks$h#4DLERNHFK+X!4qV8807VEN)w5&VdBFYmszr zPwJR3dg<*yAAL>DXW5(fO#UJ`SM?rmEzG*6;etjS`sEo2r4dVol2!gfC3&3pUP@%0 zZJ|-^(zDTKEbk?g-{<5-2Ze@~p084P3Jk-bosKi^wbf6VA}z8Vb2pGovx(ZsXX z_z1lec!2t))v(NA)nE$wF?DhvR@5{c%oveNX2|^FN%3kE*;rO|O#47A`LYEvP*x7b zqRdkQHwnU^d&Bx~y||`RFWxjL5zH;G{7DYCHr%fvE?qOR=q8(Xp_V?#hIOA;Zuy3| zEG21kZ-J`VydFOK=r@_epKp%}Wb7YcVEG~bsoCX!SY@oLDlU`?&sLHFvJDmCcM->p zZ&tq@eXUgduzBRYVK{2J<>-#W@VhH1=3JjH!o#S|+clq$d$kiw`seKO*{W06_Q)%SvxY>#wP z!jq|*UzY0TfHxC9YFY*W|1%;F->fZRw8&%mxMj7+kC@iB$P|)z#jU!@v0*2XLmF@S zzYhmnySNpEuz%S66aL#n;sKm2?+J(FJqcT*P!{;4L@#??s?%OdVAo+bzc5I=%O3&dPs`^gY4!upO^0O4G@7B77XD0lPI$sVRj|T%b;>!z>k(fOUqL&G60!<_L{P~*{ z?muq=VgVx`j78o44h%+ z^#q=3kI0!_`rq*~S$*&~hTiU)NS%lT=PvX5g}RQ?c8}=t1!cxM?-A2?zy2sm)o*P< z?I~a_AAKAYrvBNQ7tZ%X((%gADzt4^)~kX8bl5RzKnNf9UKwK(g2j~M9nt!svf{d- z@colmPrX3iACf$JMy^jYA*(~hc2$&*v4Kbh(jfJEeS!n8wpF^brGBI|*q#Gt9l}BF zW8G9A;!sCaDg1c2`vIu-Kqw%VBc5DuaPx1AJtjzyYFm_ z@CB^Wn()AqoVHVqYwCQ@0}+)RKa%f758RJ0c5|dg|DzR=BhLcYAq1<-pO~oy1l%~n zI@Ad>XFRmYxl~YYI;`*AqydzH-(n%s-ql-mXS2~VmyIX114ea;++KA&3GUrn8Y!6| zS=#yG_z(>c_}LU>-$+LPqbQ??;Vu6LG;DB8YzoB>;V-0KIn~b+nL^oP&1UGkfXT&E%zp!%pt>o0hHlg==@4`~MayfGDl&8@5?FCxr@XVQ`78 zC-G;?(6borw;RWe`NF5cugWp-LTLZ%N-XDtfzSJ{vJ^6OBj!YcLC+us^O(JB@b83$3XYD!rEGksM;C?QSQ&j|5Dbi zi-i=C4T?aHXgvGQ1GA>?$(be6jt1v`Y*4*Q!(zDXx=y20*^RYAx|hp$;WIELTYHrZ z)2f4S-%B`m^ftce#H^FAh{IPIa0l%t7pkJL!?cxUJG{hF_tqZyc@K#-U9HG5old0b zcj$``pbi$NloxKS#!z|L7m_Nd>!vlf7u{+W&VW$r=Gt&iFxs@>DX`NIQhRa1Bd9+g zsy+MRYU4y%Z#G`^Xegvs4ciYT-dLxB=e1Q}sMp|A6yUwpi63{&F z;L(S5$G6oxq_**0bnmguQ_*uvcL6i{Ep-luhE;nvdiln*4lZ$M#C*1Ek6wybB)z4z zDexx-;(t1JwnRkr$H5dVexO0eKHjrXD|!Hb_Hu4Y6S`B6-Ta&#NCdH_p|g|TXwqYw zQfUrori$+S8c1ECa2P~Yzdj4;jhj7aV2ZK>?fJQeQZ-4;t#E2vkY}&02W%JSGs#aR zZ9dBGB4Dhe^d?t9%^%Zdw{J$edfr6t10yCpVsN>esP3N8AFn$r`menKW}Hx9bNgRjie%f>ELzz z*)$SEJ7Pcadtq-2jlI+PhoYYyNDbz?KdotdMnc|{|IT!evwU3bUN7P?@F61oAMo=x z#6h#_fhu=n{ot74D1YziRd%{U1aW*WzdRNf;6dW@#DH<}O&7haEmc|*)=%m~-=*u9 z4tcYVl-f?n$P)}E)o0jYm|-R=;o_mBwj+Z4ZY0U$Vv#cvp9Mik3$QrM_n5B&BQY2Nt z5y_s`^U9(D6TmQJ{0KbPj*eJ=nIwzq`f)U_5=Ae#WK+xV3C%gR8ofRZdODf%`)9Zm zSs?dR4>xyPLQ-ula*V!d>^Zid3&kh<`TD`yZ)B&Z5tlSg)ULb(efoY8cU^$yR_^W3 zIREn2!`p*7$0qpJ((A?y5NtLl)?5dfBjDnuJBuN-xc4Ss$aITJL@Sf!UxFV?^_HFN zPEbB5AuNKhWmb{tyH=52$#X< zGE7aXth+f$Oyp)^>DGwri8;WO`pEyMgg36e8@ch)Wsi_HbiEHYd$f#T3>1sUNqvva zp;<b) zL0h_nYs8!!FV9HqydnbGu;u02$KO3>l*JWlIS69QLi_>ed2Jv@_F{!s!Xp*v1g`!A z3u&m-w;<&<&`>>p`QGMF(O~P}rjL%U*Vv@=VuWGTi=F{!VAOWHLSqZkmFilL=2q2MvWt^btz`E9 zWdl5LTrgX6R+hl4UauSTLRkemvThN3SO9zwj?Z9troIG>a=hyQFn9KhzW(jK&2`4& z>5oTLGv99FUld_a6=0jNGO5bv4DNg{7Cs>+MaQYFpJrm`t(wMAk6g<#pg$OuZ0Y#@ zkHh(hC4tW`mN9-FK+LGxH8fJY-keUiYByzZB(eTNtt9MZ|ADBQ?B7Fm8SRKDmk>=M zpD1c{6)5=MEKVGIjSxwlmN6&qj{wtG&megvDQVwf3pE z_6e3Twy+|aT|8pB;}IR#2L^K`3#SZRE#X26SYxzhpqnkV%es)e9V-6cRRUuWK7j%m zEH5p>Q%GOc03!{F^uT^1yF1_J8T2m$5X>duq3jhLk-+=-zmR4ky*|Bk22EWAQ@4f^ zhy2C_BPHv>F51tc3voi#`SMSwF`@%)8a8HT)CNergJ;-CPA6+?_}E2Q@%psQ%Yp#l7ZH9cB>&L#|I+ZPP}Jd!3Tl5H#@Os$7{PUP1= zE=7K$1Zi7>^^GYF;6q%bQz(7bs$v7ogsDHgxLr+8vVJ@qKXy{00Js-qA2adAnx0Y5 zqZO8P)m^>4#c%7z?Wx&Vb0YxB#b2$6ceYGdbjLgjS^;MfOB`Th(t$^szc^-G`u-#P zIY2x12AS+PiE8hWV=)I~Y-OD2ZuLY=<9YZy3!B#=3{6|C_?7-P!GmA1NPG$n@2!H? zzlJS%Ew!I}&HDV|sVctQhTu#5?;J$m;<@!uTcr)yct3u#4_Jqz=EC&Sm);h=C|^s3@&Tld%dS? z9o-@0?ss{fj%5N6Kg7olO>DVToI4WI8%d>c}Kzojf+K z%-vof3K*=;!?LtdNm|#z8;3wL{2ZxvQ zsX)HdsBWNK{BYkr%A(=s>5u#JSc-Y8pH{OxzB7a9oW^Z`?!^bZN!dojcwqA-(NNX( z;%3Qx$MXRF%X8?nGgde^P8#|o5C&55)+2BLb~sNv9@7v78nH8A-!KM#pKPFX9i$Pu9#$8L9d#lPPa5_yAVf&tt?>O~5>`^HA3~Of*+n7wA*|26F~s~l>>p~|W42-G z{eL<~#=zEA93QDX9(Qto>oEYh?|f`%<#kV0hyVS5GlqxzxC4Ju_IZ!pEOK@yan@6{ z%vZwd2Bd6TM}Mc+)vXw=4Qq$W8(8PQy5~V&JL*x>TXl~OI9MJve74FT`{kVt8ouf} zJy!KOTutYROLAFAK%w`)|2CNYe$D*tnR9%XW6HzJ9g79$tKNlTG3ALBcyitQj2_d!$ zolyG!0XSfMrOP+X?$CQa{r<-yPf^aRQeQutz}l_}E{OiAQu_p{F~I8v)mrxhFj8iR_WS_PQv@_lCJy zx9_3{FNm^|>#v?CkE!Ve&Eh0Q@bxi1VKd#WG%^f=U>|bBXAns+afA!>u$#uBAtI82 zuwByltlP__;jlI(m{OLp=M8F6G!E$o>Oj8JL%prO-gI@$|7aCeA-34h(T3k)ViJJ* zrK}v)2K>nyddU{sFzOzWB_nir08bbHNggZT-|7o%3^0DHan~1j@^~=!-qBuuTH9nU zCJBAnJKL->%rP>mBXp*JnH z>>2t(CCp~?NTn=1nq4-Y=}le^DmA%p2}l1AUj&uemqeb2yfBlH++1r!bl19`4khv& z=+#A%Nwgs|$TWM9ERUmWyQ6fU5_02FNK_9@hFz3$C}0L=v-||@Kzpf}9_zLxWPFjq z{2WbZ+^0b9QDi7_HU@`Xh9eP-f0R)RaT4eMXco97W!nGa%wJoDl-JR=-38%Gc#NJb z4x~Vim>01i*~i#L|446e;>7tVY>I(=aY9w4`)yi6Rrxsaf>VK+o^*C51~+2BbbY~Z zFr3PJE5psB{@Ibug2xGa7oXoQ2#-2bnV5)@r`m24|*$B;WHC0VvNNv zT;{K~5=`ueyofO2y+zc8{>4sNsX2a<$6!UH7PyTyfvNqg0f02(Oe}Ejdkh%6xMZQn zHOpcLrde-;8@@Vu7%f4IXwf{DtY$rQ`a5Gx!pZjLYZz*#$GJwaaV2gQ6QNRGl!Vdv z&)wU7lNVuF7L-`ZV&31>6V}gIiBukqDH2ft7=^YN9Gu#R4IElgw{0F#Uj1$ zs;9^913Vi46B)=}g2{rXFuxx9Ot;z@;ASL5`CN|UZA$ZnuhpFZBVyAw{=q42xEsqR zzV&dj7b7$LN4VsVnu6z~sd9(;n7d+bAP3gGw0((_fk;^y$LOE#y^v*025T0AF%hj; zB6yJ?(M@+6QZ_VA9A}yEotDDVuPPH<9nsz>Zei$`%*Cq_FYVw`SYL4NWPsx|C^I!B zH^9t7g;RW&!EzS(txJfvraL;h6h`N%yWZW87evrMc=Fx8TyIV#4zhCWQgcdyU`dkXgfXFH%`=X`;`^HpAbZT6KPC32E1@1R!3j(h>y@D=Wn&RQjcaqf zM=8YJ#lH^N>K0KRDM7R5j5QmhXD&Z5+&b zE0U=A8=`zCsWx9!KAZi44mmNQMJH`FU(xM8P=yAbZ;FVj4oJWL2j)`mL-6S&w1_d$D}MZm?5y0BX}AF|cSOPcE05S|G0r_I@tF7#CT(cv?E z-Q6~Pc$dj_Fk+*DzVPlzA;@!jI_ecgiW&>=qwO03^?CH|gKE=rpNQXUdFd;rl($9v z77ic_qb^5e{EyhuS6JRZT1R~meZTYEw_gb-lNcY9r>Jd9GU_GqBG~fZCXDv!f$)wr%D2PhyD*a~E*>QD?T0>s*7lY55+y$I(V{MfJ2W|S7 z$@MRq!3jz%c;}{%4UWYPfX>RwqcQJ+=lf@5Gv9FHgV8R5EYqXB=_}rutX~d=*;TVu zh5yRaOL+GPWRKn69o`3IO~6A)p~Y35;^WF_d%wTWS|WrTJ+{q9rc1EB2iG(+LOnMB zLleiE?Wuwp)!SZAfhh$j+zV-)Y5eW@Yy{{0YD+V#y#H|QNb^>k-0tX1tAPPxfo{3n zd_@$>smsWBp~iUvwS-D-oPb+?p{7uZ&VZYGQr)qOfUze9f`i$-nuvu-yJ`%Y15M@q z#@=g06{)odNnT(Nno6CH%I=b}qQ(L)ndps4c9!mM zmvp*^zVPnw09S)$`Om3tlmI+B>k=;Sf2Ox2FC{FaqXQ!WDszb5OKbK%9LQ>jCnV7A zaP#iQFs@z_tkf!u9g68(<+sjZOS_kA`>!3{~#KSca-rTX}b5Wl%f zm%V|7O~c@0H&SQddd?nj{kLYlQ7Kh#dsZVB2dQJLQ8jSx*xo>80Hby(toaTbF?b3i z#rk@Qbl(qVv%FG{(gM28Ar7`dSbxOihlKL`De|c0~`8$_+Tj3S6+qs_l znI?0{e|q7pbG;YuE|FUm<#)>rce#I=@L~0R#=kP;rdevbp6Goa(iJg) zj#6EDr->_{W~nM)0x5CUP}6?Cn%=lUW_5meK2sDGPh}Fv*)NbG_dfIevxWMH#hGw- zLK9IQx!jk?QF&=e%}F}dT6p)Z~58QU}#>NUpLeCx9ye8(wE@5 zE{}#p_^xKG8m=}*>XM|M$l)OIP|ig&7QM&N4zZm4S67UvAGOg#HN#y;cB9>h536IQ zD5X9XZIMOQ%PGRMClQ`vw;$)q1Hfhi0&Q1q*1Y;ZMR>^$cceZwDrlu&o#u8RxbOs< zzzVh65yuyLfRb-t$m(POUIy`TX=hEO8DwadS`sEX^z;no6-q6x@8Z@WNvmgs1RZKC zTh*eIZ~6kGskP-Hj%TM))OD2j?OnkLdTlnVOYKUF_fLsAE+5q5m}d-}!5QV$uWNAB zrk2&R`C)czj&1!t3x|^DUL4Uguc%ju0^A~Hqehki<&4uT$!ePA@Ly?nS`164T~Z7f zMGs1&{qeNPw7Y8k0tWP0G(CxU;HGz-j?^z~DWg^4ej*SWqPqH}{EWmXSIr|fATd|) z`a*jG-@GkXt+I#F2ZUn*Z7nH93)3d|F5+Xn3W^-ltz|c*DRDUC zFZ0!+o*0ZptJ?a4=tJK{x;5}--y*j&&J15Pz4S|mgV_ZLo%8!QRkZIhLA7J}8E&Dy zU1oKDRp(c|T@8h<^|sGVla&M5pi_Z}9YJ8xW=2Y$Me2s;Tl8aytj*N!2tz7@57>_Q3UKX*3)8^icPYQbRUVs!^8hRAga~TK0|8Godfi0 znOLnvAY!DTt&8VWlEHBMzRQknrocIoVfG|J)_3|F(luaeDwY$eGOtFQ>)vYoa!tS7kyD&09;JQ^2n?RsCz zq4u5V2N$gj4~VA|Wh|$6-QoJG1P1uJG_h4prU?Qa2>+(G)>RIVHf7iN!F4Jlo8^Zm zZGh6{qItROW&em7b^4RW-uY|X>N}@)*t`C4Le1xk`HS8*OnDArf^;-ops@XBE+Q3} z{L%X$$HCA|u}+*Gh+-K*zIAPR0>7HVVhi&5f;P%!fO-J`fe-^T zyIB91l#PWatm<}%cv)_meST)U8adnioGo`gMNMK**{$#YlmteySotQS-y431pC6L+ z{WB-F@@2sOwi$&!c~2CW1sZA2l!r|jR@=OQt%;+(H&%%DB7gsU?8lK;=qKmCc7p|L zYpW`~j`W6s79>f5!*qh1mPQo^ zg>D(sl0|+^Ao3;&<`0d>^2@5?#|00P?O2{UZJw8N(g@Cb?K8b~e6z8#B@P2DAr6C6 zK^j_Oz|-g-%BJkcExI9j7G+nY9$?W^2cIC7hUTURTCpWN)JPNacs% zgH&ah9l*+Htw?Psnf;OO_^ZS`qnayLo6krK*z55&VvjugV zsOo zF2P|had4!$!9T=e;gP*^*{b@fLJ&&73HeHLi&}3a1q&4BS_pD@mYS?IP;hQUPvZ@c zGEmw)Xb_N|$zA{0%A>ej3gl`JW*!6v*D1wYw}a~)CJ{grK&V3dmPK<`w2Vi^m66KO zB|ze@v?0bSatkZ6JX%9xX1^Zcju+8-yG@+eC4}8W55<1pva?fWm+kXO223K)im7Hg zk=E5^%{y0nu&_>T;+VL!F>_6-h6lVfFQq$L@1rna57wO9Teu*VM{#mZ77x)=mx!1Y8EHV?08O; zuxQiF=IZ0EPKC%7D&aY%kVK|**{8LNBW(CiHDkSp?0s^MM8Pub5te04h>wfNz}t*`?15$c)frsvW`4DE-N|KW}rZN(>BeV@24)1b$+X zecSj(5U4|8Y?}0s;GOehF|CmrW0H}EbOLRJ3i33o|K zZ0p13Vyk1S=x>9rbf`|Z8=V%e#(y>Rn+eohcf!wZh(5S8D@DhJ5*7g0BN0p64YNKJ z!rQ!WLVuC5J}4BjSpq|XrkP_wRe7VhWrU?q`g%nO?`rhBU=~qTUnDja0LO&J@zfhwAtd`t9((`J^LmupsQSvdVDp{TgD`vu0<{Z;qvEny+Z( z${7n=X0KQ~txEqn<0%Hno~vkQGF)wmIrb(6^l4jOW(EG~dX%hL3DoJ~@QcuWo=~q> zJ7!Xx_=*u1^fFEoz2!3>hRu8y#i*!YXBcqBGZ1-6R4?&g)YJxNa#01Ct=3M*RjbNq zeBQF*l<(If7TIS*w;x-Zax{KX`i!HoqbBO`%M6!tCLDvR`knIx6|*AG`%uq^{Ff&FA{XReOi!K1 zQ*MECM9BWivoGjwjH?J!_nF(vwcT)vw(!NGFb`SA5^4F^cTkA=$F~1Cy^ov^&>n&1 zV7cYh=K2eKK|p}@aWsDSwlE%cy85d!%Cj9CydD#`fY|VVX>DsPpE3BGh^wSK{;PU= z?V~4>zmbIB{aczwSMvB(b`DBK*5N}2q zpXP}cFPnkiR$PB&;roX#x!dJ*?dxdbDx4oF%g-)C3y?-)-YW8uDm{7eo}P`nfI#E zY_bD{t^mQv0eQ+u{E7iBORRz~Skl^i8^mjJJ*!jp({lc8g}@y;FqZe%GNsfdg~Yx% zhvSlM(X}?dN~hdGM)Vd@Q`Xp9A=vF6HV55^OkOXFdbOmaWR?e|qHzQQbqGUiI%~Gl z_(v4)S0YC2n4mcdYMBdfso-4+0)>5vi#c#8pvVeYv#9w*&bkEEI;B?)6WS4KIrP9! zqC<1*8=iK^5{rBqkzLVx(Ci@36aT|>9q@u*eb43c%~l2p#7_!@6Ei}IsbrTk%F`Pr zLu8&&t6ViiKV>r0{)6#ORpNCu$~(#{_;OJLCz zl}<(T`D-<5uNWRLiUFuHT6irOI(<^7rQ5m(yf@8N6aCNeeh3PLl%ywvceU z9y_-O?5?n#U*nf1JJdKU?n~|8I{9T3Rz`OO4v2 z#HQ3HMNzeD*WN)mwyM+~wJELIwbkClo>dgFY7?7S-@M+R&+YREe1A-C$?cq+>&m&# z^LjiU_h+fve-61%${k!;O{}Beb}D@4_Jz78Y}-*$PmXzd>=@)STlRh3)QQaUW{_jN-a;WL16l-Gsh3~NUvE}$zw%}{@UjmM;R`R^YK%b?(OsK-Ng9we;kmtxu|rBR%-t>8-Kj0c^vq05s5 ztMW=ZFjhv-nnBwqIY0aHWo>?!*Ss=Fj=QG&Lq{Vr#af@m^3&snV2z1M z}Bc8Sga-`fgjl= z+@b>o0uP#&N^(vih6gf)m!}y{1NwfGIz>b@m*y*Y8(La&c z=Q+)2g{6Xi_8U#5BeoLKJIA0#jB;CCR8#AW(gBtDHy$5A>aF&eGNe6H88Wt9v&GC& zb+z9#GtFocVfGGda@>RF5S;SLur){-jgQ+~MoxMXrCLrO4tM-hbf6aCaw_5fZ%r$C zi|572zy8gRBkLsbJ-F43D1Q{h8fk%J>@i%semrP7==dY^!3*;FBkj-n!AAMU*~0x& z!Zh0gJVZdf{C%*^kj$XfMxwm?q~>kMSBDSGUGE?F_R~LhwT<{pEDIKzy9lGCKssuK zbUBU&QJP$Cr!90AW=n#D50SwdQ$_)w6MzzyuS`mi^e9O%#ggDHsI|@&4ijh)o(${j zfeAT-gm1?fYJEK;Uc*viS)|%`GGq-`=r#8ubASf~C7;3U3<30t%yXbf9}4Y>#S_}O z#Z{hUfBkYMtK{x6AvA{lNQVVLa4xdaI`tmZzKSewx@{bgeH&2hw3bIPNA;_7hlyDL zW71SRh%ho#BM|qHt5;IUMX1(^amtjqGf(u@2y{+WD z3B-RE9ZYOr6(7xPscc{VkOPe|pJaAo6LX?4JxS_%#k@vyGrS?_$2|Ldw4o?05-ZI) z6O$r(g4=;EavAE+HVTV_U!JQ;V&JO*d0a%_&0OlPWsDaM2->RF6Sp-7GWc0g|B7XE zj>gjWn6I(<`n&9FJ+B<{yH7_P$VOx1^*1u(r1don@=rHX0p)uA zdqoV?W@h!YUA~k=xvlw5#!QC2*0-OL?dNM!o((ygPv))YhbBTQb0RZ1o2jQu%V|k7 zeFp(Do>!+BFRa^aNZ9y}Q%N0of9!vFf7H?b6x^Js1ck#>yH`-%4=Z$S0&|D)X z)x_bVlQo9rJVY1HqShm^4*Oq6{}d`Hg|S*9b9?>z&H1kj#sQ-LZUNZienqS*!b9js z=@bkTd(;al(od9f4xZ&Hy^d~xQ>rfXLqdLZ?C0;1bv)|#{a&~p9pWS zyU?#Qjb1(TGkw(D5r4493*;ObJh}}>89vzkG%znZbPATbxia?JSFxtI9xUN#`Axso3XP+=9#@s_fAnTj8a zS$WO;g?b&wPCdTL35PGSQs-`Q+;Pxq%#+}4xrxidY(J%i@Y?-GppMsOexFkbg~cUk z%#zpid|4LRsb%eUrfia>yWEW-)jBUw)oLGk=Cw<)-9;3M@gDng!%CDFPUd`$g0}n} zwrvqMzF8k?m3#)wF+>;_d?4r_f2Y>{ymv9E?aCm(ni{{DJb7MP!3#I8Gg znz5aAKBIg}Dk3!x!6SrKPTKb}n{Zc0AVT*M39Q-}SEnpA`)GC3Nt&gsZvEFfF9-Qc zd?f;rt_|SVfz+HtN2-Lqg8932-qIsF?#qzjnpyq9epb(9;@A!2zpAokOuY-*bcjkt z=apA%htzheynzR3HD0ZQybWi&+IPC7jZ?x`0PDQL_mSRyYp&+6z5^B?g-LPowMzu$Kgd?2l&Zr*4h9O>bi zstytZY;j2MNv*{xd>H#8CyLZ&u=!jkBC)C*m)=ptZXHlw%}W~4!o@Tc1hjRd~8T3%Nq z7_*PemG)Gm4xM(E_d*vHI-$wFTaF-$HB1s1%)khUrF?lF_U?PTh#;o=nX!8Y|-)2Fkw>V84JR`M=jgyzR9zbE{31BUq zMx$jyA33=~PyUM$1S+{@Cs!9kGN!C+hHlAmHXdGrx;9l26&)*?EJ}ZdhSIbV5r&nx z^0VU>?Fn>T5B?F!p;My$@7iW#cD?SRk+B^bZyx63NP{?Ojmwf;J zefyB%;Y^9GfS*Drw3arG3rE9L=gLRXLuldVOp$DHdTLNi{{t>7wvKSh8$~5> z?MFXMp{)2^>1ID-F`?w6yX(nkRyG$3-qpxffeCOJDYbFz%8tWbra2`o$C!l&R5>KIqpF*kJBKKh5y(@zD&ZI1&Me` zlP^{~V1rw@ykAs935!T3eex{Bn%O5`AoqpoMggMAwCDJ}kJ-|q(vWFsp?M89 zeKsFJ3Ng*DL*Z5e47o&N#x_`?@I|o;TCjoW8&np=4CaFix^HF(3ejXnbTW{M~wcG+%QCaKpH*L7SPpD!<;Y*f$UtnZCsm*#A*jhE4B?BSQ^jL#A!K4#5{1;G`1E zqx+`s=mG}&w^{dE&MD6Ms$ja(zrz)hP=13;ZQq(MzDDod>!maFFLO`6(mG!#+8#Gu zZ{`UIriJyJy4zlhD`LL6d?v?e?#GkM>;r9A2F%Db#B}Wk6y4#5IxcwbYqqWGQqVe} zL6cgUKlC+MI`KnKM``3w0;GZ0LTCS2!ElYkSJ71GswO7veCs$^0K*uHRn`ebE zn`T7BF+fM7?ovI8(vQVsK^~S~<{Nay5wMk+Q$7w-_7R}=HQtJ9Th?Y?^ za3*e_xv-keAARXevOs!eVfSl$vNUn;#a-IPqW5vhsxZV8>s*j=j>XVhdLu3=f2A3p z0JsWQQw^Gm!)e+zz@8(NEloQi&*%C>FD!; za)nAFzga7l@zs1PJ_H(LYS@C(dqiyT#T%&yg9Uc+HLp+Y4l`=+g)BEV~cSSIkF*L!WC8i z)+>(s3wDP6XwBDDqVm1ojFbh6{qhb@(qw$r#Y+TXI>aV>A|sH%X4m~Sr9h{zmiioJ zFoz$wS5j;XYN3VT()C4QFH~qw}dzBwA{!aSHFd^U0D8D4yI%ZjeXD&+JRe0pVdLS zs6j;zo06wJuw!5&;wnT{GX#=9&mo8KTO){MhUCW0!=`NEW9WTDar(Tnav#{T02!NP z1Y&tgKjNv=qzpX%9C+g<0s^Hij|cV2uEyN{mp2BQ`~1=IxWv)lF{p7BqksuZ6?CyI zYQ1!M6*gsmxaD7xOsCttBMgC?5krYU@j^!ik>z&y;xMID1UldBka2EH*VQ%dk-}$= z1FKw(96Q>y?Y7N_em4E)<6W}EZ1x@jPbeiuSmj*vQjIy!HyDQiv z{FNp(ZYUswKPl+A4i~_nso-^f294iK3;>hi(RGg^uNtQaam_ zx12t{3{LaQS&Ah+v~x%gsA-wm;+04TXsetX8@Ezh)6c5j*mruI}Kh z-Pg$XT^feWzVD^EK}72Rinr-tMcffdD9)eQ!2{CP8%(zNJKu{30p|+*NXmD_zxA@y z_WZL|U-XgcMX0cm{vJ)jT48C~OkF;&L8O$icXh!n+r`@H7Tew2PWc`m7C6-CMTdZ^ z`lD*+*#pK3b#Vt-)^&jGe|)1O%&APW0a8WyF581pMck2)^#gFolzV>ei^} zsK*+k>87Ih``JeiP3}2g=x{WQQMPs9YyIM0?}$H7B7|-?5ceLlWgaq>l(I`lM zzy2wNeN=yp6AbwV7E>{a!|} zi$%wV$*;Y9@l;?CrIsaQ7LYzrJM9fURm4#*k|i}Y)j@T(UB?El<$ICwb(KjS60c}E zPA0v()iv->SbHXWqT{SyER%qNVPTT223 z+ju_vmCt;L=DFjv);(q)uG1F(@49s*e##s*I^{7NXMjmdyKi>br2b!3$huzUI;b2K zrjGsKDU?At z(LPgmK;9g0uiIEr&I`ve#0MFU&8jBj&AZn8C2mYMUL*MLljyjlf*--Z z@%XP3f;&geB|}LxLz!6+W#+<=%qXj~9BB*?LQ;#IRRZ^YeHCqk{uGbnB5H3Yv&s)` z>QVl|5mhEf(&roW+LRq8y7tfOGBlPb*34M}~qyFCYO)6#g{;sA# zR(y9QBNVvLwvK-U#|%a=NPka@dNtQ{t7b>_cA3gq%0Cqz@ zV{qds5*(1eTxob7boFU47C8TctDd_HBzlg0jppDzM?AkU60yVoz@sKK}(&e zDK=kIr}-<$$d9K8i}I`Jw$Ifh2F6LWDp^imO5bF@z2ErwX|`!sR<8cVCOK>*XC&b+ z=XNVcKWp53@1?q|n{mt{E*W$@cmJ;C=uS`KeWnl*_ayd@(@fB-|JZuO0MyCJpttr* z{<-$8Dwi-Fu3kth8&>;R{f{GspMdLO_0i5)>Fw(T+#y$0n|h+==~svdAedWQ2|p-t z4wnCU2gf_+L6?o3fEpsbod^FZay#gW#a~6ogR_qdA3P5qwKaTY_N=%2pe=10zU&hS zy%3BWql$9O{ee}RHazJI>;$?Iq0(Uh6+%FW0h&;$?4ya^%+Y zPu383!E;s9>xdIa^z88-!@f_zf03dOn$f8ND{+R7!|q(6-HypeUtS62W@m9($MKmq zH%R`-tnQXeccV8(C~dpTWOF^5k7CmFF&nZ`&jP zC9Rm_DV=lgbVsmFxA}5!C~kzT((lKjlE4FaYY98VGMJhR81DBnLt#@gqnlk_sCda+H1dz3mqbWdVq419fFESJw_2~4*?(7?wPGv!h%Vqr$tcIZ zO(L-RF#tiP@YGDQb+ARkPkyCI_mvK-{^wsTUd%;up;Z0BXR5MU4&QS6r#QH8LS-bt z5!3kZHa)KA?1d8R#u=#z{Dz|#^4C7N7swuN-+$e>+F5dl=dEfeoseATUhX+BpSuWj ztaKHRJ?nT;&=iZUoj;D8$EvCleO7l*x+<$5DW@a)82w&XCp4%^m#TPyk^>iVeim7#rZzKp0?nDCqro;+F>iOIw4Xt|5(@Fgf9B;_aT+<`h)-W{o%oF)Wa#&}+5$#mDPUAHuEP(*@ z5mr4&fnA$FM*&r1w%d6Y|9sC9s&@+0{hfe{^qkhGmH~1jmS$@4`*K zj(G!IE`&JJBWuaB`rnvw^nA(hig)u~Q-jiJN<3&}7ou7W=|W`72zhUAu~O*!mw6sO zcVpgu`yhirAO*X3O_9EI*KxjMtI3T|WSWtGl}$gl8PWRKsA?5E26_k8vBJlJ4=LK)~K4%ITNWy%y9rSda}&rK**p$#WC3}cY7XWJ^CNzExq z(=mfSiA@+}LVknr%S9{sa}>6}c5M!6P~$OFIcEuBAS(k?JuB!h98q zmZ%-N=fkNcAwgfKM>T4rPxS4e5FE(@5f45Ud)vlvue!!-#-xJo0MOi)D}W(Ntz3)L zi;4G_f8HMtsuMK>mT$$G=&xmIX0wLnJ1JWsltsL?d@bw}E4 z22@i2)m$Ek5|rQ%Afy9pQu9Q*Og+k8G&y}=|Gt1(k&#?1!~&g?zi|l!jB|?pz7C&X%cD*o?fmbIFr^rS{&YEvz z$TI$AdzT2yego(%vcVHk?Can5jje;XmJGgYu>gI>2Lac6{#R0rF*M%;vdK+lAY6XN zW`4lGXzuBM_-)1JFFoq6;F~`r%^JcxM|x-C0IbRSIVoEKOvgrQ&p+c}ww(Mf!*}}J zp7`PV-ppyX5IQe@16~)$f`9*l#vmgVE(Oyvbp0o7z3?G?X$u%NHbuSjE26%|6N^$Z z2SWS&k91_u+uwX$htAEXnhh8k7cu_jN?iJ#n$t`}L|HyID-b)#v+mkQ~h;Zk-CN96#{Z(vw>MCyu`-rN$-ZWLeshIW;8Y%71Q70pM3?{k#&DT zrTT5M&YH@kVUB>kLD#@HV`)Pe&CBcyI0d@aRyn#6nfgY{LTp1dFJ0UGRm_Ki6^lf& zn0_e0{J^?ju;hUM7hY2_uL1QN{enUtJB*xk7jZE$|DPi7e++*WJWGo1=UsyAzczed zl~Af1m!$G|9Sn6k8CcZ&Na{zVNO0>OoH>(SldU`Cp}8j`Q~{BM)GM`RlQgxGA6hvs z2RF^LD#NtSbr^-)$HDq|ma<>X+k{)#hRi zA66Zh7qb?fVh!AS=(7xm?P3V*yqoW-^^sxZ*?U-nV+#$q6g zX}Jm5?ULWq2uODdSoigzEL$t&-Cv78>L)TjnyRScKOa*!z2d7FHE5kKWJ2N7&hf^K z;ZFXJcS$uE!B#9a#LZF%zXsJWLCt1^pZ3?85D#0W3m2BZt+To!@v&ymo;^@`0$zsu zL0(4HnA%O9=@FiAQA{&i!<7`VS&s7+^OqV`!;F_=fEOMMWPQ)$ibCJ;Xs&4^aK4>m z^f+!mn~KgTIMcQBeBf-sqnOQ^=fT$3iL#ekkmUj@N;mJ}J3Ybss@g*HB3NS(rB5G| zkMTl+-CZ+FmQi?tW7!J#@nYm*cFkA!pS;<#sIEfy`DY$=y4zoA={kbyPU{-FV*O=V zv<$Y10o%;JA%9^=B1dn24{_|&$`M6Ghqkliv)kR(dM_RDt21=8{rw(tEhbpOtv{Nh zty3dse9ds7K#I7ohl@rbM;+xD<+U9Ip(-lNmonHayjdZyu?4k4md;w9@&Kr~1GNuJ z$;55&5gyMDZfe`gcjFFj{4068{oFWsOE=noMHWuU>#DW-_@zJ|T`DyCt6?3(Yc)ByrC6vc ziw@rKzQLKNi$R4`{X!#M#JDy)mJTtEpz6t;J>YNH!$OpMhZa3L49@jH)4-G=>^L89Ih^ zcX$Y)ED35R;~&q3i|s+qu}^EDw2!iKj5*m*iOYih^pc9Ay%kQhy67B7-K!OX7=HPb zQQr}d;$Z922{XK@8ZJR;1PV(+Ib)#4%Rwn0arih{U!0zAJ3PD<1-}C3LUm<5k!qci z*NaHg%#c959oWMdEii#^LhNH1`5!0o2#Be>Vxq@`Ndk&Y!KuYiuS_ zlTz))oW<=2QoR-ZJbCt&V8%@L6P{R?yK2&?T7jlEozg8KKTKW^j{7QUbSUPf1lBN& zy-(rUZoGc~;HNpA@kk#IW>Z=AUGkho5TYe`wEyGUqp*!Qi2*=uHW9QkWk3lX@qfuU z>X6*HP+3wh z(&Ow+cne$hegfoehp_1ji=bCsmv2b@EbR(}N2M&;CvH2V`AQ>RPBs7V?1<7&K^vXA zo*~FsGsF0p;x?oNt|3sw@*4w|()z`ZE+VJ0#JDjsV`3ZH_9cNccUp`#KiS}I|6WuS zU2NTF?oSA|1l2-~#)TC0?~crjO%EfLl`=pOEuqLnR-g%!K8~Ci=YX8VdQ_jRYAZ86 zdN?gUZeLZnG}o7Vi@K8ifmwlbNdYTgphHs+Z~-iQ*}yV}h@(Gk%aVgEPH<7?vbRg^|0 zy|bFF+-p-|)A)uFjD-qkF{k5r+de2-zS21jSFo5U+9P3zsv0Awe)}I7BH!94V6(io zwcm^aKP$tf@s|Wy=yWlj*+}8bNzfQh{|5kHM%5oABm6qPWrRe?JaOo6CW@P3F32iO z*izr8?dGgxBQV$pPC);0(_19MQhVs#E8SIH&)QA*4I@<$#|Ha4h*S9Gg8`x{!)o0y z`Y6cfzthXc!}rEn`Kv7{9>g-H8rmVGZMB?j64wUJ1rm-r;t~^M=}B)?^ao0d=@Nlw zSfs4%B@$YGX{VkUNfJQXT(@I+Q?g`w(Mg-4w|D0CHK=@5OA(l4ab0Ap?iAc~fRx_f zj8#0F`}dzg>%}72(a9{WVe`0UAk6_>PGWyF=T}nJw7~q!C_ETH_F}@80xwM0OzOX8 z4IA&obrjdcnVv{ieXsX?mPiZ91XjOQ7<+~-f2-HGISDfD$STOe68Sf#lkeLWIl&&g z?9G^I(W13n6mJ{~r=P7Jw5v6K)6^0h8>RPgU5#x`$Vyf?={)2=X@@bq%Bs-2dOhD> zq?~%ny?D36fBRMI{@65gqeaz<(B;I2l_Gz?or;gk|B7b4$|$SPLc$0jgdx|uQJ9@e zN&o$3rjK=s;xgpZP{>dN{i|x{KGq)!TOh?$+)>EeI$d`(C{iBj>Zpx?gdV6+^oAcw z@BZwvxsW4c7IAI}6!8$l5$7$;4iOWe{7~ zbkA!+W1D46h*UtGeBz-^F1eqo^eEz7+uCLi#9oE#k`fhTSVS)o+7q-*N%X0Cs*i)! z>UU;AmQ}@FP4w=NBa&fBHJ*hIy_O+rR}r{ey4j=qsoHvo4FiNmD7K>QSo}bI%B294 zR)1Uq`GxQ(r26+E@c}sBbK!JwWc(<`4C6UmJ2Ta|Sz$23cN`V7Y~}b&K%ZiQw|-IQ z@@o^OXX8mk+MyV|+E+0<^_b*5F>q|)PfSPRG_~Ov<4q)>mCb{o_C#)lknxq4v?1iH z2umvZQJOA(z$Az_ruRd3>1TQB1ai^8xdZxbcBxVG2|`@CB`0HRII*=i-*_`q1z&P# zvVS!@ar$on|ATm7wrn4TzIeA{<~cs`9?s9Ll=T4ejdPTy=f0yMada>vE9#mtw5yPU z!V0^0$$-=XWao^<>(wq&m>=+~OX+?Ij^sdMgS4ba}V8;8bD#Dw!B9jKF;;EJg4p zWYQC$wD@}ezQ%oac9JK!os6Av=vUVwa2zToQ!b@^){m^u2||MqV{-U=L67nKLvw}a zhIY*su4G$ATCXzwF-KG9i^U^*e(!2OOtp)}*03P?2x7y~Eh1g>dG{~ikFP9NsOvw*_eJIibm0nL zBx=eEsUXU{g-GUtRWJ7PDY1pgl(n`xN4o{*J5X7rRvduZ6w7(VzG`)}FQk_wG(5*yOspi9) z!P=%77fhmtYu#9Ag^aGO24icNrONekh3OV(;9IJ(grw_ou;@P?wkZdntp{IZMeGho zjmH?~?&b|hc;LN*b^?x#^1JnIzYn%%XqXdSAb6qR0yD->!=2vfN!2 zZ|2Qz6EH1|5u`lSTmN864m~tXshf09Uebb13B3TfF4oWX2#x%GsA<=C>s|8#Xp88B zQ<+7w*DM^6@EBWH=|VJwR-+6uh4c-Qg-<4u>O)T6cB&x%ZuHSX>F;dhE#%AqBcR9TS@A+wF6lXa^*4D5V)h637Gc;IMuCZ1md~zKw zlo9YCt@k94sc@B5v$bt)Mj(9~c;0eSBs38MY*WOJab!2H%$$Vj+VW=9j3EZqp$o_E zLDuJ@^9-^z%Z8_}L#);-g}V~gW5xKQmlICfE}|G2DOTvfvzFfQ)u$yePXYJdikgmB zrfU@zH7}TFyYjEDsDladsh*`rbao469a|Ls?l`hIzWs5bm*#MhUtDnvEHIM1F)3PZ z8E;(t)DqJkf_urv=zzwO;%#X29LWYpm!8{w zy*`}D%lay~H8%p#B_2prX&_%udUuBIvMAnKd#RbF7+5dz!K=`3l}Gy1>o{6VcfBtM z2Lh6|G|$FoqIFNp^2H%9 zpK0S;=1JJ9I-{g7`1S>l6WGPR>+!HZ(P96K^8DVy3lUSoP{HAphQ^0;o}qJmQU-z;>8C*_Py^!KFSXZIb zL=ay1*Bh>5^GPdP!Xevr;u0eWs{z@wrYnh!GjG*uuKax&ka3+@_sM6v2)#Tb@zmu4 zY1UU(EVkY!)o1+yt`V&~yhJ+s?t3_gr=A~1WLc@{(#-0Iuc}eI+f-kzbY6v2uUF}c zp8dHFtQDX1Z7c0L@GJ?c-7-Z(DKHKFbH3VIdv2HyCHTg{FBf$cu~2`Bj5d?}KEaW5 z!0#Cqnd0(OIq*_On5|8~V36JPlFcmJGshXzEhK`3f|=?&0$7_L$S$6Z@p1b%Pbp<> z225lelMj3=9etTKN`jRD64zfXGMJJ=}QBE$o0FUOl96B7)V6snU~Cy z)7+v{XD;EXWDG-WRAYU=(AcKr(H!ZLESzsQar(~BZB+y#Br{@tk?t~7@yzj-_SY*` zgJjv76Z_o{vuojzuytxMSmack-@v}4RV%sV#4hfr2NyRuWq6=0Sp>B@MV(G zOuuV7U+U{um8pVk?ZC+x)4uu_1BW|a3_^m|!t#lGgmLGhhB5)+t zh{zt4T9M01<7eT8%94QZQN4pB>0fn^ia($e_{i?KzMLy1vEC!TVOk@8FJ3gxC|&r8 zAkmRAc?iqK0Cl2xWD3~zY4sVGQP$Z%k>)x=N)e(cxKKh_9jVJq84AhyfiX?!L5Fch zjSnZVIL9e_Jt0cnAWXCw+v-}AMXoYGrM}poBxIlJ7fXKg9g57$8c;mj41y&dLl0^K z&mfZpQS}~APji2WdR*9%8EZa-O`oI&wgs2eY=+k*$eZL%m!p#+B6Nw$Zgpc-qbBud zeksxx#1lHNJz|d~3>L=b4o}1|OtY5)U&VmVqv@#BpY9{FX(GCdzD4~XBd!OImSbX? z!GMB`*mVlzx{$)R;&ypjU&+_r^R;ix{un)lnaCW1{RUKj@+9rAduek`&7PtxqIkGoj`D+v)H>^2{v@&a9mUF7iUcIWc%KSWS+XN=B7g+#h zu`G+HIkHvp!O`W`V57efb$rU^^8_P^ii&t9fsaam9zTxSq^~UIoaIFj*ctCj)O?iT z35EWaC-I0zGrM336LHRd<4(B^0T@0hFVRctK-_XcF(7?0hTY3zs+kDhmv^TK%gdXJ zy~T{{M~0dcB_Khv+&pf?81UKCXdu)}VxXXqRr4tFc57_6)&IcZ(^;ngZlDds#1XGO zR{Qv}pkpKE={gg;FfvhIQWGz!!@LU5XYNbhIyl|q%Rtz&7I)0w4s41g^s|_8|Ju(C zZwFchr?}2E5c|s}5xREjz)V~vKK#%LhW2f%Fb($3x#C4#sN^EM(nOXL1rT-F{AYxU zw-o%cD|IDNdFhwKVD6yWi%1k0G8wpG#C&<$`)Mx7E)qrL7s^EqrLgMk48vPGCt`9> zP59Xee$5u$VV4jdpWGOHwlyicfNl8VI?e|pOH^juV*53{{!scIe6vg;7`y=Ug;Y9m zAaTUkq5PRskrlTS8z*t40BoDpYl}K^r-tma=iW1ZxCR~#%)rWt!dT2bQ%ppl zr0Wk;CGEBeVPes}@=ZFEN!kNYZ=%$G#{~4YA5YmYIJL^PfDDri_cYADT0s!{ZI8a~ ziZ!LrznJ7YYSJQH+`lJ$IAQs=INDU)^CN$Y8>e=bfGrN{^Adh2VA>vP$|B+U<1^_o zQ5wn`u^4dPM(!l#CF6`{qs~U>=3@rF=%*g0_x!+*LkF`miI`eo`zCC(3VV%nIgLTr z3@Tt0Wh?n+{i?R;$qh`5R)@kJ{rp@}W=ZH~SY@u$KS4~W(mb!Ju+nLnIF+-j=iL`5 z8j#);2}mfH-Bbsx=C~sY_T)r*!)#xASO>=l!XRoY7XR5byr1i*>rPWh3z8h+FrKF^ zS4rJ_AGfW+v_C+^?Y*v`;_nI5?iGuXm-p$Q$vv}m!!b4BOnAR z^2ZcHU9z^yA5%a1=KeuHn{+dL!^}?YLpziBkz-=?`xW5Z@Lahi`O8z%#EvZ0quL&} zT$6{U{+jJa|DKb=I{Ot>ku{;gL60ONQXOIT(f)B7y=a}q9cCw+=H5>+}e<6p0y+8<<*nVw*nU^6fRjJepO}+A+!nNMRCs`CbwwT)WAvp zlhozc5v&{NZR>r6gVR@sxh&-9f}v+mdA}-LWCh%u&oXfBOK1CEi_=Nlb!@9j6v`Xb z9-rd9;>2yDzyBMrRg$xH;Vp>Znoh16 z9VLvOpo~{#_U&ZJ9{xdb&pt%RR|3hil#G?Voj&QtV$dJq+b>8=94P#?e4T&@CS!*i zB379^`Ma66n_7BuDb_?}WS7F9f#DAz3V_)&DwH0qLBVbidWI6Xp#N!}#|*4}++D%M z-_keJkae!D)F`)PE_`}aa2vz?eQ%r`(`oMkv*Y+RQGp2ev&eHX@2`+R5KA4tFhxJ* zU~tpQCVc7LV_+7b*%a`uDH+gHG8!)$RO~7u;{!``l=MW1ju%1pY8+B+pVpu%tA1m9 zEKtc>Pv!4VMf=Q^vB}F0vGplpLeRS&58&wtMuIcv-GdImi*tgL1BaJ&9nV~Hg5qTt)FP4SFmoR z0@S&DJ4|$CFP4=%8ynjM<+@odvT>V!_NHUCLq3{Isf@gJi2W(@R)L((Xo^)in~D9L zn-O&cg5hL)oQZ3S8^VLW^yA(W`DBwkUANN3mKR$3)bpO1?LB|6RjrlzJ^!Tm49(@a zB-e{4+@YOv?TI=Gu?c`-c(HD4+f`&A&V?>T>?6-Wc24~9;@*4Il%d>-VSNyyI3y>2 zipIkvA(B;SR4w!d=C&qk-cLam8g|r0!V99HNDMtoHy(edsbjijb;>z*@0GuFXHe?V z+(*+EL+h0?ijt>)3?D38)Y=oO6D1b)5v_{a*9+N)CiCEzf5re|rCj;U)L9*>d`q_7?T&vi$?gzFhLPpvo%!JkPl>A`V#M*7RLq z?X*Iw249CtYaj5^HFtC^xCKsKSob3XbfPC&+Kp`u*hR@Vr>1{{;}VNH5zguzTxD>w z&D=AGyk&@`p&7{bU;I@Ti#mv>@@wAAf%H8#yx)<|qyKxmabxrix`gem}b8E%E9 zbeohlAht`PzRe6C&iZC6H}dyMt?VspQa;7tlXuJ%03~SwKOdCKn?U%NbbV&ZR&&q7{5rwcfGCN}t%65H$>$G!vfdklP zbwIQAa*_MQ^P7jm#n*bi%hsn`pHA@aV7cTH_)f;oVCZb6*;Y!#pm>a$@V{rK$JESM zy6e66T*Chhw<3tSzb~ge#9ZjE{~peGZnR?}mWk;N9N-85L;c{FFTj|h6KhZGS>z|h{t4@fKw)V)LW9?o zI(=#nc3tJX8Rl z-e?ax4i#RmxEVVLKlc5#<>?~R1!VX+?{Oz=Dzvf}fp!eoRV&~+(4*p{@w*SLK6~w}&#dzAx*4AiQ}D0wZ|3w5rejZd1W@L9 z9c;G9f!MKIf3vaB#eS1H!{9Y!uWoMK7gfjV-pyaS(P7$0^ss~T7Mx3U0X%-YJg67& z9Q*Fn6N_Y?vi9$$-!#5K=Q7<$r<&h=j{{SlNyNln9yZ9tOek$CbgQulGLJ}!E38&u zZ>QrTt=7KPbqNiYYV!W+`rqZwW&K(I;A6Z`+=L;Rh|T_8E1IH!F{Y&q)Z+DjhJ%CT zkCj!v_8>o9T>6tCVB(Ef%uF-$K6dORumg4z-mZh6Ak2XJxcrfDz+>u$P|w9lIro2~ z`-UKe;eKqjvDnIDIvqu7cI}4QB8kt;|HfSc?}{Oqmx!&2JQcinTTx%nsQ%;x%ONef z;f!VZw^jasr-uZd5lH2++x(W-jM`Ej~*QZA>^cKA5J1>>Z+lji@eKKils2OC8X@x{*4$ z=)0>k{!RybcyiT}`7_7�VATvpSx;dFS=NpAit<-pR@n(P`$9AxpqE@)q4<427F? zGqh=@bn=>#@dM1>F5-DbC#puA5*-yOqJ2)-Lvb#z3)DBn(95MaR}f=$>_{lt_Jmcxn7@ z@vYu}sJR~R>Mfuej)Oy-s;Vge=33P>L*u!oIwoxUhm%^vK#J@2Sa*(Ejv86OHTEq2 zf4+eFT>}Njg%b&8$5b&a=@-W*tGYT>eoP*0qIfKX`juq)#Wds}Y5y(y!;F(3bu`Gu z{=c~)7sQ07xW+=Zoo*YZorqVQx!WjRe;e8kFT#(9&!}4H#&>O;54@W&i|yxqB)(;m`_8UjRP!R-<(AI#C$h5W zB;HxYdvUdy126_{=B2%`uL3FWb=3U@Zs5W&pn5vJ=m{w30Ikt=6^aC zSJWrYX9$1tlb_6uN94mgbTuq3@v$Fz{$Kv`m-gaGxbkd;`+psQjzC9X4|7pw^wGxmt6%+UtH()4d`$2r`m3+L zy77GMvB%m)j)x8%n*H&Qe{3h=j~qENyX2Bf8gKP5CU3m)Mmt6S`s=T^iT{c#u9)HZ z7_h0$SS7zs(ci!x&r=FU9=}TXl9X)!qwbRE3em59a>i+I`?-@Rc zK4o_6t+&p7&lN%z4AADo$_9b3Qm-h1Z;;CtWu zUc052kuYJOb>>;KU;gr!?SJu)iP|T?b{!0hOBWf0pa1;l&G;}XCRy%3pLn8Oi()cX z<~!f{PP^ro@9`9)r2G$l@Piq{VRC=%wb$CJ{`BET-IXB&$EesXU2wq#vu}U<+f8Oh zkRg$N@x>RnNYhU}??Ed@jZ@d_x@MRR#!@=S=zkm5n+wEL+)m6QjH;jG*>#-FP$@`hOjP zj=&y5pc#-nVtMP$x7y@?%PqIG)x1gC4&cfwuWUOJle7uly9X=nWA7iEoqO)N4GzY^ zr(Sqj7|!8!-Nl+@$xB}U4>niFhh0y_18CJ zXNMKX2;FeQ4b3QcT*r`Tzq#GHY4DLwjBmu*}GZUSdS zyx$OK@a$|nK7TX8+d<%k{tI9D!tC(Vhv&u+Z}QrOXb)Ztp~rWOkX?l~*dfV-nYQB1 zAd*wNggNzh*AeIlbOiPq0_`g-6C49!vdpgydZc5rx9YY6H*r4y{PS%xm&SOQ^_ zAzQs$`74=+D85WbfcME=uinF>`*JYPoHhcT+w}0CKMur2=Q%^f>_STT6toIC7 z{A7{G2ykRIadV6Wz9w;(Ka$yd6h@1YUph}V&SNk94=6X! zpYbl6PqlwcyIp*W$GT}_-s_gzj&9jmk?qPY%m1k4TvlIC?+A1RIszXT0`sr1 ztm;j6{)Q!fd)GjSq{pulV$ve)vUtkK=TcANwOqpdoF@tY>ZfdYS07#Yq)g*C>|pF< zwyQs7?0A%`yo9;rg_a*Weq;}QrR(92Ku4e>uv`}qnD0RLLSuRxIszSmjzCA?<3nKK zCHlu#ZLg^#&=KeebOd%g0^NY@_8#o=cLX{D9f3~>fo?!PA>ezp9f6KOM_{)j@c)sR VrC8~Q*b)E$002ovPDHLkV1o8Ui=6-f From e7375e8610584ab50e03e56fe44a0aa4b5a7a017 Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Wed, 5 Jun 2024 16:22:24 +0600 Subject: [PATCH 53/75] pkp/plagiarism#52 added some precautionary checks --- IThenticate.inc.php | 6 +++--- PlagiarismPlugin.inc.php | 5 +++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/IThenticate.inc.php b/IThenticate.inc.php index 599ce39..383be16 100644 --- a/IThenticate.inc.php +++ b/IThenticate.inc.php @@ -747,13 +747,13 @@ protected function getApiPath($apiPathSegment) { * * @param string $entity The entity name (e.g. owner/submitter etc). * @param mixed $id Entity id associated with requesting system. - * @param bool $silent Silently return the passed `$id` is no matching entity mapping - * not found. Default to `true` and when set to `false`, will throw + * @param bool $silent Silently return the passed `$id` if no matching entity mapping + * not found. Default to `false` and when set to `true`, will not throw * exception. * * @return mixed */ - protected function getGeneratedId($entity, $id, $silent = true) { + protected function getGeneratedId($entity, $id, $silent = false) { if (!in_array($entity, array_keys(static::ENTITY_ID_PREFIXES))) { if ($silent) { return $id; diff --git a/PlagiarismPlugin.inc.php b/PlagiarismPlugin.inc.php index bac740e..bfe2361 100644 --- a/PlagiarismPlugin.inc.php +++ b/PlagiarismPlugin.inc.php @@ -558,6 +558,11 @@ public function stampEulaToSubmittingUser($context, $submission, $user = null) { $request = Application::get()->getRequest(); $user ??= $request->getUser(); + if (is_null($submission->getData('ithenticateEulaVersion'))) { + $submissionDao = DAORegistry::getDAO("SubmissionDAO"); /** @var SubmissionDAO $submissionDao */ + $submission = $submissionDao->getById(1); /** @var Submission $submission */ + } + $submissionEulaVersion = $submission->getData('ithenticateEulaVersion'); // If submission EULA version has already been stamped to user From a0ad8d95b519afb822a5417170cad3522db8a812 Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Fri, 7 Jun 2024 14:13:54 +0600 Subject: [PATCH 54/75] pkp/plagiarism#52 added better enable/disable control --- PlagiarismPlugin.inc.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/PlagiarismPlugin.inc.php b/PlagiarismPlugin.inc.php index bfe2361..abeaae1 100644 --- a/PlagiarismPlugin.inc.php +++ b/PlagiarismPlugin.inc.php @@ -140,29 +140,29 @@ public function getDescription() { * @copydoc LazyLoadPlugin::getCanEnable() */ public function getCanEnable($contextId = null) { - if (!Config::getVar('ithenticate', 'ithenticate')) { - return false; - } - - return !$this->getEnabled($contextId); + return !Config::getVar('ithenticate', 'ithenticate'); } /** * @copydoc LazyLoadPlugin::getCanDisable() */ public function getCanDisable($contextId = null) { - if (!Config::getVar('ithenticate', 'ithenticate')) { - return false; - } - - return !$this->getEnabled($contextId); + return !Config::getVar('ithenticate', 'ithenticate'); } /** * @copydoc LazyLoadPlugin::getEnabled() */ public function getEnabled($contextId = null) { - return parent::getEnabled($contextId) && Config::getVar('ithenticate', 'ithenticate'); + if (!Config::getVar('general', 'installed')) { + return false; + } + + if (Config::getVar('ithenticate', 'ithenticate') && !parent::getEnabled($contextId)) { + $this->setEnabled(true); + } + + return parent::getEnabled($contextId) || Config::getVar('ithenticate', 'ithenticate'); } /** From 63e783a7f0a1db29ccd81777e35b9df03b9b3aad Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Wed, 12 Jun 2024 14:44:36 +0600 Subject: [PATCH 55/75] pkp/plagiarism#52 added all serach repos and removed viewer_permissions from viewer launch url create process --- IThenticate.inc.php | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/IThenticate.inc.php b/IThenticate.inc.php index 383be16..e166893 100644 --- a/IThenticate.inc.php +++ b/IThenticate.inc.php @@ -386,9 +386,7 @@ public function scheduleSimilarityReportGenerationProcess($submissionUuid, $sett // section `generation_settings` settings 'generation_settings' => [ - 'search_repositories' => $this->getEnabledFeature( - 'similarity.generation_settings.search_repositories' - ) ?? [ + 'search_repositories' => [ 'INTERNET', 'SUBMITTED_WORK', 'PUBLICATION', @@ -474,13 +472,6 @@ public function createViewerLaunchUrl($submissionUuid, $user, $locale, $viewerPe 'viewer_user_id' => $this->getGeneratedId('submitter', $user->getId()), 'locale' => $locale, 'viewer_default_permission_set' => $viewerPermission, - 'viewer_permissions' => [ - 'may_view_submission_full_source' => true, - 'may_view_match_submission_info' => true, - 'may_view_flags_panel' => true, - 'may_view_document_details_panel' => true, - 'may_view_sections_exclusion_panel' => true, - ], 'similarity' => [ 'view_settings' => [ 'save_changes' => $allowUpdateInViewer From 9a401d3217934c24c273ff35e893a2e8e383f8eb Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Wed, 12 Jun 2024 22:28:09 +0600 Subject: [PATCH 56/75] pkp/plagiarism#52 added check before manula similarity report scheduling --- IThenticate.inc.php | 27 +++++++++ PlagiarismPlugin.inc.php | 10 ++++ TestIThenticate.inc.php | 23 ++++++++ ...PlagiarismIthenticateActionHandler.inc.php | 56 +++++++++++++++++++ controllers/PlagiarismWebhookHandler.inc.php | 4 ++ locale/en_US/locale.po | 12 ++++ 6 files changed, 132 insertions(+) diff --git a/IThenticate.inc.php b/IThenticate.inc.php index e166893..75a5011 100644 --- a/IThenticate.inc.php +++ b/IThenticate.inc.php @@ -360,6 +360,33 @@ public function uploadFile($submissionTacId, $fileName, $fileContent) { return $response ? $response->getStatusCode() === 202 : false; } + /** + * Get the submission details + * @see https://developers.turnitin.com/docs/tca#get-submission-info + * + * @param string $submissionTacId The submission UUID return back from service + * @return string|null On successful retrieval of submission details it will return + * details JSON data and on failure, will return null. + */ + public function getSubmissionInfo($submissionUuid) { + + $response = $this->makeApiRequest( + 'GET', + $this->getApiPath("submissions/{$submissionUuid}"), + [ + 'headers' => $this->getRequiredHeaders(), + 'verify' => false, + 'exceptions' => false, + ] + ); + + if ($response->getStatusCode() === 200) { + return $response->getBody()->getContents(); + } + + return null; + } + /** * Schedule the similarity report generation process * @see https://developers.turnitin.com/docs/tca#generate-similarity-report diff --git a/PlagiarismPlugin.inc.php b/PlagiarismPlugin.inc.php index abeaae1..44f8630 100644 --- a/PlagiarismPlugin.inc.php +++ b/PlagiarismPlugin.inc.php @@ -237,6 +237,16 @@ public function addPlagiarismCheckDataToSubmissionFileSchema($hookName, $params) 'validation' => ['nullable'], ]; + $schema->properties->ithenticateSubmissionAcceptedAt = (object) [ + 'type' => 'string', + 'description' => 'The timestamp at which this submission file successfully accepted at iThenticate service end', + 'writeOnly' => true, + 'validation' => [ + 'date:Y-m-d H:i:s', + 'nullable', + ], + ]; + return false; } diff --git a/TestIThenticate.inc.php b/TestIThenticate.inc.php index e1d4ea1..b109b07 100644 --- a/TestIThenticate.inc.php +++ b/TestIThenticate.inc.php @@ -224,6 +224,29 @@ public function uploadFile($submissionTacId, $fileName, $fileContent) { return true; } + /** + * @copydoc IThenticate::getSubmissionInfo() + */ + public function getSubmissionInfo($submissionUuid) { + + return '{ + "id": "'.$submissionUuid.'", + "owner": "a9c14691-9523-4f44-b5fc-4a673c5d4a35", + "title": "History 101 Final Esssay", + "status": "COMPLETE", + "content_type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "page_count": 3, + "word_count": 145, + "character_count": 760, + "created_time": "2023-08-30T22:13:41Z", + "capabilities" : [ + "INDEX", + "VIEWER", + "SIMILARITY" + ] + }'; + } + /** * @copydoc IThenticate::scheduleSimilarityReportGenerationProcess() */ diff --git a/controllers/PlagiarismIthenticateActionHandler.inc.php b/controllers/PlagiarismIthenticateActionHandler.inc.php index f5eaf14..9f37fb4 100644 --- a/controllers/PlagiarismIthenticateActionHandler.inc.php +++ b/controllers/PlagiarismIthenticateActionHandler.inc.php @@ -126,6 +126,62 @@ public function scheduleSimilarityReport($args, $request) { ...static::$_plugin->getServiceAccess($context) ); + // If no confirmation of submission file completed the processing at iThenticate service'e end + // we first need to check it's processing status to see has set to `COMPLETED` + // see more at https://developers.turnitin.com/turnitin-core-api/best-practice/retry-polling + if (!$submissionFile->getData('ithenticateSubmissionAcceptedAt')) { + $submissionInfo = $ithenticate->getSubmissionInfo($submissionFile->getData('ithenticateId')); + ray($submissionInfo); + + // submission info not available to schedule report generation process + if (!$submissionInfo) { + $this->generateUserNotification( + $request, + NOTIFICATION_TYPE_ERROR, + __('plugins.generic.plagiarism.webhook.similarity.schedule.error', [ + 'submissionFileId' => $submissionFile->getId(), + 'error' => __('plugins.generic.plagiarism.submission.status.unavailable'), + ]) + ); + return $this->triggerDataChangedEvent($submissionFile); + } + + $submissionInfo = json_decode($submissionInfo); + + // submission has not completed yet to schedule report generation process + if ($submissionInfo->status !== 'COMPLETE') { + $similaritySchedulingError = ''; + + switch($submissionInfo->status) { + case 'CREATED' : + $similaritySchedulingError = __('plugins.generic.plagiarism.submission.status.CREATED'); + break; + case 'PROCESSING' : + $similaritySchedulingError = __('plugins.generic.plagiarism.submission.status.PROCESSING'); + break; + case 'ERROR' : + $similaritySchedulingError = property_exists($submissionInfo, 'error_code') + ? __("plugins.generic.plagiarism.submission.status.{$submissionInfo->error_code}") + : __('plugins.generic.plagiarism.submission.status.ERROR'); + break; + } + + $this->generateUserNotification( + $request, + NOTIFICATION_TYPE_ERROR, + __('plugins.generic.plagiarism.webhook.similarity.schedule.error', [ + 'submissionFileId' => $submissionFile->getId(), + 'error' => $similaritySchedulingError, + ]) + ); + + return $this->triggerDataChangedEvent($submissionFile); + } + + $submissionFile->setData('ithenticateSubmissionAcceptedAt', Core::getCurrentDate()); + $submissionFileDao->updateObject($submissionFile); + } + $scheduleSimilarityReport = $ithenticate->scheduleSimilarityReportGenerationProcess( $submissionFile->getData('ithenticateId'), static::$_plugin->getSimilarityConfigSettings($context) diff --git a/controllers/PlagiarismWebhookHandler.inc.php b/controllers/PlagiarismWebhookHandler.inc.php index ff1c86f..7817a2a 100644 --- a/controllers/PlagiarismWebhookHandler.inc.php +++ b/controllers/PlagiarismWebhookHandler.inc.php @@ -123,6 +123,10 @@ protected function handleSubmissionCompleteEvent($context, $payload, $event) { ); return; } + + $submissionFile->setData('ithenticateSubmissionAcceptedAt', Core::getCurrentDate()); + $submissionFileDao->updateObject($submissionFile); + $submissionFile = $submissionFileDao->getById($submissionFile->getId()); if ((int)$submissionFile->getData('ithenticateSimilarityScheduled')) { static::$_plugin->sendErrorMessage( diff --git a/locale/en_US/locale.po b/locale/en_US/locale.po index c82ed86..e724606 100644 --- a/locale/en_US/locale.po +++ b/locale/en_US/locale.po @@ -233,3 +233,15 @@ msgstr "Could not create the submission at iThenticate for submission file id : msgid "plugins.generic.plagiarism.ithenticate.file.upload.failed" msgstr "Could not complete the file upload at iThenticate for submission file id : {$submissionFileId}" + +msgid "plugins.generic.plagiarism.submission.status.unavailable" +msgstr "Submission details is unavailable." + +msgid "plugins.generic.plagiarism.submission.status.CREATED" +msgstr "Submission has been created but no file has been uploaded" + +msgid "plugins.generic.plagiarism.submission.status.PROCESSING" +msgstr "File contents have been uploaded and the submission is still being processed" + +msgid "plugins.generic.plagiarism.submission.status.ERROR" +msgstr "An error occurred during submission processing." From 2972f3d227d599843ad507fb11d1e0f60cff5703 Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Wed, 12 Jun 2024 22:30:34 +0600 Subject: [PATCH 57/75] pkp/plagiarism#52 translation update --- controllers/PlagiarismIthenticateActionHandler.inc.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/controllers/PlagiarismIthenticateActionHandler.inc.php b/controllers/PlagiarismIthenticateActionHandler.inc.php index 9f37fb4..6426a89 100644 --- a/controllers/PlagiarismIthenticateActionHandler.inc.php +++ b/controllers/PlagiarismIthenticateActionHandler.inc.php @@ -131,7 +131,6 @@ public function scheduleSimilarityReport($args, $request) { // see more at https://developers.turnitin.com/turnitin-core-api/best-practice/retry-polling if (!$submissionFile->getData('ithenticateSubmissionAcceptedAt')) { $submissionInfo = $ithenticate->getSubmissionInfo($submissionFile->getData('ithenticateId')); - ray($submissionInfo); // submission info not available to schedule report generation process if (!$submissionInfo) { @@ -161,7 +160,7 @@ public function scheduleSimilarityReport($args, $request) { break; case 'ERROR' : $similaritySchedulingError = property_exists($submissionInfo, 'error_code') - ? __("plugins.generic.plagiarism.submission.status.{$submissionInfo->error_code}") + ? __("plugins.generic.plagiarism.ithenticate.submission.error.{$submissionInfo->error_code}") : __('plugins.generic.plagiarism.submission.status.ERROR'); break; } From 207361b19fab2a2c43d54d175491218199da7a11 Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Fri, 14 Jun 2024 22:47:37 +0600 Subject: [PATCH 58/75] pkp/plagiarism#52 added comment for issue no 49 and install mode conflict --- PlagiarismPlugin.inc.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/PlagiarismPlugin.inc.php b/PlagiarismPlugin.inc.php index 44f8630..3f29710 100644 --- a/PlagiarismPlugin.inc.php +++ b/PlagiarismPlugin.inc.php @@ -154,10 +154,17 @@ public function getCanDisable($contextId = null) { * @copydoc LazyLoadPlugin::getEnabled() */ public function getEnabled($contextId = null) { + + // This check is required as plugin can be forced enable by setting `ithenticate` to `On` + // in the config file which cuase the hooks to run but unavailable + // in the installation mode by setting `installed` to `Off` if (!Config::getVar('general', 'installed')) { return false; } + // This allow to force enable the plugin into the system if `ithenticate` set to `On` but the plugin + // itself still disable as in `plugin_setings` table, the `enabled` value not set or set to `0` + // for more details, see https://github.com/pkp/plagiarism/issues/49 if (Config::getVar('ithenticate', 'ithenticate') && !parent::getEnabled($contextId)) { $this->setEnabled(true); } From 38cb063f418cfdeb6d4a7cdb3f0f27ca9aaf7391 Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Wed, 19 Jun 2024 14:21:43 +0600 Subject: [PATCH 59/75] pkp/plagiarism#52 readme updated --- README.md | 18 ++++++++++-------- .../PlagiarismIthenticateActionHandler.inc.php | 9 +++------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index bb6e576..87a6cd7 100644 --- a/README.md +++ b/README.md @@ -4,24 +4,26 @@ For OJS/OMP/OPS 3.x ## Overview -This plugin permits automatic submission of uploaded manuscripts to the [iThenticate service](http://www.ithenticate.com/) for plagiarism checking. +This plugin permits automatic or manula submission of uploaded manuscripts to the [iThenticate service](http://www.ithenticate.com/) for plagiarism checking. + 1. You need an account on ithenticate.com (costs involved) * paid via Crossref Similarity Check * or, paid directly to iThenticate -2. Install the plugin via the Plugin Gallery -3. Configure the plugin (see below) +2. Configure the API credentials following this [guide](https://help.turnitin.com/ithenticate/administrator/api-custom.htm) +3. Install the plugin via the Plugin Gallery +4. Configure the plugin (see below) * Enable the iThenticate service from `config.inc.php` by setting `ithenticate` to `On`. * Enable the plugin from Plugin Gallery by clicking on the checkbox. * ![Example Enabling Plugin](images/enable-plugin.png) - * Configure the plugin with the **API URL** and **API KEY** you get from ithenticate.com + * Configure the plugin with the **API URL** and **API KEY** you get from ithenticate.com at plugin's setting page or in the config file. * ![Example Settings configuration](images/ithenticate-settings.png) -4. The author logs in and makes a submission +5. The author logs in and makes a submission * At Step 4 of the submission process, submitting user must confirm iThenticate's End User License Agreement to complete the submission. * The submission files will be sent to iThenticate in Step 4 of the submission process. -5. The Editor logs in to OJS/OMP/OPS installation and opens the Submission workflow page. +6. The Editor logs in to OJS/OMP/OPS installation and opens the Submission workflow page. * In the submission files grid view, the Editor can see the similarity scores if the similarity process has completed. * The Editor can also launch iThenticate's similarity viewer. -6. If auto upload to iThenticate is disabled, the Editor can send each submission file to iThenticate from the workflow stage. +7. If auto upload to iThenticate is disabled, the Editor can send each submission file to iThenticate from the workflow stage. ## Similarity Check Settings @@ -73,7 +75,7 @@ ithenticate = On ; Other settings can be configured here; see README.md for all options. ``` -> NOTE : Changing the api credentails (api_url and/or api_key) in the `config.inc.php` file will not update the webhook settings automatically and will require action from the submission workflow section to complete plagiarism similarity score generation process. +> NOTE : Changing the api credentails (`api_url` and/or `api_key`) in the `config.inc.php` file will not update the webhook settings automatically and will require action from the submission workflow section to complete plagiarism similarity score generation process. ## Restrictions 1. The submitting user must confirm the iThenticate End User License Agreement to send files to iThenticate service for plagiarism checking. diff --git a/controllers/PlagiarismIthenticateActionHandler.inc.php b/controllers/PlagiarismIthenticateActionHandler.inc.php index 6426a89..ab60bad 100644 --- a/controllers/PlagiarismIthenticateActionHandler.inc.php +++ b/controllers/PlagiarismIthenticateActionHandler.inc.php @@ -306,11 +306,8 @@ public function submitSubmission($args, $request) { } /** - * Accept the EULA, stamp it to proper entity (Submission/User or both) and may run - * one of following intended action - * - Upload submission file - * - Schedule similarity report generation process - * - Refresh the similarity report scores + * Accept the EULA, stamp it to proper entity (Submission/User or both) and upload + * submission file * * @param array $args * @param Request $request @@ -355,7 +352,7 @@ public function acceptEulaAndExecuteIntendedAction($args, $request) { } /** - * Show the EULA confirmation modal before the intended action + * Show the EULA confirmation modal before the uploading submission file to iThenticate * * @param array $args * @param Request $request From 450e03b1d31700ce4d47fbdb54f3fa1cb7a39bc7 Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Thu, 20 Jun 2024 20:08:44 +0600 Subject: [PATCH 60/75] pkp/plagiarism#52 existing webook delete added before registering a new one --- IThenticate.inc.php | 21 +++++++++++++++++++++ PlagiarismPlugin.inc.php | 2 +- PlagiarismSettingsForm.inc.php | 19 +++++++++++-------- TestIThenticate.inc.php | 8 ++++++++ grids/SimilarityActionGridColumn.inc.php | 2 +- 5 files changed, 42 insertions(+), 10 deletions(-) diff --git a/IThenticate.inc.php b/IThenticate.inc.php index 75a5011..d6d7f95 100644 --- a/IThenticate.inc.php +++ b/IThenticate.inc.php @@ -571,6 +571,9 @@ public function validateEulaVersion($version) { * Register webhook end point * @see https://developers.turnitin.com/docs/tca#create-webhook * + * NOTE : with same webhook url, it will return response with status code 409(HTTP_CONFLICT) + * So it's important to verify one before create a new one + * * @param string $signingSecret * @param string $url * @param array $events @@ -601,6 +604,24 @@ public function registerWebhook($signingSecret, $url, $events = self::DEFAULT_WE return null; } + /** + * Delete webhook end point + * @see https://developers.turnitin.com/docs/tca#delete-webhook + * + * @param string $webhookId + * @return bool + */ + public function deleteWebhook($webhookId) { + + $response = $this->makeApiRequest('DELETE', $this->getApiPath("webhooks/{$webhookId}"), [ + 'headers' => $this->getRequiredHeaders(), + 'verify' => false, + 'exceptions' => false, + ]); + + return $response && $response->getStatusCode() === 204; + } + /** * Get the stored EULA details * diff --git a/PlagiarismPlugin.inc.php b/PlagiarismPlugin.inc.php index 3f29710..6e9df77 100644 --- a/PlagiarismPlugin.inc.php +++ b/PlagiarismPlugin.inc.php @@ -367,7 +367,7 @@ public function confirmEulaAcceptance($hookName, $params) { return false; } - // If submission has EULA stamped and user has EULA stamped and both are save version + // If submission has EULA stamped and user has EULA stamped and both are same version // so there is no need to confirm EULA again if ($submission->getData('ithenticateEulaVersion') && $submission->getData('ithenticateEulaVersion') == $user->getData('ithenticateEulaVersion')) { diff --git a/PlagiarismSettingsForm.inc.php b/PlagiarismSettingsForm.inc.php index b21b94a..922b332 100644 --- a/PlagiarismSettingsForm.inc.php +++ b/PlagiarismSettingsForm.inc.php @@ -132,16 +132,19 @@ public function execute(...$functionArgs) { if (!empty(array_filter([$ithenticateApiUrl, $ithenticateApiKey]))) { + // access updated or new access entered, need to update webhook registration if ($this->_plugin->getSetting($this->_context->getId(), 'ithenticateApiUrl') !== $ithenticateApiUrl || $this->_plugin->getSetting($this->_context->getId(), 'ithenticateApiKey') !== $ithenticateApiKey) { - - // access updated or new access entered, need to update webhook registration - $this->_plugin->registerIthenticateWebhook( - $this->_plugin->initIthenticate( - $this->getData('ithenticateApiUrl'), - $this->getData('ithenticateApiKey') - ) - ); + + $ithenticate = $this->_plugin->initIthenticate($ithenticateApiUrl, $ithenticateApiKey); + + // If there is a already registered webhook for this context, need to delete it first + // before creating a new one as webhook URL remains same which will return 409(HTTP_CONFLICT) + if ($this->_context->getData('ithenticateWebhookId')) { + $ithenticate->deleteWebhook($this->_context->getData('ithenticateWebhookId')); + } + + $this->_plugin->registerIthenticateWebhook($ithenticate); } $this->_plugin->updateSetting($this->_context->getId(), 'ithenticateApiUrl', $ithenticateApiUrl, 'string'); diff --git a/TestIThenticate.inc.php b/TestIThenticate.inc.php index b109b07..08db832 100644 --- a/TestIThenticate.inc.php +++ b/TestIThenticate.inc.php @@ -319,6 +319,14 @@ public function registerWebhook($signingSecret, $url, $events = self::DEFAULT_WE return \Illuminate\Support\Str::uuid()->__toString(); } + /** + * @copydoc IThenticate::deleteWebhook() + */ + public function deleteWebhook($webhookId) { + error_log("ithenticate webhook with id : {$webhookId} removed"); + return true; + } + /** * @copydoc IThenticate::getEulaDetails() */ diff --git a/grids/SimilarityActionGridColumn.inc.php b/grids/SimilarityActionGridColumn.inc.php index 072fb57..c2756f9 100644 --- a/grids/SimilarityActionGridColumn.inc.php +++ b/grids/SimilarityActionGridColumn.inc.php @@ -306,7 +306,7 @@ protected function isEulaConfirmationRequired($context, $submission, $user) { return true; } - // If no EULA is stamped with submission + // If no EULA is stamped with submitting user // means user has never previously interacted with iThenticate process if (!$user->getData('ithenticateEulaVersion')) { return true; From a6fa2b89e49de352c51387fff4d5d710df58e9af Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Mon, 24 Jun 2024 01:45:08 +0600 Subject: [PATCH 61/75] pkp/plagiarism#52 fixed webhook registration issue in settings form --- PlagiarismSettingsForm.inc.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/PlagiarismSettingsForm.inc.php b/PlagiarismSettingsForm.inc.php index 922b332..d4ff924 100644 --- a/PlagiarismSettingsForm.inc.php +++ b/PlagiarismSettingsForm.inc.php @@ -130,7 +130,10 @@ public function execute(...$functionArgs) { $ithenticateApiUrl = trim($this->getData('ithenticateApiUrl'), "\"\';"); $ithenticateApiKey = trim($this->getData('ithenticateApiKey'), "\"\';"); - if (!empty(array_filter([$ithenticateApiUrl, $ithenticateApiKey]))) { + // if proper api url and api key provided and if there is no forced credentails defined in + // `config.inc.php` at global or for this context + if (!empty(array_filter([$ithenticateApiUrl, $ithenticateApiKey])) && + !$this->_plugin->hasForcedCredentials($this->_context->getId())) { // access updated or new access entered, need to update webhook registration if ($this->_plugin->getSetting($this->_context->getId(), 'ithenticateApiUrl') !== $ithenticateApiUrl || From 5c493ac71c161e8e82991d0dbe0a7f279518debc Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Wed, 3 Jul 2024 19:31:27 +0600 Subject: [PATCH 62/75] pkp/plagiarism#52 added CLI tool update webhook on config creds change --- PlagiarismPlugin.inc.php | 16 ++++-- README.md | 5 +- tools/registerWebhooks.php | 111 +++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 7 deletions(-) create mode 100644 tools/registerWebhooks.php diff --git a/PlagiarismPlugin.inc.php b/PlagiarismPlugin.inc.php index 6e9df77..136f89e 100644 --- a/PlagiarismPlugin.inc.php +++ b/PlagiarismPlugin.inc.php @@ -675,7 +675,7 @@ public function createNewSubmission($request, $user, $submission, $submissionFil * @param IThenticate|TestIThenticate $ithenticate * @param Context|null $context * - * @return void + * @return bool */ public function registerIthenticateWebhook($ithenticate, $context = null) { @@ -683,7 +683,7 @@ public function registerIthenticateWebhook($ithenticate, $context = null) { $context ??= $request->getContext(); $signingSecret = \Illuminate\Support\Str::random(12); - $webhookUrl = $request->getDispatcher()->url( + $webhookUrl = Application::get()->getDispatcher()->url( $request, ROUTE_COMPONENT, $context->getData('urlPath'), @@ -697,9 +697,13 @@ public function registerIthenticateWebhook($ithenticate, $context = null) { 'ithenticateWebhookSigningSecret' => $signingSecret, 'ithenticateWebhookId' => $webhookId ], $request); - } else { - error_log("unable to complete the iThenticate webhook registration for context id {$context->getId()}"); + + return true; } + + error_log("unable to complete the iThenticate webhook registration for context id {$context->getId()}"); + + return false; } /** @@ -838,7 +842,7 @@ public function retrieveEulaDetails($cache, $cacheId) { public function initIthenticate($apiUrl, $apiKey) { if (static::isRunningInTestMode()) { - $this->import('TestIThenticate'); + import('plugins.generic.plagiarism.TestIThenticate'); return new TestIThenticate( $apiUrl, $apiKey, @@ -847,7 +851,7 @@ public function initIthenticate($apiUrl, $apiKey) { ); } - $this->import('IThenticate'); + import('plugins.generic.plagiarism.IThenticate'); return new IThenticate( $apiUrl, diff --git a/README.md b/README.md index 87a6cd7..9ef6962 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,9 @@ ithenticate = On ; api_url[Journal_or_Server_or_Press_path] = "https://some-ithenticate-account.com" ; api_key[Journal_or_Server_or_Press_path] = "YOUR_API_KEY" +; To update webhook after changing the API URL or/both KEY defined in the config file, +; run the command `php plugins/generic/plagiarism/tools/registerWebhooks.php`. + ; To globally disable auto upload of submission files to iThenticate service, uncomment following line. ; disableAutoSubmission = On ; It is possible to disable auto upload at specific Journal/Server/Press level rather than globally @@ -75,7 +78,7 @@ ithenticate = On ; Other settings can be configured here; see README.md for all options. ``` -> NOTE : Changing the api credentails (`api_url` and/or `api_key`) in the `config.inc.php` file will not update the webhook settings automatically and will require action from the submission workflow section to complete plagiarism similarity score generation process. +> NOTE : Changing the api credentails (`api_url` and/or `api_key`) in the `config.inc.php` file will not update the webhook settings automatically and will require action from the submission workflow section to complete plagiarism similarity score generation process. However it is possible to use the command line tool to update it from CLI via command `php plugins/generic/plagiarism/tools/registerWebhooks.php` to update webhook for forced credentails. ## Restrictions 1. The submitting user must confirm the iThenticate End User License Agreement to send files to iThenticate service for plagiarism checking. diff --git a/tools/registerWebhooks.php b/tools/registerWebhooks.php new file mode 100644 index 0000000..056fb6c --- /dev/null +++ b/tools/registerWebhooks.php @@ -0,0 +1,111 @@ +argv[0])) { + $this->contextPath = $this->argv[0]; + } + } + + /** + * Print command usage information. + */ + public function usage() { + echo "Register Webhooks for iThenticate Account.\n\n" + . "Usage: {$this->scriptName} optional.context.path \n\n"; + } + + /** + * Execute the specified migration. + */ + public function execute() { + try { + + $plagiarismPlugin = new PlagiarismPlugin(); + + if ($this->contextPath) { + $contextDao = Application::getContextDAO(); /** @var ContextDAO $contextDao */ + $context = $contextDao->getByPath($this->contextPath); /** @var Context $context */ + if (!$context) { + throw new \Exception("No context found for given context path: {$this->contextPath}"); + } + + $this->updateWebhook($context, $plagiarismPlugin); + + return; + } + + // check if there is a global level config e.g. one config for all context + // - Run webhook update for all contexts + // If there is no global level config, then check if each context level config + // - Run webhook update only for those specific context + // if no global level or context level config defined, e.g. configs are managed via plugin setting from + // - nothing to do as plugin's setting will handle webhook update on config update + + $contextService = Services::get("context"); /** @var \APP\Services\ContextService $contextService */ + foreach($contextService->getMany() as $context) { /** @var Context $context */ + $this->updateWebhook($context, $plagiarismPlugin); + } + + } catch (\Throwable $exception) { + echo 'EXCEPTION: ' . $exception->getMessage() . "\n\n"; + exit(2); + } + } + + /** + * Update the webhook details for given context + * + * @param Context $context + * @param PlagiarismPlugin $plagiarismPlugin + * + * @return void + */ + protected function updateWebhook($context, $plagiarismPlugin) { + if (!$plagiarismPlugin->hasForcedCredentials($context)) { + echo "ERROR: No forced credentails defined for context path : {$context->getData('urlPath')}\n\n"; + return; + } + + /** @var IThenticate|TestIThenticate $ithenticate */ + $ithenticate = $plagiarismPlugin->initIthenticate( + ...$plagiarismPlugin->getForcedCredentials($context) + ); + + // If there is a already registered webhook for this context, need to delete it first + // before creating a new one as webhook URL remains same which will return 409(HTTP_CONFLICT) + $existingWebhookId = $context->getData('ithenticateWebhookId'); + if ($existingWebhookId) { + $ithenticate->deleteWebhook($existingWebhookId); + } + + $webhookUpdateStatus = $plagiarismPlugin->registerIthenticateWebhook($ithenticate, $context); + + echo $webhookUpdateStatus + ? "SUCCESS: updated the webhook for context path : {$context->getData('urlPath')}\n\n" + : "ERROR: unable to updated the webhook for context path : {$context->getData('urlPath')}\n\n"; + } +} + +$tool = new RegisterWebhooks(isset($argv) ? $argv : []); +$tool->execute(); From 0e935692b9c0224808a1775c6694420653876ef4 Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Mon, 8 Jul 2024 13:19:38 +0600 Subject: [PATCH 63/75] Update to version 1.0.6.2 --- version.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.xml b/version.xml index 5950b4c..b89e685 100644 --- a/version.xml +++ b/version.xml @@ -13,8 +13,8 @@ plagiarism plugins.generic - 1.0.6.0 - 2023-08-02 + 1.0.6.2 + 2024-07-08 1 PlagiarismPlugin From fda3e40e148a28db194ce3ad14339c911ce5f4ea Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Mon, 8 Jul 2024 13:36:00 +0600 Subject: [PATCH 64/75] Update to version 1.0.7.0 --- version.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.xml b/version.xml index b89e685..b5bc580 100644 --- a/version.xml +++ b/version.xml @@ -13,7 +13,7 @@ plagiarism plugins.generic - 1.0.6.2 + 1.0.7.0 2024-07-08 1 PlagiarismPlugin From c642ad11ac555375990097bc45a7a7f1a1efc2d5 Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Fri, 9 Aug 2024 12:22:13 +0600 Subject: [PATCH 65/75] pkp/plagiarism#52 fixed issue with settings update --- PlagiarismSettingsForm.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlagiarismSettingsForm.inc.php b/PlagiarismSettingsForm.inc.php index d4ff924..f58b2c9 100644 --- a/PlagiarismSettingsForm.inc.php +++ b/PlagiarismSettingsForm.inc.php @@ -133,7 +133,7 @@ public function execute(...$functionArgs) { // if proper api url and api key provided and if there is no forced credentails defined in // `config.inc.php` at global or for this context if (!empty(array_filter([$ithenticateApiUrl, $ithenticateApiKey])) && - !$this->_plugin->hasForcedCredentials($this->_context->getId())) { + !$this->_plugin->hasForcedCredentials($this->_context)) { // access updated or new access entered, need to update webhook registration if ($this->_plugin->getSetting($this->_context->getId(), 'ithenticateApiUrl') !== $ithenticateApiUrl || From 0207f2e81ec9b8bbec64d02dc49fe6f2f08a0fb2 Mon Sep 17 00:00:00 2001 From: Alec Smecher Date: Thu, 15 Aug 2024 12:00:42 -0700 Subject: [PATCH 66/75] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9ef6962..76e58bf 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ For OJS/OMP/OPS 3.x ## Overview -This plugin permits automatic or manula submission of uploaded manuscripts to the [iThenticate service](http://www.ithenticate.com/) for plagiarism checking. +This plugin permits automatic or manual submission of uploaded manuscripts to the [iThenticate service](http://www.ithenticate.com/) for plagiarism checking. 1. You need an account on ithenticate.com (costs involved) * paid via Crossref Similarity Check @@ -35,7 +35,7 @@ There are several iThenticate similarity check settings that can be configured v * `excludeAbstract` -- Text in the abstract section of the submission will not count as similar content * `excludeMethods` -- Text in the method section of the submission will not count as similar content * `excludeCitations` -- The citations of the submission will be excluded from similarity check - * `excludeSmallMatches` -- Similarity matches that match less than the specified amount of words will not count as similar content. Mimimum value is 8. + * `excludeSmallMatches` -- Similarity matches that match less than the specified amount of words will not count as similar content. Minimum value is 8. * `allowViewerUpdate` -- Changes made in reports will be saved for the next time the report is viewed * ![Available Similarity Check Options](images/similarity-check-settings.png) 2. Each of this settings can also be configured at global or Journal/Press/Server level from the `config.inc.php` file. From 0b3fcd636aa5ddc6af65b894bd218871cd63658c Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Fri, 23 Aug 2024 19:40:57 +0600 Subject: [PATCH 67/75] pkp/plagiarism#52 added revision files history feature --- PlagiarismPlugin.inc.php | 67 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/PlagiarismPlugin.inc.php b/PlagiarismPlugin.inc.php index 136f89e..55e6f5f 100644 --- a/PlagiarismPlugin.inc.php +++ b/PlagiarismPlugin.inc.php @@ -102,6 +102,7 @@ public function register($category, $path, $mainContextId = null) { HookRegistry::register('Schema::get::' . SCHEMA_SUBMISSION, [$this, 'addPlagiarismCheckDataToSubmissionSchema']); HookRegistry::register('Schema::get::' . SCHEMA_SUBMISSION_FILE, [$this, 'addPlagiarismCheckDataToSubmissionFileSchema']); HookRegistry::register('Schema::get::' . SCHEMA_CONTEXT, [$this, 'addIthenticateConfigSettingsToContextSchema']); + HookRegistry::register('SubmissionFile::edit', [$this, 'updateIthenticateRevisionHistory']); HookRegistry::register('userdao::getAdditionalFieldNames', [$this, 'handleAdditionalEulaConfirmationFieldNames']); @@ -223,6 +224,13 @@ public function addPlagiarismCheckDataToSubmissionSchema($hookName, $params) { public function addPlagiarismCheckDataToSubmissionFileSchema($hookName, $params) { $schema =& $params[0]; + $schema->properties->ithenticateFileId = (object) [ + 'type' => 'integer', + 'description' => 'The file id from the files table', + 'writeOnly' => true, + 'validation' => ['nullable'], + ]; + $schema->properties->ithenticateId = (object) [ 'type' => 'string', 'description' => 'The iThenticate submission id for submission file', @@ -254,6 +262,13 @@ public function addPlagiarismCheckDataToSubmissionFileSchema($hookName, $params) ], ]; + $schema->properties->ithenticateRevisionHistory = (object) [ + 'type' => 'string', + 'description' => 'The similarity check action history on the previous revisions of this submission file', + 'writeOnly' => true, + 'validation' => ['nullable'], + ]; + return false; } @@ -286,6 +301,57 @@ public function addIthenticateConfigSettingsToContextSchema($hookName, $params) return false; } + /** + * Add plagiarism action history for revision files. + * Only contains action history for files that has been sent for plagiarism check. + * + * @param string $hookName `SubmissionFile::edit` + * @param array $params + * + * @return bool + */ + public function updateIthenticateRevisionHistory($hookName, $params) { + $submissionFile = & $params[0]; /** @var SubmissionFile $submissionFile */ + $submissionFileDao = DAORegistry::getDAO('SubmissionFileDAO'); /** @var SubmissionFileDAO $submissionFileDao */ + $currentSubmissionFile = $submissionFileDao->getById($submissionFile->getId()); /** @var SubmissionFile $currentSubmissionFile */ + + // Do not track for plagiarism revision history until marked for tracking + if (is_null($currentSubmissionFile->getData('ithenticateFileId'))) { + return false; + } + + // If file has not changed, no change in plagiarism revision history + if ($currentSubmissionFile->getId() === $submissionFile->getData('fileId')) { + return false; + } + + // new file revision added, so add/update itnenticate revision hisotry + $revisionHistory = json_decode($currentSubmissionFile->getData('ithenticateRevisionHistory') ?? '{}', true); + $submissionFile->setData('ithenticateFileId', $submissionFile->getData('fileId')); + + // If the previous file not sent schedule for plagiarism check + // no need to store it's plagiarism revision history + if (is_null($currentSubmissionFile->getData('ithenticateId'))) { + return false; + } + + array_push($revisionHistory, [ + 'ithenticateFileId' => $currentSubmissionFile->getData('ithenticateFileId'), + 'ithenticateId' => $currentSubmissionFile->getData('ithenticateId'), + 'ithenticateSimilarityResult' => $currentSubmissionFile->getData('ithenticateSimilarityResult'), + 'ithenticateSimilarityScheduled' => $currentSubmissionFile->getData('ithenticateSimilarityScheduled'), + 'ithenticateSubmissionAcceptedAt' => $currentSubmissionFile->getData('ithenticateSubmissionAcceptedAt'), + ]); + + $submissionFile->setData('ithenticateRevisionHistory', json_encode($revisionHistory)); + $submissionFile->setData('ithenticateId', null); + $submissionFile->setData('ithenticateSimilarityResult', null); + $submissionFile->setData('ithenticateSimilarityScheduled', 0); + $submissionFile->setData('ithenticateSubmissionAcceptedAt', null); + + return false; + } + /** * Add additional fields for users to stamp EULA details * @@ -663,6 +729,7 @@ public function createNewSubmission($request, $user, $submission, $submissionFil } $submissionFile->setData('ithenticateId', $submissionUuid); + $submissionFile->setData('ithenticateFileId', $submissionFile->getData('fileId')); $submissionFile->setData('ithenticateSimilarityScheduled', 0); $submissionFileDao->updateObject($submissionFile); From 8d210b934492a09a6c2660067ca614944d64bdfb Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Tue, 3 Sep 2024 15:06:35 +0600 Subject: [PATCH 68/75] pkp/plagiarism#52 removed weird EULA determining from first submission and retrieved from API --- PlagiarismPlugin.inc.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/PlagiarismPlugin.inc.php b/PlagiarismPlugin.inc.php index 55e6f5f..0c58e9e 100644 --- a/PlagiarismPlugin.inc.php +++ b/PlagiarismPlugin.inc.php @@ -641,13 +641,18 @@ public function stampEulaToSubmittingUser($context, $submission, $user = null) { $request = Application::get()->getRequest(); $user ??= $request->getUser(); - if (is_null($submission->getData('ithenticateEulaVersion'))) { - $submissionDao = DAORegistry::getDAO("SubmissionDAO"); /** @var SubmissionDAO $submissionDao */ - $submission = $submissionDao->getById(1); /** @var Submission $submission */ - } - $submissionEulaVersion = $submission->getData('ithenticateEulaVersion'); + if (is_null($submissionEulaVersion)) { + $eulaDetails = $this->getContextEulaDetails($context, [ + $submission->getData('locale'), + $request->getSite()->getPrimaryLocale(), + IThenticate::DEFAULT_EULA_LANGUAGE + ]); + + $submissionEulaVersion = $eulaDetails['version']; + } + // If submission EULA version has already been stamped to user // no need to do the confirmation and stamping again if ($user->getData('ithenticateEulaVersion') === $submissionEulaVersion) { From 62d3ccd6f0efc06ac7757788be9d3421724d3f9f Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Tue, 10 Sep 2024 08:29:28 +0600 Subject: [PATCH 69/75] pkp/plagiarism#52 fixed bug preserving plagiarism history --- PlagiarismPlugin.inc.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/PlagiarismPlugin.inc.php b/PlagiarismPlugin.inc.php index 0c58e9e..f9c5229 100644 --- a/PlagiarismPlugin.inc.php +++ b/PlagiarismPlugin.inc.php @@ -321,7 +321,7 @@ public function updateIthenticateRevisionHistory($hookName, $params) { } // If file has not changed, no change in plagiarism revision history - if ($currentSubmissionFile->getId() === $submissionFile->getData('fileId')) { + if ($currentSubmissionFile->getData('fileId') === $submissionFile->getData('fileId')) { return false; } @@ -1096,8 +1096,10 @@ public function hasAutoSubmissionDisabled() { $context = Application::get()->getRequest()->getContext(); /** @var Context $context */ $contextPath = $context ? $context->getPath() : 'index'; - return $this->getForcedConfigSetting($contextPath, 'disableAutoSubmission') - ?? $this->getSetting($context->getId(), 'disableAutoSubmission'); + return (bool)( + $this->getForcedConfigSetting($contextPath, 'disableAutoSubmission') + ?? $this->getSetting($context->getId(), 'disableAutoSubmission') + ); } /** From e17e29965fb2314b02879a6c7853ebe5f6a5d1f3 Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Thu, 12 Sep 2024 11:05:56 +0600 Subject: [PATCH 70/75] pkp/plagiarism#52 PHP 7.4 compatibility --- IThenticate.inc.php | 27 ++++++++++++++++++--------- TestIThenticate.inc.php | 11 ++++++++--- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/IThenticate.inc.php b/IThenticate.inc.php index d6d7f95..4c05a86 100644 --- a/IThenticate.inc.php +++ b/IThenticate.inc.php @@ -182,21 +182,28 @@ public function getEnabledFeature($feature = null) { static $result; if (!isset($result) && !$this->validateAccess($result)) { - return $this->suppressApiRequestException - ? [] - : throw new \Exception('unable to validate access details'); + if ($this->suppressApiRequestException) { + return []; + } + + throw new \Exception('unable to validate access details'); } if (!$feature) { return json_decode($result, true); } + $self = $this; return data_get( json_decode($result, true), $feature, - fn () => $this->suppressApiRequestException - ? null - : throw new \Exception("Feature details {$feature} does not exist") + function () use ($self, $feature) { + if ($self->suppressApiRequestException) { + return null; + } + + throw new \Exception("Feature details {$feature} does not exist"); + } ); } @@ -684,9 +691,11 @@ public function makeApiRequest($method, $url, $options = []) { ) ); - $this->suppressApiRequestException - ? error_log($exception->__toString()) - : throw $exception; + if ($this->suppressApiRequestException) { + error_log($exception->__toString()); + } else { + throw $exception; + } } return $response; diff --git a/TestIThenticate.inc.php b/TestIThenticate.inc.php index 08db832..a116332 100644 --- a/TestIThenticate.inc.php +++ b/TestIThenticate.inc.php @@ -170,12 +170,17 @@ public function getEnabledFeature($feature = null) { return json_decode($result, true); } + $self = $this; $featureStatus = data_get( json_decode($result, true), $feature, - fn () => $this->suppressApiRequestException - ? null - : throw new \Exception("Feature details {$feature} does not exist") + function () use ($self, $feature) { + if ($self->suppressApiRequestException) { + return null; + } + + throw new \Exception("Feature details {$feature} does not exist"); + } ); error_log("iThenticate specific enable feature details {$featureStatus}"); From 27b723d29695c1f9d60f6bb213a9d8e75d2c028f Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Wed, 18 Sep 2024 13:40:37 +0600 Subject: [PATCH 71/75] pkp/plagiarism#52 added error log if ithenticate creating submission failed --- IThenticate.inc.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/IThenticate.inc.php b/IThenticate.inc.php index 4c05a86..85062d1 100644 --- a/IThenticate.inc.php +++ b/IThenticate.inc.php @@ -333,6 +333,8 @@ public function createSubmission($site, $submission, $user, $author, $authorPerm if ($response && $response->getStatusCode() === 201) { $result = json_decode($response->getBody()->getContents()); return $result->id; + } else { + error_log((string)$response->getBody()->getContents()); } return null; From c5c817e719a6802fd3e4d624a7ac2091b282baf8 Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Thu, 19 Sep 2024 10:47:03 +0600 Subject: [PATCH 72/75] pkp/plagiarism#52 moved default eula lang details under the checking of eula required and validation passes --- PlagiarismPlugin.inc.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/PlagiarismPlugin.inc.php b/PlagiarismPlugin.inc.php index f9c5229..b58bd76 100644 --- a/PlagiarismPlugin.inc.php +++ b/PlagiarismPlugin.inc.php @@ -875,7 +875,7 @@ public function retrieveEulaDetails($cache, $cacheId) { // 'url' => '', // ], // ... - if ($eulaDetails['require_eula'] === true && + if ($eulaDetails['require_eula'] == true && $ithenticate->validateEulaVersion($ithenticate::DEFAULT_EULA_VERSION)) { foreach($context->getSupportedSubmissionLocaleNames() as $localeKey => $localeName) { @@ -884,14 +884,14 @@ public function retrieveEulaDetails($cache, $cacheId) { 'url' => $ithenticate->getApplicableEulaUrl($localeKey), ]; } - } - // Also store the default iThenticate language version details - if (!isset($eulaDetails[$ithenticate::DEFAULT_EULA_LANGUAGE])) { - $eulaDetails[$ithenticate::DEFAULT_EULA_LANGUAGE] = [ - 'version' => $ithenticate->getApplicableEulaVersion(), - 'url' => $ithenticate->getApplicableEulaUrl($ithenticate::DEFAULT_EULA_LANGUAGE), - ]; + // Also store the default iThenticate language version details + if (!isset($eulaDetails[$ithenticate::DEFAULT_EULA_LANGUAGE])) { + $eulaDetails[$ithenticate::DEFAULT_EULA_LANGUAGE] = [ + 'version' => $ithenticate->getApplicableEulaVersion(), + 'url' => $ithenticate->getApplicableEulaUrl($ithenticate::DEFAULT_EULA_LANGUAGE), + ]; + } } $cache->setEntireCache([$cacheId => $eulaDetails]); From c5dae25d71e6c776c9dab90096a42a7f0aca524c Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Fri, 20 Sep 2024 12:00:27 +0600 Subject: [PATCH 73/75] pkp/plagiarism#52 Better handling of EULA non required case --- PlagiarismPlugin.inc.php | 5 ++++- TestIThenticate.inc.php | 20 +++++++++++++++---- ...PlagiarismIthenticateActionHandler.inc.php | 13 ++++++++++-- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/PlagiarismPlugin.inc.php b/PlagiarismPlugin.inc.php index b58bd76..fb8f627 100644 --- a/PlagiarismPlugin.inc.php +++ b/PlagiarismPlugin.inc.php @@ -530,7 +530,10 @@ public function submitForPlagiarismCheck($hookName, $args) { $this->registerIthenticateWebhook($ithenticate, $context); } - $ithenticate->setApplicableEulaVersion($submission->getData('ithenticateEulaVersion')); + // Only set applicable EULA if EULA required + if ($this->getContextEulaDetails($context, 'require_eula') == true) { + $ithenticate->setApplicableEulaVersion($submission->getData('ithenticateEulaVersion')); + } // Check EULA stamped to submission or submitter only if it is required if ($this->getContextEulaDetails($context, 'require_eula') !== false) { diff --git a/TestIThenticate.inc.php b/TestIThenticate.inc.php index a116332..889084d 100644 --- a/TestIThenticate.inc.php +++ b/TestIThenticate.inc.php @@ -17,7 +17,7 @@ class TestIThenticate { /** * @copydoc IThenticate::$eulaVersion */ - protected $eulaVersion = 'v1beta'; + protected $eulaVersion = null; /** * @copydoc IThenticate::$eulaVersionDetails @@ -105,7 +105,17 @@ class TestIThenticate { * @copydoc IThenticate::__construct() */ public function __construct($apiUrl, $apiKey, $integrationName, $integrationVersion, $eulaVersion = null) { - error_log("Constructing iThenticate with API URL : {$apiUrl}, API Key : {$apiKey}, Integration Name : {$integrationName}, Integration Version : {$integrationVersion} and EUlA Version : {$eulaVersion}"); + + // These following 2 conditions are to facilitate the mock the EULA requirement + if ($eulaVersion) { + $this->eulaVersion = $eulaVersion; + } + + if (!$eulaVersion) { + $this->eulaVersion = Config::getVar('ithenticate', 'test_mode_eula', true) ? 'v1beta' : null; + } + + error_log("Constructing iThenticate with API URL : {$apiUrl}, API Key : {$apiKey}, Integration Name : {$integrationName}, Integration Version : {$integrationVersion} and EUlA Version : {$this->eulaVersion}"); } /** @@ -122,7 +132,9 @@ public function withoutSuppressingApiRequestException() { */ public function getEnabledFeature($feature = null) { - static $result = '{ + static $result; + + $result = '{ "similarity": { "viewer_modes": { "match_overview": true, @@ -154,7 +166,7 @@ public function getEnabledFeature($feature = null) { } }, "tenant": { - "require_eula": true + "require_eula": '.($this->eulaVersion ? "true" : "false").' }, "product_name": "Turnitin Originality", "access_options": [ diff --git a/controllers/PlagiarismIthenticateActionHandler.inc.php b/controllers/PlagiarismIthenticateActionHandler.inc.php index ab60bad..05bbf7e 100644 --- a/controllers/PlagiarismIthenticateActionHandler.inc.php +++ b/controllers/PlagiarismIthenticateActionHandler.inc.php @@ -13,6 +13,8 @@ * @brief Handle the different iThenticate service related actions */ +use Illuminate\Support\Arr; + import("plugins.generic.plagiarism.controllers.PlagiarismComponentHandler"); import('lib.pkp.classes.core.JSONMessage'); import('lib.pkp.classes.db.DAORegistry'); @@ -77,11 +79,18 @@ public function launchViewer($args, $request) { ...static::$_plugin->getServiceAccess($context) ); + // If EULA is required and submission has EULA stamped, we set the applicable EULA + // Otherwise get the current EULA from default one and set the applicable + // Basically we need to retrieve the available langs details from EULA details + static::$_plugin->getContextEulaDetails($context, 'require_eula') == true && + $submission->getData('ithenticateEulaVersion') + ? $ithenticate->setApplicableEulaVersion($submission->getData('ithenticateEulaVersion')) + : $ithenticate->validateEulaVersion($ithenticate::DEFAULT_EULA_VERSION); + $locale = $ithenticate - ->setApplicableEulaVersion($submission->getData('ithenticateEulaVersion')) ->getApplicableLocale( collect([$submission->getData("locale")]) - ->merge($user->getData("locales")) + ->merge(Arr::wrap($user->getData("locales"))) ->merge([$context->getPrimaryLocale(), $site->getPrimaryLocale()]) ->unique() ->toArray() From d859cfe8ce205b31a731a69e354e498f8d8a3872 Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Fri, 20 Sep 2024 15:51:40 +0600 Subject: [PATCH 74/75] pkp/plagiarism#52 Better handling submission file name for multi lang --- PlagiarismPlugin.inc.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/PlagiarismPlugin.inc.php b/PlagiarismPlugin.inc.php index fb8f627..791035b 100644 --- a/PlagiarismPlugin.inc.php +++ b/PlagiarismPlugin.inc.php @@ -718,10 +718,19 @@ public function createNewSubmission($request, $user, $submission, $submissionFil if (in_array($file->mimetype, $this->uploadRestrictedArchiveMimeTypes)) { return true; } + + $submissionFileName = $submissionFile->getData("name", $publication->getData("locale")) + ?? collect([$context->getPrimaryLocale()]) + ->merge($context->getData("supportedSubmissionLocales") ?? []) + ->merge([$request->getSite()->getPrimaryLocale()]) + ->unique() + ->map(fn ($locale) => $submissionFile->getData("name", $locale)) + ->filter() + ->first(); $uploadStatus = $ithenticate->uploadFile( $submissionUuid, - $submissionFile->getData("name", $publication->getData("locale")), + $submissionFileName, $pkpFileService->fs->read($file->path), ); From a675e7b39a4f12a9d995b784f342601d4c04bbeb Mon Sep 17 00:00:00 2001 From: Touhidur Rahman Date: Tue, 24 Sep 2024 17:02:56 +0600 Subject: [PATCH 75/75] pkp/plagiarism#52 score value escape --- controllers/PlagiarismIthenticateActionHandler.inc.php | 1 + templates/similarityScore.tpl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/controllers/PlagiarismIthenticateActionHandler.inc.php b/controllers/PlagiarismIthenticateActionHandler.inc.php index 05bbf7e..82d61ff 100644 --- a/controllers/PlagiarismIthenticateActionHandler.inc.php +++ b/controllers/PlagiarismIthenticateActionHandler.inc.php @@ -93,6 +93,7 @@ public function launchViewer($args, $request) { ->merge(Arr::wrap($user->getData("locales"))) ->merge([$context->getPrimaryLocale(), $site->getPrimaryLocale()]) ->unique() + ->filter() ->toArray() ); diff --git a/templates/similarityScore.tpl b/templates/similarityScore.tpl index 31ed882..f675e63 100644 --- a/templates/similarityScore.tpl +++ b/templates/similarityScore.tpl @@ -9,7 +9,7 @@ alt="{translate key="plugins.generic.plagiarism.similarity.match.title"}" /> - {$score}% + {$score|escape}%