From 597e023aef7d31db0e80e2e9f3cd70829a04eda5 Mon Sep 17 00:00:00 2001 From: <> Date: Fri, 8 Sep 2023 07:27:33 +0000 Subject: [PATCH] Deployed df715b1 with MkDocs version: 1.5.2 --- .nojekyll | 0 404.html | 1910 +++++ assets/images/favicon.png | Bin 0 -> 1870 bytes assets/javascripts/bundle.2a6f1dda.min.js | 29 + assets/javascripts/bundle.2a6f1dda.min.js.map | 8 + assets/javascripts/lunr/min/lunr.ar.min.js | 1 + assets/javascripts/lunr/min/lunr.da.min.js | 18 + assets/javascripts/lunr/min/lunr.de.min.js | 18 + assets/javascripts/lunr/min/lunr.du.min.js | 18 + assets/javascripts/lunr/min/lunr.es.min.js | 18 + assets/javascripts/lunr/min/lunr.fi.min.js | 18 + assets/javascripts/lunr/min/lunr.fr.min.js | 18 + assets/javascripts/lunr/min/lunr.hi.min.js | 1 + assets/javascripts/lunr/min/lunr.hu.min.js | 18 + assets/javascripts/lunr/min/lunr.it.min.js | 18 + assets/javascripts/lunr/min/lunr.ja.min.js | 1 + assets/javascripts/lunr/min/lunr.jp.min.js | 1 + assets/javascripts/lunr/min/lunr.ko.min.js | 1 + assets/javascripts/lunr/min/lunr.multi.min.js | 1 + assets/javascripts/lunr/min/lunr.nl.min.js | 18 + assets/javascripts/lunr/min/lunr.no.min.js | 18 + assets/javascripts/lunr/min/lunr.pt.min.js | 18 + assets/javascripts/lunr/min/lunr.ro.min.js | 18 + assets/javascripts/lunr/min/lunr.ru.min.js | 18 + .../lunr/min/lunr.stemmer.support.min.js | 1 + assets/javascripts/lunr/min/lunr.sv.min.js | 18 + assets/javascripts/lunr/min/lunr.ta.min.js | 1 + assets/javascripts/lunr/min/lunr.th.min.js | 1 + assets/javascripts/lunr/min/lunr.tr.min.js | 18 + assets/javascripts/lunr/min/lunr.vi.min.js | 1 + assets/javascripts/lunr/min/lunr.zh.min.js | 1 + assets/javascripts/lunr/tinyseg.js | 206 + assets/javascripts/lunr/wordcut.js | 6708 +++++++++++++++++ .../workers/search.208ed371.min.js | 42 + .../workers/search.208ed371.min.js.map | 8 + assets/stylesheets/main.ffa9267a.min.css | 1 + assets/stylesheets/main.ffa9267a.min.css.map | 1 + assets/stylesheets/palette.a0c5b2b5.min.css | 1 + .../stylesheets/palette.a0c5b2b5.min.css.map | 1 + dpl-cms/api-development/index.html | 2075 +++++ .../index.html | 2214 ++++++ .../adr-002-user-handling/index.html | 2111 ++++++ .../adr-003-ddb-react-integration/index.html | 2060 +++++ .../adr-004-ddb-react-caching/index.html | 2078 +++++ .../adr-005-api-mocking/index.html | 2177 ++++++ .../adr-006-api-specification/index.html | 2122 ++++++ .../index.html | 2121 ++++++ .../index.html | 2101 ++++++ .../adr-009-translation-system/index.html | 2189 ++++++ dpl-cms/caching/index.html | 2057 +++++ dpl-cms/code-guidelines/index.html | 2596 +++++++ dpl-cms/config-import/index.html | 2078 +++++ dpl-cms/configuration-management/index.html | 2310 ++++++ .../diagrams/add-or-update-translation.puml | 6 + dpl-cms/diagrams/adgangsplatform-login.puml | 56 + dpl-cms/diagrams/adgangsplatform-logout.puml | 30 + .../render-png/adgangsplatform-login.png | Bin 0 -> 74299 bytes .../render-png/adgangsplatform-logout.png | Bin 0 -> 43257 bytes .../render-svg/adgangsplatform-login.svg | 66 + .../render-svg/adgangsplatform-logout.svg | 40 + dpl-cms/example-content/index.html | 2092 +++++ dpl-cms/images/backup_tab.png | Bin 0 -> 8829 bytes dpl-cms/images/retrieve.png | Bin 0 -> 59691 bytes dpl-cms/images/virtiofs.png | Bin 0 -> 333032 bytes dpl-cms/index.html | 2023 +++++ dpl-cms/lagoon-environments/index.html | 2288 ++++++ dpl-cms/local-development/index.html | 2117 ++++++ dpl-cms/translation-system/index.html | 1975 +++++ dpl-cms/translation/index.html | 2163 ++++++ .../adr-001-skeleton-screens/index.html | 2129 ++++++ dpl-design-system/index.html | 2417 ++++++ .../adr/adr-001-lagoon/index.html | 2094 +++++ .../adr/adr-002-rightsizing/index.html | 2275 ++++++ .../adr/adr-003-system-alerts/index.html | 2079 +++++ .../index.html | 2128 ++++++ dpl-platform/architecture/adr/index.html | 2024 +++++ .../alertmanager-setup/index.html | 2123 ++++++ dpl-platform/architecture/index.html | 1985 +++++ .../performance-strategy/index.html | 2095 +++++ .../index.html | 2356 ++++++ dpl-platform/backup/index.html | 2043 +++++ dpl-platform/code-guidelines/index.html | 2235 ++++++ .../diagrams/build-release-deploy.drawio | 1 + .../diagrams/cluster-support-workloads.drawio | 1 + .../diagrams/dpl-platform-azure.drawio | 1 + .../github-environment-repositories.drawio | 1 + dpl-platform/diagrams/profiles.drawio | 1 + .../render-png/build-release-deploy.png | Bin 0 -> 823071 bytes .../render-png/cluster-support-workloads.png | Bin 0 -> 294591 bytes .../render-png/dpl-platform-azure.png | Bin 0 -> 486690 bytes .../github-environment-repositories.png | Bin 0 -> 121204 bytes dpl-platform/diagrams/render-png/profiles.png | Bin 0 -> 157415 bytes .../diagrams/render-png/request-path.png | Bin 0 -> 447820 bytes .../render-png/terraform_overview.png | Bin 0 -> 37988 bytes .../render-svg/build-release-deploy.svg | 2 + .../render-svg/cluster-support-workloads.svg | 2 + .../render-svg/dpl-platform-azure.svg | 2 + .../github-environment-repositories.svg | 2 + dpl-platform/diagrams/render-svg/profiles.svg | 2 + .../diagrams/render-svg/request-path.svg | 2 + .../render-svg/terraform_overview.svg | 54 + dpl-platform/diagrams/request-path.drawio | 1 + dpl-platform/diagrams/terraform-setup.puml | 28 + .../images/loki-grafana-download-logs.png | Bin 0 -> 36231 bytes dpl-platform/index.html | 1998 +++++ dpl-platform/infrastructure/index.html | 2241 ++++++ .../infrastructure/terraform/index.html | 2143 ++++++ dpl-platform/platform-environments/index.html | 2118 ++++++ .../runbooks/access-kubernetes/index.html | 2077 +++++ .../add-generic-site-to-platform/index.html | 2145 ++++++ .../add-library-site-to-platform/index.html | 2246 ++++++ .../connecting-the-lagoon-cli/index.html | 2178 ++++++ .../runbooks/deploy-a-release/index.html | 2086 +++++ dpl-platform/runbooks/index.html | 2000 +++++ .../remove-site-from-platform/index.html | 2109 ++++++ .../retrieve-restore-backup/index.html | 2268 ++++++ .../runbooks/retrieve-sites-logs/index.html | 2090 +++++ .../runbooks/run-a-lagoon-task/index.html | 2069 +++++ dpl-platform/runbooks/scale-aks/index.html | 2124 ++++++ .../set-environment-variable/index.html | 2108 ++++++ .../runbooks/update-upgrade-status/index.html | 2074 +++++ .../runbooks/upgrading-aks/index.html | 2204 ++++++ .../runbooks/upgrading-lagoon/index.html | 2132 ++++++ .../upgrading-support-workloads/index.html | 2938 ++++++++ dpl-platform/runbooks/using-dplsh/index.html | 2099 ++++++ .../adr-001-rehydration/index.html | 2247 ++++++ .../adr-002-ui-text-handling/index.html | 2101 ++++++ .../architecture/adr-003-downshift/index.html | 2158 ++++++ .../adr-004-relative-ci/index.html | 2167 ++++++ .../architecture/adr-005-react-use/index.html | 2098 ++++++ .../adr-006-unit-tests/index.html | 2080 +++++ dpl-react/campaigns/index.html | 2123 ++++++ dpl-react/code_guidelines/index.html | 2666 +++++++ dpl-react/error_handling/index.html | 2174 ++++++ dpl-react/fbs-adapter-client/index.html | 2125 ++++++ dpl-react/index.html | 2791 +++++++ dpl-react/skeleton_screens/index.html | 2102 ++++++ dpl-react/ui_text_handling/index.html | 2210 ++++++ index.html | 2091 +++++ search/search_index.json | 1 + sitemap.xml | 3 + sitemap.xml.gz | Bin 0 -> 127 bytes 142 files changed, 157008 insertions(+) create mode 100644 .nojekyll create mode 100644 404.html create mode 100644 assets/images/favicon.png create mode 100644 assets/javascripts/bundle.2a6f1dda.min.js create mode 100644 assets/javascripts/bundle.2a6f1dda.min.js.map create mode 100644 assets/javascripts/lunr/min/lunr.ar.min.js create mode 100644 assets/javascripts/lunr/min/lunr.da.min.js create mode 100644 assets/javascripts/lunr/min/lunr.de.min.js create mode 100644 assets/javascripts/lunr/min/lunr.du.min.js create mode 100644 assets/javascripts/lunr/min/lunr.es.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hu.min.js create mode 100644 assets/javascripts/lunr/min/lunr.it.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ja.min.js create mode 100644 assets/javascripts/lunr/min/lunr.jp.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ko.min.js create mode 100644 assets/javascripts/lunr/min/lunr.multi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.nl.min.js create mode 100644 assets/javascripts/lunr/min/lunr.no.min.js create mode 100644 assets/javascripts/lunr/min/lunr.pt.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ro.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ru.min.js create mode 100644 assets/javascripts/lunr/min/lunr.stemmer.support.min.js create mode 100644 assets/javascripts/lunr/min/lunr.sv.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ta.min.js create mode 100644 assets/javascripts/lunr/min/lunr.th.min.js create mode 100644 assets/javascripts/lunr/min/lunr.tr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.vi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.zh.min.js create mode 100644 assets/javascripts/lunr/tinyseg.js create mode 100644 assets/javascripts/lunr/wordcut.js create mode 100644 assets/javascripts/workers/search.208ed371.min.js create mode 100644 assets/javascripts/workers/search.208ed371.min.js.map create mode 100644 assets/stylesheets/main.ffa9267a.min.css create mode 100644 assets/stylesheets/main.ffa9267a.min.css.map create mode 100644 assets/stylesheets/palette.a0c5b2b5.min.css create mode 100644 assets/stylesheets/palette.a0c5b2b5.min.css.map create mode 100644 dpl-cms/api-development/index.html create mode 100644 dpl-cms/architecture/adr-001-configuration-management/index.html create mode 100644 dpl-cms/architecture/adr-002-user-handling/index.html create mode 100644 dpl-cms/architecture/adr-003-ddb-react-integration/index.html create mode 100644 dpl-cms/architecture/adr-004-ddb-react-caching/index.html create mode 100644 dpl-cms/architecture/adr-005-api-mocking/index.html create mode 100644 dpl-cms/architecture/adr-006-api-specification/index.html create mode 100644 dpl-cms/architecture/adr-007-cypress-functional-testing/index.html create mode 100644 dpl-cms/architecture/adr-008-external-system-integration/index.html create mode 100644 dpl-cms/architecture/adr-009-translation-system/index.html create mode 100644 dpl-cms/caching/index.html create mode 100644 dpl-cms/code-guidelines/index.html create mode 100644 dpl-cms/config-import/index.html create mode 100644 dpl-cms/configuration-management/index.html create mode 100644 dpl-cms/diagrams/add-or-update-translation.puml create mode 100644 dpl-cms/diagrams/adgangsplatform-login.puml create mode 100644 dpl-cms/diagrams/adgangsplatform-logout.puml create mode 100644 dpl-cms/diagrams/render-png/adgangsplatform-login.png create mode 100644 dpl-cms/diagrams/render-png/adgangsplatform-logout.png create mode 100644 dpl-cms/diagrams/render-svg/adgangsplatform-login.svg create mode 100644 dpl-cms/diagrams/render-svg/adgangsplatform-logout.svg create mode 100644 dpl-cms/example-content/index.html create mode 100644 dpl-cms/images/backup_tab.png create mode 100644 dpl-cms/images/retrieve.png create mode 100644 dpl-cms/images/virtiofs.png create mode 100644 dpl-cms/index.html create mode 100644 dpl-cms/lagoon-environments/index.html create mode 100644 dpl-cms/local-development/index.html create mode 100644 dpl-cms/translation-system/index.html create mode 100644 dpl-cms/translation/index.html create mode 100644 dpl-design-system/architecture/adr-001-skeleton-screens/index.html create mode 100644 dpl-design-system/index.html create mode 100644 dpl-platform/architecture/adr/adr-001-lagoon/index.html create mode 100644 dpl-platform/architecture/adr/adr-002-rightsizing/index.html create mode 100644 dpl-platform/architecture/adr/adr-003-system-alerts/index.html create mode 100644 dpl-platform/architecture/adr/adr-004-declarative-site-management/index.html create mode 100644 dpl-platform/architecture/adr/index.html create mode 100644 dpl-platform/architecture/alertmanager-setup/index.html create mode 100644 dpl-platform/architecture/index.html create mode 100644 dpl-platform/architecture/performance-strategy/index.html create mode 100644 dpl-platform/architecture/platform-environment-architecture/index.html create mode 100644 dpl-platform/backup/index.html create mode 100644 dpl-platform/code-guidelines/index.html create mode 100644 dpl-platform/diagrams/build-release-deploy.drawio create mode 100644 dpl-platform/diagrams/cluster-support-workloads.drawio create mode 100644 dpl-platform/diagrams/dpl-platform-azure.drawio create mode 100644 dpl-platform/diagrams/github-environment-repositories.drawio create mode 100644 dpl-platform/diagrams/profiles.drawio create mode 100644 dpl-platform/diagrams/render-png/build-release-deploy.png create mode 100644 dpl-platform/diagrams/render-png/cluster-support-workloads.png create mode 100644 dpl-platform/diagrams/render-png/dpl-platform-azure.png create mode 100644 dpl-platform/diagrams/render-png/github-environment-repositories.png create mode 100644 dpl-platform/diagrams/render-png/profiles.png create mode 100644 dpl-platform/diagrams/render-png/request-path.png create mode 100644 dpl-platform/diagrams/render-png/terraform_overview.png create mode 100644 dpl-platform/diagrams/render-svg/build-release-deploy.svg create mode 100644 dpl-platform/diagrams/render-svg/cluster-support-workloads.svg create mode 100644 dpl-platform/diagrams/render-svg/dpl-platform-azure.svg create mode 100644 dpl-platform/diagrams/render-svg/github-environment-repositories.svg create mode 100644 dpl-platform/diagrams/render-svg/profiles.svg create mode 100644 dpl-platform/diagrams/render-svg/request-path.svg create mode 100644 dpl-platform/diagrams/render-svg/terraform_overview.svg create mode 100644 dpl-platform/diagrams/request-path.drawio create mode 100644 dpl-platform/diagrams/terraform-setup.puml create mode 100644 dpl-platform/images/loki-grafana-download-logs.png create mode 100644 dpl-platform/index.html create mode 100644 dpl-platform/infrastructure/index.html create mode 100644 dpl-platform/infrastructure/terraform/index.html create mode 100644 dpl-platform/platform-environments/index.html create mode 100644 dpl-platform/runbooks/access-kubernetes/index.html create mode 100644 dpl-platform/runbooks/add-generic-site-to-platform/index.html create mode 100644 dpl-platform/runbooks/add-library-site-to-platform/index.html create mode 100644 dpl-platform/runbooks/connecting-the-lagoon-cli/index.html create mode 100644 dpl-platform/runbooks/deploy-a-release/index.html create mode 100644 dpl-platform/runbooks/index.html create mode 100644 dpl-platform/runbooks/remove-site-from-platform/index.html create mode 100644 dpl-platform/runbooks/retrieve-restore-backup/index.html create mode 100644 dpl-platform/runbooks/retrieve-sites-logs/index.html create mode 100644 dpl-platform/runbooks/run-a-lagoon-task/index.html create mode 100644 dpl-platform/runbooks/scale-aks/index.html create mode 100644 dpl-platform/runbooks/set-environment-variable/index.html create mode 100644 dpl-platform/runbooks/update-upgrade-status/index.html create mode 100644 dpl-platform/runbooks/upgrading-aks/index.html create mode 100644 dpl-platform/runbooks/upgrading-lagoon/index.html create mode 100644 dpl-platform/runbooks/upgrading-support-workloads/index.html create mode 100644 dpl-platform/runbooks/using-dplsh/index.html create mode 100644 dpl-react/architecture/adr-001-rehydration/index.html create mode 100644 dpl-react/architecture/adr-002-ui-text-handling/index.html create mode 100644 dpl-react/architecture/adr-003-downshift/index.html create mode 100644 dpl-react/architecture/adr-004-relative-ci/index.html create mode 100644 dpl-react/architecture/adr-005-react-use/index.html create mode 100644 dpl-react/architecture/adr-006-unit-tests/index.html create mode 100644 dpl-react/campaigns/index.html create mode 100644 dpl-react/code_guidelines/index.html create mode 100644 dpl-react/error_handling/index.html create mode 100644 dpl-react/fbs-adapter-client/index.html create mode 100644 dpl-react/index.html create mode 100644 dpl-react/skeleton_screens/index.html create mode 100644 dpl-react/ui_text_handling/index.html create mode 100644 index.html create mode 100644 search/search_index.json create mode 100644 sitemap.xml create mode 100644 sitemap.xml.gz diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/404.html b/404.html new file mode 100644 index 00000000..1a177d2d --- /dev/null +++ b/404.html @@ -0,0 +1,1910 @@ + + + +
+ + + + + + + + + + + + + +We use the RESTful Web Services and OpenAPI REST Drupal modules +to expose endpoints from Drupal as an API to be consumed by external parties.
+Drupal\rest\Plugin\ResourceBase
and annotating it with @RestResource
uri_paths
, route_parameters
and responses
in the annotation as
+ detailed as possible to create a strong specification.drush pm-enable restui
dpl_login_user_token
authentication provider for all resources which will
+ be used by the frontend this will provide a library or user token by default./openapi/rest?_format=json
to
+ ensure looks as intendedtask ci:openapi:validate
to validate the updated OpenAPI specificationtask ci:openapi:download
to download the updated OpenAPI specificationdrush pm-uninstall restui
drush config-export
openapi.json
Configuration management for DPL CMS is a complex issue. The complexity stems +from different types of DPL CMS sites.
+There are two approaches to the problem:
+A solution to configuration management must live up to the following test:
+drush site-install --existing-config -y
drush config-import -y
and see that the change is rolled back and the
+ configuration value is back to default. This shows that Core configuration
+ will remain managed by the configuration system.drush config-import -y
to see that no configuration is imported. This
+ shows that local configuration which can be managed by Editor libraries will
+ be left unchanged.drush config-import -y
to see that the module is not disabled and the
+ configuration remains unchanged. This shows that local configuration in the
+ form of new modules added by Webmaster libraries will be left unchanged.We use the Configuration Ignore module +to manage configuration.
+The module maintains a list of patterns for configuration which will be ignored +during the configuration import process. This allows us to avoid updating local +configuration.
+By adding the wildcard *
at the top of this list we choose an approach where
+all configuration is considered local by default.
Core configuration which should not be ignored can then be added to subsequent
+lines with the ~
which prefix. On a site these configuration entries will be
+updated to match what is in the core configuration.
Config Ignore also has the option of ignoring specific values within settings.
+This is relevant for settings such as system.site
where we consider the site
+name local configuration but 404 page paths core configuration.
The Deconfig module allows developers +to mark configuration entries as exempt from import/export. This would allow us +to exempt configuration which can be managed by the library.
+This does not handle configuration coming from new modules uploaded on webmaster +sites. Since we cannot know which configuration entities such modules will +provide and Deconfig has no concept of wildcards we cannot exempt the +configuration from these modules. Their configuration will be removed again at +deployment.
+We could use partial imports through drush config-import --partial
to not
+remove configuration which is not present in the configuration filesystem.
We prefer Config Ignore as it provides a single solution to handle the entire +problem space.
+The Config Ignore Auto module +extends the Config Ignore module. Config Ignore Auto registers configuration +changes and adds them to an ignore list. This way they are not overridden on +future deployments.
+The module is based on the assumption that if an user has access to a +configuration form they should also be allowed to modify that configuration for +their site.
+This turns the approach from Config Ignore on its head. All configuration is now +considered core until it is changed on the individual site.
+We prefer Config Ignore as it only has local configuration which may vary +between sites. With Config Ignore Auto we would have local configuration and +the configuration of Config Ignore Auto.
+Config Ignore Auto also have special handling of the core.extensions
+configuration which manages the set of installed modules. Since webmaster sites
+can have additional modules installed we would need workarounds to handle these.
The Config Split module allows +developers to split configurations into multiple groups called settings.
+This would allow us to map the different types of configuration to different +settings.
+We have not been able to configure this module in a meaningful way which also +passed the provided test.
+drush config-export
+ and have the appropriate configuration not ignored.core.extension
is ignored Core developers will have to explicitly
+ enable and uninstall modules through code as a part of the development
+ process.There are different types of users that are interacticting with the CMS system:
+We need to be able to handle that both type of users can be authenticated and +authorized in the scope of permissions that are tied to the user type.
+We had some discussions wether the Adgangsplatform users should be tied to a +Drupal user or not. As we saw it we had two options when a user logs in:
+We ended up with desicion no. 2 mentioned above. So we create a Drupal user upon +login if it is not existing already.
+We use the OpeOpenID Connect / OAuth client module +to manage patron authentication and authorization. And we have developed a +plugin for the module called: Adgangsplatformen which connects the external +oauth service with dpl-cms.
+Editors and administrators a.k.a normal Drupal users and does not require +additional handling.
+Instead of creating a new user for every single user logging in via +Adgangsplatformen you could consider having just one Drupal user for all the +external users. That would get rid of the UUID -> Drupal user id mapping that +has been implemented as it is now. And it would prevent creation of a lot +of users. The decision depends on if it is necessary to distinguish between the +different users on a server side level.
+ + + + + + +The DPL React components needs to be integrated and available for rendering in +Drupal. The components are depending on a library token and an access token +being set in javascript.
+We decided to download the components with composer and integrate them as Drupal +libraries.
+As described in adr-002-user-handling +we are setting an access token in the user session when a user has been through +a succesful login at Adgangsplatformen.
+We decided that the library token is fetched by a cron job on a regular basis
+and saved in a KeyValueExpirable
store which automatically expires the token
+when it is outdated.
The library token and the access token are set in javascript on the endpoint:
+/dpl-react/user.js
. By loading the script asynchronically when mounting the
+components i javascript we are able to complete the rendering.
The general caching strategy is defined in another document and this focused on +describing the caching strategy of DPL react and other js resources.
+We need to have a caching strategy that makes sure that:
+We have created a purger in the Drupal Varnish/Purge setup that is able to purge
+everything. The purger is being used in the deploy routine by the command:
+drush cache:rebuild-external -y
PURGE
request we found out, by studing the vcl of Lagoon, that the PURGE
+ request actually is being translated into a BAN
on req.url
.DPL CMS integrates with a range of other business systems through APIs. These +APIs are called both clientside (from Browsers) and serverside (from +Drupal/PHP).
+Historically these systems have provided setups accessible from automated +testing environments. Two factors make this approach problematic going forward:
+To address these problems and help achieve a goal of a high degree of test +coverage the project needs a way to decouple from these external APIs during +testing.
+We use WireMock to mock API calls. Wiremock provides +the following feature relevant to the project:
+wiremock-php
+ client library to instrument WireMock from PHP code. We modernized the
+ behat-wiremock-extension
+ to instrument with Behat tests which we use for integration testing.Software for mocking API requests generally provide two approaches:
+Generally record/replay makes it easy to setup a lot of mock data quickly. +However, it can be hard to maintain these records as it is not obvious what part +of the data is important for the test and the relationship between the +individual tests and the corresponding data is hard to determine.
+Consequently, this project prefers instrumentation.
+There are many other tools which provide features similar to Wiremock. These +include:
+wiremock-php
and
+ behat-wiremock-extension
libraryInstrumentation of Wiremock with PHP is made obsolete with the migration from +Behat to Cypress.
+ + + + + + +DPL CMS provides HTTP end points which are consumed by the React components. We +want to document these in an established structured format.
+Documenting endpoints in a established structured format allows us to use tools +to generate client code for these end points. This makes consumption easier and +is a practice which is already used with other +services +in the React components.
+Currently these end points expose business logic tied to configuration in the +CMS. There might be a future where we also need to expose editorial content +through APIs.
+We use the RESTful Web Services Drupal module +to expose an API from DPL CMS and document the API using the OpenAPI 2.0/Swagger +2.0 specification as supported by the +OpenAPI and OpenAPI REST +Drupal modules.
+This is a technically manageable, standards compliant and performant solution +which supports our initial use cases and can be expanded to support future +needs.
+There are two other approaches to working with APIs and specifications for +Drupal:
+DPL CMS employs functional testing to ensure the functional integrity of the +project.
+This is currently implemented using Behat +which allows developers to instrument a browser navigating through different use +cases using Gherkin, a +business readable, domain specific language. Behat is used within the project +based on experience using it from the previous generation of DPL CMS.
+Several factors have caused us to reevaluate that decision:
+We choose to replace Behat with Cypress for functional testing.
+There are other prominent tools which can be used for browser based functional +testing:
+DPL CMS is only intended to integrate with one external system: +Adgangsplatformen. This integration is necessary to obtain patron and library +tokens needed for authentication with other business systems. All these +integrations should occur in the browser through React components.
+The purpose of this is to avoid having data passing through the CMS as an +intermediary. This way the CMS avoids storing or transmitting sensitive data. +It may also improve performance.
+In some situations it may be beneficiary to let the CMS access external systems +to provide a better experience for business users e.g. by displaying options +with understandable names instead of technical ids or validating data before it +reaches end users.
+We choose to allow CMS to access external systems server-side using PHP. +This must be done on behalf of the library - never the patron.
+dpl_library_token.handler
service.The current translation system for UI strings in DPL CMS is based solely on code
+deployment of .po
files.
However DPL CMS is expected to be deployed in about 100 instances just to cover +the Danish Public Library institutions. Making small changes to the UI texts in +the codebase would require a new deployment for each of the instances.
+Requiring code changes to update translations also makes it difficult for
+non-technical participants to manage the process themselves. They have to find a
+suitable tool to edit .po
files and then pass the updated files to a
+developer.
This process could be optimized if:
+We keep using GitHub as a central source for translation files.
+We configure Drupal to consume translations from GitHub. The Drupal translation +system already supports runtime updates and consuming translations from a +remote source.
+We use POEditor to perform translations. POEditor is a
+translation management tool that supports .po
files and integrates with
+GitHub. To detect new UI strings a GitHub Actions workflow scans the codebase
+for new strings and notifies POEditor. Here they can be translated by
+non-technical users. POEditor supports committing translations back to GitHub
+where they can be consumed by DPL CMS instances.
This approach has a number of benefits apart from addressing the original +issue:
+.po
files.A consequence of this approach is that developers have to write code that
+supports scanning. This is partly supported by the Drupal Code Standards. To
+support contexts developers also have to include these as a part of the t()
+function call e.g.
// Good
+$this->t('A string to be translated', [], ['context' => 'The context']);
+$this->t('Another string', [], ['context' => 'The context']);
+// Bad
+$c = ['context' => 'The context']
+$this->t('A string to be translated', [], $c);
+$this->t('Another string', [], $c);
+
We could consider writing a custom sniff or PHPStan rule to enforce this
+For covering the functionality of scanning the code we had two potential +projects that could solve the case:
+ +Both projects can scan the codebase and generate a .po
or .pot
file with the
+translation strings and context.
At first it made most sense to go for Potx since it is used by
+localize.drupal.org and it has a long history.
+But Potx is extracting strings to a .pot
file without having the possibility
+of filling in the existing translations. So we ended up using Potion which can
+fill in the existing strings.
A flip side using Potion is that it is not being maintained anymore. But it +seems quite stable and a lot of work has been put into it. We could consider to +back it ourselves.
+We considered the following alternatives:
+DPL-CMS relies on two levels of caching. Standard Drupal Core caching, and +Varnish as an accelerating HTTP cache.
+The Drupal Core cache uses Redis as its storage backend. This takes the load off +of the database-server that is typically shared with other sites.
+Further more, as we rely on Varnish for all caching of anonymous traffic, the +core Internal Page Cache module has been disabled.
+Varnish uses the standard Drupal VCL from lagoon.
+The site is configured with the Varnish Purge module and configured with a +cache-tags based purger that ensures that changes made to the site, is purged +from Varnish instantly.
+The configuration follows the Lagoon best practices - reference the +Lagoon documentation on Varnish +for further details.
+ + + + + + +The following guidelines describe best practices for developing code for the DPL +CMS project. The guidelines should help achieve:
+Contributions to the core DPL CMS project will be reviewed by members of the +Core team. These guidelines should inform contributors about what to expect in +such a review. If a review comment cannot be traced back to one of these +guidelines it indicates that the guidelines should be updated to ensure +transparency.
+The project follows the Drupal Coding Standards +and best practices for all parts of the project: PHP, JavaScript and CSS. This +makes the project recognizable for developers with experience from other Drupal +projects. All developers are expected to make themselves familiar with these +standards.
+The following lists significant areas where the project either intentionally +expands or deviates from the official standards or areas which developers should +be especially aware of.
+js-
.
+ Example: <div class="gallery js-gallery">
- .gallery
must only be used in
+ CSS, js-gallery
must only be used in JS.is-active
, has-child
or similar are classes that can be used as
+ an interlink between JS and CSS.gallery.scss
which contains
+ .gallery, .gallery__container, .gallery__*
and so on. Avoid referencing
+ other components when possible.component.scss
, there must be a comment at the top, describing
+ the purpose of the component..pane-content
. Use
+ the Drupal theme system to write custom HTML and use precise, descriptive
+ class names. It is better to have several class names on the same element,
+ rather than reuse the same class name for several components.$layout-width * 0.60
) or give it a descriptive variable name
+ ($side-bar-width // 350px works well with the current $layout-width_
).class &
). The use of parent selector
+ results in complex deeply nested code which is very hard to maintain. There
+ are times where it makes sense, but for the most part it can and should be
+ avoided.dpl
.dpl
prefix is not required for modules which provide functionality deemed
+ relevant outside the DPL community and are intended for publication on
+ Drupal.org.Files provided by modules must be placed in the following folders and have the +extensions defined here.
+MODULENAME.*.yml
MODULENAME.module
MODULENAME.install
templates/*.html.twig
src/**/*.php
tests/**/*.php
/css/COMPONENTNAME.css
/scss/COMPONENTNAME.scss
js/*.js
img/*.(png|jpeg|gif|svg)
Programmatic elements such as settings, state values and views modules must +comply to a set of common guidelines.
+As there is no finite set of programmatic elements for a DPL CMS site these +apply to all types unless explicitly specified.
+The project follows the code structure suggested by the +drupal/recommended-project Composer template.
+Modules, themes etc. must be placed within the corresponding folder in this +repository. If a module developed in relation to this project is of general +purpose to the Drupal community it should be placed on Drupal.org and included +as an external dependency.
+A module must provide all required code and resources for it to work on its own +or through dependencies. This includes all configuration, theming, CSS, images +and JavaScript libraries.
+All default configuration required for a module to function should be +implemented using the Drupal configuration system and stored in the version +control with the rest of the project source code.
+If an existing module is expanded with updates to current functionality the +default behavior must be the same as previous versions or as close to this as +possible. This also includes new modules which replaces current modules.
+If an update does not provide a way to reuse existing content and/or +configuration then the decision on whether to include the update resides with +the business.
+Modules which alter or extend functionality provided by other modules should use +appropriate methods for overriding these e.g. by implementing alter hooks or +overriding dependencies.
+All interface text in modules must be in English. Localization of such texts +must be handled using the Drupal translation API.
+All interface texts must be provided with a context. This supports separation +between the same text used in different contexts. Unless explicitly stated +otherwise the module machine name should be used as the context.
+The project uses package managers to handle code which is developed outside of +the Core project repository. Such code must not be committed to the Core project +repository.
+The project uses two package manages for this:
+When specifying third party package versions the project follows these +guidelines:
+The project uses patches rather than forks to modify third party packages. This +makes maintenance of modified packages easier and avoids a collection of forked +repositories within the project.
+Code may return null or an empty array for empty results but must throw +exceptions for signalling errors.
+When throwing an exception the exception must include a meaningful error message +to make debugging easier. When rethrowing an exception then the original +exception must be included to expose the full stack trace.
+When handling an exception code must either log the exception and continue +execution or (re)throw the exception - not both. This avoids duplicate log +content.
+Drupal modules must use the Logging API. +When logging data the module must use its name as the logging channel and +an appropriate logging level.
+Modules integrating with third party services must implement a Drupal setting +for logging requests and responses and provide a way to enable and disable this +at runtime using the administration interface. Sensitive information (such as +passwords, CPR-numbers or the like) must be stripped or obfuscated in the logged +data.
+Code comments which describe what an implementation does should only be used +for complex implementations usually consisting of multiple loops, conditional +statements etc.
+Inline code comments should focus on why an unusual implementation has been +implemented the way it is. This may include references to such things as +business requirements, odd system behavior or browser inconsistencies.
+Commit messages in the version control system help all developers understand the +current state of the code base, how it has evolved and the context of each +change. This is especially important for a project which is expected to have a +long lifetime.
+Commit messages must follow these guidelines:
+When creating a pull request the pull request description should not contain any +information that is not already available in the commit messages.
+Developers are encouraged to read How to Write a Git Commit Message +by Chris Beams.
+The project aims to automate compliance checks as much as possible using static +code analysis tools. This should make it easier for developers to check +contributions before submitting them for review and thus make the review process +easier.
+The following tools pay a key part here:
+In general all tools must be able to run locally. This allows developers to get +quick feedback on their work.
+Tools which provide automated fixes are preferred. This reduces the burden of +keeping code compliant for developers.
+Code which is to be exempt from these standards must be marked accordingly in +the codebase - usually through inline comments (Eslint, +PHP Codesniffer). +This must also include a human readable reasoning. This ensures that deviations +do not affect future analysis and the Core project should always pass through +static analysis.
+If there are discrepancies between the automated checks and the standards +defined here then developers are encouraged to point this out so the automated +checks or these standards can be updated accordingly.
+ + + + + + +Setting up a new site for testing certain scenarios can be repetitive. To avoid +this the project provides a module: DPL Config Import. This module can be used +to import configuration changes into the site and install/uninstall modules in a +single step.
+The configuration changes are described in a YAML file with configuration entry +keys and values as well as module ids to install or uninstall.
+/admin/config/configuration/import
The yaml file has two root elements configuration
and modules
.
A basic file looks like this:
+configuration:
+ # Add keys for configuration entries to set.
+ # Values will be merged with existing values.
+ system.site:
+ # Configuration values can be set directly
+ slogan: 'Imported by DPL config import'
+ # Nested configuration is also supported
+ page:
+ # All values in nested configuration must have a key. This is required to
+ # support numeric configuration keys.
+ 403: '/user/login'
+
+modules:
+ # Add module ids to install or uninstall
+ install:
+ - menu_ui
+ uninstall:
+ - redis
+
We use the Configuration Ignore module +to manage configuration.
+In general all configuration is ignored except for configuration which should +explicitly be managed by DPL CMS core.
+Configuration management for DPL CMS is a complex issue. The complexity stems +from the following factors:
+There are multiple types of DPL CMS sites all using the same code base:
+All these site types must support the following properties:
+This can be split into different types of configuration:
+drush site-install --existing-config -y
drush config-export -y
config_ignore.settings.ignored_config_entities
with the ~
prefixconfig_ignore.settings
+ filedrush config-export -y
NB: The keys for these configuration files should already be in
+config_ignore.settings.ignored_config_entities
.
drush config-export -y
function dpl_cms_update_9000() {
+ \Drupal::service('module_installer')->install(['shortcut']);
+}
+
drush updatedb -y
drush config-export -y
function dpl_cms_update_9001() {
+ \Drupal::service('module_installer')->uninstall(['shortcut']);
+}
+
drush updatedb -y
drush config-export -y
drush deploy
NB: It is important that the official Drupal deployment procedure is followed. +Database updates must be executed before configuration is imported. Otherwise +we risk ending up in a situation where the configuration contains references +to modules which are not enabled.
+ + + + + + + +4SD+v9mg{?~1j&-}P(W~q8oGkLZq?VArrDBW(k#^7>eC1~iE z(z~>uH!npci>xi)S%pL_&J>V6^6{no@|IToR-Ul&gZWme?-En}DJ=7N<*-;9AC(aY zQ>kMyh>}%!=1|xYv#nhi1i|LORIMJ&cV7tk9Ood(sIkOx#=n$*-R XRlB$nD$<;c8*HfYn?Z|s{8S=DLPk&tQWd} zsd9H@dh0Tq4sj!{av!*vKKRu}i@*CM`^xSP^VlVN-bC%(*D4-llsn9KcoMqaR5iWw zq04v))|TnQRxg?7m>k6;9Fw3=9tpF(H0M2knjN>kjzC z2-NQDyB*g&-(2FS@Vs**oMWnleTO>b`CGccXNvj4G=Z3&NIHDY(sR@4HF=fS8MMBy zRW U7pl*g(Wf4R7LO2pUNNGvgVFzBNO+5|3m|<0{YG3GmxD8P zq};XKy2=h7s-WL3JBuA$GJZNwRgGBu@x#`+=XkxqB5?g^<|syGL2dpTdI0J>sd#pr z@Y9f?e0YB3iCg^l)nmyq-pyC1FS_%X4)ZWY`C!IVH^Dn!3qNIUW(|Kx;A0b`f3j;^ zjryDvo{aKo6bn7*E)NuN`b>nLTHPH&-O&AZnLOx2wqWAp`BUgEe>s-b7(;`^$Q2~k z(K!Pf8yf=yl>H8Pv&Wv0kvC5j&-q7q(C%CflzTpHWI^rFaXybvvis-HpIu$gIMFM? z_wU0dTG09Wl|8Lmh#v|QKQt{1DX2+NZmwl9VPa%F+M14!h!8YK+lu;HDjqBQd1thQ z`)StZ6X++SiRfxVht=&|-re)H;d~`?V0@O_=&+hX3?}QvQ>+Ew*(v9f-uda5Wwy^F zR)(yzml2beR<3zPLlcOLUX};WYa{PlcHAry0>4I3$Da&&nay-0lc?9B4Q5kZ+w~FQ z;brF2wLgDK@|s>u0s~Cq`4&}hG7`yuC^kQ7(ZpjhQy)d6@?KwmVPWB6`&ICK*%7co z{2!VIzh;cnl_8r@oC*Tz@RC<_baXT{-R$(>Egoee;K4X3CrDbTI}eNDer71evftqs z)E4*kVC$uyV4B+1=F>9`&cX9&OFcL778%o (36^9(2SyjWvuJ7p=>csYMnENFijx;(0IVK6Z7 zL~=HI^S*6)#)I|x`o(WDaFniX^QU39sY-I>fKKD-DpOl?>+_|ax`RX! b`U&jSYx-(zKM&BVksTBsI(K4y*D zVwaptJ3l`jirt4LX8#br9zgvnFZ9u9p$1iahi_Xc_!vecivXEvbWBW4R8&-0SSc`s zupreNqXe!M&*~dJ)EUuA?cUd5z&doawY8mN^;oAJo6EG;dWC!B;zps+&DNOY=9 z)x^cS(gez$;8M`P2VVvToe**n^u(I)5Y9f)k#-dp(1R~5^PO#!%kUv=w4SPc_T%8- zXcb1kXAX~04)1p1^xp8nXrQTy(+pLroLdp;F`MANrdk{G7CH#LRwH9hd-kS{32E_A zVp?Bv-W>e!!c^3kk}u*8y|9sxFxQ8 !3C{X3Hu!TIRXa_)c_hn >8kK#-id3;MIz?)Pw1=)Ku zwXRV`IgDP#e-F`9CO^usv(4G09)s#})gcjQ=LTD~)C3JrIvuXdXgCSM2_6tL_kLk( zFnzee @kq@rVoRw*Q8G1&EA#RQP4SiQ~8;VJs(|;|u zp0wcdy%9gxpBfx!dinK?V7q| dVBu#R7Ww(&a&q`&r$7TpyJ3{d8yoq z>~s3|Dr$`k5R8@%8ZS$vTSPWbo}aZVhKdJ`kB^7nwcnaL{r-*Ik(Fc5_whQLSaw%% zOem(}1WkS|t?N$c=-|KrBlu!sDlaPo$2_ NAJOWxWIMn-JS7TuSB(Eg}yUN6=58 zOF$kE4Gj(Ft7K 4px{N>8I^y0}y)T|eaw~??UR2R;9IQ32H^(ZB+=$TV@nVxty1_}z{BFRUO9;vCR zwasH~D5za*xnSy7;>kSIu)84T^fb9|3@rQgvn9>gr@TH^5}|w5C2#~ia;viaps1sU znuke;yERT>dv!S(D8*!QxVu@66sTDlh)YRHNk~lA*%$AgV4nS#traW4jtK^AHuQO? zCvVgCQHUI(ht9LiN$NU(+miN~q-+?DWeAZ8BTD_l5MPdhG^5``lNu~%n}InD-@hje zB`uNpw^IoDz+qFz%PQ+-- P@me3Clkd=K{ietpPT|Ve~;`+;(WfmTtM#S)@Y0A#mZr)IKD)ObyFVj}b-!QmN zKj*#1W&K_uUE~(4g ==CpA*+14rQ%eMUwKs9S#3yB~qOyTOnl z?2VZQujO*P$_v+1{5+NDOdxs?#@PMFsp{KuYmN~OYB^M<1ABXTwZTLxZn!H4Qm?6o zaC< >^4fsM0xw+eDD=~Xg~MlY>P=-&?BeCC^?Wz zKLwkyf0#>zSUctfXQ^w?EP-TVM6f+w7eh{Icl*{Y^S)mJx-D?+`jeXFUrI-1R|t0H zUGoeKTy3B{UPP=xH*enjEM9{`!X9&0OjuVAFkcUrZ`P=$KXB=?Y&TUesj4tcb~T!0 zjkvz7aB`v+_JhLgbdO-+rcTXXa*|B$Qf;5n^Wd*v^RuLgTsOv?9I19S$BUE=0wY1h zwLI$UHweZO3q~xDyg21Us-~RjFhbnV+nli#YhEqy%!XPJGtARAu4P#?jTM=_( G^<3+h73ANg;&m{1ieW 0S$T(79(ru)WZD2IQ0CXtbGNuuFR(OHj0EvuPR< XsGqYG|09qD2nZhBFm;Mk}f>B176U7tRIU z7bQwsTeS{L@=t!&ox6AD@V-9?e~2GNgu4yZ?w`H=XtRZ=-I!F`X&fgi39SApGLd~Z zxh=TZWuuhOk(bM`_nz(g$kE2}0CF#ekJ ECk~nQ4(~iqh zhEVf?kx0(qfPhay1 Q$5=w9EinZ9+f_+|hcORmZL7_4=qev%%*uGOP|9#tj&X zSB{1=|080zoo+BIIC?MUXdyzc!j0jKaT8koW&cNDa`$dqtB{}XwQjn`15NvB7RFBn zcEDf3zP ?{#9o2 zUD$j3d?-haLSx(T_>d>5MSATItmGp0)$$~XzE@NnX0Fwk2pUg0%pXp)xD;nnGnv8~ zV+(RgiZoAUVJgJ@=61;AmR8#$4ryF4CGbhc&*L?5lWN7@`Hch=g)@y(FB}HF9nb zz91MLDIM)6J;blvL{)8Svi$m<7~k}Kq$;NXeL}hCVE1IW`)X|ymdh;~Ikbx0lMvc* znga`$mc|+4i`5Syrlu{4Tm<<^+fArnDov2n-FDR8+3DPLnSox7xTAT##h*uTU?KWL zThIsJ-s~j8{NnE>MaJ~@X#;Vr4e-_M_IzZGb+T#yGrP$uA8-o9YeI+ILKR11UJVW| zlW?Exe)Ht1Eaq6<7BaY#+gRM_B*PlRUy)W$Jr<+mrfNsGE)j8cb6ym^AJuXDe8}C; zQ(qcUNC}urM6J_dQw4tkuSM!kssjVPaRg;>?cvBw*-Hn@;?4+BW3UgFh{MsGyI*(_ zyqon=HzE=O!Vzu3MD#y$I18n%2J!TDLiv#2`qS5W&o;CWkIdC4;7l;cD14xg??67U z?6ld3X_!StikHsp2m~tRjvv3S?$dC@LMFTA+hGsPY3GBLoT@Tv)qK6t>fiB^`7kio zw{_(#+lS&T@@~`@a0rq`&o$~#w)y#4DhyRXFrc?J8EvFjN#R4C(&raSYV^dhEcL|C zju*2ga~_gx&fl*|Y20bPzdA%e(;d?!n=X=~*|5;O#PJdGr@c>oSQy=ru$zek>BZmK zX1-)aqmak`o0Dt`-CA{3u82d?p|YtPtdODC8aih`wxeiJFRH!No9ql eH&b4R&ZBa)3DdH zb}qn@V{q>Vlua#~ |^so#AuM+==5io_w~YvgQ?pE8zh!H`D^ zltXb!#_>s~zFHbSA`F>%$sTTd;nxv11U5Q2BWq)ag{2+ zD(C|4d8l$@c*c4A(Wd;eN(ZdT3HV~u`68~PV|-y1qgfVP>nWc_qx13I8f>lllhaT> zbK~K>PF%i%VLuV$I=jr9ghTltc_`}? uHFb@+1qyKqpMDWs8I`?8NFK_ zScZ(=R_X>(NqI3>F<)6qLua~tNe5{_$2XmrIps>PwpXBz{N)u>VOxNsY)4(E++CJ} zVzJG4jXl!nQM+p;-o*zDb#RZB8HY6Bc+P3Pa5da;s8~ZnGjh;jq@aCBL7Aej%53nJ zo^RKWH*R(tV*<9w W(~Q{2UDrxl6sYiy&%#TH6cZ>|UD7^yEPh<`pFV#tlQx}!*_T~y#} z;$P8(Jk$n;J1sbN6EvCO9@)R_?J~Utwm8BB8pl$6>#>s;H^Az{Bu+*dLdsD7z5E?C zILL(W-7r}I!I+RUGg~S?3!>)kPT5J#%`HjS{ZU_{27e^3s?iS17@yE&7{1smkK&qD zzN(QeO}BYlV=1NS9-WmA+%2DDefw8s7HMlAKz%cT`3l)1ZZYdqr`Zex8d0yE;F=th zmoJ@j*%*}?baM~Ke%{G%ZS4g)+69Hsnaf0;4<#>Tk-h2e)n;+r%ZXz#;oj>Yt;Ca* z(BQKQt7GLp$W*+At7LS(Rd+lr_)i~N B22&)cy;X^PdtQ%x2D|L87(a(k!@| z1c1()Q14oo^}C-R+`W6SS>1HrnQ-0=V^?yIlDexHMpd(ltsV~`0fH(ZE3=Sv+-B5w zps#paBA1ZF>3Xp8)%C@(%0KXm-JBJLv=cR3bf>H(3)&jZ7IaCx4RS?~te3d^zwSmg zIN4I~jmi!yPy9HUs I;hj?&9&ey(N3*TP(^aiQP$|8$|D+?gCXFJ9ML)5)rrZ1ycjn}P77%`B9T z`5WO1<3XGDkRLkkiL{Hkh{~YTeUx&xbfIt{5>&s(Y-Vv03Fr1^u7hVBt|*Y3?vTRX zv_(#?+ zD@{` GdALd1c zrAObP860au2@a>TfMXdmN650a#P8+wh!gAf#_1Uh7H*++X WLSS9L-bB4eeoQ>O(r+7%UtY!wpY^M>60bHp>t?|F5?$q{Kd40{F4)w_kO^^E zp aOlqz*~+a%BJy+Mr-qty`weYs&)ec11&C3++HE+t?>;z~+B@9dO(_i{EcEZ!sL zXu{En{`E{dPllx?zJ59ByF8hvC#H(_BU==rDPkv!hX((teS{U+^GeI@hUzuGYc89W zO;tvC`BekFth?o3lLwEJdFsTDo?q@N*={%vs*-LL{*FAEk6s ol})<|DBR~_-;ojwVppViO*lU^~l-rE}3I$s>n zH!t#`mer!&**m-C@(*GRBQ&dx2Z<{aqFFW0l;mOY+hmGc14Zca`^qnK12=<1Q>#p7 zW~gmfz0!F1UCoThVU?O~T8R-5rZQ>ip(AO+8`e;%a36*2fvvCeZIkBf^EDyIOJ~?o zbrt#O8dEOh9D&IEe87{hTo_(`*A-V*91Lsw=Fiy_Tfx+#3qYYRuBMqpM`vc&9zsXR z8Wa?4<^akQ_Y>X1WzLzurq#8{)fEQIY^tdjhY1=9#nSB4 iP4PE}G)=ZXIM=;r_{dsHm{8u!zWvJ <=7)3BqJjO^n0$mvd!kiVKCc_Z1-I}A{IzSv;hq? z%JXBF^Z!)LqCdRc6Hh=)JXL3JfgtV9)u=8?mac>hD>g05ddRC47hE8q+=5|4Jy5X9 zYKE9yq`~K+{QUehDn&!b1*)Y2oRxl9w~4=SJ6Zu`Me4YKH++wTgx4K;Ue1}PBQWoK zi>Trjrj)_|Y#Q5@zFB{&q`qUxc-BpoCU{h%=+9WDY`e_~NR9P!uR^wT!}+NMU?bCt z3hI!%LG__3S(KuREDREsVO{F3tgJYsI6oH0eg|T!0{~-&^OPh4sJXb#zIk4@XhPVj zs*Vk0N-XB;wTFl)M |Hx^(*5M0tJ)Q=zkbptE0Dk@AQBjpj z-_ee1rGn;cuzoD=C|^aFrh8FwaTA3aY@MFpzkk=NwFzU+frpav&7_Osc79GxO)cA5 zjM0I_*CXNUbm|q@H*ePOb 3wB!G0A`D*?I+BT7_6qz$wQ6y)U>TwUx8p0+;|C2yw?1&px)_xo>;s0|LsKQ;UL z&RJ#UDgXWeAZ4ALYU{nSv$E(5Xctr$J}rD*Sh2FQ3TnT}E|^)sOC)#FC#%`3I2;h! zhi!NYfv>mGe=`L1(B4d9SXfwebX6^PPwlp@o=Q!aUKm;Ue0X{{=uwa`{kn;-?3yVT z7NsG6pO?AlIla!;91K^v-{Zt?kB*OBJ&~NLw6?NZ*mT~WX^351J^dEaR%Au?=d5F5 z3@>I~02fbxMpGU6+{H*!PP5Tc4ilc1hY#RvuYi#^jb+*;bD_mctZ5ip!C;27x2_g_ z^T+v$7j cK3p_#dr&PH-LJ@C;_dW@*N7}{~m^z>0iUJ->`UYc~x5RTX2r%H<9}( z`FMo0wDqaq@Y&@s+0v{qiR3(r0RLaU<9kWvm(bOzPhD3{g)nPDC!@DHCSw*SA;*JA zuErzy`D+z2=H}`1^K-kcDdUZXgc#d;?nQYkb}QL7?f4VqUXf-EBQGy6GjoL@G^uSF z%BE;J(S^uBU +`wloXEa1wS1)VPa2QRS!0otK7KMHU8~PD5 zo0HWHjEsA|T-)c{?x?f*P`<61hBH95(mtn-ey%;TyQg@S-5u#-YHC_aSz |kHLV(kWa$YU;g9dxH6 yZtzC5+0Mix3?D_9!~fmj@z+Jh_Lb_H_g*RgYM{Xh`vE5 zM@>!5gfbF|?Ck6Wf$7GrTbpC0^I1~y2VMj#ZERYA{XmupxVX4vODEzKET^!UPkmLv z34Y9_ypHCcJHp7wo;{nJn|lvptB=TFCqVM~O8LsVy1HdBd>Z8(7O8AQmSzo$2K>j5 z>FVlG$g|2G5KTuj#3E{K*TqXldFh63!>qI6dZdi{pVUEX&DQg9{m#ROUy_pOBm4sb z KOP9jKZM?4C z(stft(JNLniqv=LrmH6Auo61EFOh`K6jusOiW`nV=*)_j0i>5ov35H!tkXeGYsMp{ z_c{3FxsB(0-DNv#`Nbf%4wppH9&C&=fhalmBTykr(iql=keNpobg)$7qYc903a?mr z#=)${|3EsCGZWq(O3HBk)F`#l^$e2QZ?gyJ;n>*N)6-KZ_kK_-_pmVw&mdlNOAE!9 zPMQ~j#__ns?6LwAyYuafcPOP3at`y;%O`S?u$+!j{*l$`x?_+yGj(`~d0oCr>YeT_ zVq#(*gU}5keiDe4*S#UGv2DM;dr^E00h4e2gg5adOH^G`nTi^ND*Zp_M-{>GUhFDh zOd3m%_Y|`pJR>7hDbh4n6%`24k3yUsub&MoKxiCUSy+^8>D9_IK(d8!u(O|ZGc?gY z58`?H^r>&5{;U@+uWaJo_m?hT9xlu3U^&$7gxroB)p6I7|E%7)Sv6U4|M9(hph21z z4R} _eipoaJWazr92(g$D-Hlx1RlU)aI0=w6QuKv>h zTa3zQi-aGpH=QoUx6O1b#H#NcAEP$Pp*PoURtGXc*AATf;p6=5A?5Ipfx$tgWso8k zQ`OBUt2TokF#)=H(Ga-7Esf5PN7K!T@7+EBTp(fW>l|rtk`+@i1_$q|Fs0nzGp| z3*>c$3keI0VGqf)*f?d80YaJ!*ol)<{Zd}lsfvzkX0!n%008PuoSgZIalRt?U_<-e zx8+c>lbU>vvA(AH+W93VFU_O|$>`|w@8Nqy{1M4$W^dh-l`fc(1(<*`w`I)Pky_yf zsKy3)#Ro>l!Kvv>6$Dm3K&-u}RB~}S2RU0Qo7Sjl?)hmsaKXEL P|+ch%EHf-4yI3f0O*& m2IJ*s~E=apNK0a7~NCN4GcXqGu@3xbgtkWp} z%kPw%i6~PNR2xz|5U!gOmD`PHTL5GnwUfF>o}|hLL}OO?)NR$8?ELyJ8bUl?W)L`` z%wr3_qbd6O4go)`m2)3o>lY ^PNXh&Z=*#1}_C(kza@d{t%;S zGu!NQso46C{fy)C!Rp{452zS)z=$ty02m`BDaq}2{ Qcz6IDZ~@o_ zoH?h^n5E%TC?5LU@(ycO7= 2fgdiZ zHi+0@qdVV&;10Pu*x3Z|)$HtSSs*~uDpp_B2O&;LWN#QZ#!AzFsvT82?7lPG2Qh>h zBtsB|$wY#7&ewCZxQ0pV+%72>d$~Ps5j0cdb3FAUVSy+*q_&ed|FotVbY~=W -lD za1$5M{7u0jW4<&aBqWrPnVGu?VhSS8q^RcHQIrO;;7a^`=TS=jW2C->mBV($tb5P6 z D3Tbk#HM2tcV@_FpZmlM$0Y#^{5u-S zake4s@ifzY%XS*8N%iUsQE_@cZTZdTpBU!pQLlDsiW31oL5v9OYX(0GzsEh>b)e(F z;1;{5c+ic@b#x|-Ck-V@M52;RF4 *-A~3q46Yl$85E1&S<^KZ5h;aTd*bdCJ z=-1DC!%(Qja&KbWOjqX3P`S3S{-B0lWnVuX7LIZ&PwI~ViN+6GYh zQL2wfcrh> !e1wMYdzpSUHClP^plT1-R z?KxsWA`46nX)At*aFf$A^Cm7S1_liO%;`Et3FEugPawS$I^RfS|L|_CL>KV1=tyJv z%j4i+8>Ykf`Zr!WFzNjZ4ebpD;L|8(^U@iShCLGbyhxz!kg8Vx9uz{4x$K7aAV5JP zFE8IB5J4pqJ(do?eEIU=;Gjm8=_7pnOxTajYS;`2{2*tk05Z66m4gDRm2Xyfw79*U zoRF}=!4|xV`9M`hex9TH()x5~Q!~J26l3i_e)J@83^Fkj+Nmrw#f1)5#f7%Df8Yj7 z@xXaouYCzayub|sw`e@gDy{Bo^}mOOOF|n9`T6BlIGs|q@wE={1+-aEsQXf^VH~q@ z8fT$^Poqw>^U+3ZVxsHr+>aLuSrryA?ZbZnDI)=aW{^`W4xNv;8f@2 aB#F56P z+7F2ML|Ke$Y_HV(B1R#l@!K!)t6T5hy#qTlv?ogHnz1RYH>MSaf;7rZ+VB#>+DkcI zPMY(qFcmRCr4%$O@lE@j }}a1^Io_ww6NX;bWuXS0a*n}BoKZOC@7rLqo@g>p06 zZK!VM{= S(Y8@^&4~o=(rPaeS}n{26-^)lC;er5X%s3{bVT ztv`6nFeCd5N1193IF#F@S+z0lVd^VZ)+11pj3miRGQEzVlp=9EnY~9PZ8}}6G|Bzs z$=k^)Gsr2ZR)+j=1~JlQD0g>vC1U86y30UUm U)}R(sA2J!n`JyM_XCv{FXdo>y6;i3hDU>g zpeK!LVh(`IU|U0Z;VZynaB$qS7CoK?mLg^D?>r;=+RISP8%FNU@Gi_%Jy56?h pjK8{S=sYPq@?|3ccY|2#4x71l)N4%TmH0| zCO{_+iJZ3Y^z
k8gSa7t(lq%<+3e=PruxmoQb zoLQ59I&{E@S)~GeYQb=pjfC{o1167vW}c)AW?=u+`lls2`IR0qXxH^M Cw0^leY%ljF6ySzo_w2C05eR=|tS4eYH^^Tpucx_I7^!;x z_y5O9ppx5mW_&{*-1=LBM<+7CoUnKO#xV|V6-KZB;#EM2j%GprCqb{}gGTaO|HWq{ z>-~4`{lC#O=rjFKCgj4F7mQ82a#3
~mCM z%m(J|QG#v$^@9!O!sK$Y1EPLkU!O=YA pB_nhv5lHM{9k4)rXb8>V{V+ABAfVcBCs?FcMoAbPk zm5~j&2`hI}Qc_s10+r**h=zr*sHntJJs=rwO|I#AAn!GO`}XbN;2@e#Lqu43Rb`)X zs6ee8976mD4=B&HO5gdc9ULFaNK2ao(Up;r5vTwwQ)sM7IIJ>)?hz2MSuaUK`y4<` z0 yt55 ELhzO6J}Kj)<_Z-R}23lGY(>KzD@Z1VTx8@^pH-Wd|ZaxJ*t) z{bYhN8xIKCc7gWT(a+xAMu*+G$QKF|)fUAUl!Wn)(bMZKNvXR>K%u-Ctr0@Zk%kJA z=A#%)uZr_x{j{pAeH*eil-uBR$Z5CnWrO+YQ(Z8Tyrz!FkF+Hba$g#s5JEdw*chyu zvaoVWC+b#9vY1{?6I))IkH>z?@TWs}NGyVY 8@^mv5y0Gwfddm59ri2k@brq_1+?b z1VZy1j}S|Q`G`1@l&p@1bw8Fw|KpzNUJ1 1Ej)N0^^O5> ShO }5nUccTSO4gER;2M&rR=xzF+VI}d=47Q?u=fIBt|Vc4U&2@AG <^!)&rDcM%kbeawCiyv&dD z#3CrccRT*~sH)7TA)Fz+=yJ~p6yFd>z-}b%rfWAiP57w?=-$o})mk8ytd^I=rRL>z z0~88G?E&a}XGKfdFLVbQAAWqeLX{3{wQ1rddFy#NBju-5@P5u $?UFTZ;FJHUK?s8%&E!_*K4n;#y^;0YW-gOqF z%{8V5Kteep8{fsVnq^7GS^=~PSXY4Y2bukha2s&(@$g;&p*_%{^PT+i%9>x%Ya1)o zyLay%Xfn|A8~pm_nY24!RJTP4KtLFoXqD-Bn$t}MMjpr@hY^F%s`3o3xVGhCqR7)5 zgIQ7vh%Bx$r&ovfN}Txb4+1x5n=U@SJXAhWw+!68bfSJ>N8ZD-vCEFLc@vFN&@}o& zgB2h{$3Rc$(8Le$J%@$WGkNeuq}x!A+^kOp%5grBp;0wona=+n;8+35k6auZ8v_&y zicvGQqM`zji=AIU@gXHGeH$BF7UAoiMdC!d7Nw#cc3ntRwCQZCuF_;wIZ^qQ;N0BK zY|HvkE}5X1=I-&a3WBgx3ymNXrkdQ{hc6r}zL($mg=F=fo9ur9hWM?HwI4$=-`1|m zNrF9_vT2&Zm4!mKlUm|>TOs@6EzX$Dv(%HT*wyoBfc=l!62z!~+(AKq` FQ@c0-fFXmSodcyec9< zMXniu#x8k9)}mJS2v_a3VK!*-h@+hB@t#D`RWM$W@ZZWTQT;{ +=+LBn^GyZ*%|IrOArQNB!CbT5u~eS!u}|cg!zv+Sh~c z^AoTjx>1x28OGQ9=r+$Us^yS{El0XVNxP8U>liuB|GA&^r*9 e zeBgg=NOiUS7&HvlqG n@;56$`y;?jEzm_ zNiKs-6iJkr`D+-5^yjVW2tt*8MVB3ya+Ig0I{sx|VLy>Vv5eF6{kj9(ZtmHY$yla{ zckh}jwIYwV4th$~aZC){g76)mSS>l2X^k{8x5rF%{A&kjl#E=qYIt{d@lsPgA9D_& z4hFfDQ2ps*f__y68f-cC+h4Yu*xcF JJgL6f4QrZc_VMCb&SDw7T>q9wtZ);?mt_H?eEQULx=yFiDS!p5 z#nXW#*DV`pyqxEQiPF z7tIyW6A(z>ZghUaV6m4WrUgWb@(3}pM66p7%JC%`_ce$1$A!1NI u_=YHe3hRBI#YBA-&Am^WA2uq zZv}t}(qbA%WekHg#y#DbPO%F<&7Yk2d!%q56BZv5*x!b~Y9P%W#-5#JiJ`68Z1wkF z)6tnr^KKIkyq0h13TEDu$OTmUz?;8H=L*aR;0q3wwI+T0wg%x~Wp!B{kVt-4sO2o` zbuBe%K8KQD_^bdbku^ZYHaIPIA|`fPs4gwtSn0S=Q*l`7)*{;;LZM}=R5)E1tg}!a z7hbhtpp#`i7#DN7A}#|G7WT9|8X*l+nBs5 pw8d!&=ohrslm+= z%dLxGkRtCRLKnQkBqAw!;zxRWe@e5mEqML>6gnM3A_bodtgDo|bSckJf2uHArHFVg z*6?OGe452f-F|m2nb$GG=i~$%O`9~K+=3R8H#SNq6tWZ;rz;uG2B1 !z2G(3OV$-X6nVNkX 3 z1wkT@^QuLI>ZbWb#rm-Qc}8cm4$3KUt-4DOG#-1>L+wW4462fyHlvLj;Kq_x3GeHC zF^JhvPLae{9v$$VH&;kz?PHq6TWc=lxXy0LK#?^pt#`)9bpyw43RAX|_A z#T5*&TTCB2Q00Jol7K=*D>W>)Ui?+$|EURxay5$l^2$m-erG3cAWNo+Hc8BRHIpcV zkCW51Hz6LdC%K$#rVsn8%rb<+zJ9F@7rS)H4bD2f4@G4u7ZToeuHV=?SoI@uDT%oG z+-zgaL?$UA2VS`M W> zSWQP57MD#916gaUcYccM9G`dj+wYeU7C8Xp687@^TRjngM`&Demra0-`q4jdl`(!l zc5sgVKV%LWN<#ZQ%zJ;P wDOu(?kZ7Qf zjf9e>5xAJKgg9$=IEv9BW9H2MeTO(EFQw06>1W25FFQCPmfj-E%rHT+e=+@q4^uxJ zZ}o!)RTMe;Mld}4(&c=MDfTkqK$^5PfrZ(Bh3%$;)px)&`Yl;f>)Os{2Ui18q4mq` zNaXMXdSYTyQanP!u~b2X3}1sn;nMul9}jg8dGvR=N##55Hg9hcH@*l1gu=k!@1O^G zL xvwq~RBd0*r25k4OH zmob%t`T+6{PG(9^rd>}CPl}9$L2&i-T4LxMq#leEHKg-<$(lXZ5lD9 _{si 7@i&J%&E!Bz6PEFQf@^_N%CAKZ}Vyl z5Mp}q9 5!Nirsb)} 9uDDY!)`Kf6FE2LX<}NKI<#`LP-y_!1;(K>wdC2C?E9 c4G)-7%vf|nB~?(UB%`wlR&_+-pZ#=Z{G zkwd3h@pEP6?Ii3kw<2V=WD^h9{phvNC(8|~I<3}6!oWWCbjPFN#-Wnf;D-VMz3Z&m z TNFqp`ccs-KsP3-1+G~5cn;|JXpw4GNPpzbd0l$zTVQ2gi2Y= zKEK^n7r+fXT{h~G#jS2~W)ePL-GvTTkkc}yl4rDRfeOR|s0p6-%SHb_@cKqZZ#6Zi zK}f;6^2J51e@B*-P@;sRXJ*N}&jA#ex-GuLK!f&MB{IPY3=HJ|)qvXSq(t|NJ0qx+ z+~2-^>*VAF2 i!tE+@ZkfKVegPY`cc^l zW5;(dEYN2rxO;aXT{QGks3Y}{#QFrLLiI|V8#f}PlnYc-IS)~)6U%A7VFsr@1lmS_ z@l$MO6B#4b6X~-Um0D9EhZX`lY^L53s1b+ak`(r)DknxDI=|&SN!Ej3(8W19$XZ=W z 05wI1nGUuVG~C1dKxch@q%fY=+s}_dqe?Pq z_`MMe52BG7J{~9i8v63nYDgOp$B1qJ7RS60M#1lMd|JrYFs~5~QH+mY&WEhfTJ7z@ zJ95MS#%QS 8!|kHk>t
_`kixJ_|7`(pn=-R7kIY~)L zaq$3k2NPa^L_N355JeQc#6Fi`z~uz1c**Y42!s69;Di zNiPk$N>w2b0&X6|++vUp+pLwK8S;Kya~)Qy=T{XM6q}S(R7eRFHx>uL!-3KT?DY fCD+fU5yXQSrR>x&>lQopr%lz)D6_PquKX24_{c_ zad$_dDJ_lcZyQQ1HV-%)9jj!LdG~4oN9xck?gE5sS%@-PnOp ^62b%gH!qZw5>1y&B2l`mhukh-7C&AkI5&mFm+43rnfL;=~! zZnYpDK*rAw>JK!eUh6$ GH7wnWb1`Z&qYNGpG7RtaW_s~uWdThim-+D|TmVdXjG}@W(=OzKBd2wlp zgv+h~bWh>i%xj}AfchLh9`U9Hx?ib7nIvvUz!Kx~o}@TEzfpD!t{*X!xvUMnI4qq> z6Ar9^Z65IQcmXAp1a=Jw`kseZn0@&r?U?~x+1lC)w2cznMC_I+hT^*hpMm^F;`S*B zPoU2%#{+kS1hAZb`t%9F@ ?;Mjpwf~NHgb@ $7i?hb=UjIWJu>JN^*x+R i;hc3r##&rplp`<^73hI-^uPgXyxU@ z0q3R)E;(*i-{V6ZC^+W0IV*fb6ZZz^zuC2X{CXMauO9?Dkv$YS_f=(n@AIFEn8&f< z sQ-CL>}Z$7&YR5-lo4zf<*FjPUI;6fr(cEj;#+8$O2uB@#|N=N{7sRcR%fFq2E zh`4;|l46saem;8n`P`IV-P-B|^6q#lQn?{IDQ@Cfbw{8K0!lVeXI%d#`u9!mqGs+* za@|KF^tjJlb@)x(G9_FyrxKJY3(p1SYshMVK7%77QP1VlbD1AJKu&}Chn&XhdN9E2 z0shyI?+yoO^25Yq;o>zMg_0l&^dB>bEf+vl-S=C6sGKkDQ1Kxc$z^q2_`t`p{`fcm zSfIcl6R7~I&5-j*0JALWKj_)ms0s=7t@J-$&;=NdJP*_+#}g*$i?i_-Geczt4J9Rn z0}*jf@yj@(p_I2CPk>)|k}}hv*NB=q*-bAvow9bFn oAE ztuD+8j%`@)<4y#;luaQG-ixNrEOGB%{GyB^fQ3OVa(osGAQ=vBagBbb8I`o;IiMI6 zLy`MDt5Y@mq03O2SdQ`-eQ79ucsM66;n2oVt{?IsJH&pfU!AW^o#|<6zdelSGbmaH zGKw}QgdHD^*idH04^o#!f#0E^mRw4?>v`3)DM_cn1c-(1^Xj3Sa9ujD1oSp1SStIT z0~DuT@pW#-xwx|@G39WDDRm?xTb+duivR8c9v;ZePE^`68{L77iH~TOzWbz(1Qp%o z%lSmgeYk*+-v*CLiK1kNkkV-f1iB?=()q7Ryu0{KFe2a~)#fUYRJrIwna!~e7NI06 zqN08cD5UIgI@FtpEksf>i0-_}8cV!s83$Ch-@ju5W@Mnb8L}d(Y;sZZ(#9K+efiD% z8{?0IK1S5#h6>@QJltHy%!I)rH2ihvMOYZWBHnq6_-hwxh>EX-C#&Batj zNw?0VJKtuDJYO~kTL)Bt(^;vnej`Z7+bcC$yoa&3^W%mkv4ia@PqhW-7ngq-EQ|xL zvs%X0_Co{FgDW-)G3P@x7UH?>RKX?pU`tqkYOd8^38X{duye)Di+YZX;i}iESA`Be zhzK^jbFd^HF0p8`XCDEoT4FM!3?{NKj2=IrA-||XzXB)xvkaZr$mE6UN*TVZ @yR!WiN{4o!dP9M>|0KhbD`F% zgR!b+()k_#kGcPj%kl5S$MNi)Hz5r|OIt%pi=q-qOWM-jX_tmk_NAdAA!(?qMSGW! zloV}ES}H0H+I^3+vhMf$^ZWcB-@m^1Kljajxz6i+o#*TId_IroaU9Q+cPqy_ZYvPX zB2XJoh<#Y$GaTpO!Q)l%VD&j?3F}4ss1`O4-%65zhF^j}_*qZ}DkNs7$f|K`6}D;Q z7&glvnewF7TQktjMPdAlrjF8#!>2OlPq_K~P{(xcvbJM?)^eTHw2L$cEj|9=yw6pG zb2S{wMWQmCujhs;OTvyi$o{PNj!3pQq};wM5PLgB_(P?FiTxk{PlW2^MBlkpq~j)D z(kgszp$xyc`Y%_Ku*>f4AI%nbKLZ_jUzqD~d8kHuJoT275vEnyv9TGkZ KvyxKU#eh%_k<+G&5~%+}sW!^Ty-A8GO8^ zz;pIazI&*b*HXs;4+qEZ^|X7ZoCaokQeIdW {fXmiwb6;e)c-KbvXw&zPAj5J!e& z1Ql8wfj55)Z#mEZlNl^+Vo}ASw1$)%?`if64% ?O?#Ya4c&KVNfH)?=?(on%#RuVs-iRG(G(>$u_BDgQ|O{{Fqp z%sO`R)5sC?dT(A^H9PoR@3LQ7uG7b%%H1OG#V@GHf9ErLlT_?8z$B5d+_XC8yFasp zdy;Jp`Qy)P=9jPkiJ$`}kT%WAq5>`7YTWd*&()Q#-S 5t9@AG&{wnAHT^u_v5osIkXDBW^5|vA9es9j6+ld z+vz<+b5>`N^Zbfq>)FJ9@|KSK{^zOE^&!o3BD=k(YP~}bw5=!dT%YmeJNNi}qMt8O zlao_>s&eA?CP=m;#&4w3zjSHI#HjhBuN*tW{XPckue&6xMK2hyinY-{Q^Z_~eKf2U za`G8OIJjV@3aYcJS^ywxc&4PMtp$~oJT&8K6 Z}&YYbrXn8O#zzQ4*pKep? z+)9h1R?uQ=c+l) G^*%68NyX7@gy1v76V!OCoLsIVhd#wxSNT9w6nyNOTf_@2_ zx@JpO6c5y&P3qpCpMl*8iNjqrZB-8D&Wr~Y@9A3z9A!*U;+OiTlvm)riN?P+0#fwD z|9Ul~=fSD}*)#w7QKOB3#fFHpisjF zyt|z_R)K-5(TAIHm2~ z>wro(<$N-ualkz_TSwr9YWGcv9v?;FYfdTs-*PT)Pr(ygI<)-x<=%1#=Oia5SBK2I zRNZ^SCjg)>8eTxt?q+7ak`FmcvY6(-4$QI`{`u#zFT~IUmUR9ilQ(bPL_tw=K;75w z$lKk*NgZEG%ga@bu`{h+WQ_k}1sl=Oc0LeiWtFk&{{e@(RRPO{gF9~e56itx%*_>b zh=#1`uZUL8C$M<)^GOl7UA_IE2=OH3hZBse?!BILSyLGDi*cmKKQI7mt9`fsJP*)F zHEL;v`IQaJANz%HK3lk5(3wN$K|ogGvkPkljUdgu%@*I>N4@C2{S}V%QdU!vM4b9Z zhTBsMZszV7O5S>|Io9A+GK$%;u`!T?03^|dO@;_2YYcj{OvD(ZI0TbzZrb?q#cEM7 zOF^LJR55oSah1EB9wEcF4Q_p+_Z&>#0XR0z##8?fB4yFvlm+hTNL0#5sp+Yxl1A5Q zbJZ?>wnopZyL>=#!+G7}?+t1!E~>8XUHrb{B-^vT=vJ8-q>(w%TpSoTx<+B{QcC z6C9qQ{KPB(`@Is$lP7B*9=rq=!2anJoi88K;*N=%iq1)`;y+r|r_NoDG>|dcDRz6~ zo@1|n=)a4b*IC`n3+A|8d5R^4iza90EBnya3%dg2Z5IWsLWx@1)=#s09UjNw%hFGw zE&-n?wiDIdS~|gaFy}!VgwV5cKOhkr$PMOcL|g)987UyNfcnX$nSS&7^<>%(fG}V@ ztXZ|H=Uv1V(J!q91s2=qxlCynjg9{VqH-K958Yku Fe(1)ClFGCUkibff%PzxuV8aQkHI{RC(d)tJUMxz&Ef$ydWz2L zb2>wduIX)&C6#x;BOWdnYISV1BzvOF2E`+2vW-{2_~uq#Nrzhu5<31Z? mKY~ zU9D21ewtSnhLf-wOmkSx*^ec$O-WprGf#?|O4iv~wT-CMH`3-%`y1B8GSu30Jl|RJ z95})OuClM^PM?1GJz!UaX_%bLc3EJdDC|KnF-?$})o=;BCS4FMuHwwlWdC8vdKx#r zWs^}jgoa@mlh-_CPBM;(tHzmz<}Y4;GKt)?b{d{iN}&uvZ1ig8w&2D;T^_BW6lc zuN@h oQCI#6TTBmgm)3-E4g$aIw^C^=I*aKoSzHc8|}YZP%sO>tmp*g(`SX^ z2LcX)fK`)x?7;S!xtqKO*3j#H8kJm`Zl|ge)?V4MzF=m;JT1N;Ja`=PAXavExktg> zeGeP*&N+d9ZEv4yVDWta;kSn(bd^~mzP_Doi>~?~QJCsu=>o>M4Q^rNnpAn+MNuVc zHTLvr7W;`ezoK1NovznUW=7(i(-Pgo4g<5|zK2Svyv`qZue0*PiHoAqhX=1QEp^E} zyr@iZaPZ-*otVxn_4Pur$S4(WWxBGoM;9f-qrPw2@Zz79vWt}0`&SLB98l?aCZ(x) zLBQ1O&{9d;`XAjo+4M#g#{_*1D!#b2Bu#%x`%d&H-#pkGk|aVEb_XUdIw}Lc_6>TP zLHbqnj+Iuv2#FDIek?jbmGi7J6BtTBK)@Pm?wAR9;eGmaM*rx$sH4Gfu!|c4i)@?o zdduvjv@elTS12cLP`@0qsy_wLFyFL_MKwqgpi6;Ow{ccDNZ$~lnFHL;XtF&jFHa&1 zIGSe#neHjhC>EJPlmu?1s-^}UY~SF%JEFsH_-!pz8-`A)-#T>T`gK>BJE*u!e*fxf zCzp4h?h4mgF **^0$Pe;-`lR?D7J5XO=eK@6Rs7pr?%I)PVxqlBGN?cj)m4* zR{&_<396+QPcprKXY{3pptBYldqlR5ZGoq?-?%u1$r+)ov@a{erAAXc;g$*^)6FI^ zH5C=ycuXn&gcI$7h|}@@a6m VCvD4 m8ZD_$A9n(MDv+H(zz6G5S+rd#y z#&+K?t~T4rXSvGs=o;@(23K^&d>EyAWAgPaeO2^mBa{cwcTKlC xa7>_j%i2)KahKiP%nUYx_rDPA*Xg#XEt%ms zl#5@!bO#QpBn~~7n_KP&dHswF=HrVUpY`AJ1br|$=w^3~nyw{aveWvCs;Yq@A#9 Mbq60lu(iwtei lS6fR>J01-_S0UBRBsE=a+Sd3_ zpMp}qh30>2PN4arDgJ4t^-g?lu7uD#z+61~)XB2kxsBv?ulaVE{g^&^aEm0PB=Sqt zBM!Pu#U+ikY4mT@Zs=XZA|ltk;e3~2aF-ExrELD#tUx+l|5VMc`Jcxt$(UO*4pij$ z8?A@DTKlxm+8)-+)8*p(^8p-x3uwg&H@Ne~(h*b|l5fUW!@od8I4pyr=~~DduYVT4 zteXQlbbp5%s&rN(?tdizT23m3;UzjR-Yk>6I{%2a&S$;+KYuwzCi38&^SN@<&AA^= zwAQVFN?b+Ceps}8z4Hcs>Xkc#6$$~2qgQv=Jn85X$Ik6|-uN<|-`91d8U#O`AZ0$> zYtvSUd?bXLE?y@uJ3ju6R^tJyJv}t994~3JWk3J$;RE<(VWKYYn~GXU@#a@>-ISb* zyZ?OrD}|30!icS6W9r)nV&*!hZJ_+d(M`8r-_eSxC#2YsQJYODIYlTraS5?DA6I|E zk|*2)X4X&KZi(LFyOR0_1_sa{ tvB_*Gs3e}eQ1Trc#=uX)2Bj3SNCzlpRs#){1m1yb~)<;f#y1}#D zs?PRJ(51CsPFSYK$6J8 c6N?JMpxHYC +yS;C`(c*#6yFEqU-j07rTb`RGN@88WWrEaM6YCSLsBjZ4i?Ag!uUC z8@<~ixhujXBv7hRCez=GkB^_4a%(QMrC=d;@bk?t;P9)NHD&5S5rkbxJch!`OsGp$ zgO+aHwk@I0VM}jqLL+*Bk%UnLWEFkO;dDceZ_)T3al{%%CMP-zD`Oh=+N~r7HKx&} z80wd`IU&KdhMG$CZv8r?U}mM>ODSjDi;?g2EDu_;=hrSPS3hkcYTI#@y>VFz2>!3o zt{F!+xo luE&dRqs!!;zd(y=_M}nG;!J8wZ!ZHP *@K8j=8wFV6~1MIns7LI-}SFrWELF+u_}Y zD7=Z!L|EW|<78+3mvqg6J6|17W)R|Z$gy O7uCG6^$qIdKK0~)Sk>;x9YXcw zr_B_{;>|CxND;Cdll0^F_Pxun)_u(mc|`AQl?kVPS%n8kz-= zkCB&0w;9*Lj 5cp~o# !DH+5? zSy+r93n7Pe?%=9Rh>Z;qJLj0(3Udh@z%jIq>k40FZ!zKXl6LlcUNuFbb>okd>yKk_ zE^HBpj<7CK%(MR58D|!|0&3XV<+cna*Y|(z?}g)RKH@mpF2t9WJO498>|~-k(cdRI z$>+1`;9R6(9n_e^Rjlp|i?QCDiz!rhh=cq*UAJ4sD&x6Wwv>fn8MPG)x7rmEhh&%N zg;fMBoq6`{k9#(Azg6Kh5r`xnFPb|e!+jMFbe}uEZ~hW{{yLO*hMnKZaDF~~5tsV? zlku+#eb*NfVT-qW)v-TM_!E1mo Q zMP;qRndWc4tou5^-Re@98-HQndWyHdztWr7&vh5D_P(7<<74ApXA$;=d`>lfsuenO zMNsF=NR89q_w5xn-CjiWnEMT&RTN#GF*~bW zZD||Ink4@^B6J7uL~qXjeB^mgYasdIR&ub*ft7O)Q}jX|yo&IT56c_YtWcOv9_;ed zojOC7D6#AnAe-i!z98+G3%!H8$`Ix=>4^wbwUpDdyRA`pwsH1YyYISd&r3+$G7Dkq zSFAJ;UNlPWBR^QDe3p^8{W6ZLaL@T2G<}DcT3iH|+iK~5yi~jItU9Hv?qGZPqj%Nj zu4O9$BmG~Z?u)Q0irlMzz0w3c37Clpj`*K8|Gy&buN2`|&|XOz-1Yzes~`DPsvT}3 zjJulltuavH6SPZs I5P$*EoyRjQq#OV;ZXj>b#Tf9st*- z%(G5SXRl;=lR$CUTOve=k&nyE?`7UqCMObIObSR!G?iVK=;z4Jw2&3e-Lm=lM#DB~ z0Sl8&khsXn%AV*%mP$x-% 2=MfonP5 z4+sndg@IjA(D8F+_>d!xqGXVnCIEV=Tq-R6EBv Z;%ZDf_oP_CS@ib}dP1tDr?a0KcdU+N=N>+VXz1XsWCCOf^4z zYCAJE4uvZWSpuzK`VK})lGQm?eKuob 6w7EJ`R1!gXn~ zOgS9&D(ZcjPp7s`t`a>&yxPLp9`WIr;t|aYBM`)}?0mpuz3V&R2korN)?f=x4S5RW zFgoJOL<}d7G}v#Xp~>=`^;o#_``54$P*GpL! #NC!@wOzM@9nKKUf1I(-vxK-J0s|zV}gOke;cI zL*OmQLcfic)KHv!n{wO!&pfT0$_^RCA5&0hO*OsEel#5GubVNPa>K6po{{iYt~-8o zjqtO -P1>jaFwPCE5Pe4aTLg!W0)Ol)DO#dJp-5u{*Z*pcG-CV6r&7~1pI$v%7 zitX3P_jvWCkx+soMvjXk%I!Ng$B176-i$K{W*Eo;eDuU#6mkB$Pibn#sR^k53gnZ9 z7N%wv!Bw0qB9`&nwx66B>A4*otcL%bJQ;NV{x;{`i(54=7x#UB)%Vw?> ?r=eKz) yJ$?WtW>~&H6-Y)5nH34i^i_6ujdOwkAT_`Dh}4p6XRAaQ$dj;4&4P z*8D2bQuvT<`{m<|Yea7D5F+X;d6bPAyV=-W`Vul~MFW1+szr7I3}@&UIW@$yrqx8m z!t#b@>(y;?R$g?20upV9-)Jq|saMXvsr<>1*1&%HarYSslFgDUFitXGcsCJU`;`Wk zMg5UAoM%xPxVE~`n@Hy8mUX4m$BT;<;3fA*;Ig6S-aWV!{OlWler%_yGvR~x`{D%2 zgQ9-HKE+~TK2!Q!g-k)AiSljD`XkS&K pl5be_70F_f-LBZ$7jk33I1$mx3nBJw@eBk-dFUx3}S$w^DS*MTZR6AA+ zlGOZfBx}*}j@w-?>q>S`lD6{h5)!J@n%sP4bLay*6D=@T)zw4Tod#Omp{i9HgBw<& znOC2o)1$>U{0p_RUD;QjhxOVgTw&FL!4MGFPJ!jffo2;|zBKl3${P=*Fzi^s^c^J| zhWR9NHcJ)l6o8&r7+zsKmJP|B#I|;zYWgP!Pa^c^DWPfQx#(s8&K_{G{QWm78#*|Q zqC9Sd{Tf)Nh#acK)C@o+DaIApHh|uN$bT+I)hsV3*9&(%P}w+BTEW4bHuM0RUm57g zA;)yvD+JOKzhmsok*cbydGIsxw{CB5hfxZAkK}9KTge8A#cQOo3k$0Y{;1dY>8YuU zSHB$;#By%GVd fd4Mg?i^;VFknRUo5 z5c?7{?=JPA4E_*9d(C15B-~TE&QGh$*x}7_^6TEJ>y8Z9JGtxE7586Vww=DLeD9*a z7T~2jf14yQAUaX!Cp~@1!ggIZ(agB`iol>19>lXV?=Unr4uc_aVj?#WPZE^uWRI>l zAt;@vtF1dq{4Rul8?KNDu2)u9XImF(Gc)C)YMt@vzEcYvhIx+aA>K$`UaJ@gJuNJj zUSQnR1NZOhuVu+|i;xP>&WjDGZX!AICP3U}-iBbojhgqnMqON`NrvLIe8f|t57yIx zK~c#f8`Uvx!y$COwm#Kc(}=_I^&a#-Hg4WLTEggqN>LOBd>cDd&XuP=YQAzNYYpY4 zr=n*rtaxQ>M;sdmx+aYZ?=xA8LgI^%oDH+DkqB3K`Q4Uf^hOkR=x VEC;FSxZI5fM(6+DrqjMh $b_41}Kw-v-` z1T9WsoRe!~wuAX=?Xw;rnUa-;E_>{HH|Au{WJ46y=#eeGT#VUTHGzDv2f?#B)0*#& zRRm(VYqm6-Y>PiWzp{P+FOb)P=DDXrFX17|!NGyIb1_+GnsBf&q`CGbEm2Le(kdb- zT=CYOR5imM`IcV6Vjf$P^=NPLGxO-pU&S|-Y1?eQ*|}kj=)R!PC79y0gs*jW5x1I> z(yng@0+p4OZ``<%q~oD_fUk?ht)2b3`y0enmday9ivt{Prh?cECEvF-b>@y7fCnT1 zyG!19Q3g<#T>2+!U(Z)SbH$+H(h#f!;Ajw&oa%}5S;Yky>V;N;+8jlFVJNkL@RB)~ zP4`6?3r1&TTTs(3tmQv%PA?WR`|B5m8;<*qAY@GBv`+V P-ut;aT$R6mD !_%K6WgkQ(DBK zmx(t%J-xPGiIad0q<2R?oSkKk{$lJFS9W2%JX7WA!~!S=m22rIwm=nFChqUCn`851jO0a{=n-70c@y}YUZ z(hD+9Mga2-wa~|p^uk0EM!KeTiOqn*mdv`6JEem;)pt$H+6$zQj0^2YUT;tU91o%U zUA1PLrZy#uz}$ Ju~SPy*YK;ma&%+SB|St&=S@1 z91!x6Ta;;C@CghZDN3+*=)PsG(0Ffu?bu7kzoNQVPKnrl9-V%-&5rbJvs;+D9?Ucc z7pPzmVkL$KE-I94&^%Y$YJcVU%|87rRujceKGU9YTnuNC4Xo4$p<++fwQr**ol4E? z^6c)--eJf7+zQ5Cp(+z^;*DHOWHRGs1kR4csBzF&Kr+s)`-0Gij_S#pUH|ht;yWvN z8ST06CGN|5wC7IJ7P!v+l}W5wEecB)0#sk9n2WSC9~S;A;rNe_Im^;MfLYBvmOZyN z$kiw){>WX3Kc45BgM}yxw;+!yl6wE|ln7RER8~`mNLR1!gI{XacaCIP+B@cSw}+h* zp98W)AO_T&oRU&rMyqnkN6UOd;n~5#oCX7#mK#=XU5hiVfX>^M`A8iga ss`J}Eg&BOHcba3AhB?Y(=gc5 M-~3 zAubK;`1@x_H{D=*3hijuhotIBHUZ}DW`XU#(qcn8)cfof3DDqXvpQexd}wp<0_&*< zF|a=Tp#YlT^mpX4LC4OV^4Q$H)&~CNS2AtqAa<22HA$CnJ5tz?Fv^g!vy|HNb;iL* zi_#W$OOB4;VI}dVZ0eqbH%r%((C8)aon^$=o_ecAA%6)i2CMP2D|c(1Xj>J;+M5I) z$^o}-kqOL8nEp!GJ*^(HMosuTVM$XlrqGT_OeE$6VY7fZMATF5a&5f?N*^`kSo!dv z*~`BG0W&T|9UYG gG^x9D6*by9-` zk?IIKT77V5D;WE90~y*)q^57)G^H5(m>CJ5ju-$_vup~-csR#b@nyoB{P!4AGx;Bh z@=7I>*~=K&&Y>Ch&%W(t+ZV5Y7@v 4y6-x; zeY|ip*ZSn `l5?+;xc%o!tPt#- zhmhWu-cL27-})Y2#KQP{g=y(q^s(*NhkMW9FCcvg78&{pR %Q%Sw{%$okvZ8Ceu9w-su47kenX%w0p{h*VX-Dq uj(XxYK7@8?j9d<*sqn(8iNp2nhzu+}ZbvYk3-7DpZnUg+K49PQ@dTZO zpZWfw;`v3}x3+j_J`MeA(J0n+ook(Jfe*=UJXB}BBCl1^QMMedj}EU ? zuv(K*`6e4X`}-SAy`MASF8ie>F4*cj?ngHKucV8&D^9h*pw|sna%4_D7I@?aa;=Dm z_FL)G74|aLv@ PQT2+0C5p*6y{~t^ zGG-T{H*06Lm6vJBeAIa`y>Z! S}&Uoi}tQ1bL7vaMGdqy^F&; tYlbnqvsbXh@Cs z_EpvoW9!>5DNC47 t$wED8A4Y;HetS^T`T{)JS#^>v#Om6x<&>D8<&hGHTpE@CO zRE-+;8_^cS%e<+5QNVY?9-ZB~{>je4&|+61GtL#nO FSm3uAhOS5xPqU(u)$XUbOPvF!GCGeQsHu_itXuP$7~NhofaRM4Fe;3{+Qq z_L2^0WNav|VqyR`D6UJzm@Xd(i!x!GgsLOjj8mlgIXtL*UX*2LXM-jB<%>o04)i4} z!qjw26Lbs22c4F2*iRpayw27YL;i@~H+bP0d5>faHl>_!CfX(XG)T=mcFp)t} zSa^J%Z$Tng3zcT?IB57j@(7rRczgX hCE44fq^ =XrP8S`Do eguvlon2 zDO1uLai1?P1}|W^V#$tF*mxmRsqQlRKjp1QJXyaehJWxLy1zm&wcy;34pt7i{IN?? za~ ZLMRzw?;ZI_A`z!T#CFqU@`h86M_E11Z}% zWZ{|5oygp^&+Tdea>0q`@v!%G4Y%<=IdFZJMj6wMti%ZytapKrSLV^Gci1R6?eo zHJg^$>6?%@b7b`l&-SoA3Pu$2-seO?DuJKzpyEuJrxt@ !R*C;UePfPFPx0jNyze4_x+3l0iEqZ!!-oz5bgR}{GxqbD6X`4g z*RA&Gk{iS3xpw2m(IZDf;G>6rw1w5XvH5 fPw6HqAAjI8cAsinG z7J?Eq($z2(#)uwDyBpGu^SR`YrB8Oe`ak@;IH`#GR8wW_P gok&5 zzi}{Ff 0JXk#%KYSZh7n_4&j12V_~rL%+(U;M^8YcW`h3y#TWe)J9iY|N6Z@tC)*n zSsP}IY2gpV?9KYX`4gy7 pDgGv_!^O_7)H&Z! zI-244hV3Y3t5K=yXK9-fM&+uYuh@Wh%FdX(Ok&YTNrIGrKJJj)sJuRm@PLyzxI;x> z!%(te4tGlK#K?Em@#!C}8EZ*0U_6fo-T#dwoiT3f{eaWv@_L3Ake}iA-mC{2FpT9% z<%`WPHkq6z8PWULGczh0HaNM&HLk^MOU>4apj!<=je$nC2UHriK3 f^w9-@{u(`>^$gd6kA$2;Ew1K88oDM>BKnuoG zyhz@$xUoa`gzW$eDT6r)#-NhYBX;9Acl-b#_csZ@wgtFawIK!yUOaX@d_zM+%$v>@ ze{!41s|VQYl5~?iucTlr`M)wVH?PrTW@9r2840~vkEw639Ig;Xh(HzaR>8pdv>MeL z=_TejZ?>xw#Ls9&*^jST!&EF)XalA#G4TVhh}+4=nsSv8Sk5n=U#{ZHQ(9V_it>En z6$}{88(LdyjadZb3!JdZRzfZdeF;%vFrL8MUEnbdhjPMB0VNSEy?d94#FELS01#zm zeYc}k`tUB7dh#JNCUR^>>Hm;X$V!qQz{$}+b4J={yXCJRictTHZ8FLe(JKHWlj{iR z!yXr8&|q< 44)dhfG0 z%mR;G*jrsd^!t)wHCZsD<5r`4n$PUws;kA%9oGFm0I1$*NiyE$dQD1_Y2{9_z&?9! z7rfNtTm4e1e@IvQXq&u$;}DfG`D6LKRx!r}ToP_%myawE75{3x=<|0K^XT|VjVv%C zf1lki>x7b!teOqgP29;z_dG}5w0fhRlY&Q)sKm!@#OC=Yy>`Dx*2mmUg=rsVORCtp zt-ekddNv3DFiP_DC!nTf^K3@M!zZ2eYwiax&Sdf5T9=mTFj>eZB2zx%nKou{_;pT~ z^dJj?fUMMf`}9PRID9k E; zQd<|A^A7_7jfGD)yQOU{29t++CV%A|XtP?9v9f+1+IiBFv}OEV4=AIVH-;6Q3Yigt zl58F%cu7Bey-z_plm3r$)_d53Szxhzu?t@jn%=(_jN_g$NB9O4zPGnGfCTb8sD2dH zTtzx?`|N|8M0>i)`%2{8b5+~d`gkMl1(xSN$LG@mB1WF4lOY179uYQ$ZV|Dwh=` D#Tj zL`)3~3=A<((zdj;1fl_EfT>Q~vS;*OEV5R``X=;B`qmTK5+Y(Hef>MPK6Bf@?jpne z2Oz2B?3=Y;p>+}X*6QvC*XHnV|B9+f$o$cCN>f~NZE~5*KeQrQG$EI(141cvd|!QC zzPJ43rta4(gTaIRiHZ@6N|3^_H8*bDsFIbPO+*}wBEiTlG4x}qVF9i|i@EUYX$52x zVg}wu?XXrA-oM`!pd;E-gkxt03}?Yt{u}y;R?9HoaTLsj$S}eTM1R#1B=%;0&Ygj3 zXrpaoVBl$YL0C{VR99~R3=J1 sfy=~**&=a}YG(IdUhkD7Ht|Kn}Udsex7X9q?Ph3wJ0NDhOg4USOeP4YlG zhB{tnKkXFKfH9-@d?$%uX{uVMq@+X*qrd`tA7Lr FAgpcT_%EJ?ffMT=5~ o}R*ymk$S zV}YBHfLucvMV=tw7VWfOaLc~I{8s9JXu-TxQO|3hYnEkSy>+X0bid#!L0`o@q9Hb$ z;0Z$%@>-_*sV46v1Ci- 8TKnPni8Ay`)C^u3NI$`0&eagXMWobSr?8#aEnjG zX #K?$MOhP0$3<_B8%Kp 7cCidA zeOL4Bz3bPC7BAoU9h9}sAa__9Lma6RsPR{Vr3RGh(u{w3VzF&O090$zx6a#<26`9a zJhT3gdL%IF^wee 4KTQ0vuZj zK^ohiyH2Lkzec);8PzaQtcEcY>@KBMOS31mK0ML8)G0)o-wNQ~1{Ujy{D|Eu!J>a9 zi1kRGW@@9k7uD|@om1irTl|X~1Urx0hax_F&|v$4MmVsU#Kc5c7>bBA4n;SO)Y_YG z-%59L-66c;uGe`^C@H;1Tb^4te+tsIK2>5e1q$jicJPOu#I0&dLZ$~h^t$d@vi$U7 zgVQ9xZ#(9Cdjuu;m2R4%2(wHyUJ&H+L+X}lLdu3!`5X{K1%4|NC!;5N++!qyAvVL+ zq20IlYn3gN#MH<2$gtVG;W_^%OhOkoj_D0(Bl_p%0JY%^GZpZt4H7dCx+L)ZVHp-+ z#B`jOCgY5Ye|65`oIL4$ycMgF%RhNnAO18m^HhHdnwj0ht$qrjf(Z$&m};haX`WG3 z;+_?7^ypE-0*sov4ru?yi;LSC^@?}s1?zF@UwV2_UcMaX;;yOv_MZn~a24xnh@*|~ z$!~)4@0@Uifp%T|swSRmD^RZ`>*7p;t;LggUcT*1X^8Ir?P+2(pC^s#05O5){rmTC zCzowkz`KBl-wYsln(m3`*mH)Cgc)zmyzH~Gqu*)v`J*{p+C4@ Yc418+Ix}c){^!H zs-owpvrk)3r%mpsCg;+ECTDi>!Q0mcXV;ywv&=MqaIU%O4`d Jst?4QBhH37~z#JTC!X#kDl~) Z2y7dZ1u}eEQMf~CYGrjndW(VEYW{=$X+KXZ zqL+ijSZ!a$NyH12o{93<_S*EVoPmuKv%|%=81n+RE(*5$nQkp)yhvc!k9tl_drr!? z4kVEB MSo* zUbrh=lbg` #kvKA`0n~*pDWDy`rV65(}!GnUHza zj%p{^9>{?wVq1|9+cTxyF#8`kC^MV;=uQz4O=$>7gM)+X2wVHMfAz)6t(Y#*rO}6` zGR$*}4Ogg=5}mdOp3OlZsCfNa7;0(zUE_j4iGEx%D*AWP6esncDHvF6hgTy=^fqOs zkl_+wuBR8yPB3>`Doq-W{LZQ3GQ=n6)j(`)+(Z-0Fcn0n#7#^y^ZlxyKaU43G0Rj} z8N((k4UN0~FfJxxtcH@I0K tK4a3?5L`rMH6m_1^= zZEiPUl2Cm%>Wa&h+p 20FKbUIT7tVUpP#{1UjIFu)Rbbm~bQnSs=n;?&@)wXv9%C^}T%ga`f}N zh=&h%;D^?%a8#O8zJ@?$Bt{IW+N+staIIR_eq`B(3Up8|ucg`eu?{n>f^}Sv)Nlkb zK5a5-t9M(siPq2yJjmnULxt_4J&tWU&pJ0 &)H|lv7;V*($cDfpaM; z`ptNHQOLLbYKhDg 1a_gS9-p&K eUmNSMmyO181SL63U>URc}ad?%QRp37yQN+4cwe z5}td}@$j&B)mWKmetyZHF_unLU~zd!M{%8Xwsv&Q#GUY@jQp~Zml6LFNP&brv9}7S z%ieOS^=id?UD5sj4vMN7=>+7Ht9J0yp4oyd^KJhwrxH6ur5_&L<~ft*z?ENez3-9L zq;~6y8`(`MX+M^{qAn;FBIyv=$j^IR-94#-OP^Oc!wG`1=Im?hRGRd2L$`~KY3I=x z0!Ug(I#4xc^13fcra3*a^YnDhqpW4Qb0Sv)95GqkDYD)|mey**Y{N%redi$)6AN(7 z?`bKbQSx!lKIRvW@(X?gc5?pc;D4khf1x$M(+4?|rFU=s_tF{sM`cN1JME%0A8r5O zASc=6D-h7p GfYYcUFS_&UE*(k4$sQi)6&fA&`xLehS}4b+&85F6o?7P-XLibb4KeJ z_S?(e%4KilA|` sa{|Al}i>l~yz~dcX3C3Q-2^W`fHFt{4<$tc1NqyyR%w7xd^?g|S zzrxr^LgV*-ALx$+CFk(A9Z?VMj@#Rh;7sM? UilmA0!2A1QHvpiV<&DIIO zdn_d8q+fA2Z*;zo!^+G|%-ABc*vPmox>S8n#sTGX9OJ(u??y67`x>Z}uCVMSfAL+r zZA*i<^x^%%+RB~iE5Gg<*(Jb>eM$5NKTTC_vsnc)J3zv|wExuXbUa#U(g@WmmUE{c z(L?7HZU8eQRSGqYXr}b!{vstu*L Xq0dB z@gk*~qsSTh$ddyxHyhy_>H+2~)Bc`ALzW&M`Ta6}+LZ-+%}UR$+eqs z-7+W46-}|&5uv0oapc(bIl^#rEk7UMc9<5xxlb!2wQ)oHj 6&vg1XJ<0?lE=dj*g+}Z#%(*^jr_+kpkr }Sa! Y4Ca_$&RbMH8g=j>TN}k9Wb!#DZefK{bHY$el z#k1IGI)TWO$aFWr8lpLscjKN^J8)VC*UvjugM6F9rB>vvlz;Ox@A?TAe{>6TO$dM2 zy?!TwuXPescpCm_z=62U$jC#gu jApnE4{#5%|(!?FJ=Bf(TUb2CXPE%by zwv|@hY8npWpa%vP!Q*z+`jJNeRa0M$ya>Kpo}Xf18O<7VP!C*sqJmY%udzPx9U*+J z(P;!k7>~?FV*Is2ueJdVtzlBsH;LI{iKB8Vo_AFVhC8L__!biB*O3|bY(YTu9`Kmk z3F~{G?bnUii`88exJr4LMW}~$|w+s z)9rhdUSGi31{vJM?6OZg{YRK;XF7R2d3j7s{I`Qzjb@sq4#kd@^IesT>q(wGEwgVw zhoJD(&L2LXbzhU2nHjoh@(@x@*ht%q+FCpJXLZBY+d9$G1Q>K{h3AZ&9oPA``4omM zB*1-7#9Fmqs&8X*ZF=S?sXlzW+|5VmG2=nFPl2fKG&OeCZViPAF8WJAlVr1!xHQjE zU31}6Gwxz%Pw8FR&?0y9e8$fpdIk0UIikMbuus#RJ&v+MI~j!J4<$R3M{YFL>(x)B z3!~mvTy|XAned1B*|+w-?v1>{_IcTS@8}oxKv)4rmQ;BI9z(BLso&nuU~($$9m~ {evhx^?)15x|K7nUz?$D*jb(GGhEvvtpGhT`Jq0_h{ zaIa~l!1jeh`6rv!4(TkRcnZ2uO^>-`&)rx2m>PUpbUXrU 29+fD*9B&zoF z@E2+JKWmpaI%~T0eDvHzrZJ^o^0qtF6bJa{y(|7yCH;n2e=Bp*hoa~Ie@h U4 zt;+(LS#e*vmIEFC>B93!#-W?REap!b9EV;^m*aVJud1aMmy7tFmqz$Wwi85EhUw2T zYFt+I_y$Z7o#!?enRbyI?+`F&OpI*57}8(Xtf!A26*W=XkZkUrFF)bD+~>4_l1VO- z{<~e8uguqxHt6yO9oE)v7J~RnsKxnt?!`dh%(I~5^4HP!CdCRJwLR#kn4m@T#q&n? zH!fPI-n)X$PpsTzjxCmmH~-+ZUkrU >fgW9sxBBxZt;$rt^d>z=hCpXbpKCD@ z3@7oLvb^5q5}O?SIn|RpP<{stfz@5kW%b6vv$S~He^~u(ulfBo>n?`5ou~G$dZU`b zYpV&?Ns_D;Cp$Z8j_KjBSqrNbnbP~@3ypR!71HEByDj`18tHCdp1#6pgU;g`%}Q|- zSCb^$MFw)IKF-=ouO`69n|*@u7(S|;ex`+4hVKb{DEfwe 2OplnSHgXb$BSD1C4|RPd`&f#-Ozr=pJ;M&_Q9b_TOLDl*a@0J-k$ zs4huU3vvr^wh7wEEEKkVR$rG=>WF^==!jyl2^MrjSzO@}L(ZezqjYufF?H41HCkey zdfVfBT8@crrCZwnuv0O4^2tSslN)sJGXdobc(7s}Z6rI1F{8 >?VgQCBbA_>C{a0oUi{}kFVE@N{i(MyhL~NRS94IZs2+VT^bVP=4H>%2Lo<*gfmc)32uSScCBg`+ zH^GQ3^qs}DqYn8sO7)I>Pe|7Mg_ul_S_MQQ41_Jkrc^rOKE$u^ @q)zusq7F=Y4CW_;T+3TxzFsaNHNxb6{L*>tch!r+JAGSB#3YiAAhup5Z% zEU?&5vp;{T5e<#a9(;Qm+-nXbe;V-kkpsozspX~`YG}pMh`VL76LU1g fkFZlq?MQgJ^-1r_qqo8q%#*}MW|U4>@!M_l7Bz3}lE zVa&UJXxR}%+pA3BJ)7l)CWu!PBKN3445&Tg0zV!lnCk{JPGw-O))CvSn&a5S9?ikw zS8)DF08k+-Wh?2m6D%Er<*%>vRRcuZ+IUp&*~Mk#X^4d)1tSl;y*w4$OS a|!8O=DHIif|znKyeXO^A3K`owNtkZGwdG~W84Q;~0P z?M2a(;+{(!{0Yz&J^!5cTOuk^PZi3VeFmYNA_sf}$>`u}5UAmgHt|Yg22P$z&2I#9 zAxT5+Iy+i06U@0Ewh$G)mE(&~5;5ulz~j40!+8zaw_t19?Z2unLG#D$uqmb@g&LWy zlHfnx&7DRjCIW;i@64r4zZai}Tg`OMO$bSC4(x(JW;<$hVy|tV1So7ck?OMLPrIMC zM)d&p-RJ7qD$v%y;U($e`LQYQQOAmQ9v$(KN-3oVw61CV4bQcYab5CdE_*h4kq&SY zd8!ZrU=#`0@QW9RYFg}@7OM$uGnTJgvE4;^Ntm8 DIAgp^nFXn2>8k`r?6C!#=cdqOb+-y{O5-apO7C9vy0>wEl^y>r048jvU%H z1!$b*)wAwdM&4dEdgj8iEuF>&ZCl(050?0Mwz)rBr&@H=trEsnI7$NAB0q%Q(roLE z#sNH0$Y^cW#=o{=X!p2 0yc}9H z>1%If)CJECkIBZ?M4i0-K(c2AS+sV2T0WD(4E{*+1f-|dI;R=EX3I#f3Mv%bn~w7b zSFWsB^>|hNTJJWaGUnWkv~*0o6ZsRLb~9zv)kU^QyqYSv_OSbZDEsQDD!1 T(h|~0iXtT 8{^}T zJMIupJkQ?G+H=h{*IY2j9-TKsn=hD$_JD6xy#D!2y63f$c+J4bphvmD<{GYkV{oc_ z{=dJo2mz9UmB&NAhBOLpQD#ogxKqChs2h?2FM*M!neBt{%B7xM&piG8JM`b5eV4}k zEIEO4#136~ipD@^(|T*tUXnA((ttGi1X|7e+b`7s&e_7j_+f-FBMkT}w0 fT$1vYl>}eBuJ4Tfdjo@Vh4lO{rk4GWQ~$mc1W4@A zYB#>|*o5hn>g~cv3fKKxtLPIcC@2UjA@N)%kNs#n`N#PnZNY$A`||$YO^*a6+v}u) zuidt~zs9h|jkNwcoC%Q=f)l7?iL{dRX%VD_)4Lb1I7U;riX_u0+kU-3^T+)>n- IZXsidf{e~9!>ndiRsAiuWT*sL<+>zGHp 9)X!m7H7rrqh!#=di>x43eT&2*BE z3ONOqlHUmlZ8fHD?$1|&NbAd_-F$Dx4fWpGXVS9eZu^_7b8`xP-ESTw0Zw7bKj>FA zSBdYtz>?>z_vx^EEZ+O-)q=yr^XK~wqb?UA2$avZENGoR|87cJ_e!p*__|)g=a1d` zx?{IJ_H{>JXvT-KdJz-6Embawlx!q^Nx7nZNq{l^VbCdq?YbhTiqS^F0D8);v6)@> zu@>`hu64IZZhtGOwcQdF!zFEY>~))J56ROM_V*=gGwYmHe)u33h8H!~*UR3#`GJ3Y zaerr_2IKfBi&=km)hF#cuZju98nvvj!$>b#e*099j}(aG4F3{vCM UjhKc3@2svEOLom4Eh zF}us4PtUKU_p#3F#O5Q`Z#}d+aUYtrB5cH8eWKzlpcp*?y)O<94w;n%cI(GeWj0D3 zXps-5d-^d-rOqP@2trF|E{*v2HE8+|r>}k=PoWUtUW1W6w>%xFMR%0lw-;rCJucbI zH~LI|kz^@;Zavr;e?#xpX_EsMO(Cac&%+8w&9 zvzEs`(Vh(*d?YI_ey!1lnM1@h*E6U0?b`@KuG){AYg73FHzYGcU;8vty)AQIAYxb9 zwKku@Vy8Mc4O=vWeSa>eal1KbK;CTHm^}%!