From 4836c64356a10808c43203544aa264c1f02e4250 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20D=C4=85browski?=
<64841871+dabrt@users.noreply.github.com>
Date: Wed, 26 Feb 2025 19:16:44 +0100
Subject: [PATCH 01/21] IBX-9594: Describe creating a custom DAM connector
---
.../images/add_image_asset_from_dam.md | 230 +++++++++++++++++-
1 file changed, 228 insertions(+), 2 deletions(-)
diff --git a/docs/content_management/images/add_image_asset_from_dam.md b/docs/content_management/images/add_image_asset_from_dam.md
index fe5d114ee5..9a8141ec39 100644
--- a/docs/content_management/images/add_image_asset_from_dam.md
+++ b/docs/content_management/images/add_image_asset_from_dam.md
@@ -20,9 +20,9 @@ ibexa:
The configuration for each connector depends on the requirements of the specific DAM system.
-You can create your own connectors, or use the provided example DAM connector for [Unsplash](https://unsplash.com/).
+You can use the provided example DAM connector for [Unsplash](https://unsplash.com/), or [extend DAM support by creating a connector of your choice](#extend-dam-support-by-adding-custom-connector).
-To add the Unsplash connector to your system add the `ibexa/connector-unsplash` bundle to your installation.
+To add the Unsplash connector to your system, add the `ibexa/connector-unsplash` bundle to your installation.
## Add Image Asset in Page Builder [[% include 'snippets/experience_badge.md' %]] [[% include 'snippets/commerce_badge.md' %]]
@@ -83,3 +83,229 @@ In the **Content** group, create a content type for DAM images, which includes t
Now, when you use the Embed block in the Page Builder, you should see a DAM Image.
For more information about block customization (defined templates, variations), see [Create custom block](4_create_a_custom_block.md).
+
+## Extend DAM support by adding custom connector
+
+To extend the DAM support built into [= product_name =], you must create a custom Symfony bundle.
+
+!!! note "Wikimedia Commons licensing"
+
+ Before you use Wikimedia Commons assets in a production environment, ensure that you comply with their [license requirements](https://commons.wikimedia.org/wiki/Commons:Reusing_content_outside_Wikimedia#How_to_comply_with_a_file's_license_requirements).
+
+### Create bundle structure
+
+In your project's `src` directory, create a folder for the new bundle, for example, `WikimediaCommonsConnector`.
+
+In that folder, create the main class file `WikimediaCommonsConnector.php` for the bundle:
+
+```php
+ ['all' => true],
+];
+```
+
+### Create DAM handler
+
+This class handles searching through Wikimedia Commons for images and fetching assets.
+
+In `src\WikimediaCommonsConnector\Handler` folder, create the `WikimediaHandler.php` file that resembles the following example, which uses `search()` and `fetchAsset()` functions to query the server for images and return asset objects, respectively:
+
+```php
+getPhrase())
+ .'&sroffset='.$offset
+ .'&srlimit='.$limit
+ ;
+ $response = json_decode(file_get_contents($searchUrl), true);
+
+ $assets = [];
+ foreach ($response['query']['search'] as $result) {
+ $identifier = str_replace('File:', '', $result['title']);
+ $assets[] = $this->fetchAsset($identifier);
+ }
+
+ return new AssetSearchResult((int) $response['query']['searchinfo']['totalhits'], new AssetCollection($assets));
+ }
+
+ public function fetchAsset(string $id): Asset
+ {
+ $metadataUrl = 'https://commons.wikipedia.org/w/api.php?action=query&prop=imageinfo&iiprop=extmetadata&format=json'
+ .'&titles=File%3a'.urlencode($id)
+ ;
+ $response = json_decode(file_get_contents($metadataUrl), true);
+ $imageInfo = array_values($response['query']['pages'])[0]['imageinfo'][0]['extmetadata'];
+
+ return new Asset(
+ new AssetIdentifier($id),
+ new AssetSource('commons'),
+ new AssetUri('https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file/'.urlencode($id)),
+ new AssetMetadata([
+ 'page_url' => "https://commons.wikimedia.org/wiki/File:$id",
+ 'author' => array_key_exists('Artist', $imageInfo) ? $imageInfo['Artist']['value'] : null,
+ 'license' => array_key_exists('LicenseShortName', $imageInfo) ? $imageInfo['LicenseShortName']['value'] : null,
+ 'license_url' => array_key_exists('LicenseUrl', $imageInfo) ? $imageInfo['LicenseUrl']['value'] : null,
+ ])
+ );
+ }
+}
+```
+
+Then, in `config\services.yaml`, register the handler as a service:
+
+```yaml
+services:
+ WikimediaCommonsConnector\Handler\WikimediaCommonsHandler:
+ arguments:
+ $httpClient: '@http_client'
+ tags:
+ - { name: 'ibexa.platform.connector.dam.handler', source: 'commons' }
+```
+
+### Create transformation factory
+
+The transformation factory transforms image variations coming from Wikimedia Commons to the ones used by [= product_name =].
+
+In `src\WikimediaCommonsConnector\Transformation` folder, create the `TransformationFactory.php` file that resembles the following example:
+
+
+```php
+buildAll()[$transformationName];
+ }
+
+ public function buildAll(): iterable
+ {
+ return [
+ 'reference' => new Transformation('reference'),
+ 'tiny' => new Transformation('tiny', ['width' => 30]),
+ 'small' => new Transformation('small', ['width' => 100]),
+ 'medium' => new Transformation('medium', ['width' => 200]),
+ 'large' => new Transformation('large', ['width' => 300]),
+ ];
+ }
+}
+```
+
+Then register the transformation factory as a service:
+
+```yaml
+services:
+ WikimediaCommonsConnector\Transformation\TransformationFactory:
+ arguments:
+ $httpClient: '@http_client'
+ tags:
+ - { name: 'ibexa.platform.connector.dam.transformation_factory', source: 'commons' }
+```
+
+### Register variations generator
+
+The variation generator applies map parameters coming from the transformation factory to build a fetch request to the DAM.
+The `WikimediaCommonsConnector` uses the built-in `URLBasedVariationGenerator` class, which adds all the map elements as query parameters of the request.
+
+For example, the handler generates the following URL with `new AssetUri()`:
+
+`https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file/Ibexa_Logo.svg`
+
+When the user requests a specific variation of the image, the variation generator modifies the URL and returns it in the following form:
+
+`https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file/Ibexa_Logo.svg&width=300`
+
+For this to happen, register the variations generator as a service:
+
+```yaml
+services:
+ commons_asset_variation_generator:
+ class: Ibexa\Connector\Dam\Variation\URLBasedVariationGenerator
+ tags:
+ - { name: ibexa.platform.connector.dam.variation_generator, source: commons }
+```
+
+### Create Twig template for Admin UI
+
+The template deffines how images that come from Wikimedia Commons appear in the back office.
+
+In `src/WikimediaCommonsConnector/Resources/views/themes/standard/`, add the `commons_asset_view.html.twig` file that resembles the following example:
+
+```html+twig
+{% extends '@ezdesign/ui/field_type/image_asset_view.html.twig' %}
+
+{% block asset_preview %}
+ {{ parent() }}
+
+ {{ 'ezimageasset.commons.author_attribute'|trans({
+ '%page_url%': asset.assetMetadata.page_url,
+ '%author%': asset.assetMetadata.author,
+ '%license_url%': asset.assetMetadata.license_url,
+ '%license%': asset.assetMetadata.license,
+ })|desc('
Image by %author% under
%license%')|raw }}
+
+{% endblock %}
+```
+
+Then, register the template in `config/packages/ibexa_admin.yaml`:
+
+```yaml
+ibexa_admin_ui:
+ asset_view:
+ wikimedia_commons:
+ template: '@WikimediaCommonsConnector/admin/commons_asset_view.html.twig'
+```
+
+## Add Wikimedia Commons to DAM configuration
+
+You can now configure a connection with Wikimedia Commons under the `ibexa.system..content.dam` key:
+
+```yaml
+ibexa:
+ system:
+ default:
+ content:
+ dam: [ commons ]
+```
+
+Once you clear the cache, and search for images to see whether images from the newly configured DAM are displayed correctly, including their variations.
\ No newline at end of file
From 36db157613ce7da94897ea8f0dd917f1cbd8187a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20D=C4=85browski?=
<64841871+dabrt@users.noreply.github.com>
Date: Thu, 27 Feb 2025 20:32:40 +0100
Subject: [PATCH 02/21] Move code from md to code sample files
---
.../back_office/images/config/bundles.php | 6 +
.../back_office/images/config/services.yaml | 17 +
.../back_office/images/config/views.yaml | 7 +
.../Handler/WikimediaCommonsHandler.php | 55 +
.../standard/commons_asset_view.html.twig | 13 +
.../Transformation/TransformationFactory.php | 25 +
.../WikimediaCommonsConnector.php | 9 +
.../images/add_image_asset_from_dam.md | 145 +-
docs/content_management/images/images.md | 2 +-
get-pip.py | 28840 ++++++++++++++++
10 files changed, 28986 insertions(+), 133 deletions(-)
create mode 100644 code_samples/back_office/images/config/bundles.php
create mode 100644 code_samples/back_office/images/config/views.yaml
create mode 100644 code_samples/back_office/images/src/WikimediaCommonsConnector/Handler/WikimediaCommonsHandler.php
create mode 100644 code_samples/back_office/images/src/WikimediaCommonsConnector/Resources/views/themes/standard/commons_asset_view.html.twig
create mode 100644 code_samples/back_office/images/src/WikimediaCommonsConnector/Transformation/TransformationFactory.php
create mode 100644 code_samples/back_office/images/src/WikimediaCommonsConnector/WikimediaCommonsConnector.php
create mode 100644 get-pip.py
diff --git a/code_samples/back_office/images/config/bundles.php b/code_samples/back_office/images/config/bundles.php
new file mode 100644
index 0000000000..d59e921b09
--- /dev/null
+++ b/code_samples/back_office/images/config/bundles.php
@@ -0,0 +1,6 @@
+ ['all' => true],
+];
\ No newline at end of file
diff --git a/code_samples/back_office/images/config/services.yaml b/code_samples/back_office/images/config/services.yaml
index a6cebc0938..11275beac0 100644
--- a/code_samples/back_office/images/config/services.yaml
+++ b/code_samples/back_office/images/config/services.yaml
@@ -6,3 +6,20 @@ services:
- '@ibexa.api.service.content'
- '@ibexa.field_type.ezbinaryfile.io_service'
- '@Ibexa\Core\Helper\TranslationHelper'
+
+ WikimediaCommonsConnector\Handler\WikimediaCommonsHandler:
+ arguments:
+ $httpClient: '@http_client'
+ tags:
+ - { name: 'ibexa.platform.connector.dam.handler', source: 'commons' }
+
+ WikimediaCommonsConnector\Transformation\TransformationFactory:
+ arguments:
+ $httpClient: '@http_client'
+ tags:
+ - { name: 'ibexa.platform.connector.dam.transformation_factory', source: 'commons' }
+
+ commons_asset_variation_generator:
+ class: Ibexa\Connector\Dam\Variation\URLBasedVariationGenerator
+ tags:
+ - { name: ibexa.platform.connector.dam.variation_generator, source: commons }
diff --git a/code_samples/back_office/images/config/views.yaml b/code_samples/back_office/images/config/views.yaml
new file mode 100644
index 0000000000..2d873ac921
--- /dev/null
+++ b/code_samples/back_office/images/config/views.yaml
@@ -0,0 +1,7 @@
+parameters:
+ ibexa.default.image_asset_view_defaults:
+ full:
+ default:
+ template: '@@ibexadesign/commons_asset_view.html.twig'
+ match:
+ SourceBasedViewMatcher: commons
\ No newline at end of file
diff --git a/code_samples/back_office/images/src/WikimediaCommonsConnector/Handler/WikimediaCommonsHandler.php b/code_samples/back_office/images/src/WikimediaCommonsConnector/Handler/WikimediaCommonsHandler.php
new file mode 100644
index 0000000000..bc0b5c1bea
--- /dev/null
+++ b/code_samples/back_office/images/src/WikimediaCommonsConnector/Handler/WikimediaCommonsHandler.php
@@ -0,0 +1,55 @@
+getPhrase())
+ .'&sroffset='.$offset
+ .'&srlimit='.$limit
+ ;
+ $response = json_decode(file_get_contents($searchUrl), true);
+
+ $assets = [];
+ foreach ($response['query']['search'] as $result) {
+ $identifier = str_replace('File:', '', $result['title']);
+ $assets[] = $this->fetchAsset($identifier);
+ }
+
+ return new AssetSearchResult((int) $response['query']['searchinfo']['totalhits'], new AssetCollection($assets));
+ }
+
+ public function fetchAsset(string $id): Asset
+ {
+ $metadataUrl = 'https://commons.wikipedia.org/w/api.php?action=query&prop=imageinfo&iiprop=extmetadata&format=json'
+ .'&titles=File%3a'.urlencode($id)
+ ;
+ $response = json_decode(file_get_contents($metadataUrl), true);
+ $imageInfo = array_values($response['query']['pages'])[0]['imageinfo'][0]['extmetadata'];
+
+ return new Asset(
+ new AssetIdentifier($id),
+ new AssetSource('commons'),
+ new AssetUri('https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file/'.urlencode($id)),
+ new AssetMetadata([
+ 'page_url' => "https://commons.wikimedia.org/wiki/File:$id",
+ 'author' => array_key_exists('Artist', $imageInfo) ? $imageInfo['Artist']['value'] : null,
+ 'license' => array_key_exists('LicenseShortName', $imageInfo) ? $imageInfo['LicenseShortName']['value'] : null,
+ 'license_url' => array_key_exists('LicenseUrl', $imageInfo) ? $imageInfo['LicenseUrl']['value'] : null,
+ ])
+ );
+ }
+}
diff --git a/code_samples/back_office/images/src/WikimediaCommonsConnector/Resources/views/themes/standard/commons_asset_view.html.twig b/code_samples/back_office/images/src/WikimediaCommonsConnector/Resources/views/themes/standard/commons_asset_view.html.twig
new file mode 100644
index 0000000000..8551c8aaea
--- /dev/null
+++ b/code_samples/back_office/images/src/WikimediaCommonsConnector/Resources/views/themes/standard/commons_asset_view.html.twig
@@ -0,0 +1,13 @@
+{% extends '@ezdesign/ui/field_type/image_asset_view.html.twig' %}
+
+{% block asset_preview %}
+ {{ parent() }}
+
+ {{ 'ezimageasset.commons.author_attribute'|trans({
+ '%page_url%': asset.assetMetadata.page_url,
+ '%author%': asset.assetMetadata.author,
+ '%license_url%': asset.assetMetadata.license_url,
+ '%license%': asset.assetMetadata.license,
+ })|desc('
Image by %author% under
%license%')|raw }}
+
+{% endblock %}
\ No newline at end of file
diff --git a/code_samples/back_office/images/src/WikimediaCommonsConnector/Transformation/TransformationFactory.php b/code_samples/back_office/images/src/WikimediaCommonsConnector/Transformation/TransformationFactory.php
new file mode 100644
index 0000000000..b25a27d704
--- /dev/null
+++ b/code_samples/back_office/images/src/WikimediaCommonsConnector/Transformation/TransformationFactory.php
@@ -0,0 +1,25 @@
+buildAll()[$transformationName];
+ }
+
+ public function buildAll(): iterable
+ {
+ return [
+ 'reference' => new Transformation('reference'),
+ 'tiny' => new Transformation('tiny', ['width' => 30]),
+ 'small' => new Transformation('small', ['width' => 100]),
+ 'medium' => new Transformation('medium', ['width' => 200]),
+ 'large' => new Transformation('large', ['width' => 300]),
+ ];
+ }
+}
\ No newline at end of file
diff --git a/code_samples/back_office/images/src/WikimediaCommonsConnector/WikimediaCommonsConnector.php b/code_samples/back_office/images/src/WikimediaCommonsConnector/WikimediaCommonsConnector.php
new file mode 100644
index 0000000000..35670efd02
--- /dev/null
+++ b/code_samples/back_office/images/src/WikimediaCommonsConnector/WikimediaCommonsConnector.php
@@ -0,0 +1,9 @@
+ ['all' => true],
-];
+[[= include_file('code_samples/back_office/images/config/bundles.php') =]]
```
### Create DAM handler
@@ -128,74 +115,16 @@ This class handles searching through Wikimedia Commons for images and fetching a
In `src\WikimediaCommonsConnector\Handler` folder, create the `WikimediaHandler.php` file that resembles the following example, which uses `search()` and `fetchAsset()` functions to query the server for images and return asset objects, respectively:
```php
-getPhrase())
- .'&sroffset='.$offset
- .'&srlimit='.$limit
- ;
- $response = json_decode(file_get_contents($searchUrl), true);
-
- $assets = [];
- foreach ($response['query']['search'] as $result) {
- $identifier = str_replace('File:', '', $result['title']);
- $assets[] = $this->fetchAsset($identifier);
- }
-
- return new AssetSearchResult((int) $response['query']['searchinfo']['totalhits'], new AssetCollection($assets));
- }
-
- public function fetchAsset(string $id): Asset
- {
- $metadataUrl = 'https://commons.wikipedia.org/w/api.php?action=query&prop=imageinfo&iiprop=extmetadata&format=json'
- .'&titles=File%3a'.urlencode($id)
- ;
- $response = json_decode(file_get_contents($metadataUrl), true);
- $imageInfo = array_values($response['query']['pages'])[0]['imageinfo'][0]['extmetadata'];
-
- return new Asset(
- new AssetIdentifier($id),
- new AssetSource('commons'),
- new AssetUri('https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file/'.urlencode($id)),
- new AssetMetadata([
- 'page_url' => "https://commons.wikimedia.org/wiki/File:$id",
- 'author' => array_key_exists('Artist', $imageInfo) ? $imageInfo['Artist']['value'] : null,
- 'license' => array_key_exists('LicenseShortName', $imageInfo) ? $imageInfo['LicenseShortName']['value'] : null,
- 'license_url' => array_key_exists('LicenseUrl', $imageInfo) ? $imageInfo['LicenseUrl']['value'] : null,
- ])
- );
- }
-}
+[[= include_file('code_samples/back_office/images/src/WikimediaCommonsConnector/Handler/WikimediaCommonsHandler.php') =]]
```
Then, in `config\services.yaml`, register the handler as a service:
```yaml
-services:
- WikimediaCommonsConnector\Handler\WikimediaCommonsHandler:
- arguments:
- $httpClient: '@http_client'
- tags:
- - { name: 'ibexa.platform.connector.dam.handler', source: 'commons' }
+[[= include_file('code_samples/back_office/images/config/services.yaml', 9, 14) =]]
```
+
### Create transformation factory
The transformation factory transforms image variations coming from Wikimedia Commons to the ones used by [= product_name =].
@@ -204,42 +133,13 @@ In `src\WikimediaCommonsConnector\Transformation` folder, create the `Transforma
```php
-buildAll()[$transformationName];
- }
-
- public function buildAll(): iterable
- {
- return [
- 'reference' => new Transformation('reference'),
- 'tiny' => new Transformation('tiny', ['width' => 30]),
- 'small' => new Transformation('small', ['width' => 100]),
- 'medium' => new Transformation('medium', ['width' => 200]),
- 'large' => new Transformation('large', ['width' => 300]),
- ];
- }
-}
+[[= include_file('code_samples/back_office/images/src/WikimediaCommonsConnector/Transformation/TransformationFactory.php') =]]
```
Then register the transformation factory as a service:
```yaml
-services:
- WikimediaCommonsConnector\Transformation\TransformationFactory:
- arguments:
- $httpClient: '@http_client'
- tags:
- - { name: 'ibexa.platform.connector.dam.transformation_factory', source: 'commons' }
+[[= include_file('code_samples/back_office/images/config/services.yaml', 15, 20) =]]
```
### Register variations generator
@@ -258,11 +158,7 @@ When the user requests a specific variation of the image, the variation generato
For this to happen, register the variations generator as a service:
```yaml
-services:
- commons_asset_variation_generator:
- class: Ibexa\Connector\Dam\Variation\URLBasedVariationGenerator
- tags:
- - { name: ibexa.platform.connector.dam.variation_generator, source: commons }
+[[= include_file('code_samples/back_office/images/config/services.yaml', 21, 25) =]]
```
### Create Twig template for Admin UI
@@ -272,31 +168,16 @@ The template deffines how images that come from Wikimedia Commons appear in the
In `src/WikimediaCommonsConnector/Resources/views/themes/standard/`, add the `commons_asset_view.html.twig` file that resembles the following example:
```html+twig
-{% extends '@ezdesign/ui/field_type/image_asset_view.html.twig' %}
-
-{% block asset_preview %}
- {{ parent() }}
-
- {{ 'ezimageasset.commons.author_attribute'|trans({
- '%page_url%': asset.assetMetadata.page_url,
- '%author%': asset.assetMetadata.author,
- '%license_url%': asset.assetMetadata.license_url,
- '%license%': asset.assetMetadata.license,
- })|desc('
Image by %author% under
%license%')|raw }}
-
-{% endblock %}
+[[= include_file('code_samples/back_office/images/src/WikimediaCommonsConnector/Resources/views/themes/standard/commons_asset_view.html.twig') =]]
```
-Then, register the template in `config/packages/ibexa_admin.yaml`:
+Then, register the template in configuration files:
```yaml
-ibexa_admin_ui:
- asset_view:
- wikimedia_commons:
- template: '@WikimediaCommonsConnector/admin/commons_asset_view.html.twig'
+[[= include_file('code_samples/back_office/images/config/views.yaml') =]]
```
-## Add Wikimedia Commons to DAM configuration
+## Add Wikimedia Commons connection to DAM configuration
You can now configure a connection with Wikimedia Commons under the `ibexa.system..content.dam` key:
@@ -308,4 +189,4 @@ ibexa:
dam: [ commons ]
```
-Once you clear the cache, and search for images to see whether images from the newly configured DAM are displayed correctly, including their variations.
\ No newline at end of file
+Once you clear the cache, you can search for images to see whether images from the newly configured DAM are displayed correctly, including their variations.
\ No newline at end of file
diff --git a/docs/content_management/images/images.md b/docs/content_management/images/images.md
index 8afdbdcd94..4e3a0530b5 100644
--- a/docs/content_management/images/images.md
+++ b/docs/content_management/images/images.md
@@ -214,7 +214,7 @@ It points to a custom controller that handles the downloading of the SVG file.
The controller's definition (that you place in the `config/services.yaml` file under `services` key) and implementation are as follows:
```yaml
-[[= include_file('code_samples/back_office/images/config/services.yaml') =]]
+[[= include_file('code_samples/back_office/images/config/services.yaml', 0, 8) =]]
```
```php
diff --git a/get-pip.py b/get-pip.py
new file mode 100644
index 0000000000..f5f25e1430
--- /dev/null
+++ b/get-pip.py
@@ -0,0 +1,28840 @@
+#!/usr/bin/env python
+#
+# Hi There!
+#
+# You may be wondering what this giant blob of binary data here is, you might
+# even be worried that we're up to something nefarious (good for you for being
+# paranoid!). This is a base85 encoding of a zip file, this zip file contains
+# an entire copy of pip (version 25.0.1).
+#
+# Pip is a thing that installs packages, pip itself is a package that someone
+# might want to install, especially if they're looking to run this get-pip.py
+# script. Pip has a lot of code to deal with the security of installing
+# packages, various edge cases on various platforms, and other such sort of
+# "tribal knowledge" that has been encoded in its code base. Because of this
+# we basically include an entire copy of pip inside this blob. We do this
+# because the alternatives are attempt to implement a "minipip" that probably
+# doesn't do things correctly and has weird edge cases, or compress pip itself
+# down into a single file.
+#
+# If you're wondering how this is created, it is generated using
+# `scripts/generate.py` in https://github.com/pypa/get-pip.
+
+import sys
+
+this_python = sys.version_info[:2]
+min_version = (3, 8)
+if this_python < min_version:
+ message_parts = [
+ "This script does not work on Python {}.{}.".format(*this_python),
+ "The minimum supported Python version is {}.{}.".format(*min_version),
+ "Please use https://bootstrap.pypa.io/pip/{}.{}/get-pip.py instead.".format(*this_python),
+ ]
+ print("ERROR: " + " ".join(message_parts))
+ sys.exit(1)
+
+
+import os.path
+import pkgutil
+import shutil
+import tempfile
+import argparse
+import importlib
+from base64 import b85decode
+
+
+def include_setuptools(args):
+ """
+ Install setuptools only if absent, not excluded and when using Python <3.12.
+ """
+ cli = not args.no_setuptools
+ env = not os.environ.get("PIP_NO_SETUPTOOLS")
+ absent = not importlib.util.find_spec("setuptools")
+ python_lt_3_12 = this_python < (3, 12)
+ return cli and env and absent and python_lt_3_12
+
+
+def include_wheel(args):
+ """
+ Install wheel only if absent, not excluded and when using Python <3.12.
+ """
+ cli = not args.no_wheel
+ env = not os.environ.get("PIP_NO_WHEEL")
+ absent = not importlib.util.find_spec("wheel")
+ python_lt_3_12 = this_python < (3, 12)
+ return cli and env and absent and python_lt_3_12
+
+
+def determine_pip_install_arguments():
+ pre_parser = argparse.ArgumentParser()
+ pre_parser.add_argument("--no-setuptools", action="store_true")
+ pre_parser.add_argument("--no-wheel", action="store_true")
+ pre, args = pre_parser.parse_known_args()
+
+ args.append("pip")
+
+ if include_setuptools(pre):
+ args.append("setuptools")
+
+ if include_wheel(pre):
+ args.append("wheel")
+
+ return ["install", "--upgrade", "--force-reinstall"] + args
+
+
+def monkeypatch_for_cert(tmpdir):
+ """Patches `pip install` to provide default certificate with the lowest priority.
+
+ This ensures that the bundled certificates are used unless the user specifies a
+ custom cert via any of pip's option passing mechanisms (config, env-var, CLI).
+
+ A monkeypatch is the easiest way to achieve this, without messing too much with
+ the rest of pip's internals.
+ """
+ from pip._internal.commands.install import InstallCommand
+
+ # We want to be using the internal certificates.
+ cert_path = os.path.join(tmpdir, "cacert.pem")
+ with open(cert_path, "wb") as cert:
+ cert.write(pkgutil.get_data("pip._vendor.certifi", "cacert.pem"))
+
+ install_parse_args = InstallCommand.parse_args
+
+ def cert_parse_args(self, args):
+ if not self.parser.get_default_values().cert:
+ # There are no user provided cert -- force use of bundled cert
+ self.parser.defaults["cert"] = cert_path # calculated above
+ return install_parse_args(self, args)
+
+ InstallCommand.parse_args = cert_parse_args
+
+
+def bootstrap(tmpdir):
+ monkeypatch_for_cert(tmpdir)
+
+ # Execute the included pip and use it to install the latest pip and
+ # any user-requested packages from PyPI.
+ from pip._internal.cli.main import main as pip_entry_point
+ args = determine_pip_install_arguments()
+ sys.exit(pip_entry_point(args))
+
+
+def main():
+ tmpdir = None
+ try:
+ # Create a temporary working directory
+ tmpdir = tempfile.mkdtemp()
+
+ # Unpack the zipfile into the temporary directory
+ pip_zip = os.path.join(tmpdir, "pip.zip")
+ with open(pip_zip, "wb") as fp:
+ fp.write(b85decode(DATA.replace(b"\n", b"")))
+
+ # Add the zipfile to sys.path so that we can import it
+ sys.path.insert(0, pip_zip)
+
+ # Run the bootstrap
+ bootstrap(tmpdir=tmpdir)
+ finally:
+ # Clean up our temporary working directory
+ if tmpdir:
+ shutil.rmtree(tmpdir, ignore_errors=True)
+
+
+DATA = b"""
+P)h>@6aWAK2mtSfNm@P%ijnvL003nH000jF003}la4%n9X>MtBUtcb8c|B0UO2j}6z0X&KUUXrdswk@
+k1uudi>cQKxl-V|I1MSR^q%Qq?r(L=s5b}6=dAx?h06InTEzl4HD}0jZ7QUlW@UAzeEdP)tEoBKWklj
+DpTYHxoV`^+*aOAHYw^Cd#_OrlVln;l*{|X*AaPtb}wJ?w>%d+2&1X4Rc!^r6h-hMtH_d5{AF3D`nKTt~p1QY-O00;o@hDlm)_pjHy0RRA2
+0{{RI0001RX>c!JUu|J&ZeL$6aCu!)OK;mS48HqU5b43r;JP^vOMxACEp{6QLy+m1h%E`C9MAjpBNe-
+8r;{H19{ebpf{zJ27j)n8%0=-6Z#elILRo@w9oRWWbO{z8ujDS!QAC@3T%nJCf;1rX6ghzu#Z}R@K&*?Hgj1WFD91+adaM4G`4Xs@*hA^t@nbDYdL)-aOjsW~3}QVVby(8=@7U$
+Fzj5Y{w!2hUUH`?e9j7WDA;>-1aos>7j{2$~BfyL8p@__Y98dsP#Bs7^lWF
+=e_gr;(4^?am?Cp93+7b-!?~nb}-$cPSR1zckA*zNp!)$;YjlZrfn&RWNM}=QA7*cb8A{(9@{5!vBfq
+rEMoeu5FvJZngI@N#4#(2v$WnMGCAVD?b9t8W^qDfcFBe5ZZF%dPAPaq#>ikclG~yPvCg`JUGb_W2#PdCXxx}7!|T*xc9qdnTILbO-nAJaF2
+~0snMFDU<%E01X4*yW9@|}F2;vY~;0|XQR000O8?}kZQNptbL)dBzjss#W56#xJLaA|NaUte%(a4
+m9mZf<3AUtcb8d3{vDPTN2bz56Q$bEqvD7eNnI)KryFP`Qva35SZJ)y5u^rS`7bUDH^IfA5SPClJy4k
+gRuS-n@D9)?pY{{DTOK#=wHhU
+bC3>{r`H6$p=j4wBxLD(_{!uBMQ2if@UWt^sy5bB+LMxj)Z2G(UV7|ngkcy2$MEs!7j)I0&^l!_5v^+
+J)k>Ahw~(zd`wb2=&u3NRI`moV*YtX}3obEbq#zjTw2r|qOs$ARVNC^fTU+x$K&dxX8O(kzzfZ5leDd
+SwYCc)O7^3q8KF2{264O
+7trE3Xz}JJ-^2@PTqtZaE^Ca{VL`GT(a_Oau^s*w(AT6joVG|914`AACj$B4SNYmBJJg-pS8tGDosG|
+O?)?P+h{U34M&?tIfBWj)3czPd4FE2Ra(i69FMjgoH&zyeW`Sg_Ps>oQmV2Zf^%j05*$PZv#Xg{OmF5
+FlZBX1r%N)?HZmIih2UExM9lNgO6eTTRDIRK&XJZrHky`R+I#ff%RkJ@54mv2hNCfr6a??SM@ga{J|FQn$%LuR5F66J(ej0|XQR000O8?}kZQ&BwqszyJUM
+9svLV3;+NCaA|NaaCt6td2nT9C62L9#V`y-_kP9QSf2V13=C{tnX)PsolsJX_Jx&=d9p7_`6i5S
+Mvz$qHBvD4Gc2vqMK2J#u@ySRoi8HJ74pBUZpQaDYr)B{xbde@6aWAK2mtSfNm^4WVBa?Z00033000>P003}la4%nJZggdGZ
+eeUMUtei%X>?y-E^v8uQL#?LKn&gQE3C4#Qn@ThKqVNNDp=U63SAQ?v2?jR*$!3y9w((B25z~hr>E!V
+=a%yTIu%MC&`>ff>`8PBZ$&Am5S?phNulCDC@HdWepHHb)qlj?Id=n;NN3!c*LnlPC<-TpI>d;Lp*Ax
+@NYlcAX86|n4s~x3dA%{4b5C^-eJBN!K+x-$+`^E}a>&gXQM{XH`M*P*a}AmWcRbiVczN>%Eu
+!-!D~*qf!k-xtUCwxR;$%}PqvdlVHD&~%WR1u#|G-0Bu50PnTiT%Z?T3jfmjc5UXrmz##CF1#g5dw1-
+zI=Xd1etfCe>Kbz2Zb=v9mCs;VRH$CIz~P?f2K%DS#dWJIa%?;aogHQ@69cMXq8c`Di1-^-kNu8}WM7
+8UO$QaA|NaUukZ1WpZv|Y%gMUX>4R)Wo~vZ
+aCy}lU6b3k@m;?Hp&vrFB;(|%qp{k?_Bpw!Yv0)Cw3!vJGOus*7A^08AA6{lKeYEEZ5CTm?^#xtCC_kY$uz)wk#oWG*G1MUnD*H4{_V9$Grmc)yK
+7kO-y_Qg;ODE0;L_O?6nf8bfys*D5cK#R3I&azGjaOUz
+DA$9b2^qd6|z1|hz!BS;ojgwL~8C*G3X}XdvxHzI)5dz2+py4)@u!*P@tFd97zGdBsjB68t6D6URTm=t^Q{)_E{S8+@qc
+OWgb)~IEGfO3?@*Y%}R;VI+&vFXZ@)-A!+Q-3EzTz-g*uG!Ocq?j`xFK
+P_KP;mnKzQfvs}VbAco?c=)Q_?OhvXUS^U3X-#uqFl-_$mbcjlGWcLL`Tt@}NCTJ0{m1*hH)?{
+pfw>l8-s`|ddNZc0~-8)o5NY;@%bnfcw7L`nK4c=+*c)x?*Wy}%y45*B4I0OWQEQpdbzjyvY(%_WdZX
+8Dlnd1p-+sz+qNhvr+Ya(+#rBKQql$wEWoA^_o`Kdd!n#10;Uy=JrmR332rxgkWzjez9l31Arb*6KaN
+<~mY8cEILY(1GNB7J3ExkcH>TD)=!bNuqt<=fZE#k-$CBW1n85K9z?`RZD9CIj?EAyHL@RBCmZeh)=4
+gvB>Bh0r(p{7+p}zG04*LWYn*5IE?lXk14{`<{v^sAnGfZ<%6#F_07PbY+uEYE>z}pzYTqFjLx2f|0F
+>dt^dzY+8BlmjLa%dWa8c*`a?1R?JQriYb@pzCtq)ycNrL%vZNv#ss$kHD
+=YI6R9Ra9XSl;B@c^CAJ2$IgkyC2+o&g)C+8dJL|G(Q1}DbLHaJqk@
+^94e}~m|1l0p!>Z3z~KgJu_a&a|ZnNd2`I#|31=j0WXMM!chuWPr_U%bIZ@%*xFT;{e-Oo`at8b9V}7
+emJd2AKlj$J7z~(;p>6rfLeF7bj59*cZnPOAWk$%1l#5V$8BZ{4Q9zHKmT2chcc}1_ly$RQ
+PvEHl5Fk}8-ul4=#?GjZwoiQ}o|dzcQ{77Q9KX@H%3Z9zR@U$7hI$X1tJ!VlE5I!1s46IZKqc}g3JYe
+mG^IJG=bPD`>7~8>1a%e-V(CPI!w?&48!2f*VJdEWaga)$8Lk3o4kkoV=3aEU>>z=6`hAn
+TO#VCpCo}TAZ9LK9n+C1q|P`5e64az;}?72)QWQv8pK;HWl%sYPhZ&&Av5f*+*;sn5ZJ8%$Ak0fUO
+;EC^uTfS05*DbNMV^>qCe;k1UpMzy^+qjx_tHh^^aJUuYSJ%@%_7Z?>~LK`0(-a`eIlkh=Ih@;0-2!I
+3?1~B6XQ34v>-HM(sO5qC0C~*TA|`Pz^N@v24nsH4Ta6O<+~1hEAU*6SRbxod*llbG*7l`8}
+8+KL2g*+#m0Us-L$-Hm9lYpnF_tK2^cp7(4+K(QnrF0x;K;#cuf-}TrKm5DFdEd=T$Q~CD8K=ed+C_l
+Q$bxr4N2E74VS7BO0cSiLz44F=<*aC6YQ!jh9gm5@gnQ|a+5_!28b^+3&)B-D8^7Of8XNA}Yl?rPak0
+4hKAmvL;rA(IpFAMuSc_XrixeLHPLe?so1y-fgg=w{d1{S6Yo#!WD2hb_
+NLG@4?Hmf_Q!eLenNi+Ari2aI&+NW!4ItJL7$~mU!zT#dB*<5zlLhbA0Y2#MOz*jN6$-1i_`(bF%)|5
+7G6BG0#4HCm)Js9nLP?~iCQA5BL!7YQ6Jzmo&&`r+w*LfR)yTtQG(J=)}+rj5#cF8eatpCzt!hbY=1z?i6p6o
+`)mg;ObO*-7QPoi=9d+mzN?>o!l4`
+y*L+Kvcvq)WoMdlJ`N*U4<$`Ij=ht5(FwQeI&yvE@spiG*}S$ki@39rIA+@?O@?bfc7Bg7UI4IPrc*{
+`<6tvd8VcYqBIw2^v(&Nk4v-nyea&8DI;X5V^tj!)_u73<%{c8mW=aNuwGftP;3UJQ4uuPV|mvS;G2O`z%R|BDP2B{G4F55OrzB!+3y9#gQh&Re3azqhg_OrRtujnN!gfyF|m$Cc%_F
+eWsigk`uGKDDv2!M^t0Mn-WerzLy}|kvDS=B;?T3gUDJyqwO0ZKo^hRvcdp`o@WMmc3^-Xx?WE@QKBZ
+a28K1;Er!(@6KNgXcu@fY44^m9*XwCpOAT5=P-rv@{M+SvTGK~6M1&p@Rs>i$Z5;@%ZKoUeEv`FZoD<
+H-tso@tkT2s9@Ri`&dBG!uiwMpOiN@O2^VX1qzWCvIo)Uoo5gTLe^0=#IYw_5MPJ%-uxcnJ5HE4vOum
+^svgBd>6SUbs}qMs*-5CgLo+C15^fa>%mWC?IgeZZcj4yB>KPq4UJz2aFP061@s5+-Xdbn^Hd1%Ql9n
+pvCx8^6(_+9iADGQ#}FlE3vXhyPS~#QOZ?(OrTDa9JGv*UmH*Aq&$qk=6S>oUP!jDznwrbN^q$zKPTf
+Oett?R{A>}=N)}B`mTQ8jBiK%@j}qwmwpeuVN^GCOA*mwn9?QPk76{8F@M+fDE`06@0g%Y!2f82GFN~
+MVx+?V<@pk6|JVl_krtA}T6?)~O4^s_7eds+4;KFgP)h>@6aWAK2mtSfNm@Xs&khR=004m~000&M003
+}la4%nJZggdGZeeUMV_{=xWiD`e-CAvr+r|<8u3xcLV1z1UUSc?ID?mjZ=N!B6OAtHohr@wbi7RP+6v
+=RxCo4t&d!LzIl1q`gT$-j0Dj2f3FSGML&n#~`oj#N6of5BQF1Kp0ayyw$r;~}^mqlg8PMTe&SIy%`Q
+{>I>tk`aKzHJ^0Guc$dUX;?(4&jHt!=sz9#}dn%@u&H5F22!gI~T9C!S~zJ>LQof#FNowoZPBBEvmSb
+>l;aD#a3=jL*c#L&V|mcs>({?JIUo<^+#@1WkB>UinY~QOL8sqBG+q~>7Nvn3z=cUU@%sn){2>J_r1(
+-u_yhoQ!0C|GsRm+cJ7N*WhPE_rPem7tE?gL4Uha#Wq0h#bbiyUe}&(7EIkk-&06MaY%z--TeU9}aMY
+?5&yJmS&hls~VnVR4FS7wU}izoloatx|q)9Lgl8eR3gnl3qL@KQmY%OvdGhtE-;(zaUkjWR~J+@XwVM!|%zj-Qd&UL$3@vyhHNfH^AZRQ~bu*I5xQ{yHyDiK9b~-=c7haaQdGr_~&NJ`*35ILI6X3b9qWf(I!fb3xIMq1xaHr
+_`0VBphxo4zOsEe{P$d0lAOFLZxUQS?q`JUxA^uq-PBV^>#;D`xZQ68c~e^Mr7u^cvHzOr}&PX%+v0)
+wXDF+s;Eia!gx=h54dtlgx>!#1@F@ZE0O{~A@Q*%X~_Sx-KIBg6~`?_yU>PBPv+vY+v#woGez(0t3Iu
+3$|}vs;7C)inxHtgoSh>)4OdTF!lN`o+rG@#S)Hn|=m=Ma_VOdVk|f;g9KU=iB1^P(4hX>$)`7lYJP#^sSzzEZThs&nj^pZ
+JAy3YV~$T66GPu^h!7L7-PU)AlH+G{*sfowcP|TwH7+QN4<>_@X?P@&eW4LK{;nbMdD~e|a+Wu&e25Q
+D=jk4hAXZ%vLY-V7DKqblb6e>7=AM1UZgQwuQ^v6p^22nQ&3ZYHLFd-Y1OS>r7SwJ)_ojMS4M^MlQ6J
+m|_7kF)?kW(N${Y^ogGov*r
+*NHw$VT)v3yF7C9Q;M}b2ffN)T(RFXUy0i+d;}N1z}!eTSC{TR%rMn6AXD9t@bTIq)!ME+dR)viXR>f
+rCkLj2DvOWkdaxD8lm&1urK#z#{H8@FRQAkn)KqCi+VVw%d~-$1Ue60q-l&8q;!h_u?TIeG@;D9a2|x
+7$S?6;1>!?-4P^%ECLpQ|#Uu+Nqp43+bLI{~97w*(@54aAC6Jsi;NcnfQ;i3@?=;PEi^7;U;_q1peSN
+h=uyd_*=yp?s9r6)C`wZR3e-^6-*z>>OUV&H~sqOZ!eTlK0{s@`94j0S(CETR}IV-v*;j&0itaxOd^9Xc&D2
+&btpYnt?iR$lK{7^42m@zlZ7BDWH7itzKFkw)OJ_Jn5nWjaQiEbqe@Vk6kD;vXdUvXnUSZHfU7=n
+R&R8i7s}!-C2HN+1o%2O%={UH3OUM4ff*f{wy>sy80EpSBk6mg!f}4uT*?+vJ>Q?~Y-1W;;P>$cR=X)
+=f$S9hauX}*oCpHuE^kPtk7y|
+{dxe0Xtr`6_w#^x2Ecz5%ycu>wLkCVPHmlDgaBc1d8(0kZ5f#=1Va^S#X54BC_Qmy|IACdSfjmsk}=<
+_pt_dKe-s`^_OwblWlAJ@gm3yZN9dvf1VCg>1g4*Y+fr-;W%HB4zkK
+Y{O4+tc4gGZks`P9oD0%)P^O{>W_G5yjEj1{(6ABDXT;Gm)42cn9`HjY%R#nbcsUCH}(~1z~R|Drrv3ewO@5+Al<#r{9QB>WGNTQ!Hrxn?2&p8*
+_|BJyR8c;!heUaUP8ceG8XKOJ3!J{C}iq?p}BTzS5>di+=O*2nj86_zZ*klY>AQ9Vs5*`Tni+DE`!01
+>%*DGL7IMs7%8yGOYEGgl3Dmd)-xX30V%%i&QF4_3LcCvYv#ozIF{&yfQ
+!>XaY39rHjX{%!g>iBCfK|3c#DGBYP4)28n2_TP*}ky`H+`lPfCIn?K(N|O{AIxB!fT;Y!TRb(#Od7W
+>HMF)9C>WeS^Ay(@u#r>e!FU4bbLa~tM9Z>7HLsrjtKpxxDZ
+RIJA)=%h92}=bSV+LdO#Pvy&IV3c-}B>IVStS#12j3U#4#qu%o0ui4v=N
+EBH3Uor8d^YUg$Qy8E0vFj01i&<~nhZ6$Jb5U>RZoN*2MbecTBrn@seyJTR3@ujn|EDHToA&O9KQH000080PluLT5$InwA2s)0JSy%03HAU0B~t=FJEbHbY*gGVQepBZ*FF3XLWL6bZK
+vHE^v9xTWxRK$PxaoU$MvF5D6zUOKM>X8v-e+ca$z77NeL
++9e2x5ucot^i$9S1@1W09}Yn{5@>X_1RfoX0nEBlB7)S#QhH=(5;IQOjzR=0#TA>}I0_k;fZ365>#ay
+DF_~nTs?RO9muXX(m;OMYnObrB$Ekw}_Q0mT6qeMBJtITErU2f%q(USagOjfUvnvbGss~Un(H6WW2`a
+LrA+O482O@ye2G!O7ojcio2ppL?YF)N&)6Z+^uB=)YsCWW@*HU2aKF3I(k(Vn^6!1qfxpki>fw
+T%D7Upvd^+&8E4XdE0q1Dc4|ZbM7=BNVDtDe-%Z6)x~!+-1PqL?GdUHfslxX&dG}#g;_G=yD8<=SeAt
+$Nt>Khu8AfT2O?VZ`FH6bGl!ZJ7*+O`dJFcptn)aW+fjE9Fwpnsk)IZ46B2Hv79ZiPL+16>+91)jgl2
+&T(x)8!Dc(>{Flr9%b_|q4sUK`eTpaG?cN=mR4wgtnX7FjBVaVe=j~=Rx`^*Io$pyhV(v*S?
+7kK+#N`^0)^VPUeopfQ8;lUf0eugqLe2$=kE@i{m5Ocq=Of831;$mRSkydLceQA3x(jC5n}=n2K~28XH$K9O)%-BON{Zba;Al6rG+Q9!2M8r~hmKx*&Yu1aLIUSQW9nQOj`@k*A3wXat0IcK+dbC
+f>!nYbhWBb}9wi*Tf0o8O
+l6olk3u0R(Z{jKe+gNW@v8|R;jHScaqGI1WAumR-7{Z)?!TRn%(tKhw?)^VxCuG
+oq@gc$6BU`gsPwPA(#gww-IUK;TRs{_YIMz3y$3A2YH%!62p7H%|5c>?dZ!^|hNL{{m;RXyAcMXycaMSSks-g75GpyyaqypDGHn(xdVS{|(&Khj2Mzr~Ba_R!$1t&cp`#t
+X7`E&o&QIp^kJPUp^?HO1lC%?`?Syx-=DxMBO$5bKa~hsZqdV1%qf@Jg4+JdBVvCG5SC
+nWc3UAqUS^Q>-pB;?N9;7f4()SR;?F!^zSjqPtC-%m3=T?=CPo!VZtZagLaix_7DxaH8R+}{Ll6?j}o@_N>F4e>MCA-CTeuCgvU4FM57>F7I`N`I>A=6Uf
+|&ZhQiNObh7Wof^^~Dqs-KA@JkD3wfRmm^|Qie*Fy&pt>GRX{E;z0?e*B9_YYrr=%z@J7t5q&!;`dA$
+X&G7L}Fn}8n6qP9aU(mYrT|14;VC?gp&f=%&$e4b-;}wKcF0CU=I+3yyx;^>RpMce_q+)>75*b7@hf^{#Cz7`j~wDWR~0335rQoX5yCgB<(q96xO&AJJ;+
+19pP@vSqJl_Z3ZVu&5#)RjIdYeHDBZ{vx=27LZm4{qx{kX>`bR(MR#!Wm5UFe
+-@WDiL*NKo?Gg4=%XCHpA9i!^*l-%*4<#+0=$|2DElblWTF19CYP^D*Uktj9=Ix5$PDN>(N{<=6m$R5
+1j{E8QQr5AlEv1KL(@_e;C1Q<%Z_~G7i#50q2Br_Tj#Xriwk_0&j~M-!#c`7K7LNwjLF{9X9wToDe>X
+&5`Mh4Rk%0xaLG13>#MS2rINLZo_5|Xn-ZtN-e8UR&k=8$7-@e|}{7=*nLZqWilKU7lpPBJKZO{J)+C
+QMi{nYvq#b)a;?<=_}zDK=-;$e7H)J`Rhd}-
+lI$eFvM%_!Ba4~-rj^k4^+=pd~oW=O}yjOW>X@CidVI+SY3h!iSa#$O-Y{c8HUe~x{cpq+Vqpi>}mhu
+1R>biBMJ2-UTb6DR+Z#r|6l{8s~wyLa^A3?H9u**R6F>#(pYJ)K=3%B8_i*wuZnT-OO@(`tPtNSREsO
+EoE^a)GcrgvDzKKYmS0eDC|`8#{m9sMrtq1alZN^v*q2I_bjhda!eX4ac{APcNlHe2nf5X&`r#zLC}n
+PC8{7pGQsY&Bt)oMH#CYW&V3M!%OEx9~BKt`g{ro=rTLp)?F}h;ODv_Y}qpYAXRlRG8Z`1LXV!yKY4E#{E8}?N?k3@QVxpQQJq*PeL
+G}spwH~QQwI?2Yr?R&p(W_o=>7KMqfZN#fl?KA
+XF?dt!=uM82^_v6#o3@0@-Ok+uNlN1ji?2GJ39mKbzPf5|`4(4yn7u~sI2Tv&bBVmow^_Cr^s!nu`<=
+ea&uPiG^hExip0h}{tp0sN4xB~^TxRDU6h=T0Thx32ldcdUmO=SX4H`}RL-WB_+djQbFrwwWZYZNUS?
+SwlnyIi>ZncdvW9bg*J9K3P75;1oQ?+$N|@ZT5^Jr1U#%Z@$#qdV=o+AeK
+PG467Y^x0;z(8{Lf
+{X+O;++UE=Axy`-R4(KVYT@YS+P@nl8~>lnTa!CN_3=k5>lXRf(4kOvQN$J6zvvi;|?>95~^J)8L
+OIsZR-(&mRRNWLPMa;JH2?U+=*JT)%N8+~dV*?`OIdbMDNgJw1%r|yn9*xc;26ua@I3&lffYCX1T|FX
+ZF?Z3z1%}*uvXZA#8ynM$)IB7pu94&@?!ymTZn(yOHu|*E6oebp>Eu?KrnsROC0w{UkKoRt|))7N@D9o3}KM9k
+zMklo&ykhQ6#B}Yd9gL_st4Q<(q&8U?iEF5#?yOb`9H<4twn#&Jl&-|96%-l<8uN@W03Z{s(gZP^_R_
+#HyUw~Qvdl@JuXmk-ITSxZaJSt0#1U=J$YYh$tiJ&Wi5$pn$!>N@E&hbMXGF7hC`T-O8613ae}9>;I
+>xHl*=%Lk>X=d1_d(Tjz5_0whF-a8-{KF@Anb+$Se??}s^+Pv@s6W{BpD9sJTp(^;PgoDNrG#p{Nh&*
+TKN?`9yM5nHF5~soIv&LsXGC4GJ#C9b0pWx8sV2TpY)M_;Q#{iq9kKZfW*2BEhXXxCpxbkhUgj8RXTl
+Y`P*4(9FrGO^y*a>n|m|Sl~7Y*6Y?+^Ws3BA4dW`BI{z1hUIgO6s4zc+H!tvkJ}UtJx%UVKH+?q7a&`
+vSJ7GwZ6sKn=meR#v4*e`pZCbDQQ!u)o~9SAP7)YIu$9NA*Cv6+=YLcr!NY|Cxis*Hv(@kBE4m()XAP^Xmh(LhB0MarnR;BJ4a&@
+n9?{IIDC%OKZ84Ny1Q5#oXx_kP2#-8U*K1Om?CV8errDQD1MUhwYMP8L+6-IaAT>3{xSB
+pf6Wgb_l6mLIVUWs?_uS8j_MVX6axyp-D%!+&|!fahGl58#>68sdmt7PQ|Nmj}t3)5R@ew43d5th;y1
+QY%zKdxj{;>fv}N)0ZY!bk?>mtmTUS&~X+;Fb${q^hZ&Ahd}`@T^iJpO>WmR;s~stk^zMVMqGF$WB
+X_~Go`_apH#iOP{UD-m^hF%oYQRpP(+ARUSKL_qxZA%ibR43T
+hu4=BhBpD_gk_=Wsal@xL*v(nD%EV~cWB)+I$?SpVH3k9RJI{(N|yB&)pTKIrlm8XWf;syU4nJ>HmAm
+0V_k;R2nRoXKL0<{c_yJ}@1Nfm`FxuYqP(_$391Nmo7)E*xR_@my7P$4}{``|VFKB`|gfCHkWDwPjgL
+e}KH;K#TMwSwiyc6YN8{G}|zI4ncc^Se;Vmq61ZnO2C2UHxES{69QUC2k5!0{ZFF?+Ce77UIOPtv{FL
+8+tYff-GFhAQ&DU9X&gGCN86JHp|l(nfuvMEN3D}RB$J!;WUU~W&?FBU~WS({#HzZpBZU|EUO}e51>d
+HEe3`6@7Lk@&o^HT#{4<_{GUA7kVD+$xF6r;8DNCruL?O!J_fj*VKFhxctAj5Bx2!fB-aQ>y&2I9%|O
+SNb?E8m{K3#@lKg-{>IXD$gvav+7DyB!FpFSmBYHLDclbw4b0QQy0P4!lD?JyW1Tt#?gACO0$VEy|3!
+dXhO)LmaDA&jcZB(gxvmm0=t#ywFchb2-+k+g|zXCTll
+FMw}Qj)2?;0gc+H@EMDw8c-aAxKtt((<+M=BA+2IC(#Id$c$73z%I+R8G_+KySyrR3IuK`l>#-Pd@%_
+D4!sbt9T0StC9r9MZZiqUk7T1w6lNk!73jDuN~>5Bv@nhn7Pm%Yi~tU3r4sefm(VRlc9&v277q&$Ln1
+7snIWh-?#sUDy5Fihr2k`JZl`dl7e;_mDQwN841$^$l}u+N`|I=i>m4xYv3RaE(zQqP0dDmk!XksYcsI{s`n
+=`V}Vb{3lp)E>_x}ipnkq)@8Y2V(|O*AnaNbR;xV?@StqaJO$^B$)7LEn%LCNv0~`
+mk>AxO{E$|NOyR4pTsiuZ3mEMjTTLC#IFiAR*C8@EKyP+3591ndBc&WivtM7wHfO(uK})ZbVBUl+XqL
+j5nD>cw(A>kS*a4OKWab5_Md6yG;HT1i@})q(R|^~sGdx-joDl$hLf7FHSe%&FUeA9ytnj+7WR9yiRC
+D0V!yY*AVZ)=h7adW1!Nu!eY@Lc-oI|Bc@U7$4Fcb2?Cr7GG}pZS)*HGz7EHCf-yz33a*@Eeo#y1-a
+V|)GO&9S(4p4LnSue=r{&w&k7K?$K3=7%auk|590byM;@6X&e;NJWvV(>yR@Em+7@-iMiWy|mrt$~Qe
++W0yMiWOKlJwmS{X_Mgj{quv%#o1X3;4|C$6`R0HA3$Q1={`NeTM*F}0^*?rW82&7aGe*kKvbewf=YR
+k0uYdXWX)A=M2d%JaZ2vuL{<{h4UBjL`h?Jh#zp(D2ctP$w|6XqQyd5uGK#lF&(rV5a0`ziAq3xVOuV
+mN_y07y=bZvs{VtXe=Ej5>bW$+JJ1|lR9em#V%sfvHC2E)!e4@T1A>$D(0Wu4I)Tozg+g89Tnc2-Gt%
+i~`7%WlUEGq7HdbqJ{+72RaD7W
+ad-Ji0;i+4{>%*bFu;kf|E&Q?DeQdgWJ+2Sd0--sDVY=jxhGK4jQ)
+L+RcnI#c%t?xPW8#=p!koNO3utSWeF|6+OvoS1&)lM(-rLF5>C4lrQx9z$@BD}F$7k_z?s4lz<&^s^a$c6+C^Hm#^|Fi)l5tx1?ia7!O(4CmeW2Jcpzr)3qSs1S0
+{t;|k+EC5K0WI69BE4A&Swi7Rd=3zB0xkwA{3Y6blc3Gl_RU@#!s*$IdCX1NqFa02i>d(Lw#gyU6Mgi
+8(ow29b!N-W)O+ZqXFIDW%uZv*dBNlZZOAmav;4ltezSlY!9L%(;jWV_&0K~mvIJF?`=i{eYpZx_|D#
+GQeeXW|302SP`Fa6-B!a5a@tSScnwA}gEQ9ppgKaca!f7Sau}k3^c>NrG$Acc9!T!AYC29U_`}4VBwl#S^*6@=9!a65aTgs1%yp^DWOwulJdGhPMO^&MV_IYBI$*BYwDw
+tQu-}!-$w$ya1ZCn8ITwRa75}~o4#6Z$=GYF(aQ+q>o4-sW%)*s?aJ{)Vd6sz$6BKa~@#~JcVZHBg4WTKve;oK@g8b+{-X7;ok+Up&p`G
+kv*g~5*VZ8Y*GI)Vom@%RfJ7Jco}+|hQt_c-V8Bz!zm2jF#cLt2hCThk-&(Ik~}ZT(6pGFW4bj2ZYx|3i@JIOodzcNWu
+Q_1i;-Om&*5?3@McAg*>nc#_!D-0BT)~kdkvqcl9bNc)d=jkalczgnWDTz4ZTlN>h`$bB)iDiqak!YW
+Uv}6E0GL#A2_EigKR)@CwIuC2GXDVuse&QT9rc=V2!Va*JsQZ?eke1)FCAYo^(5^hG`j199v}D?I|Xk
+)wQ%d@qA+eZJ+Zf=rolk^reU0A|q>;&v(K}+N3(GJ&$r9#!#x3wIOCpB^=MCbj`n3`9RUuSRFtxL10x
+)5yB4cBdy7X+S`HE#X0RhssJKTZefR!;^4vLQ-o_O78F_2hWl8~q0u%*Zc4$x0#E6goX=0dJEED4NUd
+eo5Oj1n&F*mDMnJbeflt#dnF4cbhCxfsOtSz+*58-*`!118L`KlSMflNtL2%&>eYRd9XncjAEzd%~qR
+%I?Wjn=tVa?`^o$8iC5Dk{u)YIJ_cao{LQgc&JowBazw^|-TpqqLDjYR9PhvOf01K!$VIcMwakqY}LO
+d@n=RA?^|+4#|_>&a4L9|2hU83Y>tiN@LX$FVP~sSZi8q0^1mjk66NZwEY->s~Q!_s+QrknFRv{Q67UpPckPJ!X-`t8lK8Ap0FU63T$q6T20BU(Ye1^Mz?_
+FE?21b>u46mzsLpSHomtn$Jd6_4F)1)AEjZy1+9Y_=Nzv$AQcDhOov;+GtSKlZmz$)`6=_d`Qb10gtg
+z;fU>J~V-goUiJz{ia@rlQHQI1b0ZVT%wTl5*@Vt;RyD?GK9Af~n-G^Ry-T3=UEHneR`QfSX-Y*b0^^yr4~U$Zgk1;$$86d__`gutzfP7K6=%nFc+c
+Ti9b3iJvClw3i=n$Xo3XjPm~3y9h$%pn=a^MzI}BwMc7a@=WFWMXYpL+je-bL3KPu;i9!ZRpE5Ohwk!+T^`-XqV#!6{EY?0z>DC%B@}$M=ceZ9?3Lm!%OA4w
+JkKdqvXF}BdK}${sI!1#$Kn*duTm)HVru7!TtcRZ|1Bi!jlVYF-Y?VjIc|FLhJw
+nu08_*KBZLI^AgsN0YOldvcw@RC=du3@#Bk23xm&wf%s4GHQ*
++e;A^22^2I4u{NDipqqTYO5?6)}gc7rCSwiO-2uZ$!HDo$WZ7CgS#NW7Loh@0V;aW?~RgSJ#LWw?5jc
+dmQwkPu_$p!M#7C#>+I0!j9m|^JeoZgGwx9@WFiHrljR&t%nkOp}g}?C_N|Mp364$`u1Z9mRCJFL_6UA`G(fQ6tX^Zv
+w`CWswTvpoJd90ny?
+2$7&^FSqwqJgX6siX&GCQ#9!i@ls0DlPUGbK8`sAGI%GzGzsF(o*d5sh7>QPhXPJxCDQD6p{*0w92uw
+a6J94#L$`xpK0xw1Hvo{=(hdwN;DhO8}?U6>B6@MWPy%Q&t$+Nz|D1^n4z|HJ53?f=wqCrKuH>+9Z{7zCIQ$Q;JkdcwsvP@k0J_j1b=8*$cp-AV0WIEU@8UJc
+vlFwr^u+$>q?{ENaz7Zi06!xM0h9<(e~luO;>V(5p8T
+JY^&p3DK>6FQ&MK8#Hm|~0Z#dXEU++Zgahh4kpqc+27TyN*LJZ;0(wUIDltxY?^w+=P7I-iWxN9pW|Lj1P<7H(QVl$Z02=?eS*o`JC??^kNgs>)MvesL7e5&Yp4OJB~8>pdG$`ZQ|+;5
+R+P_)FoRa=Ska89Em(fz+z~NQ3;e*)LmWk%N@GrY^Ppnr70C3aV2%mLf;XBdRS#9Mq1+J1U)qr?wn-Z
+rD6H@g&w5PXQQ-|wiw$%oZn>|gCJ;=mmNzJ`0KB=G}P_5m<-&mYpEyai&s=_P)Jf#4@FW+KJ}0Kv)|?
+9g4r^!1=JFaDlUL*lt#8)OGC0>?I79J>&fLroS(k<;q?2-rFi+CF0*-idiCP9fOi6!5}v=hc>k7uUrh
+e(!`a2;?d09nrAxF|XKyCH(7Kc8TCHMotXv!!(vAdp4!G;Nkqf9c2Ym4!#ot4M)gtm^xI}Nkg{F&sF=
+h~EnRO-u6bV8w=A$h#X$m9sTCRwS?_we&XQ*h
+?AM;Z5qXO319gyLaG=|LY+Pp&ra_c10V#>fvz8m(e!J6)w%@HgUH2mF@<}etUfBu(N60w7^aNNMw!!i
+7Q3KiZMt4+;@atcH12%sY%R~R^Xgc=~1jSch|MFMAKJ=enVBZ55=sz5AcIZD%7vG5;&Im&RFjW@h#ej
+a)P{P<7g&!$kEcZGPHVS>Pbj2jRxD4K{5%$=$Wf+PR0GQoi#w
+xTl#eYCg22Z$+Kz69Z8M%2mrvb5?B3kd2BWFm-ydQFH7Z(8OBB7kE?KyS)5Pz9ENd&^`QFPwRJeEiyX
+loDtCpPV~pPw!3i%l*ILuYI~hSV;F6Y>{W789z@1Y_HoAhb^pCJIuU0Zx%bZbHjlTr+PA;9bl6ye&oi
+gWTl~^|In(8h^x1s%NkvV@(P6kd&joAyEP&NwpdPjW?4C{CbL$i?bSr4|B{I$|ca;El#_^2?&B?=NU<&->{J?Pa|y+~X;1H
+*C~e`7B$g7<3tCFbt|r_T@3Cf~pj4IA*;gXp*#o_HTnho8R095IvOvgXmd0D=lR?{h#1XQb@+s?Gnszt?B=ja#aZJ3
+<>Q`>c$7hSkzQ83mh7&}PXT|?QHTPWQ6YwGM8y8@uTRf($79^F9u3hG+0+A{E<5;R?j^%#@vsEO&lM`
+dr}m-Y>(GEF48{krG{9pf^*lh!AsvTN9P6vFMP`0CrQfb{p5%>!3D>i~kG2gV;@CTRa*7QTR1G@TJvs
+8e(-QFmy|Pl4I)P<+r-^te6Hx>Fh9URs45G#`%%kV$ly6#f2#^SjOv!`^)28DjkSt->T-#EFxd&C#9>
+YMKX{<^i9rxRYzJEs@X7U8}_TZgBR^i{S0#@{(c)lo}W3?=R1OZ*FQ}biNRnFpt5UW|=}q!m#wMaat3
+^MTyZfQ%Wyc!Pz7ua}1s&nCnxBze}<>e^7KLxsVR1iqOsl6S_m96FlbXRU=O5QrqOuR*r!khnR4IWd*
+P-CIO7&FhfUU3RE=Wi*Lpqr&vJDm!jHm3`uDR8egIaJ_aU~Kst>j`h{UxAK23X@WQ(si%3F|$p`2|L@
+JYeCsbP&tvjYHc24x1e1|}_JfYB%I4yaz@QK1!*-)6x`>nY>QVBbaL{JY7-W7ivn29y(heEtlWdB7fG
+mmCB-eBWa)#{8c=UE}w4ZJZP5DmPRD};Z1tfl3-e;URPBok3eEDB(owJ2V2T+R
+vnMSLe1>Q+BR^H)B4FL7_fI)&n&DgI#@v3q*{!Ocz+EfXh=)TuIirc&Cu!6oD0*l-Z5^PS9-*ELQ%$l=!cH)}YKepXKeF-_G1vkm
+mMs?H?x>-@$0jAQVg^z{5-W#$*^KQ4`99#;@{Xp!>9Zer~AmI30LgkBl;sY_@+^o|*Z`!ap%zI&M57l
+R2yQ-?g6AiS!GJ4)|`fx?%cNrt>(<#|8BqlSjPo5|!pb{_f2WeKw#zx?Je%5lma(zHlWVDLC6BFWl}h
+X&_xI+7*MiL&s{g^ZN%Mt{RkY;hf@{U-xC1(tOCW2H!G<={k}_{oX)oQ-m5auq0_lC9guT~
+l4Q4ohdq{0OhCLcdz#RF}J6y-UU^QT-uU0}s-A7H!SL;0f_Fzg)dwl`0l
+Gf@v@5Obr}K}@kD9O@isdHg0IJs_AMkulD?|5=Gq>%SJU=d_-gciyZJMWyt3a%%L~&^{@P|Mo#fRJ~wme6Y}06#xJLaA|NaUukZ1WpZv|Y
+%gtLX>KlXc|DN9YQr!LhVOm~k<$vDeHm;EY{#9(cG<0z;wDNWaBLwd8+rS=DXkDlNaEMWKS-IuR;D}x
+&0NIblhpR`%|<21-yAN72Q@h!;SIh@#vMGq17&L+)M%RKXCj4~ET|~I*uzi+O6s9
+2SxZ9DPKZsxrfBua3Tl)RoDl>E6wF;E+vLc++nSFm5&NF56wsqZO1cL{gvpGx4Phjkmb3559C+mzm^h
+H?f*PKmUSIqTaI3?`gL>gll^vyu`lV8+$8554sZ+g~bNZ9WjB-U0v_T<1QY-O00;o@hD
+loBHqblY2><|g8~^|s0001RX>c!JX>N37a&BR4FK~Hqa&Ky7V{|TXdDU6pZ`?QzexJWW=RRZ%%s371i
+pvf#J?vt;xB%U~U|V1xf?%MriaQw&<;F
+X6}(G6Mi#;nbleySgD#ulvb+NcqP{IgQ#rZHNuJ5p_A<{eEqQ<7VNz=cESGBp&oB$Gg+g>;#p_|Z#J^
+66??m8^S>|H%}u_VG5F{8tvWQ|*Gx1MwQvIWYO{RiSNL>LW}?QQj3FV?HI
+^i`^+0z{XTt)O~}>?4c-^xb1Awc19S50t~Hi74aZOKv{riIUz64Q;a;mxkh-6G*@QKW6Zusd15RBM$<
+KL#`(&nof-5^=H#!brR*9Nzq}epE2OCvyjMa0s{j|cJ$=UKP+bY$#%xYnK-7*QzKqze~P;kLeGiSW57
+=$;EzDg?&3kC*rR^vXvBa_bqxYs*O>-F2$w-UrVd>uyUrrCHR?mq%cyu
+FFq;RUe;f*Y+S0qBFNAUO6G^bfO9_!%OPuQ9o4McyX;gdTd;@BrxG8sEw0*D_-nZr9JS78?3km4Jlz#+&Ht0J&&L~%-nbQy+T@te_dk+pVyB91?5UX
+V)iWy1Wa}9=}x{T9G-DOMmZ)`0v0WUQ=(hFFsV)yUv847^iQcxZLi~XirF&at!9RzP9Gkb2@E6c>^u9
+2m*&A?12N?A)$6{CSPG2qF2RZ^ERRlA_v=PPqAywOZZk+k%mq7^}e`la`Kg$gmK7-bjS$B!fPlnOfrUjl9|4v;I>%EOtjBZtCmnK78=`~0!OqT2LS3
+i2VG=y|FlHOd~vd#7Kql*0&PTPz_e0!D!)855&eXUojMzkBtVliSTXaoR`XGX>grTH)TFNf*y~o=qcs
+qC!&{P{3Pf|<@RPxl?s%Pj3HAGxRZ1AL#=A~%jgfD$WbOyMhko#Du2^1WINR%0;#k)?Ojw7ZUm*0Fc?|=eSMxj{rKzYkh
+TsvzyFgJboCFrq3-%h4=#8kZQwGGL1b%_#z&Q?pSeCtJFMH9
+_B2GyfER1Jaf%LQF;Gs7W^(csH$+r!_g$7(|Yq=u~g=Gk7=T$%U8N$UAz>2p5qs%HCg7e%De9Q+pgJf
+q1Q39s`@&oAX?DpD$H=Dgd?7=;N&RA!zT^X?!3@VT|9{B}w8224-24cW0H)WMujf>;s#3aGKw}=bo
+yVzoI7-!H{@v;K<$Xs395)fE&WqB(U76}Fb{SzRbVURfY!G(gRWZlk;!2idzjMf!sD%c=6hRYKtQ0c}
+H!vP;Ulpg%&j^0geMc7PAT00IwR%5XKVXAP_-#$5@XH__yd88Ds7sGrA9
+sM;ZuB+k{475J0qf-`I4!3vb{TSmmIId(>#lgZV4Ax3)8@>+4FIvNte|Y484Npv=Y2Oj|X%&n4
+M`Xjei!F7WzZBk(mfEaCk3cY7mLtxrxuW2Fn{^lefdDJi@65T6ccJZH`R99`*-
+!K#96HXgU_7fEtwz5D#!i9D0}xg3g1H8LN3E-J#aA{pnaHK8vzZP~qf4nYki`Us>de%4^Auz}$ox-gICvU#mY+N;OHrZt0>xJU?-LnY8#p
+7To$=1y>qF#=>hx$Kr=EDl}a0=D49cT-wrT7*AE)S^so3fsb@{?|dZo&qlruRc%1S2+uty=hDLSi%l;I
+xTwa%m8r}^k^i_hFGqaSn+be=YUcMktNk5MjbOeWO7DC>})I8PsrzqHD6Jwd0+xNgw3)on;wqO-!YzE_7ch$=TjryXq;C0pwfYh*Xv-YC0JJecEQ6T4itrJQ!hf)8aot8yFXEAAS{{3eVjJ&rOS%@J935p6U>U#^v3=p(MnQ5
+FB5JL~nc-Ih7JYzREyGF1P3}0KmE%4h%bDOBlxxqO_*OR34(Mjs`sCWus)R8i$q*y!aP+Db5EM3#krm
+KJIQlmfwP9nnz{?fSJbDW7r9%RF{PbeHm<2ZquH{>+&JUj=@6aWAK2mtSfNm>c>F~sx=0
+04d<001Na003}la4%nJZggdGZeeUMb7gF1UvG7EWMOn=WM5-wWn*hDaCxN}Yj4}g@w;mMyq_uDYh
+sLe$D1Y^d7QeC;2w5X|4OcCC5VUH|?-nT&4zkJ
+^86Y_%AHC@*%AuoBM6Y{RrTr{*^Sd5mpX@1L^Qb@S8xS_~cdds8&C{O64ef$9oBM+g;$U8_gsrA>~cU?tp>1W?(((;otD)=7m3e7|)8&@
+(Le&AYkW?P{H~=9Wv*Y+0jcQANpWl`4j;fkyLIva0unbAS9EPMKs)!PFd;
+hUuMjrN|m=k{a{snZ;8F2ojm(_?&k{r2U%Pv;MVgBWt(3OMbVj28qxDD#>r4G6cQphlKT$Xsu
+@%7Iey2&lc@h$dMqAHKfgHG}ZcZ0m2Q$6OXf57yb#wFdW>~8>rSp>W;^XVi7ZM
+`vPah^AH%kmtc7T{SVM@1?P#871OGQMH^6;WC)$?;G4e`WZ9(|oIAziFk1CGFz%P^
+z`&u+@mbh4ZAD(H5kkxNTxg47(CAj1UqB{aCl%Q=1SoIfsbBZ|HX0@MbQh3M`%M{pT8sE1zYe#z{7;6
+1)&BvT^RUZX;XsbiQX^|d3thsa(wdi`1JJR>9f`8v(?Gd&m`88@){|8whZq!kU9ugq!B>8Yth22BUWwy+HRlM-y6=7-fQAa-H
+Wf%;ZW-Vy!>@#yze8re7d&!~uc{Bu@);g#=7sf#T+z+*|+-x(ujMM+^C4cLi%9zq~s?lTv`RA8Fk&_x(4vH{X_rR~
+f<~wOu0wob!EfMSjst^$#bA>8%w-NTo|qe=v@*;Z?T?#!{7Q$G$;Mo&eq%Esx7?%i$ae9riF3{EJ3ql
+%nX^-^tt=#ebdG$_IVjFhU_|FXu13zOK-)_^Y8?;VLP8PWCc?T-f2oNc6+2#*qH%JU6X4uB1bn6pU@V
+RQxT!bg1jYrq8u6m3NH%?XbAK{y+iNyNC^jNd@}zU$P7krin=SA5el*$QG#&&L=i@nDVdr9bGF%l{*v
+sZ&<1!y2JZ}0YXsDy74dZ~315z4ZxuLeIy4>22~H3QtHA3A$ooNLGgrCtRd(A}+4=<~1$w0%cv9Jg?C
+_bv@JB)MDvP58JDXKB)}1M_2mScG%CWjup<`9)PI5>-$WPysRB^&@ibi=GcdQ(}%)%L-oc!dcT!1
+v{*C4f)b3J)t5%JLYOIAi&?^n2-Itd2b=v66tS27#XL(X&!fUEygVg3beHenT5Rfm_@
+%Deb^*bUe&^7r;yLP>iMEoiGPHE3#0X0zQr+u4Uve~FW{>n}}mGqd?>oG9D~7;*zF1An(=XB@{TOuP)cnOovrryx9;DW?F46i812iwaP%K5~K8#TJ;-lsyRDk}C+*y-DAm&n7X-dwNVbJ?ggW+x!1{w*7p+E%q6C+hI8m(nEoN%Q6t#G$4L>4pm^SJTH)W`I#cWbFim$=NKoC@Qzg<
+*@1WfEV`LMLh!hKz83;f{2j_<*(9M75iKfLhMQr?K%toUpxTR2~|?7zok3d$3^d{3JjR%Wj#C2#2sSKNuAJkf3E8;`-fozf8l_>LbH;TX`+6
+d13YP7b}k2vV^M}w+a0A6k&mCsB85wetaBvWEiY2NP7Uk=fAwXO2V+aN+z)wGy*OvLvqlPpz)0im~Y}
+S%S*4~8Jrn4&(J;OKOVZCM-sL=!fj_-vUPVIM{k8g3{plVx~7c6&C1yJy^k7Mar!&FJskX&iy4i9RKZ
+UjGgOv~L!LiahCLBm|5xPCDoQ37%wfMlA2~p_*n$5zmNBDG%P25DTU~8%&0P8kf7QYAH>sxowD->4(R
+&P5q&a}uu*6jLt}#2TaWXX6M29YAq0SGpR{TQ+eX`u>H)+s!<5J$Xgyv~5#2dclwwPCv{ilN(
+wnsNDY<~uYN8mu#f^Bw;-K4}MNi?j2`Tdzov;5`j4>*1UB~jV!rQ0eZIpI#gl~f^ltIb*_Y{mvh{qeSJ6hY4QLuymgTN%ew>q9>oxoqj?!*B
+icba01xc7X)d7o7~(dEYK+eSXZsau)Zic;8B;{mH0{A1BZ3@Hdf0?Bd{euK$9QrJXKDBm)1>LOuHWJU
+}1Tm#qJJJ_VoFoYvup^PT=T>3c{Y9>a)|gke6>?Whf3jifONbw_0btzjIQ#2F$cU|lU~_BFy0JX#TKM
+DLf2{{c`-0|XQR000O8?}kZQS)}x!R15$B7cKw*9smFUaA|NaUukZ1WpZv|Y%h0cWo2w%Vs&Y3WMy(L
+aCzMtYj51f@%#OX4TT^)gks|$kM@8I&^mTtz=;FNNk13@u_E{G81YD&OG>^3`R|>XeR4^jl(y-I60mj
+L-I<;D%+4~3qBmWB5VG%h-*jvT|89q}D$07#9u7iOlI^Jw-XF|sC(JK-82YkW5z_wD;y!xjRWCYzTZx3dE@hvvH*H@wHLnu(c4#ZHQZQ}VrrEuyi>
+8Ae@;i>ZrifD-L^-dUy3Bc1{wlJX9|7ZN=w5UZFrUMxmsry3djKtdR-*~iKYWtP8psD~)0~4m4d6dfg
+wJtgZmIZ?3u00R8xh#cvJ#5=pK3X@I4{)99Im72dBJ;bFd?)&$zB`@Bw>5eXQa`r0P%L^?a+^f;7~OM
+=sm5<`p#f`4ZqJUCA=e^=N30DD45ty$;QTDG^8nPMf>Hmub+-16Ghph?aU!FbAJF`CH6c&%^_1WbErD
+;9{<4rd5Y6$=s0u0WWTBQAp=_01uV~CbQ$DW%G|6MU?!aa^>zt6aCyjf>q}c$zh4*hkR5`?>SwSnXp>qz8ktXY#494aF?sK~mey
+&z1X3?>&iCHPQ#%mgjGl~~kwqC6=vEKuZU6XYJ)^;Mzn_~+Sjk_p*$1i{V?DB6}dh_Y}(!G83=_L$A3
+9f$i-4AcBUOfN%^$S4u4;1i~kVDl2E{bRGFv`7~n#YZbe{(Z8tJSIyJC@~5-E%NBOJgiI44it+F27;7
+pta44!2|L6TLD5imbJiW-XDN%_z#z&omEY9Cs|eA3C3$?aHT5(-n6{qM+S)BI*7gjVRurb>_xgyAzd_
+=pQq2vX7slM%js&OBKBnn_QoOA#B#khY{)}1fM=2Q#TxkiX2xX_nyiJ;Znz=z$!f~)mD=4f3v5lXF|{
+wd73A9JXuua&`7SkllslvblwMnjk@3-<2)p){kYvib0^_c-0ABoPcec+|wwTz#=7-c1APndFl=Mb5vfiG6h2cU
+sRhVtZsUG)gdxO`L-K0#tZh6>VrcmS=)f{67?ITnS)PDGGY%COdOBAE?84nCygO?G;N94b?V4%dg4U|yJ_YnD^+Z#r)SY99*-e*Q44mngW
+NkHm)9P|BXu&f%7X~auow_Jj~i4Q$hGKQPBDtj2yR#(mz76`eXL`OeVzd`qTC~;TCEm|Q7r_Na(Bv_nuwlNso
+o8-yPEX}fY@lU>XSNE;y~QwG#{G^1r-}bil7HrNv09&&O?fZOUvDU>$Q`4i1dL_uGvT1fCSI>IT-ou5
+q(^N?IN0_Fh11cLkp$`ri7<4Mi`kL`)$0}N8RrUivnbO@TlJuc`)x)Y>FE^%>(oE$NM;F1Ng#70!AG=
+>X7tk8SsCMBc>rTFF-vRd$40c`imYcu0L0@9x>;{s)?DCtZAtj(la1$K$9eigtJC63s8{xosm19!`4n
+5eP2q6rNj3c&!uiQX+!V3lfx121+?ka@jMwi5>VeM=xTXbwq4J
+5T3K?)A9rFYVfVGH7M@YVVN4>_=jlUz|Y`>Y#11i&Yzh@7*Nzw%A6=JQ$T4W(PAq^D^*9r6)mn@iP1*
+CeD+tJ^~(N0n=3;R^}S=+MS2jnGfq6Rm4(2yamYjB*<~^|z9g`=giVTV>)77T=)l^n?Yfad@d>I1zd~
+?w)9Q_%)*)X9`k%1@QhV>|yhO1Ra;0~tYo}l475||&y?4jJBsfgu|HtFR|0F7qX^ncZ@m*OLTkV=8VA
+HyFa`sAGl$U=R!m&XL-P<3l#sjli!P@-NN`+{0@Y34_VwkkK&P4?CM6dRBLw(Q7ONH-J;X?)2?xGBgX
+P}&|ob&4_nM%Ms>yXf~HveNf3EiJS=Cu1|o>8EgyLg!=8n@lf2Tt>7)o!QSo?kz;o$b6y&4Z&k7h7Z0
+bc&cR91CWArg~H&ii!VIc}!)oCyQH16oYCSAfHH}46xy^C
+BVgmgt82BgR4-d~qEBBvl{??CX0o_B)dX;5`^RHEP5T6PN&QNr1D`*8u=^UuHhYC9?T%yZr|osj0|l`
+PJ|Qe*QVJ{0917>?JEMV^rV=-PItty$|jCajdlY*E2tg*=XKs^)rOK2w+}sys5zrzl%w`>I&3vmJfs#
+6C0ZScJkF)1uHkCU{ws^ZJt>+myUM^#>$}&Kppd?1n1!z0UNMmr53WEshnPj%HN4jswL)*{?5gXAsPH
+%oajVkvPc107q%h{Y939Tw=RvX8|
+5AD;*}_ptnqxdlYUl(82F-A>wP{)1>HgLaqcl(POus#prpfh)s$&VREd9dbU+rWfo=<8ZQy7%tCL=S&*4#`lRDIbLO*af6BE~~C@0g*s1x@OoP)Ky(4THfLJGy;rKP}_9@YbE+m5Cc
+d6?>7dS&Mx#Xv^tVzW|>ryjGg&Rg*GjdF4#{k_K0;MtBUtcb8c_oZ74g(<
+!1bbewB1ImQe830hVx6%O_=@~KNNHzAlXHIE$Dnf2$tZ3?Vqzyq72YspJlE#ElU1k~Lo9eUDvZfW!FB
+7(Dd(Kh1MiP4G|_)&A#Qv1MRi^<4@e(A1M5Dz*IRj|A5cpJ1QY-O00;o@hDlm|qNbH82mk=l8UO$z00
+01RX>c!JX>N37a&BR4FJo+JFJX0bZ)0z5aBO9CX>V>WaCx0s-E-SE5`WiUfny&`PGz>qqps>qruE!qn
+yWoYI`^Q_P%s5qxKIQOfVTACcNZT7KvHgUda(pxzjuGwg|jUCAf9+l^pR@Pi5Dgnp}iKhICTxvT(pF@
+O4Fucd-8Z8yIsdS5_WgHa*<`(V!=CHcUWUXuF`<D4wX$w_c>->gQ9=$9B%_*D(atQfIGt#_4|=)Z)t=WN*fD
+Xda|}*Q(>>MHGk9XU+Oq@g8(p#XnM={0SgRL{1+2zyW_dwwe3R?7={5Wt-rgp7Pn#D
+SnG1k@m^e{>q5?_pP!7!PFf9r;zXH`-G&!VjcJuN8!F!<3}>x%l4}HQEEj_Ai8yjg7n1rR`l@(Ga@wJpp^h-8pi_fn$4YbSDJ`P`B
+>mMuHitkdLuyJzP+DTSOP#gfAnm*?x56wj^fkRWJW12vQvW?Ej_W-P>CC*YCO1NzIR+i8Ic-Qy6_|B%WKDMybA
+@^Vx`g=^0c(g1l4m1>E|4B)NS-&vRk0Wu(uf+M_7Y+49+s8ys5*)lQ}TW5wg+CY)i?VJSyX{^ZH#p}Q
+^Km$>V@lLp4~#7q~PKF(~?c1c!ol=Wx6)Vk2bc6SLW17Jp#o7`dtCYyhzSAHRiW7qrp3BbRaf4)gM3T
+!Lp{UXgN677&5|X0Z^pGJ1VGN;g;l&y@`Krf>epNxvW3So)r^r;DQ;UaRi!rN`(QLA@gYKz`}#
+i)baTF4rS{j1MIZ;>GEeVWl0Y37a+g>LbOlm=x#~<{;?jqy7JQ>4-X&jK7FeGefQyEYLmZ3zMrc@{N!+=f?8S{_AQl9s_<&!x
+@jw5r)os|RKYjkWfveUQk#_tRcKzIc8Tas=kUx$uK-UC)E+n+ZU|!9H~LJuiS7j3k=DuwQ_k+{
+&(>M7`EhF$KF2jlRwP{Fp(3M8H9s%Ovo+OywU(NF@b=l4`5<^ZW0X4&eYo!gc-!@QR^XRGAbuN(`w|z
+6<5k2G0h!~D6ZSp7=BKHk;xK?z?gY<0o*b3>S;~nD^CaE3IrRXE|L*ZKks%+{0`*s6`N4_fkwiw7+pr((h@Sz0S6YZjBEc%dY&
+%8>JLY-n)tF@kL1qnEy8}=Hqf3W&9RuIptZ%}lqR7jU*GFiv|LnQBkDk;F#vs2pTM{w{xNlZ(w+5+iZ
+?jpDaS8#VKrWBQzMO<9Qu{_Q&<3UaaR(|hEioR0`
+6sXd=DWB$P2;!lkTC)~<4kykG$0edw#oZ)~=Beb)x^e?fuPk>Pq*A6X{y*U#Kk>Nn{rc;{JdKf!)7OC
+zv@_Rn96#THKn`>q(2V?4jMMkkVjerg&0gPB+tFQa6FVbW`9Hzid~*)BP%H(nl38po+%y<>7v>q_bu@
+P4n|XUNbDs0f3a4Iki^HaWqS?G_FWZHA%1CCz;Z5UT5K!n&Z6w9PqEZy$e78d|wO9&JYQNwqi>WxcIi
+IW`Bk5_-PhoQhV;XXgCJC6X{JR1$3e&s;<(SF0@G!%D%ENl%GmuV_5izkovf9q8EBofKniy}K@^v0??
+(}1>?LB@XZ~f!P=wadQ_Bt|HZPMA@p+t%eF($0P4ijq8YTou?+%n8f%4&%yR`|y1hcQ@rt5PG9E)12J
+g)Z~_1FGV497GPCLfcC|3s
+bdK*eGskisn8W`f!%yud^zn1n50s&RBr@jH#nZC$y8}~*gq42F1a|)$cJ$Ji*5`hEg3s=nEr-o@nYH{
+cqd6|~Cw;l`2Bm&gZBOBfn_sQY0bLJ{6DX>siuGosSMBf2Aw%}Ned3#8`f*$$7jKHa7zApXxWogd4hb
+*B=6za0bqqBut`@_UNI!PZD{>=w|#r*54Z659T5Ay-VP4E=0v5|3(3h$?OIge#7as6X;|J(fg=!_Aqk
+SBb+%Ke^KZO9|*Df7<-6LBAIPv9^Vf7*5`p6{b84kY3>_#jcaFsL-v=3K;Zm+DpwAa^j0kQW?GM(_(J
+n#(rz(jgQ+I=@05b52QE#Mw~9gUArSG`UO@Y9Dgkqh%N_=phV)bDZKbP5F$56*r$i{-*{j+6cjIZYR>1MTxL>%
+IMX|MC1~Gb&;!7+8_u?w-{ytcWPYf&V*{ZS
+^_du?_i2b)uDZ7%Y{La$ibiuriN@Z3B++&xU)>;1#chxy&pBfol@-(K_U`2%mwJ}rJ)-2Jj>4}F+FET
+1lKZx$c;;%>>`-#sm^r=!V`67nUI-gaH_S0XO0<5`wJZj8~!k6bIUNwv*Ybg#13_&mj?5(F}swuTon-
+)r+3mP=*So4YsiS?R)F6)K6Zl_{qN6~@U(Y#7T7k>zAmdRId-KD}(M5{Z+L%UvBiTN!=knaH!-Zh%*wpTcy(S+^4lpJRm?Ur=b6!)DN8A067?_XbUM8nTgZ5<>WEz8H!KI
+!YI9f~GWj4kIIiYE$ElpGhQ6KaCebUAa2m!aM+Ars#dr19FA6TIvzOMlM5GYg~c8&7}N$!04$9uM6!|C&a
+VY*NbvN0!B$!)AbBqm0IDO4<(hHqQ01JDtxVSN7vwu;@OuG~=1~4pRy#27@|m#nzp{l+rPqZXTV&YDB
+&-=vM$H^#gd_s%=}&i}6o|RUBYz*cC%NZ
+a6IWQ6LHM9AmARuXU%|Ja?SFsvgL2KL59!jr5JPry!14TT{}LEM5c0w2xNG#j}5wdBLR~2EY?=pJoJ=55Z`
+et9Hw1qllBHKp>V#HKqCO5NGj!P3XE4`nv@&v#AjLhjyuNP;A&Bpd_7gyNo@^V?irX4DPB6_Dz*CFYz
+S?2rsx2-hly_BNM=BiX2BLtO@PNL127m%f?d`q5uoICQ5H@E?1G^2*OH>MnooQY-of+iMr7Fe21cQ2SubWMq0=W{(NslMtJJ
+wB=T7%JS}!BX)cK2eiC_|~@!DLqUpg_pl9-bVUof9w_Brc(y|V}-&M_1
+4NF(oGj?^L^v85zN{!sr#2(5^yd5B8ClpoiY$q+1i&Wk8c-S1Zy7e+Ts{4846qFlIu$s~H9ivY%~t+N9#&
+eIcusAQDYE=GLg5a{%D1r*fnbuzm`VUx%>=)1cnB+NroW+dL-%b0J69A!DQaE}1@7$-
+18V)TnsI)`HqzSdL-^)5L&535%
+x+~cSQS+9Y_|nY$3ATrxBNd*{EYn~*{-n2!stAeYchPBvXZc(bcJEr6S2DY*BCW>s>blr;#J-A`Dos|
+7Km!Y6<{NZ02OMLNQ!O8Rqb3^8YNPs3^iw$S5Ihz6oYLVHNZ4ZMWLz9-KQG2vcego^O^eIE;-PZjYDo
+>5_e&e=~7*k=l%{PIh=cCVyB!o?RNWpTtD0vb}WES`l*1aZiH;f>-sXWG}=blcb4QdjliYZux;yJu
+`l$;tr3@$5Bx#1>IIuC&FWsM`*e6Yh|YfH*OeXubDvZ(qG;;jFGM{g`Cu^~kSnhi~G&m))OGZdbVz|TniWUQd*90Qji-YAdCEvz;Em4xfwO-$<8V{@Ci
+f+RG;O0*?#+SFhT>j&c-z+Y#Zf~yn`m<>8%H;JvTpUYJwYW(2b2xC^qTc_jIDN=}}!c(&;!q&kp$(5P}dcsL?}@kiN;8&19t33Q;Q
+7I4nKHu*Irup+iD73hEr$bXwOSuw2cV%88oYw8aI8R9@cbG@(*QL|c!D88(^|lf8TcZOcnc0H;6Eprn
+iEjy{>u1bb7q-_myu^vI5u-_P&)!_#6hU;M!53;y_Yb^mbp?&k3kCVy5&r?lx7t7l=9gA#;L*p7rMd@
+6gPObbqP4;&gpVQs@w(CcY_IB04kmRDIWe*izS1Z7m*&Kz{t(7452;sw1(X#b*eOTMUl?5c!Llq~PA@
+2EFB5SnhJixaq%>Qr(9B|+xDS2=Wb^8VIZ?;lFbR3IQG5wNrn+!|xhudPmE&pbR@?rv_-8*9Yh8enhh
+n?<&w-px7(08o7dg@Y}*yB5icURBsA@i8F(E$-mD`=@0<*Nnm2V2~ATWpm3#bX>6Y`Q7||{)l~^9D*y=&4L1DjoY?wOF|HJxguNoX6R1O<*@jIQ0Y@Z#Sn2txKTX&Coex0cBa)+bhj!EdiZ!t8q;
+*c_2zuO+uZo)kd-I)r!%$xsG$_CiZCjS<45^8WF*$WzdHtnx)hg#!tKF<;Rav7WMnE~*@Hf}87jLHowC^B>td
+5u0!zebRH}rDL+=@EZ!6?x%<@-gvmK?+r_Lcf+Cic6uBJIFnYVv*7$Z)g|_ym(0#fX5`a`#n5hzboqf
+Y+bjUk8oATYK24B;sODDroBCROfWrn`1a{7XKYky+9hir|3psoHr?=n#`DDG(X}8+9#qHX2%6iwd{{~
+P?0|XQR000O8?}kZQMuN3ZO&|aOq;&uQ9{>OVaA|NaUukZ1WpZv|Y%gPMX)j}KWN&bEX>V?GE^v9>J!
+^B@Mv~w8D`w%kBDqTd$#m|5>GZRVR6!Cbd@eQm;CTte7NOwvE+W=vL~aDsnZ^X}*B>No@h$r}a`LQ~Yw&P1b9j&$?=w#d3vV77pX!Q
+>D{YQCvArH%p2YP;T!U`Ay+t%p2zk{$h+WR>o8($%^sp%eYd(n-9j)66{0ip2tkHeZX%e5&=k`o2uoo
+q1WTV5odr7e!VH7(^cIRmN{&L_(%{dHM7C`Niqw<@nX<>+^wnOA|7GUm~HHFXz~;9H?KCY@;iNW=1y9
+W_kulk$2lQB1+yI=de2`fbV3I0Wtjmt2cm?Y@n_-K!P3a2pb-c?|?RnGF~Us+XPoln6OI%nkn*hnq=u
+e^*B#fL03Z$@ia?gT5M_hofP>zUHI#1>!;sMwGf5vw^{*dot9iEB^iK1cerGzJZ_m#jXj>;G&T74_mvBU+&l
+Np9r)O<_X&2&UQZ2Pz>*dwO+cz)AuZ}NYonG$mv`VX~=>p_m7ZV`TP6w$PHt5KZcMRjdrf0n|ZS8p6?
+{qrAl2n4s|>(7Zrn2%FG17_>&Q4Ifb*&?abV4yPXy^TVxtMKAy2Sm@hN{e9fcx4C@0o9I5y4;)CDB9M5<
+Tysa0hDE=LoQV(9n)jCV-UccY(xXH`v;I+Z{D!H`?C#lh+e@AqFuK}Y2JlHn_yZYS&MmYD_Ndxs7_+s
+vmK}}RK`CU(IYCz*DH5@A7<(n1o*P6Ka3?{(xq>Dt-CC=X!Ufxx=dRuubqyD*LescExnfR*&)OphpA{
++2rt|J^Tx?#k@aWzx}oL(BpETS7j8zJ;Knau>LJ^3TsP%<|B#qA%$^&V~M
+|-63guz-!xa`vYk0>Z`=D3KNhQqo_b7I*r-lnSY9A`<59LcES~Hs6C~^!fw!J{keWN6`nSk&2c()2KXYP~CJjmJI
+;_y-sr$4SDjXqhLrpG>CFL=S5zWI)Lua_L(|EUIjv26hok!;y%xcWL62E#MvotGb*(LQlddXWrDG_K&
+pyOIn~s@OhLD_+9^I6R%<;?=jl}4FEt1&(9|kqiCZE-046{d8z3hTGnOr&AO=Mc$6CWALDyhf0a9uu6
+Vey=V$_{q5{1IY~#^}}I<
+#F~I~O2=wA%!?r`PqqTE1S=N^NCiWth$A91+ol1_Ad7%;2e-2fQuP3&Hw11;1Ij2z2Goz;W1*~c9`Xe
+H9$xqaIs?irH@PL0)(!PLh?X-;%TX|uk8LPT_XK1H0^5*!u=UtssbCkBrBcHlH+iPP8Pl3p5dOz7%0H68d)n$AGop+s<65BwbkG6pysKm%QO4G4e*mObj>jf
+I*wYuA6!m^)g#8*-YVsdk>O8EB9H^tt=hZ|A3%Rwl>%^)IRy;R+%kdw;G`-}V`U`hD`Z(~GdHc^XfP^
+|rU$`Z@%61HJbnqqR3oN_sW63l{p!{RhUNp_^yH^UhLd>+#5%OV@E68)FFpi$TW(E4#oFaR}&;PeTME
+-@uZsk0S4Z*x>#n{CE^yF2VZ6k1;&%BPmQai!oXZ2Tf;4{exLJh>f{`!U3YEE;rh?pC_BFX4}}Cq&uk
+5YdG-nSE2(YB^}#9R|tKeNZOO3li#Ifk&{E?E-6!73JYUo3_g~oq~C8!5;
+y@yO8t*b3iAU<^(M&xp<)iFBeFW)usn{ieZ
+#Lixl*0EQZUTH2Al*wK%rV$#;=US#ECMbwI}CA?QYW{=Y71n%8VbXz0xUf+%@6;hr4
+_tojeo8#B7e;fXE{O0)O=@05$yb7MW$P9&5o5NPfeS;+hk9d-Xjpu7>968tdI$Upb^#gKdQ->NTL1@hHcM-G&+bn2pMt`Lc9Gi9&b&}{y3&=bEiX
+X(&(J?`2+l#+!{#vo|jX>h$8`?FEB6xj4HzJ
+2`%BgYN`N>EWTpW~l0xsPr_
+G)E2Ia!IUYi&iO_RyEzA@R$n5^sWO4v)7~_&*uZMH|}p#PvDL~sPvhR0B4WHfmMzz8lZ3Fe;LlxO#4q
+j)%F@Oirn{=t`m^J9f-{XiB+Hs4U}LN%^`LuG}+Vz66cI(JHyZHM8{8{%R
+*0RS?y3RcWmVnr#USgiFaDkjSb8l_OZAHPJq@azLA-!ES;2S?1Le`VShFti1>-P0sZ6d&PO_30)b6IH
+BT#2qS1!F#z_s7S<67K0|v^i<0gRT4$QyFr+$NzyxShkLf&ngyu&`>V*vJRgNUM5ZjdPIYw!BdLr{Ui
+x6-38zPLuLjqoP&e)eBC)G&r8clZ$2E~Ey^NSW&DP?ecFH#B1Z8LubZ5hGvw%lRpJm##J|m2XxP^v2G
+W08u)D-2~M?*X%GBE|=7xYOZThejIGhcSG
+xVxH==am*K=sl-Ij!N-eLr2}-$@^=AH2BkCH;wk7lu!E1T?-LN*&;#WGE>mpib9OMOGm1Fa;fQ@hfzcI)(uly|kQmYACv)%
+NJIv5Cf*E`JIl>&-&zs=PMu3DM}Dd_$EtIvL_7yk;+xF(&2^(m#)iXY*F=SK27Wwy6)_T!+!&G)y5Rv
+Ry@c=+c++7&nXUq`%~ctiQ7lfpt>@87kaM9`h$%NE@gabiq$3Wl8u29q?H@;23Gs}dEAwha(I5QuYr2
++>iO>Br|bD=BpyQ4s2+LsQ02vwoz!Xw##25UW@&y~F*?N|9LRKRGp075Kqzx>BO`yD9g1<_4Z-LrIsm@aTS-^$
+Bv-lwao9(lnq4HUedtW``kzT_8AjrUOSk%@KEwrf8=l$K2xsFfEKH^83Cv3;N~c5@jfcnecAQy)vw7j
+cPgCHIA%t>w(lNbj&Y{s{Rx%A^nEfZ)d}OppV*fyT7mAUS7R9{^|5lOyZ}cyycii90>7^e@7A>n3iV%D2Em4s<`Yn*LsS_EyAoVpJRM2M=e}s+$&DxygSNynC!jqu3%a!fdnX30Rj{-*NBM@a0^MkaF4
+tmBt)o8gfMvG=)v(=!7$FMru7%PM(L3hbRg7M3yZImEC4ckw-^By&L;|`9G-?hSfr&&&CKdiQF#*^FR
++-ebiSmr^B*=}Y5#t`os5n`e;K8N`^mWQKMss$O3|$*TJ7Jh`uiv-`fW=Kf
+jWJF_`FiASQRv__qR>Xvp;~OoNr(YOXI+?s*u8RAWN_oD^E>qVMc?8bD-qClUm)6I)!prgl9`hN%oSk
+8ou`|!M2icSF5SCMyBg#2!+NKLglCx0j;#p$0GHggxIdIuX|;S2Vstio6%Jsa#c&oV$;u`b$ppz>!NA8`=I+I
+6jovEXP6NEHlC7F2X@*UN53_@{_B5@uVlAs618UV&uly7KIqBJpMEyJz-FlY)5So@y=KpIn-I&$`G;N
+92qv^-fFHwzg2nJpvY>g_1oUSm|oAd4VQl|&z89)dEjpl(dN
+{(}i&$qQe`|*ME>?0!VoAfpjSER;_iVYz$yv>DV6pnS(!psDNwMMEspLY_HnKQyei1ccvN3rXek>L52
+P<@#FbTun1EH)Euv-!!G)(@eHD@TMl6bPo(|TBICiV5ETo;)2$w~$sJutjYj+)8S=rzKODR=Oi|4lKg
+6L$W_B^P3v(#=hnc67pkIi7*Sdyq2ew)+;)`vR}LUVIbLxrkoG-^4E>(vqP=jpHD;(d0KdFwE9Q>R5d
+>xZ%w_MnhNh>tm&h>>u-<3g7P
+f2Lzdp|YugcHcO6pFzPlbo+`1WWNVpY^r7!j8BrL*Pb(m*1|)q!&0Z~k@6966T|;Zo@JV|ud{thBlVv
+C{;B)`A1%laj<4>`TQw%jQ6b2Len*^sDJ161n?|x4o;h#z9TQnQeoF9UV|}4G48ZTm#J0DO^;@*1;q8
+mSX$VwKIQPVA6#Wl4-9%p8`B?1`XJ$KtHOPPB*K2<#v+VT@ff`Qbx
+;rH)=KOw%l>veaay1#Gn-zk3fN5N777OXhH6ZqwvNwL}`u{X@cGLwu?js8#dM
+ZCqGOUIS6E%ei>?ZnDTnqCPL3(=MYkJzg(Noq*%+&VgBB?@Q>S=?Rq=@>+^2&s`6v|;3FS_*2%(Q-2?
+S;O?*fFM*Mi1w+C#$60TlykrY6}w%D+hl}m!G86dpKZzPfW$)=p~*^qiiY<*S0HQkfljw`T@!u<6R4YpBRDto9*2FnrL;3bAG_xg_ZyMnmmK4(w>w#65;6B**O4KF&R
+g?G^S=LEm$5u`Y~U6%@7ma}=blQA8(+bfBTMI?)HHN}gcq)yOu`4%sB{D>LPpKNEc*N}Lk5pm8Tn;wgl=YI9E<*GH5b4J{?gQQ@W$_%7n
+yk&0RDrtRI8p&xK8Ho(G%_3aeyh44RcO@EdSobc_>+2}=;ZK$>!vItC4a^$m=7%BUAXf?*kyJ3$UYI~
+pjd>J`|{K(_+{RNEJc#HVC{wJ#gITpG9VZy)C{Wt6MF;FTIX^oezj^D(>Ijdat-!!Tx0+gFw
+{z$bIVM=+Z)B|90$Z)N|osOOb#_8*VUI4?y&7v5dEX!&C~B
+Rk|h*R}({GKkzci&2OjNx7$yqEQ|0jRgZmCbL3>~&&Z3Y4?9ZEQG3X2ogB`!5LjS8aNZJTr&1co3;-4
+jRP`wMuS!_6$S}CS1X}?%W&@1w-h%RINzT5#XU2W~9sLf*Hm-P0vaN->0&?I=a=p1&9?ujWt^1^$RSi
+>%>&SrsC4*!iNaEs@NMoFX+uPPZ*Rvir$7vx-|xa))dwvcn;e^!
+V^}%SW;C$J*9D-wlHUDwhO=4O|WvmI^s|_SiXUJg{|DLbGkR*399#T$DU!E)mR?g%8>UVe_C8hg6N9l
+8(%VvNXK#!%qf55!CKI5zV0
+vJ`N`o?1Pju*~JlI8gTRV^KTkUZ7OW=YP{BKX!yUYvB5lsJdeXwwqQAXG`369teQjaQ?CY|I%OUTpjJ
+K41G%H<1uC8qW=45CTx~M~mZ~(gt8IuM{Vt*Oib#|bFb&2`Af&%Vk5S;*R}Q#5mR5LGC5xOFWfKLS^;
+#Aan95c>3Ua$mnI_HIv@XE{l8ugnaU#VPOE{TFww+vI=;&NynV6F5*wUmOtht@RM~1h7$m(-k!`^B#QP{B7*ybahHe~`5O(pK
+Llg8MhIDd}qI%+NHwHH};6hC`9Lo0
+xyC%1KhbVtOWmUo6$Lt`*7Vr~zFeufWw>_{9v6+e)oLLmB`S!Blpo(8)PB4fTGfiMOFWADzt(RGY|waQ*kDQ;NLjgfA=4=
+C9jHjKpfig9H+Iovv@-cR(C5DW}25bIFJOB!CRz
+TX;1<_0~&3I-G|hYDqdKl*_BpY6g+6DQ^v8rxel(uxnPZ^__>0M6WxvaKHw>)t`1xRGmJro}9klE5k6Cx+)Iwe5$hVvCH7z?*`gTDQm|35AQUq`Nrc8{e7%sF!ZB2Ufms^mc2O05i6uZt6y+T^f=NRQgM
+a&BNA(NdI@K$K
+5BGJCexV)DsS3@7`aQhEGU{Y_<4-SEQQN#!gOfD2m$x2ou1zW+dG`uh)YB(>dl>sHI!f&2&NCm(`I
+^n)J##`N1ZGzQ@(N1(^Mczx41dM$4#9tdoF7zeBUquAJE?)#DA&6IR`A#oXg%nQWsup*C5SVw$~-ag{6*L;
+^c41w*A?>x3n}$uy1CRp`x6jR>RKQu)?*EhP?6BQ+go1Fspw#!wW*B15I}-UkP31jUOetmT0sj1MU37
+gGP;YN_@H#IL=}3Ey1OgEK9R&Sac-z5NOIK?M}Pqp<4_f5#*YdUE0mIHCfyz+;tR3;K3jfv!|J=;+>tBz5yBwdsIsX3j=?~){PmiyDzM$VExE
+8}7tEbTNK<1*`+zcV%I$!-Y{)$`Lyxk$kUku4ifg=S3a1q3Gol0Kpc@vuZ3+A
+x)wU`#cz$YYJdkZQLH^Xr5HHA0ohxt-q)}_zeyM7cE5_#^jGB7$!2{y~R}5iMFvM!2P_RfMI$-{26-E
+v!|oc!3vGNogqFmQrQU(g1RcQI~|mPkylun&Z68yYR_QR&AAo1=04N>#9{cOhLOqm^MBcbe`7NEVT(>
+je!p?t`Xgd!G{_M_COA@&L^2ERZCHu%xF!uw7rxj%UzV^xm@12pB(SiE;Umb*7W4BFA5{5kY&Sf0Ph5F7Z^r)uP)h>@6aWAK2mtSfN
+m?RDO)V<{000I9001Na003}la4%nJZggdGZeeUMV{B2dXae9Y?=zgZewZ5Fs$(Rwu=-&;?AL=GjAU6y|hGI@!T4Mj)^sPme!TBt44f`0YunO+`hgPomSk;EW28sPdki
+z7TIQKLPp0&u%{K6{ZJE}@C+Pc~O_L7*1RipO*=WGNwL-%v{f1QY-O00;o@hDloJzD=T`2LJ#q761Su
+0001RX>c!JX>N37a&BR4FJo+JFKKRMWq4m>Z*6U1Ze%WSd97G$Z{xTX{qA2ucs`7c%F1jP-J(HVbdgD
+CgJvg#Nm`&71Og+`HXB(~Nh*$8^uPC9iWDVT&K5kLQr0x4=3z2S9R>CPeTqw3$sm2!Eih?OUTdkVfD*CzfR
+w{v&14oF=%DwPjWwm8rWPLA;k*Z<@#YRhk5YpKkK+Re)R;uk5vf-yP;hQ;{*+#29Q?;$RHo-9aD=!=2
+*X*$-M}FnuZ(pvntDml~{(STKQ^IbsgM{7H76I^b)@szUPO}%pp>$Bo1;X9PzJNO;D5ZHR(8l-SUA0etmajJzfY=NJznn3AoMB_ipn89Q>(yp)edsuF$9T-WW;})2jL-&?)&cf(E9|
+X%w#c%I??sj^XR}!$HZ04vz$s@|H^v&Pw8#)n*wJFiR)6TQ{Wg!`%^%whU|TrC^hIcLjVL#Y{hlqpPu
+O=KmaPbV+KAFZJT=?J{G&AdsiY%~ZrPK_IY`aE9PJL<@)nsi#J=y-?>_u$zU=I2VH;hsDqFP*xwKx
+4KrelpZ`y=0mr)JcBAy(Bj_U+
+#ajXA_7$v?pA;3v56A^7ZcF?&|I~d$_&Nu5NFxKR+ykVp=L*U~gJ(j#;U4PNXplpLXeCC$v~BTXF9
+gTA-n;oy?Qh=MIuaR*Q*5@|>dDLjQkkD=!WM@(kNOsmN5f2%+q$k!6wjtXVA6&W`)yasl*}Hp>=9lpD
+u^8-DCXF1S