From f152f133d483046ad6e77044e3b1e96a882ea2f9 Mon Sep 17 00:00:00 2001 From: Paolo Salvatori Date: Tue, 17 Mar 2026 16:21:56 +0100 Subject: [PATCH 1/2] Add Azure Functions App + Service Bus Sample --- .../python/README.md | 2 +- .../function-app-service-bus/dotnet/README.md | 123 ++ .../dotnet/bicep/README.md | 317 +++++ .../dotnet/bicep/deploy.sh | 173 +++ .../dotnet/bicep/main.bicep | 575 ++++++++ .../dotnet/bicep/main.bicepparam | 6 + .../bicep/modules/app-service-plan.bicep | 154 +++ .../bicep/modules/application-insights.bicep | 78 ++ .../dotnet/bicep/modules/function-app.bicep | 219 +++ .../dotnet/bicep/modules/log-analytics.bicep | 45 + .../bicep/modules/managed-identity.bicep | 142 ++ .../bicep/modules/private-dns-zone.bicep | 41 + .../bicep/modules/private-endpoint.bicep | 69 + .../dotnet/bicep/modules/service-bus.bicep | 108 ++ .../bicep/modules/storage-account.bicep | 265 ++++ .../bicep/modules/virtual-network.bicep | 239 ++++ .../dotnet/images/architecture.png | Bin 0 -> 99495 bytes .../dotnet/scripts/README.md | 285 ++++ .../dotnet/scripts/call-http-trigger.sh | 168 +++ .../dotnet/scripts/deploy.sh | 1207 +++++++++++++++++ .../dotnet/scripts/validate.sh | 166 +++ .../dotnet/src/GreetingFunctions.cs | 502 +++++++ .../dotnet/src/Program.cs | 7 + .../dotnet/src/host.json | 39 + .../dotnet/src/local.settings.json | 12 + .../dotnet/src/sample.csproj | 31 + .../dotnet/terraform/README.md | 321 +++++ .../dotnet/terraform/deploy.sh | 106 ++ .../dotnet/terraform/main.tf | 340 +++++ .../modules/app_service_plan/main.tf | 25 + .../modules/app_service_plan/outputs.tf | 19 + .../modules/app_service_plan/variables.tf | 42 + .../modules/application_insights/main.tf | 18 + .../modules/application_insights/outputs.tf | 24 + .../modules/application_insights/variables.tf | 56 + .../terraform/modules/function_app/main.tf | 67 + .../terraform/modules/function_app/outputs.tf | 24 + .../modules/function_app/variables.tf | 148 ++ .../terraform/modules/log_analytics/main.tf | 14 + .../terraform/modules/log_analytics/output.tf | 30 + .../modules/log_analytics/variables.tf | 37 + .../modules/managed_identity/main.tf | 55 + .../modules/managed_identity/output.tf | 25 + .../modules/managed_identity/variables.tf | 35 + .../terraform/modules/nat_gateway/main.tf | 42 + .../terraform/modules/nat_gateway/output.tf | 14 + .../modules/nat_gateway/variables.tf | 43 + .../modules/network_security_group/main.tf | 53 + .../modules/network_security_group/outputs.tf | 9 + .../network_security_group/variables.tf | 51 + .../modules/private_dns_zone/main.tf | 26 + .../modules/private_dns_zone/outputs.tf | 9 + .../modules/private_dns_zone/variables.tf | 20 + .../modules/private_endpoint/main.tf | 26 + .../modules/private_endpoint/outputs.tf | 19 + .../modules/private_endpoint/variables.tf | 61 + .../terraform/modules/service_bus/main.tf | 77 ++ .../terraform/modules/service_bus/outputs.tf | 17 + .../modules/service_bus/variables.tf | 173 +++ .../terraform/modules/storage_account/main.tf | 123 ++ .../modules/storage_account/outputs.tf | 30 + .../modules/storage_account/variables.tf | 134 ++ .../terraform/modules/virtual_network/main.tf | 55 + .../modules/virtual_network/outputs.tf | 19 + .../modules/virtual_network/variables.tf | 40 + .../dotnet/terraform/outputs.tf | 19 + .../dotnet/terraform/providers.tf | 24 + .../dotnet/terraform/terraform.tfvars | 4 + .../dotnet/terraform/variables.tf | 557 ++++++++ .../dotnet/visio/architecture.vsdx | Bin 0 -> 359166 bytes .../python/bicep/README.md | 25 +- .../web-app-managed-identity/python/README.md | 1 - 72 files changed, 8015 insertions(+), 15 deletions(-) create mode 100644 samples/function-app-service-bus/dotnet/README.md create mode 100644 samples/function-app-service-bus/dotnet/bicep/README.md create mode 100755 samples/function-app-service-bus/dotnet/bicep/deploy.sh create mode 100644 samples/function-app-service-bus/dotnet/bicep/main.bicep create mode 100644 samples/function-app-service-bus/dotnet/bicep/main.bicepparam create mode 100644 samples/function-app-service-bus/dotnet/bicep/modules/app-service-plan.bicep create mode 100644 samples/function-app-service-bus/dotnet/bicep/modules/application-insights.bicep create mode 100644 samples/function-app-service-bus/dotnet/bicep/modules/function-app.bicep create mode 100644 samples/function-app-service-bus/dotnet/bicep/modules/log-analytics.bicep create mode 100644 samples/function-app-service-bus/dotnet/bicep/modules/managed-identity.bicep create mode 100644 samples/function-app-service-bus/dotnet/bicep/modules/private-dns-zone.bicep create mode 100644 samples/function-app-service-bus/dotnet/bicep/modules/private-endpoint.bicep create mode 100644 samples/function-app-service-bus/dotnet/bicep/modules/service-bus.bicep create mode 100644 samples/function-app-service-bus/dotnet/bicep/modules/storage-account.bicep create mode 100644 samples/function-app-service-bus/dotnet/bicep/modules/virtual-network.bicep create mode 100644 samples/function-app-service-bus/dotnet/images/architecture.png create mode 100644 samples/function-app-service-bus/dotnet/scripts/README.md create mode 100755 samples/function-app-service-bus/dotnet/scripts/call-http-trigger.sh create mode 100755 samples/function-app-service-bus/dotnet/scripts/deploy.sh create mode 100755 samples/function-app-service-bus/dotnet/scripts/validate.sh create mode 100644 samples/function-app-service-bus/dotnet/src/GreetingFunctions.cs create mode 100644 samples/function-app-service-bus/dotnet/src/Program.cs create mode 100644 samples/function-app-service-bus/dotnet/src/host.json create mode 100644 samples/function-app-service-bus/dotnet/src/local.settings.json create mode 100644 samples/function-app-service-bus/dotnet/src/sample.csproj create mode 100644 samples/function-app-service-bus/dotnet/terraform/README.md create mode 100755 samples/function-app-service-bus/dotnet/terraform/deploy.sh create mode 100644 samples/function-app-service-bus/dotnet/terraform/main.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/app_service_plan/main.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/app_service_plan/outputs.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/app_service_plan/variables.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/application_insights/main.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/application_insights/outputs.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/application_insights/variables.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/function_app/main.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/function_app/outputs.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/function_app/variables.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/log_analytics/main.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/log_analytics/output.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/log_analytics/variables.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/managed_identity/main.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/managed_identity/output.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/managed_identity/variables.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/nat_gateway/main.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/nat_gateway/output.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/nat_gateway/variables.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/network_security_group/main.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/network_security_group/outputs.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/network_security_group/variables.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/private_dns_zone/main.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/private_dns_zone/outputs.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/private_dns_zone/variables.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/private_endpoint/main.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/private_endpoint/outputs.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/private_endpoint/variables.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/service_bus/main.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/service_bus/outputs.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/service_bus/variables.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/storage_account/main.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/storage_account/outputs.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/storage_account/variables.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/virtual_network/main.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/virtual_network/outputs.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/modules/virtual_network/variables.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/outputs.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/providers.tf create mode 100644 samples/function-app-service-bus/dotnet/terraform/terraform.tfvars create mode 100644 samples/function-app-service-bus/dotnet/terraform/variables.tf create mode 100644 samples/function-app-service-bus/dotnet/visio/architecture.vsdx diff --git a/samples/function-app-managed-identity/python/README.md b/samples/function-app-managed-identity/python/README.md index 7d0c015..ec3b2db 100644 --- a/samples/function-app-managed-identity/python/README.md +++ b/samples/function-app-managed-identity/python/README.md @@ -45,9 +45,9 @@ The LocalStack emulator emulates the following services, which are necessary at - [Azure Subscription](https://azure.microsoft.com/free/) - [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) +- [Azure Functions Core Tools](https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local) - [Python](https://www.python.org/downloads/) - [Flask](https://flask.palletsprojects.com/) -- [pyodbc](https://github.com/mkleehammer/pyodbc) - [Bicep extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-bicep), if you plan to install the sample via Bicep. - [Terraform](https://developer.hashicorp.com/terraform/downloads), if you plan to install the sample via Terraform. diff --git a/samples/function-app-service-bus/dotnet/README.md b/samples/function-app-service-bus/dotnet/README.md new file mode 100644 index 0000000..31b19d5 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/README.md @@ -0,0 +1,123 @@ +# Azure Functions App with Service Bus Messaging + +This sample demonstrates how to deploy an [Azure Functions App](https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview) on an [Azure App Service Plan](https://learn.microsoft.com/en-us/azure/app-service/overview-hosting-plans) that exchanges messages through queues in a [Service Bus](https://learn.microsoft.com/en-us/azure/service-bus/service-bus-overview) namespace. The function app authenticates to Azure resources using a [user-assigned managed identity](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview) and connects to the Service Bus namespace via an [Azure Private Endpoint](https://learn.microsoft.com/azure/private-link/private-endpoint-overview) for secure, private network communication. + +## Architecture + +The following diagram illustrates the architecture of the solution: + +![Architecture Diagram](./images/architecture.png) + +The function app is composed of the following functions: + +- **GreetingRequester**: Timer-triggered function that periodically sends a request message containing a randomly generated name to the `input` queue. +- **GreetingHandler**: Uses the [Azure Service Bus trigger](https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-service-bus-trigger) to listen for incoming messages on the `input` queue. When a message arrives, it extracts the name, composes a greeting, and sends the result to the `output` queue using the [Azure Service Bus output binding](https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-service-bus-output). +- **GreetingConsumer**: Timer-triggered function that periodically polls the `output` queue, retrieves greeting response messages, and logs them for monitoring. +- **GetGreetings**: HTTP-triggered function that returns the most recent greetings stored in an in-memory circular buffer. Greetings are returned in reverse chronological order (newest first), providing a quick way to verify the message pipeline is working. + +The solution is composed of the following Azure resources: + +1. [Azure Resource Group](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-cli): A logical container scoping all resources in this sample. +2. [Azure Virtual Network](https://learn.microsoft.com/azure/virtual-network/virtual-networks-overview): Hosts two subnets: + - *app-subnet*: Dedicated to [regional VNet integration](https://learn.microsoft.com/azure/azure-functions/functions-networking-options?tabs=azure-portal#outbound-networking-features) with the Function App. + - *pe-subnet*: Used for hosting Azure Private Endpoints. +3. [Azure Private DNS Zones](https://learn.microsoft.com/azure/dns/private-dns-privatednszone): Provide internal DNS resolution so that resources within the virtual network can reach Private Endpoints by hostname rather than public addresses. There is a separate Azure Private DNS Zone for the following resource types: + - Azure Service Bus namespace + - Azure Blob Storage + - Azure Queue Storage + - Azure Table Storage +4. [Azure Private Endpoints](https://learn.microsoft.com/azure/private-link/private-endpoint-overview): Provide secure, private network connectivity to Azure resources by exposing them through private IP addresses within the virtual network, eliminating the need for traffic to traverse the public internet. There is a separate Azure Private Endpoint for the following resources: + - Azure Service Bus namespace + - Azure Blob Storage + - Azure Queue Storage + - Azure Table Storage +5. [Azure NAT Gateway](https://learn.microsoft.com/azure/nat-gateway/nat-overview): Provides deterministic outbound connectivity and a stable public IP address for the Function App's outbound traffic. Included for architectural completeness; the sample app itself does not call any external services. +6. [Azure Network Security Group](https://learn.microsoft.com/en-us/azure/virtual-network/network-security-groups-overview): Enforces inbound and outbound traffic rules across the virtual network's subnets. +7. [Azure Log Analytics Workspace](https://learn.microsoft.com/azure/azure-monitor/logs/log-analytics-overview): Centralizes diagnostic logs and metrics from all resources in the solution, enabling unified querying and analysis across the entire deployment. +8. [Azure App Service Plan](https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview-hosting-plans): Defines the underlying compute tier and scaling behavior for the function app. +9. [Azure Functions App](https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview): Hosts the sample function app. +10. [Azure Application Insights](https://learn.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview): Provides application performance monitoring (APM), collecting and analyzing requests, traces, and metrics generated by the function app to surface performance bottlenecks and failures. +11. [Azure Service Bus](https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messaging-overview): A fully managed enterprise message broker. This namespace hosts the `input` and `output` queues used by the function app to exchange messages asynchronously. +12. [Azure Storage Account](https://learn.microsoft.com/en-us/azure/storage/common/storage-account-overview): Provides durable storage used internally by the Azure Functions runtime for state management, including distributed locks, checkpoints, and timer trigger coordination. +13. [User-Assigned Managed Identity](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview): This identity is assigned the necessary RBAC roles and is used by the function app to authenticate securely—without storing credentials—to the following Azure resources: + - Azure Service Bus namespace + - Azure Storage + - Azure Application Insights + +## Prerequisites + +- [Azure Subscription](https://azure.microsoft.com/free/) +- [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) +- [Azure Functions Core Tools](https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local) is required to build, run, and deploy the Azure Functions app locally +- [.NET SDK](https://dotnet.microsoft.com/en-us/download) is required to compile and run the C# Azure Functions project +- [Bicep extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-bicep), if you plan to install the sample via Bicep. +- [Terraform](https://developer.hashicorp.com/terraform/downloads), if you plan to install the sample via Terraform. + +## Deployment + +Set up the Azure emulator using the LocalStack for Azure Docker image. Before starting, ensure you have a valid `LOCALSTACK_AUTH_TOKEN` to access the Azure emulator. Refer to the [Auth Token guide](https://docs.localstack.cloud/getting-started/auth-token/?__hstc=108988063.8aad2b1a7229945859f4d9b9bb71e05d.1743148429561.1758793541854.1758810151462.32&__hssc=108988063.3.1758810151462&__hsfp=3945774529) to obtain your Auth Token and set it in the `LOCALSTACK_AUTH_TOKEN` environment variable. The Azure Docker image is available on the [LocalStack Docker Hub](https://hub.docker.com/r/localstack/localstack-azure-alpha). To pull the image, execute: + +```bash +docker pull localstack/localstack-azure-alpha +``` + +Start the LocalStack Azure emulator by running: + +```bash +export LOCALSTACK_AUTH_TOKEN= +IMAGE_NAME=localstack/localstack-azure-alpha localstack start + ``` + +Deploy the application to LocalStack for Azure using one of these methods: + +- [Azure CLI Deployment](./scripts/README.md) +- [Bicep Deployment](./bicep/README.md) +- [Terraform Deployment](./terraform/README.md) + +All deployment methods have been fully tested against Azure and the LocalStack for Azure local emulator. + +> **Note** +> When you deploy the application to LocalStack for Azure for the first time, the initialization process involves downloading and building Docker images. This is a one-time operation—subsequent deployments will be significantly faster. Depending on your internet connection and system resources, this initial setup may take several minutes. + +## Test + +Once the resources and function app have been deployed, you can use the [call-http-trigger.sh](./scripts/call-http-trigger.sh) Bash script to invoke the **GetGreetings** HTTP-triggered function. This function returns the most recent greetings stored in the in-memory circular buffer, allowing you to verify that the entire message pipeline is working end to end. + +You can also inspect the function app's runtime behavior by viewing the logs of its Docker container. Run `docker logs ls-local-func-test-xxxxxx` (replacing `xxxxxx` with the actual container suffix) to see output similar to the following: + +```bash +[2026-03-17T13:11:30.000Z] Executing 'Functions.GreetingRequester' (Reason='Timer fired at 2026-03-17T13:11:30.0002087+00:00', Id=1677eef3-d54a-434a-b21c-0bb1606ebedc) +[2026-03-17T13:11:30.001Z] [GreetingRequester] Timer trigger function started. +[2026-03-17T13:11:30.001Z] [GreetingRequester] Creating Service Bus client for sending messages... +[2026-03-17T13:11:30.001Z] [GreetingRequester] Creating sender for input queue 'input' +[2026-03-17T13:11:30.001Z] [GreetingRequester] Sending message to input queue 'input'... +[2026-03-17T13:11:30.219Z] [GreetingRequester] Successfully sent message to input queue 'input' with name: Jane +[2026-03-17T13:11:30.219Z] [GreetingRequester] Function Ran. Next timer schedule = (null) +[2026-03-17T13:11:30.219Z] Executed 'Functions.GreetingRequester' (Succeeded, Id=1677eef3-d54a-434a-b21c-0bb1606ebedc, Duration=218ms) +[2026-03-17T13:11:30.298Z] Executing 'Functions.GreetingHandler' (Reason='(null)', Id=5ec3e867-0073-44d4-8dc8-869e0ce95401) +[2026-03-17T13:11:30.298Z] Trigger Details: MessageId: c5a1b026-b435-4f62-b273-de9f6e2224a1, SequenceNumber: 1, DeliveryCount: 1, EnqueuedTimeUtc: 2026-03-17T13:11:30.2170000+00:00, LockedUntilUtc: 2026-03-17T13:12:30.2170000+00:00, SessionId: (null) +[2026-03-17T13:11:30.299Z] [GreetingHandler] Message ID: c5a1b026-b435-4f62-b273-de9f6e2224a1 +[2026-03-17T13:11:30.299Z] [GreetingHandler] Message Body: {"name":"Jane"} +[2026-03-17T13:11:30.299Z] [GreetingHandler] Message Content-Type: application/json +[2026-03-17T13:11:30.299Z] [GreetingHandler] Processing request for name: Jane +[2026-03-17T13:11:30.299Z] Start processing HTTP request POST http://127.0.0.1:43127/Settlement/Complete +[2026-03-17T13:11:30.299Z] Sending HTTP request POST http://127.0.0.1:43127/Settlement/Complete +[2026-03-17T13:11:30.302Z] Received HTTP response headers after 2.609ms - 200 +[2026-03-17T13:11:30.302Z] End processing HTTP request after 2.6465ms - 200 +[2026-03-17T13:11:30.302Z] [GreetingHandler] Processed message [c5a1b026-b435-4f62-b273-de9f6e2224a1] successfully: Hi Jane, great to see you! +[2026-03-17T13:11:30.303Z] Executed 'Functions.GreetingHandler' (Succeeded, Id=5ec3e867-0073-44d4-8dc8-869e0ce95401, Duration=4ms) +[2026-03-17T13:11:34.375Z] [GreetingConsumer] Function Ran. Next timer schedule = (null) +[2026-03-17T13:11:34.375Z] Executed 'Functions.GreetingConsumer' (Succeeded, Id=32dbc94a-4ff7-4315-9de4-ea36593589fc, Duration=10427ms) +[2026-03-17T13:11:34.380Z] Executing 'Functions.GreetingConsumer' (Reason='Timer fired at 2026-03-17T13:11:34.3806261+00:00', Id=af37440c-360b-4114-97ea-bf88f1843bcf) +[2026-03-17T13:11:34.381Z] [GreetingConsumer] Timer trigger function started. +[2026-03-17T13:11:34.381Z] [GreetingConsumer] Creating Service Bus client for receiving messages... +[2026-03-17T13:11:34.381Z] [GreetingConsumer] Starting to receive messages from output queue 'output' +[2026-03-17T13:11:34.799Z] [GreetingConsumer] Successfully received and deserialized message from output queue. Date: 2026-03-17T13:06:30, Text: Hi Jane, great to see you! +[2026-03-17T13:11:39.802Z] [GreetingConsumer] No more messages available in output queue 'output' +``` + +## References + +- [Azure Functions Apps Documentation](https://learn.microsoft.com/en-us/azure/app-service/) +- [Azure Service Bus](https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messaging-overview) +- [LocalStack for Azure](https://azure.localstack.cloud/) \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/bicep/README.md b/samples/function-app-service-bus/dotnet/bicep/README.md new file mode 100644 index 0000000..d1c3c23 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/bicep/README.md @@ -0,0 +1,317 @@ +# Bicep Deployment + +This directory contains the Bicep template and a deployment script for provisioning Azure services in LocalStack for Azure. For further details about the sample application, refer to the [Azure Functions App with Service Bus Messaging](../README.md). + +## Prerequisites + +Before deploying this solution, ensure you have the following tools installed: + +- [Azure Subscription](https://azure.microsoft.com/free/) +- [LocalStack for Azure](https://azure.localstack.cloud/): Local Azure cloud emulator for development and testing +- [Visual Studio Code](https://code.visualstudio.com/): Code editor installed on one of the [supported platforms](https://code.visualstudio.com/docs/supporting/requirements#_platforms) +- [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli): Azure command-line interface +- [Azlocal CLI](https://azure.localstack.cloud/user-guides/sdks/az/): LocalStack Azure CLI wrapper +- [Azure Functions Core Tools](https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local) is required to build, run, and deploy the Azure Functions app locally +- [Bicep extension](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-bicep): VS Code extension for Bicep language support and IntelliSense +- [Docker](https://docs.docker.com/get-docker/): Container runtime required for LocalStack +- [.NET SDK](https://dotnet.microsoft.com/en-us/download) is required to compile and run the C# Azure Functions project +- [jq](https://jqlang.org/): JSON processor for scripting and parsing command outputs + +### Installing azlocal CLI + +The [deploy.sh](deploy.sh) Bash script uses the `azlocal` CLI instead of the standard Azure CLI to work with LocalStack. Install it using: + +```bash +pip install azlocal +``` + +For more information, see [Get started with the az tool on LocalStack](https://azure.localstack.cloud/user-guides/sdks/az/). + +## Architecture Overview + +The [deploy.sh](deploy.sh) script creates the [Azure Resource Group](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-cli) for all the Azure resources, while the Bicep modules create the following Azure resources: + +1. [Azure Virtual Network](https://learn.microsoft.com/azure/virtual-network/virtual-networks-overview): Hosts two subnets: + - *app-subnet*: Dedicated to [regional VNet integration](https://learn.microsoft.com/azure/azure-functions/functions-networking-options?tabs=azure-portal#outbound-networking-features) with the Function App. + - *pe-subnet*: Used for hosting Azure Private Endpoints. +2. [Azure Private DNS Zones](https://learn.microsoft.com/azure/dns/private-dns-privatednszone): Provide internal DNS resolution so that resources within the virtual network can reach Private Endpoints by hostname rather than public addresses. There is a separate Azure Private DNS Zone for the following resource types: + - Azure Service Bus namespace + - Azure Blob Storage + - Azure Queue Storage + - Azure Table Storage +3. [Azure Private Endpoints](https://learn.microsoft.com/azure/private-link/private-endpoint-overview): Provide secure, private network connectivity to Azure resources by exposing them through private IP addresses within the virtual network, eliminating the need for traffic to traverse the public internet. There is a separate Azure Private Endpoint for the following resources: + - Azure Service Bus namespace + - Azure Blob Storage + - Azure Queue Storage + - Azure Table Storage +4. [Azure NAT Gateway](https://learn.microsoft.com/azure/nat-gateway/nat-overview): Provides deterministic outbound connectivity and a stable public IP address for the Function App's outbound traffic. Included for architectural completeness; the sample app itself does not call any external services. +5. [Azure Network Security Group](https://learn.microsoft.com/en-us/azure/virtual-network/network-security-groups-overview): Enforces inbound and outbound traffic rules across the virtual network's subnets. +6. [Azure Log Analytics Workspace](https://learn.microsoft.com/azure/azure-monitor/logs/log-analytics-overview): Centralizes diagnostic logs and metrics from all resources in the solution, enabling unified querying and analysis across the entire deployment. +7. [Azure App Service Plan](https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview-hosting-plans): Defines the underlying compute tier and scaling behavior for the function app. +8. [Azure Functions App](https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview): Hosts the sample function app. +9. [Azure Application Insights](https://learn.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview): Provides application performance monitoring (APM), collecting and analyzing requests, traces, and metrics generated by the function app to surface performance bottlenecks and failures. +10. [Azure Service Bus](https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messaging-overview): A fully managed enterprise message broker. This namespace hosts the `input` and `output` queues used by the function app to exchange messages asynchronously. +11. [Azure Storage Account](https://learn.microsoft.com/en-us/azure/storage/common/storage-account-overview): Provides durable storage used internally by the Azure Functions runtime for state management, including distributed locks, checkpoints, and timer trigger coordination. +12. [User-Assigned Managed Identity](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview): This identity is assigned the necessary RBAC roles and is used by the function app to authenticate securely—without storing credentials—to the following Azure resources: + - Azure Service Bus namespace + - Azure Storage + - Azure Application Insights + +For more information on the sample application, see [Azure Functions App with Service Bus Messaging](../README.md). + +## Configuration + +Before deploying the `main.bicep` template, update the `bicep.bicepparam` file with your specific values: + +```bicep +using 'main.bicep' + +param prefix = 'local' +param suffix = 'test' +param runtimeName = 'python' +param runtimeVersion = '3.13' +param databaseName = 'sampledb' +param collectionName = 'activities' +param username = 'paolo' +param primaryRegion = 'westeurope' +param secondaryRegion = 'northeurope' +``` + +## Provisioning Scripts + +See [deploy.sh](deploy.sh) for the complete deployment automation. The script performs: + +- Detects environment (LocalStack vs Azure Cloud) and uses appropriate CLI +- Creates resource group if it doesn't exist +- Optionally validates the Bicep template +- Optionally runs what-if deployment for preview +- Deploys the main.bicep template with parameters from [main.bicepparam](main.bicepparam) +- Extracts deployment outputs (Function App name, Service Bus Namespace name details) +- Creates zip package of the Python application +- Deploys the zip to the Azure Functions App + +## Deployment + +You can set up the Azure emulator by utilizing LocalStack for Azure Docker image. Before starting, ensure you have a valid `LOCALSTACK_AUTH_TOKEN` to access the Azure emulator. Refer to the [Auth Token guide](https://docs.localstack.cloud/getting-started/auth-token/?__hstc=108988063.8aad2b1a7229945859f4d9b9bb71e05d.1743148429561.1758793541854.1758810151462.32&__hssc=108988063.3.1758810151462&__hsfp=3945774529) to obtain your Auth Token and specify it in the `LOCALSTACK_AUTH_TOKEN` environment variable. The Azure Docker image is available on the [LocalStack Docker Hub](https://hub.docker.com/r/localstack/localstack-azure-alpha). To pull the Azure Docker image, execute the following command: + +```bash +docker pull localstack/localstack-azure-alpha +``` + +Start the LocalStack Azure emulator using the localstack CLI, execute the following command: + +```bash +export LOCALSTACK_AUTH_TOKEN= +IMAGE_NAME=localstack/localstack-azure-alpha localstack start +``` + +Navigate to the `bicep` folder: + +```bash +cd samples/function-app-service-bus/dotnet/bicep +``` + +Make the script executable: + +```bash +chmod +x deploy.sh +``` + +Run the deployment script: + +```bash +./deploy.sh +``` + +## Validation + +Once the deployment completes, run the [validate.sh](../scripts/validate.sh) script to confirm that all resources were provisioned and configured as expected: + +```bash +#!/bin/bash + +# Variables +PREFIX='local' +SUFFIX='test' +RESOURCE_GROUP_NAME="${PREFIX}-rg" +LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" +FUNCTION_APP_SUBNET_NSG_NAME="${PREFIX}-func-subnet-nsg-${SUFFIX}" +PE_SUBNET_NSG_NAME="${PREFIX}-pe-subnet-nsg-${SUFFIX}" +NAT_GATEWAY_NAME="${PREFIX}-nat-gateway-${SUFFIX}" +VIRTUAL_NETWORK_NAME="${PREFIX}-vnet-${SUFFIX}" +APP_SERVICE_PLAN_NAME="${PREFIX}-plan-${SUFFIX}" +FUNCTION_APP_NAME="${PREFIX}-func-${SUFFIX}" +SERVICE_BUS_NAMESPACE_NAME="${PREFIX}-service-bus-${SUFFIX}" +STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}" +APPLICATION_INSIGHTS_NAME="${PREFIX}-func-${SUFFIX}" +ENVIRONMENT=$(az account show --query environmentName --output tsv) +PRIVATE_DNS_ZONE_NAMES=( + "privatelink.servicebus.windows.net" + "privatelink.blob.core.windows.net" + "privatelink.queue.core.windows.net" + "privatelink.table.core.windows.net" +) +PE_NAMES=( + "${PREFIX}-service-bus-pe-${SUFFIX}" + "${PREFIX}-blob-storage-pe-${SUFFIX}" + "${PREFIX}-queue-storage-pe-${SUFFIX}" + "${PREFIX}-table-storage-pe-${SUFFIX}" +) + +# Choose the appropriate CLI based on the environment +if [[ $ENVIRONMENT == "LocalStack" ]]; then + echo "Using azlocal for LocalStack emulator environment." + AZ="azlocal" +else + echo "Using standard az for AzureCloud environment." + AZ="az" +fi + +# Check resource group +echo -e "[$RESOURCE_GROUP_NAME] resource group:\n" +$AZ group show \ + --name "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check App Service Plan +echo -e "\n[$APP_SERVICE_PLAN_NAME] app service plan:\n" +$AZ appservice plan show \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --name "$APP_SERVICE_PLAN_NAME" \ + --output table \ + --only-show-errors + +# Check Azure Functions App +echo -e "\n[$FUNCTION_APP_NAME] web app:\n" +$AZ functionapp show \ + --name "$FUNCTION_APP_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Service Bus Namespace +echo -e "\n[$SERVICE_BUS_NAMESPACE_NAME] service bus namespace:\n" +$AZ servicebus namespace show \ + --name "$SERVICE_BUS_NAMESPACE_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --query '{Name:name,ServiceBusEndpoint:serviceBusEndpoint}' \ + --only-show-errors + +# Check Service Bus Queues +echo -e "\n[$SERVICE_BUS_NAMESPACE_NAME] service bus queues:\n" +$AZ servicebus queue list \ + --namespace-name "$SERVICE_BUS_NAMESPACE_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --query '[].{Name:name,Status:status}' \ + --only-show-errors + + # Check Application Insights +echo -e "\n[$APPLICATION_INSIGHTS_NAME] application insights:\n" +$AZ monitor app-insights component show \ + --app "$APPLICATION_INSIGHTS_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query '{Name:name,Location:location,ResourceGroup:resourceGroup}' \ + --output table \ + --only-show-errors + +# Check Storage Account +echo -e "\n[$STORAGE_ACCOUNT_NAME] storage account:\n" +$AZ storage account show \ + --name "$STORAGE_ACCOUNT_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query '{Name:name,Location:primaryLocation,ResourceGroup:resourceGroup}' \ + --output table \ + --only-show-errors + +# Check Log Analytics Workspace +echo -e "\n[$LOG_ANALYTICS_NAME] log analytics workspace:\n" +$AZ monitor log-analytics workspace show \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --workspace-name "$LOG_ANALYTICS_NAME" \ + --query '{Name:name,Location:location,ResourceGroup:resourceGroup}' \ + --output table \ + --only-show-errors + +# Check NAT Gateway +echo -e "\n[$NAT_GATEWAY_NAME] nat gateway:\n" +$AZ network nat gateway show \ + --name "$NAT_GATEWAY_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Virtual Network +echo -e "\n[$VIRTUAL_NETWORK_NAME] virtual network:\n" +$AZ network vnet show \ + --name "$VIRTUAL_NETWORK_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Private DNS Zone +for PRIVATE_DNS_ZONE_NAME in "${PRIVATE_DNS_ZONE_NAMES[@]}"; do + echo -e "\n[$PRIVATE_DNS_ZONE_NAME] private dns zone:\n" + $AZ network private-dns zone show \ + --name "$PRIVATE_DNS_ZONE_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query '{Name:name,ResourceGroup:resourceGroup,RecordSets:recordSets,VirtualNetworkLinks:virtualNetworkLinks}' \ + --output table \ + --only-show-errors +done + +# Check Private Endpoint +for PRIVATE_ENDPOINT_NAME in "${PE_NAMES[@]}"; do + echo -e "\n[$PRIVATE_ENDPOINT_NAME] private endpoint:\n" + $AZ network private-endpoint show \ + --name "$PRIVATE_ENDPOINT_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors +done + +# Check Functions App Subnet NSG +echo -e "\n[$FUNCTION_APP_SUBNET_NSG_NAME] network security group:\n" +$AZ network nsg show \ + --name "$FUNCTION_APP_SUBNET_NSG_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Private Endpoint Subnet NSG +echo -e "\n[$PE_SUBNET_NSG_NAME] network security group:\n" +$AZ network nsg show \ + --name "$PE_SUBNET_NSG_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# List resources +echo -e "\n[$RESOURCE_GROUP_NAME] all resources:\n" +$AZ resource list \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors +``` + +## Cleanup + +To destroy all created resources: + +```bash +# Delete resource group and all contained resources +az group delete --name local-rg --yes --no-wait + +# Verify deletion +az group list --output table +``` + +This will remove all Azure resources created by the CLI deployment script. + +## Related Documentation + +- [Azure Bicep Documentation](https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/) +- [Bicep Language Reference](https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/bicep-functions) +- [LocalStack for Azure Documentation](https://azure.localstack.cloud/) \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/bicep/deploy.sh b/samples/function-app-service-bus/dotnet/bicep/deploy.sh new file mode 100755 index 0000000..41d77ca --- /dev/null +++ b/samples/function-app-service-bus/dotnet/bicep/deploy.sh @@ -0,0 +1,173 @@ +#!/bin/bash + +# Variables +PREFIX='local' +SUFFIX='test' +TEMPLATE="main.bicep" +PARAMETERS="main.bicepparam" +RESOURCE_GROUP_NAME="${PREFIX}-rg" +LOCATION="westeurope" +VALIDATE_TEMPLATE=1 +USE_WHAT_IF=0 +SUBSCRIPTION_NAME=$(az account show --query name --output tsv) +CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)" +ZIPFILE="functionapp.zip" +ENVIRONMENT=$(az account show --query environmentName --output tsv) + +# Change the current directory to the script's directory +cd "$CURRENT_DIR" || exit + +# Choose the appropriate CLI based on the environment +if [[ $ENVIRONMENT == "LocalStack" ]]; then + echo "Using azlocal for LocalStack emulator environment." + AZ="azlocal" +else + echo "Using standard az for AzureCloud environment." + AZ="az" +fi + +# Validates if the resource group exists in the subscription, if not creates it +echo "Checking if resource group [$RESOURCE_GROUP_NAME] exists in the subscription [$SUBSCRIPTION_NAME]..." +$AZ group show --name $RESOURCE_GROUP_NAME &>/dev/null + +if [[ $? != 0 ]]; then + echo "No resource group [$RESOURCE_GROUP_NAME] exists in the subscription [$SUBSCRIPTION_NAME]" + echo "Creating resource group [$RESOURCE_GROUP_NAME] in the subscription [$SUBSCRIPTION_NAME]..." + + # Create the resource group + $AZ group create \ + --name $RESOURCE_GROUP_NAME \ + --location $LOCATION \ + --only-show-errors 1> /dev/null + + if [[ $? == 0 ]]; then + echo "Resource group [$RESOURCE_GROUP_NAME] successfully created in the subscription [$SUBSCRIPTION_NAME]" + else + echo "Failed to create resource group [$RESOURCE_GROUP_NAME] in the subscription [$SUBSCRIPTION_NAME]" + exit + fi +else + echo "Resource group [$RESOURCE_GROUP_NAME] already exists in the subscription [$SUBSCRIPTION_NAME]" +fi + +# Validates the Bicep template +if [[ $VALIDATE_TEMPLATE == 1 ]]; then + if [[ $USE_WHAT_IF == 1 ]]; then + # Execute a deployment What-If operation at resource group scope. + echo "Previewing changes deployed by Bicep template [$TEMPLATE]..." + $AZ deployment group what-if \ + --resource-group $RESOURCE_GROUP_NAME \ + --template-file $TEMPLATE \ + --parameters $PARAMETERS \ + --parameters location=$LOCATION \ + prefix=$PREFIX \ + suffix=$SUFFIX \ + --only-show-errors + + if [[ $? == 0 ]]; then + echo "Bicep template [$TEMPLATE] validation succeeded" + else + echo "Failed to validate Bicep template [$TEMPLATE]" + exit + fi + else + # Validate the Bicep template + echo "Validating Bicep template [$TEMPLATE]..." + output=$($AZ deployment group validate \ + --resource-group $RESOURCE_GROUP_NAME \ + --template-file $TEMPLATE \ + --parameters $PARAMETERS \ + --parameters location=$LOCATION \ + prefix=$PREFIX \ + suffix=$SUFFIX \ + --only-show-errors) + + if [[ $? == 0 ]]; then + echo "Bicep template [$TEMPLATE] validation succeeded" + else + echo "Failed to validate Bicep template [$TEMPLATE]" + echo "$output" + exit + fi + fi +fi + +# Deploy the Bicep template +echo "Deploying Bicep template [$TEMPLATE]..." +if DEPLOYMENT_OUTPUTS=$($AZ deployment group create \ + --resource-group $RESOURCE_GROUP_NAME \ + --only-show-errors \ + --template-file $TEMPLATE \ + --parameters $PARAMETERS \ + --parameters location=$LOCATION \ + prefix=$PREFIX \ + suffix=$SUFFIX \ + --query 'properties.outputs' -o json); then + # Extract only the JSON portion (everything from first { to the end) + DEPLOYMENT_JSON=$(echo "$DEPLOYMENT_OUTPUTS" | sed -n '/{/,$ p') + echo "Bicep template [$TEMPLATE] deployed successfully. Outputs:" + echo "$DEPLOYMENT_JSON" | jq . + FUNCTION_APP_NAME=$(echo "$DEPLOYMENT_JSON" | jq -r '.functionAppName.value') + SERVICE_BUS_NAME=$(echo "$DEPLOYMENT_JSON" | jq -r '.serviceBusName.value') + echo "Deployment details:" + echo "Function App Name: $FUNCTION_APP_NAME" + echo "Service Bus Namespace: $SERVICE_BUS_NAME" +else + echo "Failed to deploy Bicep template [$TEMPLATE]" + exit 1 +fi + +if [[ -z "$FUNCTION_APP_NAME" || -z "$SERVICE_BUS_NAME" ]]; then + echo "Function App Name or Service Bus Namespace is empty. Exiting." + exit 1 +fi + +# Print the application settings of the function app +echo "Retrieving application settings for function app [$FUNCTION_APP_NAME]..." +$AZ functionapp config appsettings list \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --name "$FUNCTION_APP_NAME" + +# CD into the function app directory +cd ../src || exit + +# Remove any existing zip package of the function app +if [ -f "$ZIPFILE" ]; then + rm "$ZIPFILE" +fi + +# Build and publish the function app +echo "Building function app [$FUNCTION_APP_NAME]..." +if dotnet publish -c Release -o ./publish; then + echo "Function app [$FUNCTION_APP_NAME] built successfully." +else + echo "Failed to build function app [$FUNCTION_APP_NAME]." + exit 1 +fi + +# Create the zip package of the publish output +echo "Creating zip package of the function app..." +cd ./publish || exit +zip -r "../$ZIPFILE" . +cd .. + +# Deploy the function app +echo "Deploying function app [$FUNCTION_APP_NAME] with zip file [$ZIPFILE]..." +if $AZ functionapp deployment source config-zip \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --name "$FUNCTION_APP_NAME" \ + --src "$ZIPFILE" 1>/dev/null; then + echo "Function app [$FUNCTION_APP_NAME] deployed successfully." +else + echo "Failed to deploy function app [$FUNCTION_APP_NAME]." + exit 1 +fi + +# Remove the zip package of the function app +if [ -f "$ZIPFILE" ]; then + rm "$ZIPFILE" +fi + +# Print the list of resources in the resource group +echo "Listing resources in resource group [$RESOURCE_GROUP_NAME]..." +az resource list --resource-group "$RESOURCE_GROUP_NAME" --output table \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/bicep/main.bicep b/samples/function-app-service-bus/dotnet/bicep/main.bicep new file mode 100644 index 0000000..60f3b54 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/bicep/main.bicep @@ -0,0 +1,575 @@ +//******************************************** +// Parameters +//******************************************** +@description('Specifies the prefix for the name of the Azure resources.') +@minLength(2) +param prefix string = take(uniqueString(resourceGroup().id), 4) + +@description('Specifies the suffix for the name of the Azure resources.') +@minLength(2) +param suffix string = take(uniqueString(resourceGroup().id), 4) + +@description('Specifies the location for all resources.') +param location string = resourceGroup().location + +@description('Specifies the tier name for the hosting plan.') +@allowed([ + 'Basic' + 'Standard' + 'ElasticPremium' + 'Premium' + 'PremiumV2' + 'Premium0V3' + 'PremiumV3' + 'PremiumMV3' + 'Isolated' + 'IsolatedV2' + 'WorkflowStandard' + 'FlexConsumption' +]) +param skuTier string = 'Standard' + +@description('Specifies the SKU name for the hosting plan.') +@allowed([ + 'B1' + 'B2' + 'B3' + 'S1' + 'S2' + 'S3' + 'EP1' + 'EP2' + 'EP3' + 'P1' + 'P2' + 'P3' + 'P1V2' + 'P2V2' + 'P3V2' + 'P0V3' + 'P1V3' + 'P2V3' + 'P3V3' + 'P1MV3' + 'P2MV3' + 'P3MV3' + 'P4MV3' + 'P5MV3' + 'I1' + 'I2' + 'I3' + 'I1V2' + 'I2V2' + 'I3V2' + 'I4V2' + 'I5V2' + 'I6V2' + 'WS1' + 'WS2' + 'WS3' + 'FC1' +]) +param skuName string = 'S1' + +@description('Specifies the kind of the hosting plan.') +@allowed([ + 'app' + 'elastic' + 'functionapp' + 'windows' + 'linux' +]) +param appServicePlanKind string = 'linux' + +@description('Specifies whether the hosting plan is reserved.') +param reserved bool = true + +@description('Specifies whether the hosting plan is zone redundant.') +param zoneRedundant bool = false + +@description('Specifies the language runtime used by the Azure Functions App.') +@allowed([ + 'dotnet' + 'dotnet-isolated' + 'python' + 'java' + 'node' + 'powerShell' + 'custom' +]) +param runtimeName string + +@description('Specifies the target language version used by the Azure Functions App.') +param runtimeVersion string + +@description('Specifies the kind of the hosting plan.') +@allowed([ + 'app' // Windows Web app + 'app,linux' // Linux Web app + 'app,linux,container' // Linux Container Web app + 'hyperV' // Windows Container Web App + 'app,container,windows' // Windows Container Web App + 'app,linux,kubernetes' // Linux Web App on ARC + 'app,linux,container,kubernetes' // Linux Container Web App on ARC + 'functionapp' // Function Code App + 'functionapp,linux' // Linux Consumption Function app + 'functionapp,linux,container,kubernetes' // Function Container App on ARC + 'functionapp,linux,kubernetes' // Function Code App on ARC +]) +param functionAppKind string = 'functionapp,linux' + +@description('Specifies whether HTTPS is enforced for the Azure Functions App.') +param httpsOnly bool = false + +@description('Specifies the minimum TLS version for the Azure Functions App.') +@allowed([ + '1.0' + '1.1' + '1.2' + '1.3' +]) +param minTlsVersion string = '1.2' + +@description('Specifies whether the public network access is enabled or disabled') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccess string = 'Enabled' + +@description('Specifies whether Always On is enabled for the Azure Functions App.') +param alwaysOn bool = true + +@description('Specifies the optional Git Repo URL.') +param repoUrl string = '' + +@description('Enabling this property creates a Premium Service Bus Namespace in regions supported availability zones.') +param serviceBusNamespaceZoneRedundant bool = true + +@description('Specifies the messaging units for the Service Bus namespace. For Premium tier, capacity are 1,2 and 4.') +param serviceBusNamespaceCapacity int = 1 + +@description('Specifies the name of Service Bus namespace SKU.') +@allowed([ + 'Basic' + 'Premium' + 'Standard' +]) +param serviceBusSkuName string = 'Premium' + +@description('Specifies a list of queue names.') +param queueNames array = [ + 'input' + 'output' +] + +@description('Specifies the name of the virtual network.') +param virtualNetworkName string = '' + +@description('Specifies the address prefixes of the virtual network.') +param virtualNetworkAddressPrefixes string = '10.0.0.0/8' + +@description('Specifies the name of the subnet used by the Azure Functions App for the regional virtual network integration.') +param functionAppSubnetName string = 'func-subnet' + +@description('Specifies the address prefix of the subnet used by the Azure Functions App for the regional virtual network integration.') +param functionAppSubnetAddressPrefix string = '10.0.0.0/24' + +@description('Specifies the name of the network security group associated to the subnet hosting the Azure Functions App.') +param functionAppSubnetNsgName string = '' + +@description('Specifies the name of the subnet which contains the private endpoint to the Service Bus namespace.') +param peSubnetName string = 'pe-subnet' + +@description('Specifies the address prefix of the subnet which contains the private endpoint to the Service Bus namespace.') +param peSubnetAddressPrefix string = '10.0.1.0/24' + +@description('Specifies the name of the network security group associated to the subnet hosting the private endpoint to the Service Bus namespace.') +param peSubnetNsgName string = '' + +@description('Specifies the length of the Public IP Prefix.') +@minValue(28) +@maxValue(32) +param natGatewayPublicIpPrefixLength int = 31 + +@description('Specifies the name of the Azure NAT Gateway.') +param natGatewayName string = '' + +@description('Specifies a list of availability zones denoting the zone in which Nat Gateway should be deployed.') +param natGatewayZones array = [] + +@description('Specifies the idle timeout in minutes for the Azure NAT Gateway.') +param natGatewayIdleTimeoutMins int = 30 + +@description('Specifies whether to allow public network access for the storage account.') +@allowed([ + 'Disabled' + 'Enabled' +]) +param storageAccountPublicNetworkAccess string = 'Enabled' + +@description('Specifies the access tier of the Azure Storage Account resource. The default value is Hot.') +param storageAccountAccessTier string = 'Hot' + +@description('Specifies whether the Azure Storage Account resource allows public access to blobs.') +param storageAccountAllowBlobPublicAccess bool = true + +@description('Specifies whether the Azure Storage Account resource allows shared key access.') +param storageAccountAllowSharedKeyAccess bool = true + +@description('Specifies whether the Azure Storage Account resource allows cross-tenant replication.') +param storageAccountAllowCrossTenantReplication bool = false + +@description('Specifies the minimum TLS version to be permitted on requests to the Azure Storage Account resource. The default value is TLS1_2.') +param storageAccountMinimumTlsVersion string = 'TLS1_2' + +@description('The default action of allow or deny when no other rules match. Allowed values: Allow or Deny') +@allowed([ + 'Allow' + 'Deny' +]) +param storageAccountANetworkAclsDefaultAction string = 'Allow' + +@description('Specifies whether the Azure Storage Account resource should only support HTTPS traffic.') +param storageAccountSupportsHttpsTrafficOnly bool = true + +@description('Specifies whether to create containers.') +param storageAccountCreateContainers bool = false + +@description('Specifies an array of containers to create.') +param storageAccountContainerNames array = [] + +@description('Specifies the name of the Azure Log Analytics resource.') +param logAnalyticsName string = '' + +@description('Specifies the service tier of the workspace: Free, Standalone, PerNode, Per-GB.') +@allowed([ + 'Free' + 'Standalone' + 'PerNode' + 'PerGB2018' +]) +param logAnalyticsSku string = 'PerNode' + +@description('Specifies the workspace data retention in days. -1 means Unlimited retention for the Unlimited Sku. 730 days is the maximum allowed for all other Skus.') +param logAnalyticsRetentionInDays int = 60 + +@description('Specifies the type of managed identity.') +@allowed([ + 'SystemAssigned' + 'UserAssigned' +]) +param managedIdentityType string = 'UserAssigned' + +@description('Specifies the tags to be applied to the resources.') +param tags object = { + environment: 'test' + deployment: 'bicep' +} + +@description('Specifies a list of names to be used as part of the sample data in the Azure Function App.') +param names string = 'Paolo,John,Jane,Max,Mary,Leo,Mia,Anna,Lisa,Anastasia' + +//******************************************** +// Variables +//******************************************** +var functionAppName = '${prefix}-func-${suffix}' +var appServicePlanName = '${prefix}-plan-${suffix}' +var serviceBusNamespaceName = '${prefix}-service-bus-${suffix}' +var storageAccountName = '${prefix}storage${suffix}' +var managedIdentityName = '${prefix}-identity-${suffix}' +var blobStoragePrivateEndpointName = '${prefix}-blob-storage-pe-${suffix}' +var queueStoragePrivateEndpointName = '${prefix}-queue-storage-pe-${suffix}' +var tableStoragePrivateEndpointName = '${prefix}-table-storage-pe-${suffix}' +var serviceBusPrivateEndpointName = '${prefix}-service-bus-pe-${suffix}' + +//******************************************** +// Modules and Resources +//******************************************** +module applicationInsights 'modules/application-insights.bicep' = { + name: 'applicationInsights' + params: { + // properties + name: functionAppName + location: location + tags: tags + workspaceId: workspace.outputs.id + } +} + +module workspace 'modules/log-analytics.bicep' = { + name: 'workspace' + params: { + // properties + name: empty(logAnalyticsName) ? toLower('${prefix}-log-analytics-${suffix}') : logAnalyticsName + location: location + tags: tags + sku: logAnalyticsSku + retentionInDays: logAnalyticsRetentionInDays + } +} + +module storageAccount 'modules/storage-account.bicep' = { + name: 'storageAccount' + params: { + // properties + name: storageAccountName + location: location + tags: tags + publicNetworkAccess: storageAccountPublicNetworkAccess + accessTier: storageAccountAccessTier + allowBlobPublicAccess: storageAccountAllowBlobPublicAccess + allowSharedKeyAccess: storageAccountAllowSharedKeyAccess + allowCrossTenantReplication: storageAccountAllowCrossTenantReplication + minimumTlsVersion: storageAccountMinimumTlsVersion + networkAclsDefaultAction: storageAccountANetworkAclsDefaultAction + supportsHttpsTrafficOnly: storageAccountSupportsHttpsTrafficOnly + workspaceId: workspace.outputs.id + createContainers: storageAccountCreateContainers + containerNames: storageAccountContainerNames + createFileShares: false + fileShareNames: [] + } +} + +module serviceBus 'modules/service-bus.bicep' = { + name: 'serviceBus' + params: { + name: serviceBusNamespaceName + location: location + capacity: serviceBusNamespaceCapacity + skuName: serviceBusSkuName + zoneRedundant: serviceBusNamespaceZoneRedundant + workspaceId: workspace.outputs.id + queueNames: queueNames + tags: tags + } +} + +module network 'modules/virtual-network.bicep' = { + name: 'network' + params: { + virtualNetworkName: empty(virtualNetworkName) ? toLower('${prefix}-vnet-${suffix}') : virtualNetworkName + virtualNetworkAddressPrefixes: virtualNetworkAddressPrefixes + functionAppSubnetName: functionAppSubnetName + functionAppSubnetAddressPrefix: functionAppSubnetAddressPrefix + functionAppSubnetNsgName: empty(functionAppSubnetNsgName) + ? toLower('${prefix}-webapp-subnet-nsg-${suffix}') + : functionAppSubnetNsgName + peSubnetName: peSubnetName + peSubnetAddressPrefix: peSubnetAddressPrefix + peSubnetNsgName: empty(peSubnetNsgName) ? toLower('${prefix}-pe-subnet-nsg-${suffix}') : peSubnetNsgName + natGatewayName: empty(natGatewayName) ? toLower('${prefix}-nat-gateway-${suffix}') : natGatewayName + natGatewayZones: natGatewayZones + natGatewayPublicIpPrefixName: toLower('${prefix}-nat-gateway-pip-prefix-${suffix}') + natGatewayPublicIpPrefixLength: natGatewayPublicIpPrefixLength + natGatewayIdleTimeoutMins: natGatewayIdleTimeoutMins + delegationServiceName: skuTier == 'FlexConsumption' ? 'Microsoft.App/environments' : 'Microsoft.Web/serverfarms' + workspaceId: workspace.outputs.id + location: location + tags: tags + } +} + +module blobStoragePrivateDnsZone 'modules/private-dns-zone.bicep' = { + name: 'blobStoragePrivateDnsZone' + params: { + name: 'privatelink.blob.core.windows.net' + vnetId: network.outputs.virtualNetworkId + tags: tags + } +} + +module blobStoragePrivateEndpoint 'modules/private-endpoint.bicep' = { + name: 'blobStoragePrivateEndpoint' + params: { + name: blobStoragePrivateEndpointName + privateLinkServiceId: storageAccount.outputs.id + privateDnsZoneId: blobStoragePrivateDnsZone.outputs.id + subnetId: network.outputs.peSubnetId + groupIds: [ + 'blob' + ] + location: location + tags: tags + } +} + +module queueStoragePrivateDnsZone 'modules/private-dns-zone.bicep' = { + name: 'queueStoragePrivateDnsZone' + params: { + name: 'privatelink.queue.core.windows.net' + vnetId: network.outputs.virtualNetworkId + tags: tags + } +} + +module queueStoragePrivateEndpoint 'modules/private-endpoint.bicep' = { + name: 'queueStoragePrivateEndpoint' + params: { + name: queueStoragePrivateEndpointName + privateLinkServiceId: storageAccount.outputs.id + privateDnsZoneId: queueStoragePrivateDnsZone.outputs.id + subnetId: network.outputs.peSubnetId + groupIds: [ + 'queue' + ] + location: location + tags: tags + } +} + +module tableStoragePrivateDnsZone 'modules/private-dns-zone.bicep' = { + name: 'tableStoragePrivateDnsZone' + params: { + name: 'privatelink.table.core.windows.net' + vnetId: network.outputs.virtualNetworkId + tags: tags + } +} + +module tableStoragePrivateEndpoint 'modules/private-endpoint.bicep' = { + name: 'tableStoragePrivateEndpoint' + params: { + name: tableStoragePrivateEndpointName + privateLinkServiceId: storageAccount.outputs.id + privateDnsZoneId: tableStoragePrivateDnsZone.outputs.id + subnetId: network.outputs.peSubnetId + groupIds: [ + 'table' + ] + location: location + tags: tags + } +} + +module serviceBusPrivateDnsZone 'modules/private-dns-zone.bicep' = { + name: 'serviceBusPrivateDnsZone' + params: { + name: 'privatelink.servicebus.windows.net' + vnetId: network.outputs.virtualNetworkId + tags: tags + } +} + +module serviceBusPrivateEndpoint 'modules/private-endpoint.bicep' = { + name: 'serviceBusPrivateEndpoint' + params: { + name: serviceBusPrivateEndpointName + privateLinkServiceId: serviceBus.outputs.id + privateDnsZoneId: serviceBusPrivateDnsZone.outputs.id + subnetId: network.outputs.peSubnetId + groupIds: [ + 'namespace' + ] + location: location + tags: tags + } +} + +module appServicePlan 'modules/app-service-plan.bicep' = { + name: 'appServicePlan' + params: { + name: appServicePlanName + location: location + skuName: skuName + skuTier: skuTier + kind: appServicePlanKind + reserved: reserved + zoneRedundant: zoneRedundant + workspaceId: workspace.outputs.id + tags: tags + } +} + +module managedIdentity 'modules/managed-identity.bicep' = if (managedIdentityType == 'UserAssigned') { + name: 'managedIdentity' + params: { + // properties + name: managedIdentityName + storageAccountName: storageAccount.outputs.name + applicationInsightsName: applicationInsights.outputs.name + serviceBusName: serviceBus.outputs.name + location: location + tags: tags + } +} + +module functionApp 'modules/function-app.bicep' = { + name: functionAppName + params: { + name: functionAppName + location: location + kind: functionAppKind + httpsOnly: httpsOnly + runtimeName: runtimeName + runtimeVersion: runtimeVersion + alwaysOn: alwaysOn + minTlsVersion: minTlsVersion + publicNetworkAccess: publicNetworkAccess + repoUrl: repoUrl + virtualNetworkName: network.outputs.virtualNetworkName + subnetName: network.outputs.functionAppSubnetName + hostingPlanName: appServicePlan.outputs.name + workspaceId: workspace.outputs.id + tags: tags + managedIdentityType: managedIdentityType + managedIdentityName: managedIdentityName + settings: [ + { + name: 'SCM_DO_BUILD_DURING_DEPLOYMENT' + value: 'false' + } + { + name: 'AzureWebJobsStorage' + value: storageAccount.outputs.connectionString + } + { + name: 'FUNCTIONS_WORKER_RUNTIME' + value: runtimeName + } + { + name: 'FUNCTIONS_EXTENSION_VERSION' + value: '~4' + } + { + name: 'AZURE_CLIENT_ID' + value: managedIdentityType == 'UserAssigned' ? managedIdentity.outputs.clientId : '' + } + { + name: 'SERVICE_BUS_CONNECTION_STRING__fullyQualifiedNamespace' + value: '${serviceBus.outputs.name}.servicebus.windows.net' + } + { + name: 'APPLICATIONINSIGHTS_CONNECTION_STRING' + value: applicationInsights.outputs.connectionString + } + { + name: 'APPLICATIONINSIGHTS_AUTHENTICATION_STRING' + value: managedIdentityType == 'UserAssigned' ? 'ClientId=${managedIdentity.outputs.clientId};Authorization=AAD' : '' + } + { + name: 'INPUT_QUEUE_NAME' + value: 'input' + } + { + name: 'OUTPUT_QUEUE_NAME' + value: 'output' + } + { + name: 'NAMES' + value: names + } + { + name: 'TIMER_SCHEDULE' + value: '*/10 * * * * *' + } + ] + } +} + +//******************************************** +// Outputs +//******************************************** +output functionAppName string = functionApp.outputs.name +output serviceBusName string = serviceBus.outputs.name diff --git a/samples/function-app-service-bus/dotnet/bicep/main.bicepparam b/samples/function-app-service-bus/dotnet/bicep/main.bicepparam new file mode 100644 index 0000000..59c8ca1 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/bicep/main.bicepparam @@ -0,0 +1,6 @@ +using 'main.bicep' + +param prefix = 'paolo' +param suffix = 'test' +param runtimeName = 'dotnet-isolated' +param runtimeVersion = '10.0' diff --git a/samples/function-app-service-bus/dotnet/bicep/modules/app-service-plan.bicep b/samples/function-app-service-bus/dotnet/bicep/modules/app-service-plan.bicep new file mode 100644 index 0000000..4b5cfb3 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/bicep/modules/app-service-plan.bicep @@ -0,0 +1,154 @@ +//******************************************** +// Parameters +//******************************************** +@description('Specifies the name of the App Service Plan.') +param name string + +@description('Specifies the location.') +param location string = resourceGroup().location + +@description('Specifies the tier name for the hosting plan.') +@allowed([ + 'Basic' + 'Standard' + 'ElasticPremium' + 'Premium' + 'PremiumV2' + 'Premium0V3' + 'PremiumV3' + 'PremiumMV3' + 'Isolated' + 'IsolatedV2' + 'WorkflowStandard' + 'FlexConsumption' +]) +param skuTier string = 'Standard' + +@description('Specifies the SKU name for the hosting plan.') +@allowed([ + 'B1' + 'B2' + 'B3' + 'S1' + 'S2' + 'S3' + 'EP1' + 'EP2' + 'EP3' + 'P1' + 'P2' + 'P3' + 'P1V2' + 'P2V2' + 'P3V2' + 'P0V3' + 'P1V3' + 'P2V3' + 'P3V3' + 'P1MV3' + 'P2MV3' + 'P3MV3' + 'P4MV3' + 'P5MV3' + 'I1' + 'I2' + 'I3' + 'I1V2' + 'I2V2' + 'I3V2' + 'I4V2' + 'I5V2' + 'I6V2' + 'WS1' + 'WS2' + 'WS3' + 'FC1' +]) +param skuName string = 'S1' + +@description('Specifies the kind of the hosting plan.') +@allowed([ + 'app' + 'elastic' + 'functionapp' + 'windows' + 'linux' +]) +param kind string = 'linux' + +@description('Specifies whether the hosting plan is reserved.') +param reserved bool = true + +@description('Specifies whether the hosting plan is zone redundant.') +param zoneRedundant bool = false + +@description('Specifies the resource id of the Log Analytics workspace.') +param workspaceId string + +@description('Specifies the tags to be applied to the resources.') +param tags object = {} + +//******************************************** +// Variables +//******************************************** + +var diagnosticSettingsName = 'default' +var logCategories = [] +var metricCategories = [ + 'AllMetrics' +] +var logs = [ + for category in logCategories: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: 0 + } + } +] +var metrics = [ + for category in metricCategories: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: 0 + } + } +] + +//******************************************** +// Resources +//******************************************** +resource appServicePlan 'Microsoft.Web/serverfarms@2024-11-01' = { + name: name + location: location + tags: tags + kind: kind + sku: { + tier: skuTier + name: skuName + } + properties: { + reserved: reserved + zoneRedundant: zoneRedundant + maximumElasticWorkerCount: skuTier == 'FlexConsumption' ? 1 : 20 + } +} + +resource diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if(!empty(workspaceId)) { + name: diagnosticSettingsName + scope: appServicePlan + properties: { + workspaceId: workspaceId + logs: logs + metrics: metrics + } +} + +//******************************************** +// Outputs +//******************************************** +output id string = appServicePlan.id +output name string = appServicePlan.name diff --git a/samples/function-app-service-bus/dotnet/bicep/modules/application-insights.bicep b/samples/function-app-service-bus/dotnet/bicep/modules/application-insights.bicep new file mode 100644 index 0000000..39ab4dd --- /dev/null +++ b/samples/function-app-service-bus/dotnet/bicep/modules/application-insights.bicep @@ -0,0 +1,78 @@ + +//******************************************** +// Parameters +//******************************************** + +@description('Specifies the name of the Azure Application Insights.') +param name string + +@description('Specifies the location.') +param location string = resourceGroup().location + +@description('Specifies the type of application being monitored..') +@allowed([ + 'web' + 'other' +]) +param applicationType string = 'web' + +@description('Specifies whether IP masking is enabled.') +param disableIpMasking bool = false + +@description('Specifies whether the application is enabled for local authentication.') +param disableLocalAuth bool = false + +@description('Specifies whether purging data immediately after 30 days.') +param immediatePurgeDataOn30Days bool = true + +@description('Specifies the network access type for accessing Application Insights ingestion.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccessForIngestion string = 'Enabled' + +@description('Specifies the network access type for accessing Application Insights query.') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccessForQuery string = 'Enabled' + +@description('Specifies the Azure Log Analytics workspace ID.') +param workspaceId string + +@description('Specifies the resource tags.') +param tags object + +//******************************************** +// Resources +//******************************************** + +resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = { + name: name + location: location + tags: tags + kind: 'web' + properties: { + Application_Type: applicationType + DisableIpMasking: disableIpMasking + DisableLocalAuth: disableLocalAuth + Flow_Type: 'Bluefield' + ImmediatePurgeDataOn30Days: immediatePurgeDataOn30Days + IngestionMode: 'LogAnalytics' + publicNetworkAccessForIngestion: publicNetworkAccessForIngestion + publicNetworkAccessForQuery: publicNetworkAccessForQuery + Request_Source: 'rest' + WorkspaceResourceId: workspaceId + } +} + +//******************************************** +// Outputs +//******************************************** + +output id string = applicationInsights.id +output name string = applicationInsights.name +output connectionString string = applicationInsights.properties.ConnectionString +output instrumentationKey string = applicationInsights.properties.InstrumentationKey diff --git a/samples/function-app-service-bus/dotnet/bicep/modules/function-app.bicep b/samples/function-app-service-bus/dotnet/bicep/modules/function-app.bicep new file mode 100644 index 0000000..72a7574 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/bicep/modules/function-app.bicep @@ -0,0 +1,219 @@ +//******************************************** +// Parameters +//******************************************** + +@description('Specifies a globally unique name the Azure Functions App.') +param name string + +@description('Specifies the location.') +param location string = resourceGroup().location + +@description('Specifies the kind of the hosting plan.') +@allowed([ + 'app' // Windows Web app + 'app,linux' // Linux Web app + 'app,linux,container' // Linux Container Web app + 'hyperV' // Windows Container Web App + 'app,container,windows' // Windows Container Web App + 'app,linux,kubernetes' // Linux Web App on ARC + 'app,linux,container,kubernetes' // Linux Container Web App on ARC + 'functionapp' // Function Code App + 'functionapp,linux' // Linux Consumption Function app + 'functionapp,linux,container,kubernetes' // Function Container App on ARC + 'functionapp,linux,kubernetes' // Function Code App on ARC +]) +param kind string = 'functionapp,linux' + +@description('Specifies the language runtime used by the Azure Functions App.') +@allowed([ + 'dotnet' + 'dotnet-isolated' + 'python' + 'java' + 'node' + 'powerShell' + 'custom' +]) +param runtimeName string + +@description('Specifies the target language version used by the Azure Functions App.') +param runtimeVersion string + +@description('Specifies the minimum TLS version for the Azure Functions App.') +@allowed([ + '1.0' + '1.1' + '1.2' + '1.3' +]) +param minTlsVersion string = '1.2' + +@description('Specifies whether the public network access is enabled or disabled') +@allowed([ + 'Enabled' + 'Disabled' +]) +param publicNetworkAccess string = 'Enabled' + +@description('Specifies whether Always On is enabled for the Azure Functions App.') +param alwaysOn bool = true + +@description('Specifies whether HTTPS is enforced for the Azure Functions App.') +param httpsOnly bool = true + +@description('Specifies the type of managed identity.') +@allowed([ + 'SystemAssigned' + 'UserAssigned' +]) +param managedIdentityType string = 'UserAssigned' + +@description('Specifies the name of a user-assigned managed identity.') +param managedIdentityName string = '' + +@description('Specifies the name of the hosting plan.') +param hostingPlanName string + +@description('Specifies allowed origins for client-side CORS requests on the site.') +param allowedCorsOrigins string[] = [] + +@description('Specifies the name of the virtual network.') +param virtualNetworkName string + +@description('Specifies the name of the subnet used by Azure Functions for the regional virtual network integration.') +param subnetName string + +@description('Specifies the app settings of the Azure Functions App') +param settings array = [] + +@description('Specifies the resource id of the Log Analytics workspace.') +param workspaceId string + +@description('Specifies the optional Git Repo URL.') +param repoUrl string = ' ' + +@description('Specifies the resource tags.') +param tags object + +//******************************************** +// Variables +//******************************************** + +// Generates a unique container name for deployments. +var diagnosticSettingsName = 'diagnosticSettings' +var logCategories = [ + 'FunctionAppLogs' + 'AppServiceAuthenticationLogs' +] +var metricCategories = [ + 'AllMetrics' +] +var logs = [ + for category in logCategories: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: 0 + } + } +] +var metrics = [ + for category in metricCategories: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: 0 + } + } +] + +//******************************************** +// Resources +//******************************************** + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2025-01-31-preview' existing = { + name: managedIdentityName +} + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2025-05-01' existing = { + name: virtualNetworkName +} + +resource subnet 'Microsoft.Network/virtualNetworks/subnets@2025-05-01' existing = { + parent: virtualNetwork + name: subnetName +} + +resource hostingPlan 'Microsoft.Web/serverfarms@2025-03-01' existing = { + name: hostingPlanName +} + +resource functionApp 'Microsoft.Web/sites@2025-03-01' = { + name: name + location: location + kind: kind + tags: tags + identity: { + type: managedIdentityType + userAssignedIdentities : managedIdentityType == 'SystemAssigned' ? null : { + '${managedIdentity.id}': {} + } + } + properties: { + httpsOnly: httpsOnly + serverFarmId: hostingPlan.id + virtualNetworkSubnetId: subnet.id + outboundVnetRouting: { + allTraffic: true + } + siteConfig: { + minTlsVersion: minTlsVersion + alwaysOn: alwaysOn + linuxFxVersion: toUpper('${runtimeName}|${runtimeVersion}') + cors: { + allowedOrigins: union(['https://portal.azure.com', 'https://ms.portal.azure.com'], allowedCorsOrigins) + } + publicNetworkAccess: publicNetworkAccess + appSettings: [ + for setting in settings: { + name: setting.name + value: setting.value + } + ] + netFrameworkVersion: runtimeName == 'dotnet' || runtimeName == 'dotnet-isolated' ? runtimeVersion : null + nodeVersion: runtimeName == 'node' ? runtimeVersion : null + pythonVersion: runtimeName == 'python' ? runtimeVersion : null + javaVersion: runtimeName == 'java' ? runtimeVersion : null + } + } +} + +resource webAppSourceControl 'Microsoft.Web/sites/sourcecontrols@2024-11-01' = if (contains(repoUrl,'http')){ + name: 'web' + parent: functionApp + properties: { + repoUrl: repoUrl + branch: 'master' + isManualIntegration: true + } +} + +resource diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if(!empty(workspaceId)) { + name: diagnosticSettingsName + scope: functionApp + properties: { + workspaceId: workspaceId + logs: logs + metrics: metrics + } +} + +//******************************************** +// Outputs +//******************************************** + +output id string = functionApp.id +output name string = functionApp.name +output defaultHostName string = functionApp.properties.defaultHostName diff --git a/samples/function-app-service-bus/dotnet/bicep/modules/log-analytics.bicep b/samples/function-app-service-bus/dotnet/bicep/modules/log-analytics.bicep new file mode 100644 index 0000000..2618829 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/bicep/modules/log-analytics.bicep @@ -0,0 +1,45 @@ +//******************************************** +// Parameters +//******************************************** +@description('Specifies the name of the Log Analytics workspace.') +param name string + +@description('Specifies the location.') +param location string = resourceGroup().location + +@description('Specifies the service tier of the workspace: Free, Standalone, PerNode, Per-GB.') +@allowed([ + 'Free' + 'Standalone' + 'PerNode' + 'PerGB2018' +]) +param sku string = 'PerNode' + +@description('Specifies the workspace data retention in days. -1 means Unlimited retention for the Unlimited Sku. 730 days is the maximum allowed for all other Skus.') +param retentionInDays int = 60 + +@description('Specifies the resource tags.') +param tags object + +//******************************************** +// Resources +//******************************************** +resource workspace 'Microsoft.OperationalInsights/workspaces@2025-07-01' = { + name: name + tags: tags + location: location + properties: { + sku: { + name: sku + } + retentionInDays: retentionInDays + } +} + +//******************************************** +// Outputs +//******************************************** +output id string = workspace.id +output name string = workspace.name +output customerId string = workspace.properties.customerId diff --git a/samples/function-app-service-bus/dotnet/bicep/modules/managed-identity.bicep b/samples/function-app-service-bus/dotnet/bicep/modules/managed-identity.bicep new file mode 100644 index 0000000..83ff9ef --- /dev/null +++ b/samples/function-app-service-bus/dotnet/bicep/modules/managed-identity.bicep @@ -0,0 +1,142 @@ +//******************************************** +// Parameters +//******************************************** + +@description('Specifies the name of the user-defined managed identity.') +param name string + +@description('Specifies the location.') +param location string = resourceGroup().location + +@description('Specifies the name for the Azure Storage Account resource.') +param storageAccountName string + +@description('Specifies the name of the Azure Application Insights.') +param applicationInsightsName string + +@description('Specifies the name for the Azure Service Bus namespace.') +param serviceBusName string + +@description('Specifies the resource tags.') +param tags object + +//******************************************** +// Resources +//******************************************** + +resource storageAccount 'Microsoft.Storage/storageAccounts@2025-06-01' existing = { + name: storageAccountName +} + +resource applicationInsights 'Microsoft.Insights/components@2020-02-02' existing = { + name: applicationInsightsName +} + +resource namespace 'Microsoft.ServiceBus/namespaces@2025-05-01-preview' existing = { + name: serviceBusName +} + +resource storageAccountContributorRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '17d1049b-9a84-46fb-8f53-869881c3d3ab' + scope: subscription() +} + +resource storageBlobDataOwnerRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: 'b7e6dc6d-f1e8-4753-8033-0f276bb0955b' + scope: subscription() +} + +resource storageQueueDataContributorRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '974c5e8b-45b9-4653-ba55-5f855dd0fb88' + scope: subscription() +} + +resource storageTableDataContributorRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3' + scope: subscription() +} + +resource azureServiceBusDataOwnerRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '090c5cfd-751d-490a-894a-3ce6f1109419' + scope: subscription() +} + +resource monitoringMetricsPublisherRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = { + name: '3913510d-42f4-4e42-8a64-420c390055eb' + scope: subscription() +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2025-01-31-preview' = { + name: name + location: location + tags: tags +} + +resource storageAccountContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(storageAccount.id, managedIdentity.id, storageAccountContributorRoleDefinition.id) + scope: storageAccount + properties: { + roleDefinitionId: storageAccountContributorRoleDefinition.id + principalId: managedIdentity.properties.principalId + principalType: 'ServicePrincipal' + } +} + +resource storageBlobDataOwnerRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(storageAccount.id, managedIdentity.id, storageBlobDataOwnerRoleDefinition.id) + scope: storageAccount + properties: { + roleDefinitionId: storageBlobDataOwnerRoleDefinition.id + principalId: managedIdentity.properties.principalId + principalType: 'ServicePrincipal' + } +} + +resource storageQueueDataContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(storageAccount.id, managedIdentity.id, storageQueueDataContributorRoleDefinition.id) + scope: storageAccount + properties: { + roleDefinitionId: storageQueueDataContributorRoleDefinition.id + principalId: managedIdentity.properties.principalId + principalType: 'ServicePrincipal' + } +} + +resource storageTableDataContributorRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(storageAccount.id, managedIdentity.id, storageTableDataContributorRoleDefinition.id) + scope: storageAccount + properties: { + roleDefinitionId: storageTableDataContributorRoleDefinition.id + principalId: managedIdentity.properties.principalId + principalType: 'ServicePrincipal' + } +} + +resource azureServiceBusDataOwnerRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(namespace.id, managedIdentity.id, azureServiceBusDataOwnerRoleDefinition.id) + scope: namespace + properties: { + roleDefinitionId: azureServiceBusDataOwnerRoleDefinition.id + principalId: managedIdentity.properties.principalId + principalType: 'ServicePrincipal' + } +} + +resource monitoringMetricsPublisherRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(applicationInsights.id, managedIdentity.id, monitoringMetricsPublisherRoleDefinition.id) + scope: applicationInsights + properties: { + roleDefinitionId: monitoringMetricsPublisherRoleDefinition.id + principalId: managedIdentity.properties.principalId + principalType: 'ServicePrincipal' + } +} + +//******************************************** +// Outputs +//******************************************** + +output id string = managedIdentity.id +output name string = managedIdentity.name +output clientId string = managedIdentity.properties.clientId +output principalId string = managedIdentity.properties.principalId diff --git a/samples/function-app-service-bus/dotnet/bicep/modules/private-dns-zone.bicep b/samples/function-app-service-bus/dotnet/bicep/modules/private-dns-zone.bicep new file mode 100644 index 0000000..d849259 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/bicep/modules/private-dns-zone.bicep @@ -0,0 +1,41 @@ +//******************************************** +// Parameters +//******************************************** +@description('Specifies the name of the private DNS zone.') +param name string + +@description('Specifies the resource ID of the virtual network where private endpoints will be created.') +param vnetId string + +@description('Specifies the resource tags.') +param tags object + +//******************************************** +// Resources +//******************************************** + +// Private DNS Zones +resource privateDnsZone 'Microsoft.Network/privateDnsZones@2024-06-01' = { + name: name + location: 'global' + tags: tags +} + +// Virtual Network Links +resource privateDnsZoneVirtualNetworkLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2024-06-01' = { + parent: privateDnsZone + name: 'link-to-vnet' + location: 'global' + properties: { + registrationEnabled: false + virtualNetwork: { + id: vnetId + } + } +} + +//******************************************** +// Outputs +//******************************************** +output id string = privateDnsZone.id +output name string = privateDnsZone.name diff --git a/samples/function-app-service-bus/dotnet/bicep/modules/private-endpoint.bicep b/samples/function-app-service-bus/dotnet/bicep/modules/private-endpoint.bicep new file mode 100644 index 0000000..e758fa7 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/bicep/modules/private-endpoint.bicep @@ -0,0 +1,69 @@ +//******************************************** +// Parameters +//******************************************** +@description('Specifies the name of the private endpoint.') +param name string + +@description('Specifies the location.') +param location string = resourceGroup().location + +@description('Specifies the resource ID of the subnet where private endpoints will be created.') +param subnetId string + +@description('Specifies the group IDs for the private link service connection.') +param groupIds array + +@description('Specifies the resource ID of the target resource.') +param privateLinkServiceId string + +@description('Specifies the resource ID of the private DNS zone.') +param privateDnsZoneId string + +@description('Specifies the resource tags.') +param tags object + +//******************************************** +// Resources +//******************************************** + +// Private Endpoints +resource privateEndpoint 'Microsoft.Network/privateEndpoints@2025-05-01' = { + name: name + location: location + tags: tags + properties: { + privateLinkServiceConnections: [ + { + name: '${name}-pls-connection' + properties: { + privateLinkServiceId: privateLinkServiceId + groupIds: groupIds + } + } + ] + subnet: { + id: subnetId + } + } +} + +resource privateDnsZoneGroupName 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2025-05-01' = { + parent: privateEndpoint + name: 'private-dns-zone-group' + properties: { + privateDnsZoneConfigs: [ + { + name: 'dnsConfig' + properties: { + privateDnsZoneId: privateDnsZoneId + } + } + ] + } +} + +//******************************************** +// Outputs +//******************************************** +output id string = privateEndpoint.id +output name string = privateEndpoint.name diff --git a/samples/function-app-service-bus/dotnet/bicep/modules/service-bus.bicep b/samples/function-app-service-bus/dotnet/bicep/modules/service-bus.bicep new file mode 100644 index 0000000..96e1780 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/bicep/modules/service-bus.bicep @@ -0,0 +1,108 @@ +// Parameters +@description('Specifies the name of the Service Bus namespace.') +param name string + +@description('Enabling this property creates a Premium Service Bus Namespace in regions supported availability zones.') +param zoneRedundant bool = true + +@description('Specifies the name of Service Bus namespace SKU.') +@allowed([ + 'Basic' + 'Premium' + 'Standard' +]) +param skuName string = 'Premium' + +@description('Specifies the messaging units for the Service Bus namespace. For Premium tier, capacity are 1,2 and 4.') +param capacity int = 1 + +@description('Specifies a list of queue names.') +param queueNames array = [] + +@description('Specifies the lock duration of the queue.') +param queueLockDuration string = 'PT5M' + +@description('Specifies the resource id of the Log Analytics workspace.') +param workspaceId string + +@description('Specifies the location.') +param location string = resourceGroup().location + +@description('Specifies the resource tags.') +param tags object + +// Variables +var diagnosticSettingsName = 'diagnosticSettings' +var logCategories = [ + 'OperationalLogs' + 'VNetAndIPFilteringLogs' + 'RuntimeAuditLogs' + 'ApplicationMetricsLogs' +] +var metricCategories = [ + 'AllMetrics' +] +var logs = [for category in logCategories: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: 0 + } +}] +var metrics = [for category in metricCategories: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: 0 + } +}] + +// Resources +resource namespace 'Microsoft.ServiceBus/namespaces@2025-05-01-preview' = { + name: name + location: location + tags: tags + sku: { + name: skuName + capacity: capacity + } + properties: { + zoneRedundant: zoneRedundant + } +} + +resource queue 'Microsoft.ServiceBus/namespaces/queues@2025-05-01-preview' = [for queueName in queueNames: { + parent: namespace + name: queueName + properties: { + lockDuration: queueLockDuration + maxSizeInMegabytes: 1024 + requiresDuplicateDetection: false + requiresSession: false + defaultMessageTimeToLive: 'P10675199DT2H48M5.4775807S' + deadLetteringOnMessageExpiration: false + duplicateDetectionHistoryTimeWindow: 'PT10M' + maxDeliveryCount: 10 + autoDeleteOnIdle: 'P10675199DT2H48M5.4775807S' + enablePartitioning: false + enableExpress: false + } +}] + +resource diagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + name: diagnosticSettingsName + scope: namespace + properties: { + workspaceId: workspaceId + logs: logs + metrics: metrics + } +} + +// Outputs +output id string = namespace.id +output name string = namespace.name +output queueIds array = [for i in range(0, length(queueNames)): queue[i].id] +output queueNames array = [for i in range(0, length(queueNames)): queue[i].name] diff --git a/samples/function-app-service-bus/dotnet/bicep/modules/storage-account.bicep b/samples/function-app-service-bus/dotnet/bicep/modules/storage-account.bicep new file mode 100644 index 0000000..69c1458 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/bicep/modules/storage-account.bicep @@ -0,0 +1,265 @@ +//******************************************** +// Parameters +//******************************************** + +@description('Specifies the name for the Azure Storage Account resource.') +param name string + +@description('Specifies the location.') +param location string = resourceGroup().location + +@description('Specifies whether to allow public network access for the storage account.') +@allowed([ + 'Disabled' + 'Enabled' +]) +param publicNetworkAccess string = 'Disabled' + +@description('Specifies the resource id of the Log Analytics workspace.') +param workspaceId string + +@description('Specifies the the storage SKU.') +@allowed([ + 'Standard_LRS' + 'Standard_ZRS' + 'Standard_GRS' + 'Standard_GZRS' + 'Standard_RAGRS' + 'Standard_RAGZRS' + 'Premium_LRS' + 'Premium_ZRS' +]) +param skuName string = 'Standard_LRS' + +@description('Specifies the access tier of the storage account. The default value is Hot.') +param accessTier string = 'Hot' + +@description('Specifies whether the storage account allows public access to blobs.') +param allowBlobPublicAccess bool = true + +@description('Specifies whether the storage account allows shared key access.') +param allowSharedKeyAccess bool = true + +@description('Specifies whether the storage account allows cross-tenant replication.') +param allowCrossTenantReplication bool = false + +@description('Specifies the minimum TLS version to be permitted on requests to storage. The default value is TLS1_2.') +param minimumTlsVersion string = 'TLS1_2' + +@description('The default action of allow or deny when no other rules match. Allowed values: Allow or Deny') +@allowed([ + 'Allow' + 'Deny' +]) +param networkAclsDefaultAction string = 'Deny' + +@description('Specifies whether Hierarchical Namespace is enabled.') +param isHnsEnabled bool = false + +@description('Specifies whether NFSv3 is enabled.') +param isNfsV3Enabled bool = false + +@description('Specifies the key expiration period in days.') +param keyExpirationPeriodInDays int = 7 + +@description('Specifies whether the storage account should only support HTTPS traffic.') +param supportsHttpsTrafficOnly bool = true + +@description('Specifies whether large file shares are enabled. The default value is Disabled.') +@allowed([ + 'Disabled' + 'Enabled' +]) +param largeFileSharesState string = 'Disabled' + +@description('Specifies the resource tags.') +param tags object + +@description('Specifies whether to create containers.') +param createContainers bool = false + +@description('Specifies an array of containers to create.') +param containerNames array = [] + +@description('Specifies whether to create file shares.') +param createFileShares bool = false + +@description('Specifies an array of file shares to create.') +param fileShareNames array = [] + +//******************************************** +// Variables +//******************************************** + +var diagnosticSettingsName = 'diagnosticSettings' +var logCategories = [ + 'StorageRead' + 'StorageWrite' + 'StorageDelete' +] +var metricCategories = [ + 'Transaction' +] +var logs = [ + for category in logCategories: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: 0 + } + } +] +var metrics = [ + for category in metricCategories: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: 0 + } + } +] + +//******************************************** +// Resources +//******************************************** + +resource storageAccount 'Microsoft.Storage/storageAccounts@2025-06-01' = { + name: name + location: location + tags: tags + sku: { + name: skuName + } + kind: 'StorageV2' + + // Containers live inside of a blob service + resource blobService 'blobServices' = { + name: 'default' + + // Creating containers with provided names if contition is true + resource containers 'containers' = [ + for containerName in containerNames: if (createContainers) { + name: containerName + properties: { + publicAccess: 'None' + } + } + ] + } + + resource queueService 'queueServices' = { + name: 'default' + } + + resource tableService 'tableServices' = { + name: 'default' + } + + resource fileService 'fileServices' = { + name: 'default' + + // Creating file shares with provided names if contition is true + resource shares 'shares' = [ + for fileShareName in fileShareNames: if (createFileShares) { + name: fileShareName + properties: { + enabledProtocols: 'SMB' + shareQuota: 100 // Quota in GB (adjust as needed) + } + } + ] + } + + properties: { + publicNetworkAccess: publicNetworkAccess + accessTier: accessTier + allowBlobPublicAccess: allowBlobPublicAccess + allowCrossTenantReplication: allowCrossTenantReplication + allowSharedKeyAccess: allowSharedKeyAccess + encryption: { + keySource: 'Microsoft.Storage' + requireInfrastructureEncryption: false + services: { + blob: { + enabled: true + keyType: 'Account' + } + file: { + enabled: true + keyType: 'Account' + } + queue: { + enabled: true + keyType: 'Service' + } + table: { + enabled: true + keyType: 'Service' + } + } + } + isHnsEnabled: isHnsEnabled + isNfsV3Enabled: isNfsV3Enabled + keyPolicy: { + keyExpirationPeriodInDays: keyExpirationPeriodInDays + } + largeFileSharesState: largeFileSharesState + minimumTlsVersion: minimumTlsVersion + networkAcls: { + bypass: 'AzureServices' + defaultAction: networkAclsDefaultAction + } + supportsHttpsTrafficOnly: supportsHttpsTrafficOnly + } +} + +resource blobServicesDiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + name: '${diagnosticSettingsName}-blobService' + scope: storageAccount::blobService + properties: { + workspaceId: workspaceId + logs: logs + metrics: metrics + } +} + +resource queueServicesDiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + name: '${diagnosticSettingsName}-queueService' + scope: storageAccount::queueService + properties: { + workspaceId: workspaceId + logs: logs + metrics: metrics + } +} + + +resource tableServicesDiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + name: '${diagnosticSettingsName}-tableService' + scope: storageAccount::tableService + properties: { + workspaceId: workspaceId + logs: logs + metrics: metrics + } +} + +resource fileServicesDiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { + name: '${diagnosticSettingsName}-fileService' + scope: storageAccount::fileService + properties: { + workspaceId: workspaceId + logs: logs + metrics: metrics + } +} + +//******************************************** +// Outputs +//******************************************** + +output id string = storageAccount.id +output name string = storageAccount.name +output connectionString string = 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};AccountKey=${storageAccount.listKeys().keys[0].value};EndpointSuffix=${environment().suffixes.storage}' diff --git a/samples/function-app-service-bus/dotnet/bicep/modules/virtual-network.bicep b/samples/function-app-service-bus/dotnet/bicep/modules/virtual-network.bicep new file mode 100644 index 0000000..15a0d98 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/bicep/modules/virtual-network.bicep @@ -0,0 +1,239 @@ +//******************************************** +// Parameters +//******************************************** +@description('Specifies the name of the virtual network.') +param virtualNetworkName string + +@description('Specifies the location.') +param location string = resourceGroup().location + +@description('Specifies the address prefixes of the virtual network.') +param virtualNetworkAddressPrefixes string = '10.0.0.0/8' + +@description('Specifies the name of the subnet used by the Web App for the regional virtual network integration.') +param functionAppSubnetName string = 'functionAppSubnet' + +@description('Specifies the address prefix of the subnet used by the Web App for the regional virtual network integration.') +param functionAppSubnetAddressPrefix string = '10.0.0.0/24' + +@description('Specifies the name of the network security group associated to the subnet hosting the Web App.') +param functionAppSubnetNsgName string = '' + +@description('Specifies the name of the subnet which contains the private endpoint to the Azure CosmosDB for MongoDB API account.') +param peSubnetName string = 'pe-subnet' + +@description('Specifies the address prefix of the subnet which contains the private endpoint to the Azure CosmosDB for MongoDB API account.') +param peSubnetAddressPrefix string = '10.0.1.0/24' + +@description('Specifies the name of the network security group associated to the subnet hosting the private endpoint to the Azure CosmosDB for MongoDB API account.') +param peSubnetNsgName string = '' + +@description('Specifies the name of the Azure NAT Gateway.') +param natGatewayName string + +@description('Specifies a list of availability zones denoting the zone in which Nat Gateway should be deployed.') +param natGatewayZones array = [] + +@description('Specifies the name of the public IP prefix for the Azure NAT Gateway.') +param natGatewayPublicIpPrefixName string + +@description('Specifies the length of the Public IP Prefix.') +@minValue(28) +@maxValue(32) +param natGatewayPublicIpPrefixLength int = 31 + +@description('Specifies the idle timeout in minutes for the Azure NAT Gateway.') +param natGatewayIdleTimeoutMins int = 30 + +@description('Specifies the delegation service name.') +param delegationServiceName string + +@description('Specifies the resource id of the Log Analytics workspace.') +param workspaceId string + +@description('Specifies the resource tags.') +param tags object + +//******************************************** +// Variables +//******************************************** +var diagnosticSettingsName = 'default' +var nsgLogCategories = [ + 'NetworkSecurityGroupEvent' + 'NetworkSecurityGroupRuleCounter' +] +var nsgLogs = [for category in nsgLogCategories: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: 0 + } +}] +var vnetLogCategories = [ + 'VMProtectionAlerts' +] +var vnetMetricCategories = [ + 'AllMetrics' +] +var vnetLogs = [for category in vnetLogCategories: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: 0 + } +}] +var vnetMetrics = [for category in vnetMetricCategories: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: 0 + } +}] + +//******************************************** +// Resources +//******************************************** + +// Virtual Network +resource vnet 'Microsoft.Network/virtualNetworks@2024-03-01' = { + name: virtualNetworkName + location: location + tags: tags + properties: { + addressSpace: { + addressPrefixes: [ + virtualNetworkAddressPrefixes + ] + } + subnets: [ + { + name: functionAppSubnetName + properties: { + addressPrefix: functionAppSubnetAddressPrefix + privateEndpointNetworkPolicies: 'Disabled' + privateLinkServiceNetworkPolicies: 'Disabled' + networkSecurityGroup: { + id: functionAppSubnetNsg.id + } + natGateway: { + id: natGateway.id + } + delegations: [ + { + name: 'delegation' + properties: { + serviceName: delegationServiceName + } + } + ] + } + } + { + name: peSubnetName + properties: { + addressPrefix: peSubnetAddressPrefix + networkSecurityGroup: { + id: peSubnetNsg.id + } + privateEndpointNetworkPolicies: 'Disabled' + privateLinkServiceNetworkPolicies: 'Disabled' + natGateway: { + id: natGateway.id + } + } + } + ] + } +} + +resource functionAppSubnetNsg 'Microsoft.Network/networkSecurityGroups@2025-05-01' = { + name: functionAppSubnetNsgName + location: location + tags: tags + properties: { + securityRules: [ + ] + } +} + +resource peSubnetNsg 'Microsoft.Network/networkSecurityGroups@2025-05-01' = { + name: peSubnetNsgName + location: location + tags: tags + properties: { + securityRules: [ + ] + } +} + +// NAT Gateway +resource natGatewayPublicIpPrefix 'Microsoft.Network/publicIPPrefixes@2025-05-01' = { + name: natGatewayPublicIpPrefixName + location: location + sku: { + name: 'Standard' + } + zones: !empty(natGatewayZones) ? natGatewayZones : [] + properties: { + publicIPAddressVersion: 'IPv4' + prefixLength: natGatewayPublicIpPrefixLength + } +} + +resource natGateway 'Microsoft.Network/natGateways@2025-05-01' = { + name: natGatewayName + location: location + sku: { + name: 'Standard' + } + zones: !empty(natGatewayZones) ? natGatewayZones : [] + properties: { + publicIpPrefixes: [ + { + id: natGatewayPublicIpPrefix.id + } + ] + idleTimeoutInMinutes: natGatewayIdleTimeoutMins + } +} + +resource peSubnetNsgDiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(workspaceId)) { + name: diagnosticSettingsName + scope: peSubnetNsg + properties: { + workspaceId: workspaceId + logs: nsgLogs + } +} + +resource functionAppSubnetNsgDiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(workspaceId)) { + name: diagnosticSettingsName + scope: functionAppSubnetNsg + properties: { + workspaceId: workspaceId + logs: nsgLogs + } +} + +resource vnetDiagnosticSettings 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if (!empty(workspaceId)) { + name: diagnosticSettingsName + scope: vnet + properties: { + workspaceId: workspaceId + logs: vnetLogs + metrics: vnetMetrics + } +} + +//******************************************** +// Outputs +//******************************************** +output virtualNetworkId string = vnet.id +output virtualNetworkName string = vnet.name +output functionAppSubnetId string = resourceId('Microsoft.Network/virtualNetworks/subnets', vnet.name, functionAppSubnetName) +output functionAppSubnetName string = functionAppSubnetName +output peSubnetId string = resourceId('Microsoft.Network/virtualNetworks/subnets', vnet.name, peSubnetName) +output peSubnetName string = peSubnetName diff --git a/samples/function-app-service-bus/dotnet/images/architecture.png b/samples/function-app-service-bus/dotnet/images/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..4498534276c0bc817c267cf7fca8376038bf094b GIT binary patch literal 99495 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 R41Bt>w77y;nTVnP{{k{)1?2z$ literal 0 HcmV?d00001 diff --git a/samples/function-app-service-bus/dotnet/scripts/README.md b/samples/function-app-service-bus/dotnet/scripts/README.md new file mode 100644 index 0000000..cfac814 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/scripts/README.md @@ -0,0 +1,285 @@ +# Azure CLI Deployment + +This directory includes Bash scripts designed for deploying and testing the sample function app utilizing the `azlocal` CLI. For further details about the sample application, refer to the [Azure Functions App with Service Bus Messaging](../README.md). + +## Prerequisites + +Before deploying this solution, ensure you have the following tools installed: + +- [Azure Subscription](https://azure.microsoft.com/free/) +- [LocalStack for Azure](https://azure.localstack.cloud/): Local Azure cloud emulator for development and testing +- [Visual Studio Code](https://code.visualstudio.com/): Code editor installed on one of the [supported platforms](https://code.visualstudio.com/docs/supporting/requirements#_platforms) +- [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli): Azure command-line interface +- [Azlocal CLI](https://azure.localstack.cloud/user-guides/sdks/az/): LocalStack Azure CLI wrapper +- [Azure Functions Core Tools](https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local) is required to build, run, and deploy the Azure Functions app locally +- [Docker](https://docs.docker.com/get-docker/): Container runtime required for LocalStack +- [.NET SDK](https://dotnet.microsoft.com/en-us/download) is required to compile and run the C# Azure Functions project +- [jq](https://jqlang.org/): JSON processor for scripting and parsing command outputs + +### Installing azlocal CLI + +The [deploy.sh](deploy.sh) Bash script uses the `azlocal` CLI to work with LocalStack. Install it using: + +```bash +pip install azlocal +``` + +For more information, see [Get started with the az tool on LocalStack](https://azure.localstack.cloud/user-guides/sdks/az/). + +## Architecture Overview + +This [deploy.sh](deploy.sh) script creates the following Azure resources using Azure CLI commands: + +1. [Azure Resource Group](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-cli): A logical container scoping all resources in this sample. +2. [Azure Virtual Network](https://learn.microsoft.com/azure/virtual-network/virtual-networks-overview): Hosts two subnets: + - *app-subnet*: Dedicated to [regional VNet integration](https://learn.microsoft.com/azure/azure-functions/functions-networking-options?tabs=azure-portal#outbound-networking-features) with the Function App. + - *pe-subnet*: Used for hosting Azure Private Endpoints. +3. [Azure Private DNS Zones](https://learn.microsoft.com/azure/dns/private-dns-privatednszone): Provide internal DNS resolution so that resources within the virtual network can reach Private Endpoints by hostname rather than public addresses. There is a separate Azure Private DNS Zone for the following resource types: + - Azure Service Bus namespace + - Azure Blob Storage + - Azure Queue Storage + - Azure Table Storage +4. [Azure Private Endpoints](https://learn.microsoft.com/azure/private-link/private-endpoint-overview): Provide secure, private network connectivity to Azure resources by exposing them through private IP addresses within the virtual network, eliminating the need for traffic to traverse the public internet. There is a separate Azure Private Endpoint for the following resources: + - Azure Service Bus namespace + - Azure Blob Storage + - Azure Queue Storage + - Azure Table Storage +5. [Azure NAT Gateway](https://learn.microsoft.com/azure/nat-gateway/nat-overview): Provides deterministic outbound connectivity and a stable public IP address for the Function App's outbound traffic. Included for architectural completeness; the sample app itself does not call any external services. +6. [Azure Network Security Group](https://learn.microsoft.com/en-us/azure/virtual-network/network-security-groups-overview): Enforces inbound and outbound traffic rules across the virtual network's subnets. +7. [Azure Log Analytics Workspace](https://learn.microsoft.com/azure/azure-monitor/logs/log-analytics-overview): Centralizes diagnostic logs and metrics from all resources in the solution, enabling unified querying and analysis across the entire deployment. +8. [Azure App Service Plan](https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview-hosting-plans): Defines the underlying compute tier and scaling behavior for the function app. +9. [Azure Functions App](https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview): Hosts the sample function app. +10. [Azure Application Insights](https://learn.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview): Provides application performance monitoring (APM), collecting and analyzing requests, traces, and metrics generated by the function app to surface performance bottlenecks and failures. +11. [Azure Service Bus](https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messaging-overview): A fully managed enterprise message broker. This namespace hosts the `input` and `output` queues used by the function app to exchange messages asynchronously. +12. [Azure Storage Account](https://learn.microsoft.com/en-us/azure/storage/common/storage-account-overview): Provides durable storage used internally by the Azure Functions runtime for state management, including distributed locks, checkpoints, and timer trigger coordination. +13. [User-Assigned Managed Identity](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview): This identity is assigned the necessary RBAC roles and is used by the function app to authenticate securely—without storing credentials—to the following Azure resources: + - Azure Service Bus namespace + - Azure Storage + - Azure Application Insights + +For more information on the sample application, see [Azure Functions App with Service Bus Messaging](../README.md). + +## Deployment + +You can set up the Azure emulator by utilizing LocalStack for Azure Docker image. Before starting, ensure you have a valid `LOCALSTACK_AUTH_TOKEN` to access the Azure emulator. Refer to the [Auth Token guide](https://docs.localstack.cloud/getting-started/auth-token/?__hstc=108988063.8aad2b1a7229945859f4d9b9bb71e05d.1743148429561.1758793541854.1758810151462.32&__hssc=108988063.3.1758810151462&__hsfp=3945774529) to obtain your Auth Token and specify it in the `LOCALSTACK_AUTH_TOKEN` environment variable. The Azure Docker image is available on the [LocalStack Docker Hub](https://hub.docker.com/r/localstack/localstack-azure-alpha). To pull the Azure Docker image, execute the following command: + +```bash +docker pull localstack/localstack-azure-alpha +``` + +Start the LocalStack Azure emulator using the localstack CLI, execute the following command: + +```bash +export LOCALSTACK_AUTH_TOKEN= +IMAGE_NAME=localstack/localstack-azure-alpha localstack start +``` + +Navigate to the `scripts` folder: + +```bash +cd samples/function-app-service-bus/dotnet/scripts +``` + +Make the script executable: + +```bash +chmod +x deploy.sh +``` + +Run the deployment script: + +```bash +./deploy.sh +``` + +## Validation + +Once the deployment completes, run the [validate.sh](../scripts/validate.sh) script to confirm that all resources were provisioned and configured as expected: + +```bash +#!/bin/bash + +# Variables +PREFIX='local' +SUFFIX='test' +RESOURCE_GROUP_NAME="${PREFIX}-rg" +LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" +FUNCTION_APP_SUBNET_NSG_NAME="${PREFIX}-func-subnet-nsg-${SUFFIX}" +PE_SUBNET_NSG_NAME="${PREFIX}-pe-subnet-nsg-${SUFFIX}" +NAT_GATEWAY_NAME="${PREFIX}-nat-gateway-${SUFFIX}" +VIRTUAL_NETWORK_NAME="${PREFIX}-vnet-${SUFFIX}" +APP_SERVICE_PLAN_NAME="${PREFIX}-plan-${SUFFIX}" +FUNCTION_APP_NAME="${PREFIX}-func-${SUFFIX}" +SERVICE_BUS_NAMESPACE_NAME="${PREFIX}-service-bus-${SUFFIX}" +STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}" +APPLICATION_INSIGHTS_NAME="${PREFIX}-func-${SUFFIX}" +ENVIRONMENT=$(az account show --query environmentName --output tsv) +PRIVATE_DNS_ZONE_NAMES=( + "privatelink.servicebus.windows.net" + "privatelink.blob.core.windows.net" + "privatelink.queue.core.windows.net" + "privatelink.table.core.windows.net" +) +PE_NAMES=( + "${PREFIX}-service-bus-pe-${SUFFIX}" + "${PREFIX}-blob-storage-pe-${SUFFIX}" + "${PREFIX}-queue-storage-pe-${SUFFIX}" + "${PREFIX}-table-storage-pe-${SUFFIX}" +) + +# Choose the appropriate CLI based on the environment +if [[ $ENVIRONMENT == "LocalStack" ]]; then + echo "Using azlocal for LocalStack emulator environment." + AZ="azlocal" +else + echo "Using standard az for AzureCloud environment." + AZ="az" +fi + +# Check resource group +echo -e "[$RESOURCE_GROUP_NAME] resource group:\n" +$AZ group show \ + --name "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check App Service Plan +echo -e "\n[$APP_SERVICE_PLAN_NAME] app service plan:\n" +$AZ appservice plan show \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --name "$APP_SERVICE_PLAN_NAME" \ + --output table \ + --only-show-errors + +# Check Azure Functions App +echo -e "\n[$FUNCTION_APP_NAME] function app:\n" +$AZ functionapp show \ + --name "$FUNCTION_APP_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Service Bus Namespace +echo -e "\n[$SERVICE_BUS_NAMESPACE_NAME] service bus namespace:\n" +$AZ servicebus namespace show \ + --name "$SERVICE_BUS_NAMESPACE_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --query '{Name:name,ServiceBusEndpoint:serviceBusEndpoint}' \ + --only-show-errors + +# Check Service Bus Queues +echo -e "\n[$SERVICE_BUS_NAMESPACE_NAME] service bus queues:\n" +$AZ servicebus queue list \ + --namespace-name "$SERVICE_BUS_NAMESPACE_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --query '[].{Name:name,Status:status}' \ + --only-show-errors + + # Check Application Insights +echo -e "\n[$APPLICATION_INSIGHTS_NAME] application insights:\n" +$AZ monitor app-insights component show \ + --app "$APPLICATION_INSIGHTS_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query '{Name:name,Location:location,ResourceGroup:resourceGroup}' \ + --output table \ + --only-show-errors + +# Check Storage Account +echo -e "\n[$STORAGE_ACCOUNT_NAME] storage account:\n" +$AZ storage account show \ + --name "$STORAGE_ACCOUNT_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query '{Name:name,Location:primaryLocation,ResourceGroup:resourceGroup}' \ + --output table \ + --only-show-errors + +# Check Log Analytics Workspace +echo -e "\n[$LOG_ANALYTICS_NAME] log analytics workspace:\n" +$AZ monitor log-analytics workspace show \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --workspace-name "$LOG_ANALYTICS_NAME" \ + --query '{Name:name,Location:location,ResourceGroup:resourceGroup}' \ + --output table \ + --only-show-errors + +# Check NAT Gateway +echo -e "\n[$NAT_GATEWAY_NAME] nat gateway:\n" +$AZ network nat gateway show \ + --name "$NAT_GATEWAY_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Virtual Network +echo -e "\n[$VIRTUAL_NETWORK_NAME] virtual network:\n" +$AZ network vnet show \ + --name "$VIRTUAL_NETWORK_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Private DNS Zone +for PRIVATE_DNS_ZONE_NAME in "${PRIVATE_DNS_ZONE_NAMES[@]}"; do + echo -e "\n[$PRIVATE_DNS_ZONE_NAME] private dns zone:\n" + $AZ network private-dns zone show \ + --name "$PRIVATE_DNS_ZONE_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query '{Name:name,ResourceGroup:resourceGroup,RecordSets:recordSets,VirtualNetworkLinks:virtualNetworkLinks}' \ + --output table \ + --only-show-errors +done + +# Check Private Endpoint +for PRIVATE_ENDPOINT_NAME in "${PE_NAMES[@]}"; do + echo -e "\n[$PRIVATE_ENDPOINT_NAME] private endpoint:\n" + $AZ network private-endpoint show \ + --name "$PRIVATE_ENDPOINT_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors +done + +# Check Functions App Subnet NSG +echo -e "\n[$FUNCTION_APP_SUBNET_NSG_NAME] network security group:\n" +$AZ network nsg show \ + --name "$FUNCTION_APP_SUBNET_NSG_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Private Endpoint Subnet NSG +echo -e "\n[$PE_SUBNET_NSG_NAME] network security group:\n" +$AZ network nsg show \ + --name "$PE_SUBNET_NSG_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# List resources +echo -e "\n[$RESOURCE_GROUP_NAME] all resources:\n" +$AZ resource list \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors +``` + +## Cleanup + +To destroy all created resources: + +```bash +# Delete resource group and all contained resources +az group delete --name local-rg --yes --no-wait + +# Verify deletion +az group list --output table +``` + +This will remove all Azure resources created by the CLI deployment script. + +## Related Documentation + +- [Azure CLI Documentation](https://docs.microsoft.com/en-us/cli/azure/) +- [LocalStack for Azure Documentation](https://azure.localstack.cloud/) \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/scripts/call-http-trigger.sh b/samples/function-app-service-bus/dotnet/scripts/call-http-trigger.sh new file mode 100755 index 0000000..0ca3d53 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/scripts/call-http-trigger.sh @@ -0,0 +1,168 @@ +#!/bin/bash + +get_docker_container_name_by_prefix() { + local app_prefix="$1" + local container_name + + # Check if Docker is running + if ! docker info >/dev/null 2>&1; then + echo "Error: Docker is not running" >&2 + return 1 + fi + + echo "Looking for containers with names starting with [$app_prefix]..." >&2 + + # Find the container using grep + container_name=$(docker ps --format "{{.Names}}" | grep "^${app_prefix}" | head -1) + + if [ -z "$container_name" ]; then + echo "Error: No running container found with name starting with [$app_prefix]" >&2 + return 1 + fi + + echo "Found matching container [$container_name]" >&2 + echo "$container_name" +} + +get_docker_container_ip_address_by_name() { + local container_name="$1" + local ip_address + + if [ -z "$container_name" ]; then + echo "Error: Container name is required" >&2 + return 1 + fi + + # Get IP address + ip_address=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$container_name") + + if [ -z "$ip_address" ]; then + echo "Error: Container [$container_name] has no IP address assigned" >&2 + return 1 + fi + + echo "$ip_address" +} + +get_docker_container_port_mapping() { + local container_name="$1" + local container_port="$2" + local host_port + + if [ -z "$container_name" ] || [ -z "$container_port" ]; then + echo "Error: Container name and container port are required" >&2 + return 1 + fi + + # Get host port mapping + host_port=$(docker inspect -f "{{(index (index .NetworkSettings.Ports \"${container_port}/tcp\") 0).HostPort}}" "$container_name") + + if [ -z "$host_port" ]; then + echo "Error: No host port mapping found for container [$container_name] port [$container_port]" >&2 + return 1 + fi + + echo "$host_port" +} + +call_http_trigger_function() { + # Get the function app name + echo "Getting function app name..." + function_app_name=$(azlocal functionapp list --query '[0].name' --output tsv) + + if [ -n "$function_app_name" ]; then + echo "Function app [$function_app_name] successfully retrieved." + else + echo "Error: No function app found" + exit 1 + fi + + # Get the resource group name + echo "Getting resource group name for function app [$function_app_name]..." + resource_group_name=$(azlocal functionapp list --query '[0].resourceGroup' --output tsv) + + if [ -n "$resource_group_name" ]; then + echo "Resource group [$resource_group_name] successfully retrieved." + else + echo "Error: No resource group found for function app [$function_app_name]" + exit 1 + fi + + # Get the the default host name of the function app + echo "Getting the default host name of the function app [$function_app_name]..." + function_host_name=$(azlocal functionapp show \ + --name "$function_app_name" \ + --resource-group "$resource_group_name" \ + --query 'defaultHostName' \ + --output tsv) + + if [ -n "$function_host_name" ]; then + echo "Function app default host name [$function_host_name] successfully retrieved." + else + echo "Error: No function app default host name found" + exit 1 + fi + + # Get the Docker container name + echo "Finding container name with prefix [ls-$function_app_name]..." + container_name=$(get_docker_container_name_by_prefix "ls-$function_app_name") + + if [ $? -eq 0 ] && [ -n "$container_name" ]; then + echo "Container [$container_name] found successfully" + else + echo "Failed to get container name" + exit 1 + fi + + # Get the container IP address + echo "Getting IP address for container [$container_name]..." + container_ip=$(get_docker_container_ip_address_by_name "$container_name") + greeting_count=10 + + if [ $? -eq 0 ] && [ -n "$container_ip" ]; then + echo "IP address [$container_ip] retrieved successfully for container [$container_name]" + else + echo "Failed to get container IP address" + exit 1 + fi + + # Get the mapped host port for function app HTTP trigger (internal port 80) + echo "Getting the host port mapped to internal port 80 in container [$container_name]..." + host_port=$(get_docker_container_port_mapping "$container_name" "80") + + if [ $? -eq 0 ] && [ -n "$host_port" ]; then + echo "Mapped host port [$host_port] retrieved successfully for container [$container_name]" + else + echo "Failed to get mapped host port for container [$container_name]" + exit 1 + fi + + # Retrieve LocalStack proxy port + proxy_port=$(curl http://localhost:4566/_localstack/proxy -s | jq '.proxy_port') + + if [ -n "$proxy_port" ]; then + # Call the GetGreetings HTTP trigger function to retrieve the last greetings via emulator + echo "Calling HTTP trigger function to retrieve the last [$greeting_count] greetings via emulator..." + curl --proxy "http://localhost:$proxy_port/" -s "http://$function_host_name/api/greetings?count=$greeting_count" | jq + else + echo "Failed to retrieve LocalStack proxy port" + fi + + if [ -n "$container_ip" ]; then + # Call the GetGreetings HTTP trigger function to retrieve the last greetings via the container IP address + echo "Calling HTTP trigger function to retrieve the last [$greeting_count] greetings via container IP address [$container_ip]..." + curl -s "http://$container_ip/api/greetings?count=$greeting_count" | jq + else + echo "Failed to retrieve container IP address" + fi + + if [ -n "$host_port" ]; then + # Call the GetGreetings HTTP trigger function to retrieve the last greetings via the host port + echo "Calling HTTP trigger function to retrieve the last [$greeting_count] greetings via host port [$host_port]..." + curl -s "http://localhost:$host_port/api/greetings?count=$greeting_count" | jq + else + echo "Failed to retrieve host port" + fi +} + +call_http_trigger_function \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/scripts/deploy.sh b/samples/function-app-service-bus/dotnet/scripts/deploy.sh new file mode 100755 index 0000000..9c2de5b --- /dev/null +++ b/samples/function-app-service-bus/dotnet/scripts/deploy.sh @@ -0,0 +1,1207 @@ +WEBAP#!/bin/bash + +PREFIX='local' +SUFFIX='test' +LOCATION='westeurope' +RESOURCE_GROUP_NAME="${PREFIX}-rg" +LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" +DIAGNOSTIC_SETTINGS_NAME='default' +MANAGED_IDENTITY_NAME="${PREFIX}-identity-${SUFFIX}" +FUNCTION_APP_SUBNET_NSG_NAME="${PREFIX}-func-subnet-nsg-${SUFFIX}" +PE_SUBNET_NSG_NAME="${PREFIX}-pe-subnet-nsg-${SUFFIX}" +NAT_GATEWAY_NAME="${PREFIX}-nat-gateway-${SUFFIX}" +PIP_PREFIX_NAME="${PREFIX}-nat-gateway-pip-prefix-${SUFFIX}" +VIRTUAL_NETWORK_NAME="${PREFIX}-vnet-${SUFFIX}" +VIRTUAL_NETWORK_ADDRESS_PREFIX="10.0.0.0/8" +FUNCTION_APP_SUBNET_NAME="func-subnet" +FUNCTION_APP_SUBNET_PREFIX="10.0.0.0/24" +PE_SUBNET_NAME="pe-subnet" +PE_SUBNET_PREFIX="10.0.1.0/24" +VIRTUAL_NETWORK_LINK_NAME="link-to-vnet" +PRIVATE_DNS_ZONE_GROUP_NAME="default" +APPLICATION_INSIGHTS_NAME="${PREFIX}-func-${SUFFIX}" +APP_SERVICE_PLAN_NAME="${PREFIX}-plan-${SUFFIX}" +FUNCTION_APP_NAME="${PREFIX}-func-${SUFFIX}" +STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}" +SERVICE_BUS_NAMESPACE="${PREFIX}-service-bus-${SUFFIX}" +FUNCTIONS_VERSION="4" +RUNTIME="DOTNET-ISOLATED" +RUNTIME_VERSION="10" +SERVICE_BUS_CONNECTION_STRING='' +INPUT_QUEUE_NAME="input" +OUTPUT_QUEUE_NAME="output" +TAGS='environment=test deployment=azcli' +SUBSCRIPTION_ID=$(az account show --query id --output tsv) +SUBSCRIPTION_NAME=$(az account show --query name --output tsv) +ENVIRONMENT=$(az account show --query environmentName --output tsv) +DEPLOY=1 +RETRY_COUNT=3 +SLEEP=5 +ZIPFILE="functionapp.zip" +CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)" +PRIVATE_DNS_ZONE_NAMES=( + "privatelink.servicebus.windows.net" + "privatelink.blob.core.windows.net" + "privatelink.queue.core.windows.net" + "privatelink.table.core.windows.net" +) +PE_NAMES=( + "${PREFIX}-service-bus-pe-${SUFFIX}" + "${PREFIX}-blob-storage-pe-${SUFFIX}" + "${PREFIX}-queue-storage-pe-${SUFFIX}" + "${PREFIX}-table-storage-pe-${SUFFIX}" +) +PE_GROUP_IDS=("namespace" "blob" "queue" "table") +PE_CONNECTION_NAMES=("servicebus-connection" "blob-connection" "queue-connection" "table-connection") +PE_DNS_ZONES=("privatelink.servicebus.windows.net" "privatelink.blob.core.windows.net" "privatelink.queue.core.windows.net" "privatelink.table.core.windows.net") +PE_DNS_ZONE_LABELS=("servicebus-zone" "blob-zone" "queue-zone" "table-zone") + +# Change the current directory to the script's directory +cd "$CURRENT_DIR" || exit + +# Choose the appropriate CLI based on the environment +if [[ $ENVIRONMENT == "LocalStack" ]]; then + echo "Using azlocal for LocalStack emulator environment." + AZ="azlocal" +else + echo "Using standard az for AzureCloud environment." + AZ="az" +fi + +# Create a resource group +echo "Checking if resource group [$RESOURCE_GROUP_NAME] exists in the subscription [$SUBSCRIPTION_NAME]..." +$AZ group show --name $RESOURCE_GROUP_NAME &>/dev/null +if [[ $? != 0 ]]; then + echo "No resource group [$RESOURCE_GROUP_NAME] exists in the subscription [$SUBSCRIPTION_NAME]" + echo "Creating resource group [$RESOURCE_GROUP_NAME] in the subscription [$SUBSCRIPTION_NAME]..." + + # Create the resource group + $AZ group create \ + --name $RESOURCE_GROUP_NAME \ + --location $LOCATION \ + --tags $TAGS \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "Resource group [$RESOURCE_GROUP_NAME] successfully created in the subscription [$SUBSCRIPTION_NAME]" + else + echo "Failed to create resource group [$RESOURCE_GROUP_NAME] in the subscription [$SUBSCRIPTION_NAME]" + exit + fi +else + echo "Resource group [$RESOURCE_GROUP_NAME] already exists in the subscription [$SUBSCRIPTION_NAME]" +fi + +# Create a service bus namespace +echo "Checking if [$SERVICE_BUS_NAMESPACE] service bus namespace exists in the [$RESOURCE_GROUP_NAME] resource group..." +$AZ servicebus namespace show \ + --name $SERVICE_BUS_NAMESPACE \ + --resource-group $RESOURCE_GROUP_NAME &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$SERVICE_BUS_NAMESPACE] service bus namespace exists in the [$RESOURCE_GROUP_NAME] resource group" + echo "Creating [$SERVICE_BUS_NAMESPACE] service bus namespace in the [$RESOURCE_GROUP_NAME] resource group..." + $AZ servicebus namespace create \ + --name $SERVICE_BUS_NAMESPACE \ + --sku Premium \ + --location $LOCATION \ + --resource-group $RESOURCE_GROUP_NAME \ + --tags $TAGS 1>/dev/null + + if [ $? == 0 ]; then + echo "[$SERVICE_BUS_NAMESPACE] service bus namespace successfully created in the [$RESOURCE_GROUP_NAME] resource group" + else + echo "Failed to create [$SERVICE_BUS_NAMESPACE] service bus namespace in the [$RESOURCE_GROUP_NAME] resource group" + exit + fi +else + echo "[$SERVICE_BUS_NAMESPACE] service bus namespace already exists in the [$RESOURCE_GROUP_NAME] resource group" +fi + +# Create the service bus input queue +echo "Checking if [$INPUT_QUEUE_NAME] service bus queue exists in the [$SERVICE_BUS_NAMESPACE] service bus namespace..." +$AZ servicebus queue show \ + --name $INPUT_QUEUE_NAME \ + --namespace-name $SERVICE_BUS_NAMESPACE \ + --resource-group $RESOURCE_GROUP_NAME &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$INPUT_QUEUE_NAME] service bus queue exists in the [$SERVICE_BUS_NAMESPACE] service bus namespace" + echo "Creating [$INPUT_QUEUE_NAME] service bus queue in the [$SERVICE_BUS_NAMESPACE] service bus namespace..." + + $AZ servicebus queue create \ + --name $INPUT_QUEUE_NAME \ + --namespace-name $SERVICE_BUS_NAMESPACE \ + --resource-group $RESOURCE_GROUP_NAME 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$INPUT_QUEUE_NAME] service bus queue successfully created in the [$SERVICE_BUS_NAMESPACE] service bus namespace" + else + echo "Failed to create [$INPUT_QUEUE_NAME] service bus queue in the [$SERVICE_BUS_NAMESPACE] service bus namespace" + exit + fi +else + echo "[$INPUT_QUEUE_NAME] service bus queue already exists in the [$SERVICE_BUS_NAMESPACE] service bus namespace" +fi + +# Create the service bus output queue +echo "Checking if [$OUTPUT_QUEUE_NAME] service bus queue exists in the [$SERVICE_BUS_NAMESPACE] service bus namespace..." +$AZ servicebus queue show \ + --name $OUTPUT_QUEUE_NAME \ + --namespace-name $SERVICE_BUS_NAMESPACE \ + --resource-group $RESOURCE_GROUP_NAME &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$OUTPUT_QUEUE_NAME] service bus queue exists in the [$SERVICE_BUS_NAMESPACE] service bus namespace" + echo "Creating [$OUTPUT_QUEUE_NAME] service bus queue in the [$SERVICE_BUS_NAMESPACE] service bus namespace..." + + $AZ servicebus queue create \ + --name $OUTPUT_QUEUE_NAME \ + --namespace-name $SERVICE_BUS_NAMESPACE \ + --resource-group $RESOURCE_GROUP_NAME 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$OUTPUT_QUEUE_NAME] service bus queue successfully created in the [$SERVICE_BUS_NAMESPACE] service bus namespace" + else + echo "Failed to create [$OUTPUT_QUEUE_NAME] service bus queue in the [$SERVICE_BUS_NAMESPACE] service bus namespace" + exit + fi +else + echo "[$OUTPUT_QUEUE_NAME] service bus queue already exists in the [$SERVICE_BUS_NAMESPACE] service bus namespace" +fi + +# Retrieve and display connection string +SERVICE_BUS_CONNECTION_STRING=$($AZ servicebus namespace authorization-rule keys list \ + --name RootManageSharedAccessKey \ + --namespace-name $SERVICE_BUS_NAMESPACE \ + --resource-group $RESOURCE_GROUP_NAME \ + --query primaryConnectionString \ + --output tsv) + +echo "Service Bus connection string: $SERVICE_BUS_CONNECTION_STRING" + +# Get the Service Bus namespace resource id +echo "Getting [$SERVICE_BUS_NAMESPACE] service bus namespace resource id in the [$RESOURCE_GROUP_NAME] resource group..." +SERVICE_BUS_NAMESPACE_ID=$($AZ servicebus namespace show \ + --name $SERVICE_BUS_NAMESPACE \ + --resource-group $RESOURCE_GROUP_NAME \ + --query id \ + --output tsv) + +if [[ -n $SERVICE_BUS_NAMESPACE_ID ]]; then + echo "[$SERVICE_BUS_NAMESPACE] service bus namespace resource id retrieved successfully: $SERVICE_BUS_NAMESPACE_ID" +else + echo "Failed to retrieve [$SERVICE_BUS_NAMESPACE] service bus namespace resource id in the [$RESOURCE_GROUP_NAME] resource group" + exit 1 +fi + +# Check if the user-assigned managed identity already exists +echo "Checking if [$MANAGED_IDENTITY_NAME] user-assigned managed identity actually exists in the [$RESOURCE_GROUP_NAME] resource group..." + +$AZ identity show \ + --name"$MANAGED_IDENTITY_NAME" \ + --resource-group $"$RESOURCE_GROUP_NAME" &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$MANAGED_IDENTITY_NAME] user-assigned managed identity actually exists in the [$RESOURCE_GROUP_NAME] resource group" + echo "Creating [$MANAGED_IDENTITY_NAME] user-assigned managed identity in the [$RESOURCE_GROUP_NAME] resource group..." + + # Create the user-assigned managed identity + $AZ identity create \ + --name "$MANAGED_IDENTITY_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --location "$LOCATION" \ + --subscription "$SUBSCRIPTION_ID" \ + --tags $TAGS 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$MANAGED_IDENTITY_NAME] user-assigned managed identity successfully created in the [$RESOURCE_GROUP_NAME] resource group" + else + echo "Failed to create [$MANAGED_IDENTITY_NAME] user-assigned managed identity in the [$RESOURCE_GROUP_NAME] resource group" + exit 1 + fi +else + echo "[$MANAGED_IDENTITY_NAME] user-assigned managed identity already exists in the [$RESOURCE_GROUP_NAME] resource group" +fi + +# Retrieve the clientId of the user-assigned managed identity +echo "Retrieving clientId for [$MANAGED_IDENTITY_NAME] managed identity..." +CLIENT_ID=$($AZ identity show \ + --name "$MANAGED_IDENTITY_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query clientId \ + --output tsv) + +if [[ -n $CLIENT_ID ]]; then + echo "[$CLIENT_ID] clientId for the [$MANAGED_IDENTITY_NAME] managed identity successfully retrieved" +else + echo "Failed to retrieve clientId for the [$MANAGED_IDENTITY_NAME] managed identity" + exit 1 +fi + +# Retrieve the principalId of the user-assigned managed identity +echo "Retrieving principalId for [$MANAGED_IDENTITY_NAME] managed identity..." +PRINCIPAL_ID=$($AZ identity show \ + --name "$MANAGED_IDENTITY_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query principalId \ + --output tsv) + +if [[ -n $PRINCIPAL_ID ]]; then + echo "[$PRINCIPAL_ID] principalId for the [$MANAGED_IDENTITY_NAME] managed identity successfully retrieved" +else + echo "Failed to retrieve principalId for the [$MANAGED_IDENTITY_NAME] managed identity" + exit 1 +fi + +# Retrieve the resource id of the user-assigned managed identity +echo "Retrieving resource id for the [$MANAGED_IDENTITY_NAME] managed identity..." +IDENTITY_ID=$($AZ identity show \ + --name "$MANAGED_IDENTITY_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query id \ + --output tsv) + +if [[ -n $IDENTITY_ID ]]; then + echo "Resource id for the [$MANAGED_IDENTITY_NAME] managed identity successfully retrieved" +else + echo "Failed to retrieve the resource id for the [$MANAGED_IDENTITY_NAME] managed identity" + exit 1 +fi + +# Assign the Azure Service Bus Data Owner role to the managed identity with the Service Bus namespace as a scope +ROLE="Azure Service Bus Data Owner" +echo "Checking if the managed identity with principal ID [$PRINCIPAL_ID] has the [$ROLE] role assignment on the Service Bus namespace [$SERVICE_BUS_NAMESPACE]..." +current=$($AZ role assignment list \ + --assignee "$PRINCIPAL_ID" \ + --scope "$SERVICE_BUS_NAMESPACE_ID" \ + --query "[?roleDefinitionName=='$ROLE'].roleDefinitionName" \ + --output tsv 2>/dev/null) + +if [[ $current == "$ROLE" ]]; then + echo "Managed identity already has the [$ROLE] role assignment on the Service Bus namespace [$SERVICE_BUS_NAMESPACE]" +else + echo "Managed identity does not have the [$ROLE] role assignment on the Service Bus namespace [$SERVICE_BUS_NAMESPACE]" + echo "Creating role assignment: assigning [$ROLE] role to managed identity on the Service Bus namespace [$SERVICE_BUS_NAMESPACE]..." + ATTEMPT=1 + while [ $ATTEMPT -le $RETRY_COUNT ]; do + echo "Attempt $ATTEMPT of $RETRY_COUNT to assign role..." + $AZ role assignment create \ + --assignee "$PRINCIPAL_ID" \ + --role "$ROLE" \ + --scope "$SERVICE_BUS_NAMESPACE_ID" 1>/dev/null + + if [[ $? == 0 ]]; then + break + else + if [ $ATTEMPT -lt $RETRY_COUNT ]; then + echo "Role assignment failed. Waiting [$SLEEP] seconds before retry..." + sleep $SLEEP + fi + ATTEMPT=$((ATTEMPT + 1)) + fi + done + + if [[ $? == 0 ]]; then + echo "Successfully assigned [$ROLE] role to managed identity on the Service Bus namespace [$SERVICE_BUS_NAMESPACE]" + else + echo "Failed to assign [$ROLE] role to managed identity on the Service Bus namespace [$SERVICE_BUS_NAMESPACE]" + exit + fi +fi + +# Check if the network security group for the function app subnet already exists +echo "Checking if [$FUNCTION_APP_SUBNET_NSG_NAME] network security group for the function app subnet actually exists in the [$RESOURCE_GROUP_NAME] resource group..." +$AZ network nsg show \ + --name "$FUNCTION_APP_SUBNET_NSG_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --only-show-errors &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$FUNCTION_APP_SUBNET_NSG_NAME] network security group for the function app subnet actually exists in the [$RESOURCE_GROUP_NAME] resource group" + echo "Creating [$FUNCTION_APP_SUBNET_NSG_NAME] network security group for the function app subnet..." + + # Create the network security group for the function app subnet + $AZ network nsg create \ + --name "$FUNCTION_APP_SUBNET_NSG_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --location "$LOCATION" \ + --tags $TAGS \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$FUNCTION_APP_SUBNET_NSG_NAME] network security group for the function app subnet successfully created in the [$RESOURCE_GROUP_NAME] resource group" + else + echo "Failed to create [$FUNCTION_APP_SUBNET_NSG_NAME] network security group for the function app subnet in the [$RESOURCE_GROUP_NAME] resource group" + exit 1 + fi +else + echo "[$FUNCTION_APP_SUBNET_NSG_NAME] network security group for the function app subnet already exists in the [$RESOURCE_GROUP_NAME] resource group" +fi + +# Get the resource id of the network security group for the function app subnet +echo "Getting [$FUNCTION_APP_SUBNET_NSG_NAME] network security group for the function app subnet resource id in the [$RESOURCE_GROUP_NAME] resource group..." +FUNCTION_APP_SUBNET_NSG_ID=$($AZ network nsg show \ + --name "$FUNCTION_APP_SUBNET_NSG_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query id \ + --output tsv \ + --only-show-errors) + +if [[ -n $FUNCTION_APP_SUBNET_NSG_ID ]]; then + echo "[$FUNCTION_APP_SUBNET_NSG_NAME] network security group for the function app subnet resource id retrieved successfully: $FUNCTION_APP_SUBNET_NSG_ID" +else + echo "Failed to retrieve [$FUNCTION_APP_SUBNET_NSG_NAME] network security group for the function app subnet resource id in the [$RESOURCE_GROUP_NAME] resource group" + exit 1 +fi + +# Check if the network security group for the private endpoint subnet already exists +echo "Checking if [$PE_SUBNET_NSG_NAME] network security group for the private endpoint subnet actually exists in the [$RESOURCE_GROUP_NAME] resource group..." +$AZ network nsg show \ + --name "$PE_SUBNET_NSG_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --only-show-errors &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$PE_SUBNET_NSG_NAME] network security group for the private endpoint subnet actually exists in the [$RESOURCE_GROUP_NAME] resource group" + echo "Creating [$PE_SUBNET_NSG_NAME] network security group for the private endpoint subnet..." + + # Create the network security group for the private endpoint subnet + $AZ network nsg create \ + --name "$PE_SUBNET_NSG_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --location "$LOCATION" \ + --tags $TAGS \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$PE_SUBNET_NSG_NAME] network security group for the private endpoint subnet successfully created in the [$RESOURCE_GROUP_NAME] resource group" + else + echo "Failed to create [$PE_SUBNET_NSG_NAME] network security group for the private endpoint subnet in the [$RESOURCE_GROUP_NAME] resource group" + exit 1 + fi +else + echo "[$PE_SUBNET_NSG_NAME] network security group for the private endpoint subnet already exists in the [$RESOURCE_GROUP_NAME] resource group" +fi + +# Get the resource id of the network security group for the private endpoint subnet +echo "Getting [$PE_SUBNET_NSG_NAME] network security group for the private endpoint subnet resource id in the [$RESOURCE_GROUP_NAME] resource group..." +PE_SUBNET_NSG_ID=$($AZ network nsg show \ + --name "$PE_SUBNET_NSG_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query id \ + --output tsv \ + --only-show-errors) + +if [[ -n $PE_SUBNET_NSG_ID ]]; then + echo "[$PE_SUBNET_NSG_NAME] network security group for the private endpoint subnet resource id retrieved successfully: $PE_SUBNET_NSG_ID" +else + echo "Failed to retrieve [$PE_SUBNET_NSG_NAME] network security group for the private endpoint subnet resource id in the [$RESOURCE_GROUP_NAME] resource group" + exit 1 +fi + +# Check if the public IP prefix for the NAT Gateway already exists +echo "Checking if [$PIP_PREFIX_NAME] public IP prefix for the NAT Gateway actually exists in the [$RESOURCE_GROUP_NAME] resource group..." +$AZ network public-ip prefix show \ + --name "$PIP_PREFIX_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --only-show-errors &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$PIP_PREFIX_NAME] public IP prefix for the NAT Gateway actually exists in the [$RESOURCE_GROUP_NAME] resource group" + echo "Creating [$PIP_PREFIX_NAME] public IP prefix for the NAT Gateway in the [$RESOURCE_GROUP_NAME] resource group..." + + # Create the public IP prefix for the NAT Gateway + $AZ network public-ip prefix create \ + --name "$PIP_PREFIX_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --location "$LOCATION" \ + --length 31 \ + --tags $TAGS \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$PIP_PREFIX_NAME] public IP prefix for the NAT Gateway successfully created in the [$RESOURCE_GROUP_NAME] resource group" + else + echo "Failed to create [$PIP_PREFIX_NAME] public IP prefix for the NAT Gateway in the [$RESOURCE_GROUP_NAME] resource group" + exit 1 + fi +else + echo "[$PIP_PREFIX_NAME] public IP prefix for the NAT Gateway already exists in the [$RESOURCE_GROUP_NAME] resource group" +fi + +# Check if the NAT Gateway already exists +echo "Checking if [$NAT_GATEWAY_NAME] NAT Gateway actually exists in the [$RESOURCE_GROUP_NAME] resource group..." +$AZ network nat gateway show \ + --name "$NAT_GATEWAY_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --only-show-errors &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$NAT_GATEWAY_NAME] NAT Gateway actually exists in the [$RESOURCE_GROUP_NAME] resource group" + echo "Creating [$NAT_GATEWAY_NAME] NAT Gateway in the [$RESOURCE_GROUP_NAME] resource group..." + + # Create the NAT Gateway + $AZ network nat gateway create \ + --name "$NAT_GATEWAY_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --location "$LOCATION" \ + --public-ip-prefixes "$PIP_PREFIX_NAME" \ + --idle-timeout 4 \ + --tags $TAGS \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$NAT_GATEWAY_NAME] NAT Gateway successfully created in the [$RESOURCE_GROUP_NAME] resource group" + else + echo "Failed to create [$NAT_GATEWAY_NAME] NAT Gateway in the [$RESOURCE_GROUP_NAME] resource group" + exit 1 + fi +else + echo "[$NAT_GATEWAY_NAME] NAT Gateway already exists in the [$RESOURCE_GROUP_NAME] resource group" +fi + +# Check if the virtual network already exists +echo "Checking if [$VIRTUAL_NETWORK_NAME] virtual network actually exists in the [$RESOURCE_GROUP_NAME] resource group..." +$AZ network vnet show \ + --name "$VIRTUAL_NETWORK_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --only-show-errors &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$VIRTUAL_NETWORK_NAME] virtual network actually exists in the [$RESOURCE_GROUP_NAME] resource group" + echo "Creating [$VIRTUAL_NETWORK_NAME] virtual network in the [$RESOURCE_GROUP_NAME] resource group..." + + # Create the virtual network + $AZ network vnet create \ + --name "$VIRTUAL_NETWORK_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --location "$LOCATION" \ + --address-prefixes "$VIRTUAL_NETWORK_ADDRESS_PREFIX" \ + --subnet-name "$FUNCTION_APP_SUBNET_NAME" \ + --subnet-prefix "$FUNCTION_APP_SUBNET_PREFIX" \ + --tags $TAGS \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$VIRTUAL_NETWORK_NAME] virtual network successfully created in the [$RESOURCE_GROUP_NAME] resource group" + else + echo "Failed to create [$VIRTUAL_NETWORK_NAME] virtual network in the [$RESOURCE_GROUP_NAME] resource group" + exit + fi + + # Update the function app subnet to associate it with the NAT Gateway and the NSG + echo "Associating [$FUNCTION_APP_SUBNET_NAME] subnet with the [$NAT_GATEWAY_NAME] NAT Gateway and the [$FUNCTION_APP_SUBNET_NSG_NAME] network security group..." + + # Update the function app subnet to associate it with the NAT Gateway and the NSG + $AZ network vnet subnet update \ + --name "$FUNCTION_APP_SUBNET_NAME" \ + --vnet-name "$VIRTUAL_NETWORK_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --nat-gateway "$NAT_GATEWAY_NAME" \ + --network-security-group "$FUNCTION_APP_SUBNET_NSG_NAME" \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$FUNCTION_APP_SUBNET_NAME] subnet successfully associated with the [$NAT_GATEWAY_NAME] NAT Gateway and the [$FUNCTION_APP_SUBNET_NSG_NAME] network security group" + else + echo "Failed to associate [$FUNCTION_APP_SUBNET_NAME] subnet with the [$NAT_GATEWAY_NAME] NAT Gateway and the [$FUNCTION_APP_SUBNET_NSG_NAME] network security group" + exit 1 + fi +else + echo "[$VIRTUAL_NETWORK_NAME] virtual network already exists in the [$RESOURCE_GROUP_NAME] resource group" +fi + +# Check if the subnet already exists +echo "Checking if [$PE_SUBNET_NAME] subnet actually exists in the [$VIRTUAL_NETWORK_NAME] virtual network..." +$AZ network vnet subnet show \ + --name "$PE_SUBNET_NAME" \ + --vnet-name "$VIRTUAL_NETWORK_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --only-show-errors &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$PE_SUBNET_NAME] subnet actually exists in the [$VIRTUAL_NETWORK_NAME] virtual network" + echo "Creating [$PE_SUBNET_NAME] subnet in the [$VIRTUAL_NETWORK_NAME] virtual network..." + + # Create the subnet + $AZ network vnet subnet create \ + --name "$PE_SUBNET_NAME" \ + --vnet-name "$VIRTUAL_NETWORK_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --address-prefix "$PE_SUBNET_PREFIX" \ + --network-security-group "$PE_SUBNET_NSG_NAME" \ + --private-endpoint-network-policies "Disabled" \ + --private-link-service-network-policies "Disabled" \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$PE_SUBNET_NAME] subnet successfully created in the [$VIRTUAL_NETWORK_NAME] virtual network" + else + echo "Failed to create [$PE_SUBNET_NAME] subnet in the [$VIRTUAL_NETWORK_NAME] virtual network" + exit + fi +else + echo "[$PE_SUBNET_NAME] subnet already exists in the [$VIRTUAL_NETWORK_NAME] virtual network" +fi + +# Retrieve the virtual network resource id +echo "Getting [$VIRTUAL_NETWORK_NAME] virtual network resource id in the [$RESOURCE_GROUP_NAME] resource group..." +VIRTUAL_NETWORK_ID=$($AZ network vnet show \ + --name "$VIRTUAL_NETWORK_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --only-show-errors \ + --query id \ + --output tsv) + +if [[ -n $VIRTUAL_NETWORK_ID ]]; then + echo "[$VIRTUAL_NETWORK_NAME] virtual network resource id retrieved successfully: $VIRTUAL_NETWORK_ID" +else + echo "Failed to retrieve [$VIRTUAL_NETWORK_NAME] virtual network resource id in the [$RESOURCE_GROUP_NAME] resource group" + exit +fi + +# Create private DNS zones and virtual network links +for DNS_ZONE_NAME in "${PRIVATE_DNS_ZONE_NAMES[@]}"; do + # Check if the private DNS Zone already exists + echo "Checking if [$DNS_ZONE_NAME] private DNS zone actually exists in the [$RESOURCE_GROUP_NAME] resource group..." + $AZ network private-dns zone show \ + --name "$DNS_ZONE_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --only-show-errors &>/dev/null + + if [[ $? != 0 ]]; then + echo "No [$DNS_ZONE_NAME] private DNS zone actually exists in the [$RESOURCE_GROUP_NAME] resource group" + echo "Creating [$DNS_ZONE_NAME] private DNS zone in the [$RESOURCE_GROUP_NAME] resource group..." + + # Create the private DNS Zone + $AZ network private-dns zone create \ + --name "$DNS_ZONE_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --tags $TAGS \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$DNS_ZONE_NAME] private DNS zone successfully created in the [$RESOURCE_GROUP_NAME] resource group" + else + echo "Failed to create [$DNS_ZONE_NAME] private DNS zone in the [$RESOURCE_GROUP_NAME] resource group" + exit + fi + else + echo "[$DNS_ZONE_NAME] private DNS zone already exists in the [$RESOURCE_GROUP_NAME] resource group" + fi + + # Check if the virtual network link already exists + echo "Checking if [$VIRTUAL_NETWORK_LINK_NAME] virtual network link between [$DNS_ZONE_NAME] private DNS zone and [$VIRTUAL_NETWORK_NAME] virtual network actually exists..." + $AZ network private-dns link vnet show \ + --name "$VIRTUAL_NETWORK_LINK_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --zone-name "$DNS_ZONE_NAME" \ + --only-show-errors &>/dev/null + + if [[ $? != 0 ]]; then + echo "No [$VIRTUAL_NETWORK_LINK_NAME] virtual network link between [$DNS_ZONE_NAME] private DNS zone and [$VIRTUAL_NETWORK_NAME] virtual network actually exists" + echo "Creating [$VIRTUAL_NETWORK_LINK_NAME] virtual network link between [$DNS_ZONE_NAME] private DNS zone and [$VIRTUAL_NETWORK_NAME] virtual network..." + + # Create the virtual network link + $AZ network private-dns link vnet create \ + --name "$VIRTUAL_NETWORK_LINK_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --zone-name "$DNS_ZONE_NAME" \ + --virtual-network "$VIRTUAL_NETWORK_ID" \ + --registration-enabled false \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$VIRTUAL_NETWORK_LINK_NAME] virtual network link between [$DNS_ZONE_NAME] private DNS zone and [$VIRTUAL_NETWORK_NAME] virtual network successfully created" + else + echo "Failed to create [$VIRTUAL_NETWORK_LINK_NAME] virtual network link between [$DNS_ZONE_NAME] private DNS zone and [$VIRTUAL_NETWORK_NAME] virtual network" + exit + fi + else + echo "[$VIRTUAL_NETWORK_LINK_NAME] virtual network link between [$DNS_ZONE_NAME] private DNS zone and [$VIRTUAL_NETWORK_NAME] virtual network already exists" + fi +done + +# Create a storage account +echo "Checking if storage account [$STORAGE_ACCOUNT_NAME] exists in the resource group [$RESOURCE_GROUP_NAME]..." +$AZ storage account show \ + --name $STORAGE_ACCOUNT_NAME \ + --resource-group $RESOURCE_GROUP_NAME &>/dev/null + +if [[ $? != 0 ]]; then + echo "No storage account [$STORAGE_ACCOUNT_NAME] exists in the [$RESOURCE_GROUP_NAME] resource group." + echo "Creating storage account [$STORAGE_ACCOUNT_NAME] in the [$RESOURCE_GROUP_NAME] resource group..." + $AZ storage account create \ + --name $STORAGE_ACCOUNT_NAME \ + --location $LOCATION \ + --resource-group $RESOURCE_GROUP_NAME \ + --sku Standard_LRS \ + --tags $TAGS 1>/dev/null + + if [ $? -eq 0 ]; then + echo "Storage account [$STORAGE_ACCOUNT_NAME] created successfully in the [$RESOURCE_GROUP_NAME] resource group." + else + echo "Failed to create storage account [$STORAGE_ACCOUNT_NAME] in the [$RESOURCE_GROUP_NAME] resource group." + exit 1 + fi +else + echo "Storage account [$STORAGE_ACCOUNT_NAME] already exists in the [$RESOURCE_GROUP_NAME] resource group." +fi + +# Get the storage account key +echo "Getting storage account key for [$STORAGE_ACCOUNT_NAME]..." +STORAGE_ACCOUNT_KEY=$($AZ storage account keys list \ + --account-name $STORAGE_ACCOUNT_NAME \ + --resource-group $RESOURCE_GROUP_NAME \ + --query "[0].value" \ + --output tsv) + +if [ -n "$STORAGE_ACCOUNT_KEY" ]; then + echo "Storage account key retrieved successfully: [$STORAGE_ACCOUNT_KEY]" +else + echo "Failed to retrieve storage account key." + exit 1 +fi + +# Construct the storage connection string for LocalStack +STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=https;AccountName=$STORAGE_ACCOUNT_NAME;AccountKey=$STORAGE_ACCOUNT_KEY;EndpointSuffix=core.windows.net" +echo "Storage connection string constructed: [$STORAGE_CONNECTION_STRING]" + +# Get the storage account resource id +echo "Getting [$STORAGE_ACCOUNT_NAME] storage account resource id in the [$RESOURCE_GROUP_NAME] resource group..." +STORAGE_ACCOUNT_ID=$($AZ storage account show \ + --name "$STORAGE_ACCOUNT_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query id \ + --output tsv \ + --only-show-errors) + +if [[ -n $STORAGE_ACCOUNT_ID ]]; then + echo "[$STORAGE_ACCOUNT_NAME] storage account resource id retrieved successfully: $STORAGE_ACCOUNT_ID" +else + echo "Failed to retrieve [$STORAGE_ACCOUNT_NAME] storage account resource id in the [$RESOURCE_GROUP_NAME] resource group" + exit 1 +fi + +# Create private endpoints and DNS zone groups +PE_RESOURCE_IDS=("$SERVICE_BUS_NAMESPACE_ID" "$STORAGE_ACCOUNT_ID" "$STORAGE_ACCOUNT_ID" "$STORAGE_ACCOUNT_ID") + +for i in "${!PE_NAMES[@]}"; do + PE_NAME="${PE_NAMES[$i]}" + PE_GROUP="${PE_GROUP_IDS[$i]}" + PE_RESOURCE_ID="${PE_RESOURCE_IDS[$i]}" + PE_CONNECTION="${PE_CONNECTION_NAMES[$i]}" + PE_DNS_ZONE="${PE_DNS_ZONES[$i]}" + PE_DNS_ZONE_LABEL="${PE_DNS_ZONE_LABELS[$i]}" + + # Check if the private endpoint already exists + echo "Checking if private endpoint [$PE_NAME] exists in the [$RESOURCE_GROUP_NAME] resource group..." + privateEndpointId=$($AZ network private-endpoint list \ + --resource-group $RESOURCE_GROUP_NAME \ + --only-show-errors \ + --query "[?name=='$PE_NAME'].id" \ + --output tsv) + + if [[ -z $privateEndpointId ]]; then + echo "Private endpoint [$PE_NAME] does not exist in the [$RESOURCE_GROUP_NAME] resource group" + echo "Creating [$PE_NAME] private endpoint in the [$RESOURCE_GROUP_NAME] resource group..." + + # Create the private endpoint + $AZ network private-endpoint create \ + --name "$PE_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --location "$LOCATION" \ + --vnet-name "$VIRTUAL_NETWORK_NAME" \ + --subnet "$PE_SUBNET_NAME" \ + --private-connection-resource-id "$PE_RESOURCE_ID" \ + --group-id "$PE_GROUP" \ + --connection-name "$PE_CONNECTION" \ + --tags $TAGS \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "Private endpoint [$PE_NAME] successfully created in the [$RESOURCE_GROUP_NAME] resource group" + else + echo "Failed to create private endpoint [$PE_NAME] in the [$RESOURCE_GROUP_NAME] resource group" + exit + fi + else + echo "Private endpoint [$PE_NAME] already exists in the [$RESOURCE_GROUP_NAME] resource group" + fi + + # Check if the private DNS zone group is already created + echo "Checking if the private DNS zone group [$PRIVATE_DNS_ZONE_GROUP_NAME] for the [$PE_NAME] private endpoint already exists..." + NAME=$($AZ network private-endpoint dns-zone-group show \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --endpoint-name "$PE_NAME" \ + --name "$PRIVATE_DNS_ZONE_GROUP_NAME" \ + --query name \ + --output tsv \ + --only-show-errors) + + if [[ -z $NAME ]]; then + echo "No private DNS zone group [$PRIVATE_DNS_ZONE_GROUP_NAME] for the [$PE_NAME] private endpoint actually exists" + echo "Creating private DNS zone group [$PRIVATE_DNS_ZONE_GROUP_NAME] for the [$PE_NAME] private endpoint..." + + # Create the private DNS zone group + $AZ network private-endpoint dns-zone-group create \ + --name "$PRIVATE_DNS_ZONE_GROUP_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --endpoint-name "$PE_NAME" \ + --private-dns-zone "$PE_DNS_ZONE" \ + --zone-name "$PE_DNS_ZONE_LABEL" \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "Private DNS zone group [$PRIVATE_DNS_ZONE_GROUP_NAME] for the [$PE_NAME] private endpoint successfully created" + else + echo "Failed to create private DNS zone group [$PRIVATE_DNS_ZONE_GROUP_NAME] for the [$PE_NAME] private endpoint" + exit + fi + else + echo "Private DNS zone group [$PRIVATE_DNS_ZONE_GROUP_NAME] for the [$PE_NAME] private endpoint already exists" + fi +done + +if [ $DEPLOY -eq 0 ]; then + echo "Deployment flag is not set. Exiting deployment script." + exit 0 +fi + +# Check if the application insights component already exists +echo "Checking if [$APPLICATION_INSIGHTS_NAME] Application Insights component exists in the [$RESOURCE_GROUP_NAME] resource group..." +$AZ monitor app-insights component show \ + --app "$APPLICATION_INSIGHTS_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --only-show-errors &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$APPLICATION_INSIGHTS_NAME] Application Insights component exists in the [$RESOURCE_GROUP_NAME] resource group." + echo "Creating [$APPLICATION_INSIGHTS_NAME] Application Insights component in the [$RESOURCE_GROUP_NAME] resource group..." + + # Create the application insights component + $AZ monitor app-insights component create \ + --app "$APPLICATION_INSIGHTS_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --location "$LOCATION" \ + --application-type "web" \ + --tags $TAGS \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$APPLICATION_INSIGHTS_NAME] Application Insights component created successfully in the [$RESOURCE_GROUP_NAME] resource group." + else + echo "Failed to create [$APPLICATION_INSIGHTS_NAME] Application Insights component in the [$RESOURCE_GROUP_NAME] resource group." + exit 1 + fi +else + echo "[$APPLICATION_INSIGHTS_NAME] Application Insights component already exists in the [$RESOURCE_GROUP_NAME] resource group." +fi + +# Create the app service plan +echo "Checking if app service plan [$APP_SERVICE_PLAN_NAME] exists in the [$RESOURCE_GROUP_NAME] resource group..." +if ! $AZ appservice plan show \ + --name $APP_SERVICE_PLAN_NAME \ + --resource-group $RESOURCE_GROUP_NAME &>/dev/null; then + echo "No app service plan [$APP_SERVICE_PLAN_NAME] exists in the [$RESOURCE_GROUP_NAME] resource group." + echo "Creating app service plan [$APP_SERVICE_PLAN_NAME] in the [$RESOURCE_GROUP_NAME] resource group..." + if $AZ appservice plan create \ + --name $APP_SERVICE_PLAN_NAME \ + --resource-group $RESOURCE_GROUP_NAME \ + --location $LOCATION \ + --sku B1 \ + --is-linux \ + --tags $TAGS \ + --only-show-errors 1>/dev/null; then + echo "App service plan [$APP_SERVICE_PLAN_NAME] created successfully in the [$RESOURCE_GROUP_NAME] resource group." + else + echo "Failed to create app service plan [$APP_SERVICE_PLAN_NAME] in the [$RESOURCE_GROUP_NAME] resource group." + exit 1 + fi +else + echo "App service plan [$APP_SERVICE_PLAN_NAME] already exists in the [$RESOURCE_GROUP_NAME] resource group." +fi + +# Get the app service plan resource id +echo "Getting [$APP_SERVICE_PLAN_NAME] app service plan resource id in the [$RESOURCE_GROUP_NAME] resource group..." +APP_SERVICE_PLAN_ID=$($AZ appservice plan show \ + --name "$APP_SERVICE_PLAN_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query id \ + --output tsv \ + --only-show-errors) + +if [[ -n $APP_SERVICE_PLAN_ID ]]; then + echo "[$APP_SERVICE_PLAN_NAME] app service plan resource id retrieved successfully: $APP_SERVICE_PLAN_ID" +else + echo "Failed to retrieve [$APP_SERVICE_PLAN_NAME] app service plan resource id in the [$RESOURCE_GROUP_NAME] resource group" + exit 1 +fi + +# Check if the function app already exists +echo "Checking if function app [$FUNCTION_APP_NAME] exists in the [$RESOURCE_GROUP_NAME] resource group..." +if ! $AZ functionapp show \ + --name $FUNCTION_APP_NAME \ + --resource-group $RESOURCE_GROUP_NAME &>/dev/null; then + echo "No function app [$FUNCTION_APP_NAME] exists in the [$RESOURCE_GROUP_NAME] resource group." + echo "Creating function app [$FUNCTION_APP_NAME] in the [$RESOURCE_GROUP_NAME] resource group..." + + # Create the function app + $AZ functionapp create \ + --resource-group $RESOURCE_GROUP_NAME \ + --plan $APP_SERVICE_PLAN_NAME \ + --assign-identity "$IDENTITY_ID" \ + --runtime $RUNTIME \ + --runtime-version $RUNTIME_VERSION \ + --functions-version $FUNCTIONS_VERSION \ + --name $FUNCTION_APP_NAME \ + --os-type linux \ + --app-insights "$APPLICATION_INSIGHTS_NAME" \ + --storage-account $STORAGE_ACCOUNT_NAME \ + --vnet "$VIRTUAL_NETWORK_NAME" \ + --subnet "$FUNCTION_APP_SUBNET_NAME" \ + --tags $TAGS \ + --only-show-errors 1>/dev/null + + if [ $? -eq 0 ]; then + echo "Function app [$FUNCTION_APP_NAME] created successfully." + else + echo "Failed to create function app [$FUNCTION_APP_NAME]." + exit 1 + fi +else + echo "Function app [$FUNCTION_APP_NAME] already exists in the [$RESOURCE_GROUP_NAME] resource group." +fi + +# Get the function app resource id +echo "Getting [$FUNCTION_APP_NAME] function app resource id in the [$RESOURCE_GROUP_NAME] resource group..." +FUNCTION_APP_ID=$($AZ functionapp show \ + --name "$FUNCTION_APP_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query id \ + --output tsv \ + --only-show-errors) + +if [[ -n $FUNCTION_APP_ID ]]; then + echo "[$FUNCTION_APP_NAME] function app resource id retrieved successfully: $FUNCTION_APP_ID" +else + echo "Failed to retrieve [$FUNCTION_APP_NAME] function app resource id in the [$RESOURCE_GROUP_NAME] resource group" + exit 1 +fi + +# Enable forced tunneling for the function app to route all outbound traffic through the virtual network and thus through the NAT Gateway +echo "Enabling forced tunneling for function app [$FUNCTION_APP_NAME] to route all outbound traffic through the virtual network..." + +$AZ resource update \ + --ids "$FUNCTION_APP_ID" \ + --set properties.outboundVnetRouting.allTraffic=true \ + --only-show-errors 1>/dev/null + +if [ $? -eq 0 ]; then + echo "Forced tunneling enabled for function app [$FUNCTION_APP_NAME]." +else + echo "Failed to enable forced tunneling for function app [$FUNCTION_APP_NAME]." + exit 1 +fi + +# Set function app settings +echo "Setting function app settings for [$FUNCTION_APP_NAME]..." +$AZ functionapp config appsettings set \ + --name $FUNCTION_APP_NAME \ + --resource-group $RESOURCE_GROUP_NAME \ + --settings \ + AZURE_CLIENT_ID="$CLIENT_ID" \ + SCM_DO_BUILD_DURING_DEPLOYMENT=false \ + FUNCTIONS_WORKER_RUNTIME=${RUNTIME,,} \ + FUNCTIONS_EXTENSION_VERSION=~$FUNCTIONS_VERSION \ + AzureWebJobsStorage="$STORAGE_CONNECTION_STRING" \ + SERVICE_BUS_CONNECTION_STRING__fullyQualifiedNamespace="${SERVICE_BUS_NAMESPACE,,}.servicebus.windows.net" \ + INPUT_QUEUE_NAME="input" \ + OUTPUT_QUEUE_NAME="output" \ + NAMES="Paolo,John,Jane,Max,Mary,Leo,Mia,Anna,Lisa,Anastasia" \ + TIMER_SCHEDULE="*/10 * * * * *" 1>/dev/null + +if [ $? -eq 0 ]; then + echo "Function app settings for [$FUNCTION_APP_NAME] set successfully." +else + echo "Failed to set function app settings for [$FUNCTION_APP_NAME]." + exit 1 +fi + +# Check if the log analytics workspace already exists +echo "Checking if [$LOG_ANALYTICS_NAME] Log Analytics workspace already exists in the [$RESOURCE_GROUP_NAME] resource group..." +$AZ monitor log-analytics workspace show \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --workspace-name "$LOG_ANALYTICS_NAME" \ + --only-show-errors &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$LOG_ANALYTICS_NAME] Log Analytics workspace actually exists in the [$RESOURCE_GROUP_NAME] resource group" + echo "Creating [$LOG_ANALYTICS_NAME] Log Analytics workspace in the [$RESOURCE_GROUP_NAME] resource group..." + + # Create the Log Analytics workspace + $AZ monitor log-analytics workspace create \ + --name "$LOG_ANALYTICS_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --location "$LOCATION" \ + --query-access "Enabled" \ + --retention-time 30 \ + --sku "PerNode" \ + --tags $TAGS \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$LOG_ANALYTICS_NAME] Log Analytics workspace successfully created in the [$RESOURCE_GROUP_NAME] resource group" + else + echo "Failed to create [$LOG_ANALYTICS_NAME] Log Analytics workspace in the [$RESOURCE_GROUP_NAME] resource group" + exit 1 + fi +else + echo "[$LOG_ANALYTICS_NAME] Log Analytics workspace already exists in the [$RESOURCE_GROUP_NAME] resource group" +fi + +# Check whether the diagnostic settings for the function app already exist +echo "Checking if [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$FUNCTION_APP_NAME] function app already exist..." +$AZ monitor diagnostic-settings show \ + --name "$DIAGNOSTIC_SETTINGS_NAME" \ + --resource "$FUNCTION_APP_ID" \ + --only-show-errors &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$FUNCTION_APP_NAME] function app actually exist" + echo "Creating [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$FUNCTION_APP_NAME] function app..." + + # Create the diagnostic settings for the function app to send logs to the Log Analytics workspace + $AZ monitor diagnostic-settings create \ + --name "$DIAGNOSTIC_SETTINGS_NAME" \ + --resource "$FUNCTION_APP_ID" \ + --workspace "$LOG_ANALYTICS_NAME" \ + --logs '[ + {"category": "FunctionAppLogs", "enabled": true}, + {"category": "AppServiceAuthenticationLogs", "enabled": true} + ]' \ + --metrics '[ + {"category": "AllMetrics", "enabled": true} + ]' \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$FUNCTION_APP_NAME] function app successfully created" + else + echo "Failed to create [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$FUNCTION_APP_NAME] function app" + exit 1 + fi +else + echo "[$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$FUNCTION_APP_NAME] function app already exist" +fi + +# Check whether the diagnostic settings for the app service plan already exist +echo "Checking if [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$APP_SERVICE_PLAN_NAME] app service plan already exist..." +$AZ monitor diagnostic-settings show \ + --name "$DIAGNOSTIC_SETTINGS_NAME" \ + --resource "$APP_SERVICE_PLAN_ID" \ + --only-show-errors &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$APP_SERVICE_PLAN_NAME] app service plan actually exist" + echo "Creating [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$APP_SERVICE_PLAN_NAME] app service plan..." + + # Create the diagnostic settings for the app service plan to send logs to the Log Analytics workspace + $AZ monitor diagnostic-settings create \ + --name "$DIAGNOSTIC_SETTINGS_NAME" \ + --resource "$APP_SERVICE_PLAN_ID" \ + --workspace "$LOG_ANALYTICS_NAME" \ + --metrics '[ + {"category": "AllMetrics", "enabled": true} + ]' \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$APP_SERVICE_PLAN_NAME] app service plan successfully created" + else + echo "Failed to create [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$APP_SERVICE_PLAN_NAME] app service plan" + exit 1 + fi +else + echo "[$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$APP_SERVICE_PLAN_NAME] app service plan already exist" +fi + +# Check whether the diagnostic settings for the service bus namespace already exist +echo "Checking if [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$SERVICE_BUS_NAMESPACE] service bus namespace already exist..." +$AZ monitor diagnostic-settings show \ + --name "$DIAGNOSTIC_SETTINGS_NAME" \ + --resource "$SERVICE_BUS_NAMESPACE_ID" \ + --only-show-errors &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$SERVICE_BUS_NAMESPACE] service bus namespace actually exist" + echo "Creating [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$SERVICE_BUS_NAMESPACE] service bus namespace..." + + # Create the diagnostic settings for the service bus namespace to send logs to the Log Analytics workspace + $AZ monitor diagnostic-settings create \ + --name "$DIAGNOSTIC_SETTINGS_NAME" \ + --resource "$SERVICE_BUS_NAMESPACE_ID" \ + --workspace "$LOG_ANALYTICS_NAME" \ + --logs '[ + {"category": "ApplicationMetricsLogs", "enabled": true}, + {"category": "DiagnosticErrorLogs", "enabled": true}, + {"category": "OperationalLogs", "enabled": true}, + {"category": "RuntimeAuditLogs", "enabled": true} + ]' \ + --metrics '[ + {"category": "AllMetrics", "enabled": true} + ]' \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$SERVICE_BUS_NAMESPACE] service bus namespace successfully created" + else + echo "Failed to create [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$SERVICE_BUS_NAMESPACE] service bus namespace" + exit 1 + fi +else + echo "[$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$SERVICE_BUS_NAMESPACE] service bus namespace already exist" +fi + +# Check whether the diagnostic settings for the virtual network already exist +echo "Checking if [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$VIRTUAL_NETWORK_NAME] virtual network already exist..." +$AZ monitor diagnostic-settings show \ + --name "$DIAGNOSTIC_SETTINGS_NAME" \ + --resource "$VIRTUAL_NETWORK_ID" \ + --only-show-errors &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$VIRTUAL_NETWORK_NAME] virtual network actually exist" + echo "Creating [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$VIRTUAL_NETWORK_NAME] virtual network..." + + # Create the diagnostic settings for the virtual network to send logs to the Log Analytics workspace + $AZ monitor diagnostic-settings create \ + --name "$DIAGNOSTIC_SETTINGS_NAME" \ + --resource "$VIRTUAL_NETWORK_ID" \ + --workspace "$LOG_ANALYTICS_NAME" \ + --logs '[ + {"category": "VMProtectionAlerts", "enabled": true} + ]' \ + --metrics '[ + {"category": "AllMetrics", "enabled": true} + ]' \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$VIRTUAL_NETWORK_NAME] virtual network successfully created" + else + echo "Failed to create [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$VIRTUAL_NETWORK_NAME] virtual network" + exit 1 + fi +else + echo "[$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$VIRTUAL_NETWORK_NAME] virtual network already exist" +fi + +# Check whether the diagnostic settings for the network security group for the function app subnet already exist +echo "Checking if [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$FUNCTION_APP_SUBNET_NSG_NAME] network security group for the function app subnet already exist..." +$AZ monitor diagnostic-settings show \ + --name "$DIAGNOSTIC_SETTINGS_NAME" \ + --resource "$FUNCTION_APP_SUBNET_NSG_ID" \ + --only-show-errors &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$FUNCTION_APP_SUBNET_NSG_NAME] network security group for the function app subnet actually exist" + echo "Creating [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$FUNCTION_APP_SUBNET_NSG_NAME] network security group for the function app subnet..." + + # Create the diagnostic settings for the network security group for the function app subnet to send logs to the Log Analytics workspace + $AZ monitor diagnostic-settings create \ + --name "$DIAGNOSTIC_SETTINGS_NAME" \ + --resource "$FUNCTION_APP_SUBNET_NSG_ID" \ + --workspace "$LOG_ANALYTICS_NAME" \ + --logs '[ + {"category": "NetworkSecurityGroupEvent", "enabled": true}, + {"category": "NetworkSecurityGroupRuleCounter", "enabled": true} + ]' \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$FUNCTION_APP_SUBNET_NSG_NAME] network security group for the function app subnet successfully created" + else + echo "Failed to create [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$FUNCTION_APP_SUBNET_NSG_NAME] network security group for the function app subnet" + exit 1 + fi +else + echo "[$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$FUNCTION_APP_SUBNET_NSG_NAME] network security group for the function app subnet already exist" +fi + +# Check whether the diagnostic settings for the network security group for the private endpoint subnet already exist +echo "Checking if [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$PE_SUBNET_NSG_NAME] network security group for the private endpoint subnet already exist..." +$AZ monitor diagnostic-settings show \ + --name "$DIAGNOSTIC_SETTINGS_NAME" \ + --resource "$PE_SUBNET_NSG_ID" \ + --only-show-errors &>/dev/null + +if [[ $? != 0 ]]; then + echo "No [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$PE_SUBNET_NSG_NAME] network security group for the private endpoint subnet actually exist" + echo "Creating [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$PE_SUBNET_NSG_NAME] network security group for the private endpoint subnet..." + + # Create the diagnostic settings for the network security group for the private endpoint subnet to send logs to the Log Analytics workspace + $AZ monitor diagnostic-settings create \ + --name "$DIAGNOSTIC_SETTINGS_NAME" \ + --resource "$PE_SUBNET_NSG_ID" \ + --workspace "$LOG_ANALYTICS_NAME" \ + --logs '[ + {"category": "NetworkSecurityGroupEvent", "enabled": true}, + {"category": "NetworkSecurityGroupRuleCounter", "enabled": true} + ]' \ + --only-show-errors 1>/dev/null + + if [[ $? == 0 ]]; then + echo "[$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$PE_SUBNET_NSG_NAME] network security group for the private endpoint subnet successfully created" + else + echo "Failed to create [$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$PE_SUBNET_NSG_NAME] network security group for the private endpoint subnet" + exit 1 + fi +else + echo "[$DIAGNOSTIC_SETTINGS_NAME] diagnostic settings for the [$PE_SUBNET_NSG_NAME] network security group for the private endpoint subnet already exist" +fi + +# CD into the function app directory +cd ../src || exit + +# Remove any existing zip package of the function app +if [ -f "$ZIPFILE" ]; then + rm "$ZIPFILE" +fi + +# Build and publish the function app +echo "Building function app [$FUNCTION_APP_NAME]..." +if dotnet publish -c Release -o ./publish; then + echo "Function app [$FUNCTION_APP_NAME] built successfully." +else + echo "Failed to build function app [$FUNCTION_APP_NAME]." + exit 1 +fi + +# Create the zip package of the publish output +echo "Creating zip package of the function app..." +cd ./publish || exit +zip -r "../$ZIPFILE" . +cd .. + +# Deploy the function app +echo "Deploying function app [$FUNCTION_APP_NAME] with zip file [$ZIPFILE]..." +if $AZ functionapp deployment source config-zip \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --name "$FUNCTION_APP_NAME" \ + --src "$ZIPFILE" 1>/dev/null; then + echo "Function app [$FUNCTION_APP_NAME] deployed successfully." +else + echo "Failed to deploy function app [$FUNCTION_APP_NAME]." + exit 1 +fi + +# Remove the zip package of the function app +if [ -f "$ZIPFILE" ]; then + rm "$ZIPFILE" +fi + +# Print the list of resources in the resource group +echo "Listing resources in resource group [$RESOURCE_GROUP_NAME]..." +az resource list --resource-group "$RESOURCE_GROUP_NAME" --output table \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/scripts/validate.sh b/samples/function-app-service-bus/dotnet/scripts/validate.sh new file mode 100755 index 0000000..c1dc8dc --- /dev/null +++ b/samples/function-app-service-bus/dotnet/scripts/validate.sh @@ -0,0 +1,166 @@ +#!/bin/bash + +# Variables +PREFIX='local' +SUFFIX='test' +RESOURCE_GROUP_NAME="${PREFIX}-rg" +LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" +FUNCTION_APP_SUBNET_NSG_NAME="${PREFIX}-func-subnet-nsg-${SUFFIX}" +PE_SUBNET_NSG_NAME="${PREFIX}-pe-subnet-nsg-${SUFFIX}" +NAT_GATEWAY_NAME="${PREFIX}-nat-gateway-${SUFFIX}" +VIRTUAL_NETWORK_NAME="${PREFIX}-vnet-${SUFFIX}" +APP_SERVICE_PLAN_NAME="${PREFIX}-plan-${SUFFIX}" +FUNCTION_APP_NAME="${PREFIX}-func-${SUFFIX}" +SERVICE_BUS_NAMESPACE_NAME="${PREFIX}-service-bus-${SUFFIX}" +STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}" +APPLICATION_INSIGHTS_NAME="${PREFIX}-func-${SUFFIX}" +ENVIRONMENT=$(az account show --query environmentName --output tsv) +PRIVATE_DNS_ZONE_NAMES=( + "privatelink.servicebus.windows.net" + "privatelink.blob.core.windows.net" + "privatelink.queue.core.windows.net" + "privatelink.table.core.windows.net" +) +PE_NAMES=( + "${PREFIX}-service-bus-pe-${SUFFIX}" + "${PREFIX}-blob-storage-pe-${SUFFIX}" + "${PREFIX}-queue-storage-pe-${SUFFIX}" + "${PREFIX}-table-storage-pe-${SUFFIX}" +) + +# Choose the appropriate CLI based on the environment +if [[ $ENVIRONMENT == "LocalStack" ]]; then + echo "Using azlocal for LocalStack emulator environment." + AZ="azlocal" +else + echo "Using standard az for AzureCloud environment." + AZ="az" +fi + +# Check resource group +echo -e "[$RESOURCE_GROUP_NAME] resource group:\n" +$AZ group show \ + --name "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check App Service Plan +echo -e "\n[$APP_SERVICE_PLAN_NAME] app service plan:\n" +$AZ appservice plan show \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --name "$APP_SERVICE_PLAN_NAME" \ + --output table \ + --only-show-errors + +# Check Azure Functions App +echo -e "\n[$FUNCTION_APP_NAME] function app:\n" +$AZ functionapp show \ + --name "$FUNCTION_APP_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Service Bus Namespace +echo -e "\n[$SERVICE_BUS_NAMESPACE_NAME] service bus namespace:\n" +$AZ servicebus namespace show \ + --name "$SERVICE_BUS_NAMESPACE_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --query '{Name:name,ServiceBusEndpoint:serviceBusEndpoint}' \ + --only-show-errors + +# Check Service Bus Queues +echo -e "\n[$SERVICE_BUS_NAMESPACE_NAME] service bus queues:\n" +$AZ servicebus queue list \ + --namespace-name "$SERVICE_BUS_NAMESPACE_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --query '[].{Name:name,Status:status}' \ + --only-show-errors + + # Check Application Insights +echo -e "\n[$APPLICATION_INSIGHTS_NAME] application insights:\n" +$AZ monitor app-insights component show \ + --app "$APPLICATION_INSIGHTS_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query '{Name:name,Location:location,ResourceGroup:resourceGroup}' \ + --output table \ + --only-show-errors + +# Check Storage Account +echo -e "\n[$STORAGE_ACCOUNT_NAME] storage account:\n" +$AZ storage account show \ + --name "$STORAGE_ACCOUNT_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query '{Name:name,Location:primaryLocation,ResourceGroup:resourceGroup}' \ + --output table \ + --only-show-errors + +# Check Log Analytics Workspace +echo -e "\n[$LOG_ANALYTICS_NAME] log analytics workspace:\n" +$AZ monitor log-analytics workspace show \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --workspace-name "$LOG_ANALYTICS_NAME" \ + --query '{Name:name,Location:location,ResourceGroup:resourceGroup}' \ + --output table \ + --only-show-errors + +# Check NAT Gateway +echo -e "\n[$NAT_GATEWAY_NAME] nat gateway:\n" +$AZ network nat gateway show \ + --name "$NAT_GATEWAY_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Virtual Network +echo -e "\n[$VIRTUAL_NETWORK_NAME] virtual network:\n" +$AZ network vnet show \ + --name "$VIRTUAL_NETWORK_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Private DNS Zone +for PRIVATE_DNS_ZONE_NAME in "${PRIVATE_DNS_ZONE_NAMES[@]}"; do + echo -e "\n[$PRIVATE_DNS_ZONE_NAME] private dns zone:\n" + $AZ network private-dns zone show \ + --name "$PRIVATE_DNS_ZONE_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query '{Name:name,ResourceGroup:resourceGroup,RecordSets:recordSets,VirtualNetworkLinks:virtualNetworkLinks}' \ + --output table \ + --only-show-errors +done + +# Check Private Endpoint +for PRIVATE_ENDPOINT_NAME in "${PE_NAMES[@]}"; do + echo -e "\n[$PRIVATE_ENDPOINT_NAME] private endpoint:\n" + $AZ network private-endpoint show \ + --name "$PRIVATE_ENDPOINT_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors +done + +# Check Functions App Subnet NSG +echo -e "\n[$FUNCTION_APP_SUBNET_NSG_NAME] network security group:\n" +$AZ network nsg show \ + --name "$FUNCTION_APP_SUBNET_NSG_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Private Endpoint Subnet NSG +echo -e "\n[$PE_SUBNET_NSG_NAME] network security group:\n" +$AZ network nsg show \ + --name "$PE_SUBNET_NSG_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# List resources +echo -e "\n[$RESOURCE_GROUP_NAME] all resources:\n" +$AZ resource list \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/src/GreetingFunctions.cs b/samples/function-app-service-bus/dotnet/src/GreetingFunctions.cs new file mode 100644 index 0000000..8e0a41b --- /dev/null +++ b/samples/function-app-service-bus/dotnet/src/GreetingFunctions.cs @@ -0,0 +1,502 @@ +using System.Net; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Configuration; +using Azure.Identity; +using Azure.Messaging.ServiceBus; +using Azure.Messaging.ServiceBus.Administration; + +namespace LocalStack.Azure.Samples; + +/// +/// A simple Azure Function that processes Service Bus messages and responds with a greeting. +/// +public class HelloWorld +{ + // Instance field for logging - keeps proper Azure Functions execution context + private readonly ILogger _logger; + + // Static configuration values - initialized once per application lifetime + private static string? _connectionString; + private static string? _clientId; + private static string? _fullyQualifiedNamespace; + private static bool _hasConnectionString; + private static bool _hasClientId; + private static bool _hasFullyQualifiedNamespace; + private static string? _inputQueueName; + private static string? _outputQueueName; + private static bool _configurationValid = false; + private static string[]? _names; + + // Greeting templates used by GetGreeting to produce varied responses + private static readonly string[] _greetingTemplates = new[] + { + "Hello {0}, how are you?", + "Hi {0}, great to see you!", + "Hey {0}, hope you're having a wonderful day!", + "Good day {0}, welcome aboard!", + "Greetings {0}, nice to meet you!", + "Howdy {0}, what's going on?", + "Welcome {0}, glad you're here!", + "Salutations {0}, how's everything going?" + }; + + private static readonly Random _random = new(); + + // Circular buffer storing the last 100 greetings + private const int MaxGreetingHistory = 100; + private static readonly string[] _greetingHistory = new string[MaxGreetingHistory]; + private static int _greetingIndex = 0; + private static int _greetingCount = 0; + private static readonly object _greetingLock = new(); + + // Static initialization - runs once per application lifetime + private static readonly Lazy _initialized = new Lazy(() => { Initialize(); return true; }); + + /// + /// Initializes a new instance of the class. + /// + /// The logger factory used to create loggers for this class. + public HelloWorld(ILoggerFactory loggerFactory) + { + _logger = loggerFactory.CreateLogger(); + } + + /// + /// One-time initialization of Azure Storage infrastructure (queues, containers, tables). + /// This method runs exactly once per application lifetime and stores configuration values in static fields. + /// + /// A task representing the asynchronous initialization operation. + private static void Initialize() + { + try + { + // Create a temporary configuration instance for initialization + var configBuilder = new ConfigurationBuilder() + .AddEnvironmentVariables() + .AddJsonFile("local.settings.json", optional: true); + var config = configBuilder.Build(); + + // Create a temporary logger for initialization + using var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole()); + var logger = loggerFactory.CreateLogger(); + + logger.LogInformation("[Initialize] Starting one-time initialization..."); + + // Read and store configuration values in static fields with fallback defaults + _connectionString = config["SERVICE_BUS_CONNECTION_STRING"]; + _clientId = config["AZURE_CLIENT_ID"]; + _fullyQualifiedNamespace = config["SERVICE_BUS_CONNECTION_STRING:fullyQualifiedNamespace"]; + _inputQueueName = config["INPUT_QUEUE_NAME"] ?? "input"; + _outputQueueName = config["OUTPUT_QUEUE_NAME"] ?? "output"; + _names = config["NAMES"]?.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + + _hasConnectionString = !string.IsNullOrWhiteSpace(_connectionString); + _hasClientId = !string.IsNullOrWhiteSpace(_clientId); + _hasFullyQualifiedNamespace = !string.IsNullOrWhiteSpace(_fullyQualifiedNamespace); + + // Check if names ae configured. If not use, use default names + if (_names == null || _names.Length == 0) + { + logger.LogWarning("[Initialize] NAMES configuration is missing or empty. Using default names."); + _names = new[] { "Alice", "Paolo", "Leo", "Mia" }; + } + + // Validate configuration and set the flag + _configurationValid = ValidateConfigurationValues(logger); + } + catch (Exception ex) + { + // Log error but don't throw - let functions continue to work even if initialization fails + Console.WriteLine("[Initialize] Initialization failed: {0}", ex.Message); + _configurationValid = false; + } + } + + /// + /// Validates that all required configuration values are present and not empty. + /// With default values in place, only the connection string is mandatory. + /// + /// Logger for reporting validation errors. + /// True if all configuration values are valid, false otherwise. + private static bool ValidateConfigurationValues(ILogger logger) + { + bool isValid = true; + + // Requirement: Must have (ID AND Namespace) OR (Connection String) + if (!(_hasClientId && _hasFullyQualifiedNamespace) && !_hasConnectionString) + { + logger.LogError("[ValidateConfigurationValues] Incomplete configuration. You must provide BOTH Client ID and Namespace, OR a Connection String."); + isValid = false; + } + + // Additional Safety: If they provided a partial Identity, catch it! + if (_hasClientId != _hasFullyQualifiedNamespace && !_hasConnectionString) + { + logger.LogError("[ValidateConfigurationValues] Partial Identity detected. Both Client ID and Namespace are required."); + isValid = false; + } + + // Log the configuration values being used (helpful for debugging) + if (isValid) + { + logger.LogInformation("[ValidateConfigurationValues] Configuration loaded successfully:"); + logger.LogInformation(" - Input Queue: {inputQueue}", _inputQueueName); + logger.LogInformation(" - Output Queue: {outputQueue}", _outputQueueName); + logger.LogInformation(" - Names: {names}", string.Join(", ", _names != null ? _names : Array.Empty())); + } + + return isValid; + } + + /// + /// Checks if configuration values have been successfully loaded and validated. + /// This method provides a fast runtime check without re-reading configuration. + /// With default values, this primarily checks if the connection string is available. + /// + /// True if configuration is valid and available, false otherwise. + private static bool IsConfigurationValid() + { + // Valid if we have a connection string OR (client ID + fully qualified namespace) + return _configurationValid && (_hasConnectionString || (_hasClientId && _hasFullyQualifiedNamespace)); + } + + /// + /// Processes a Service Bus message by reading, validating, and responding to the input message. + /// + /// The received Service Bus message containing the request payload as JSON. + /// Actions for managing the Service Bus message lifecycle (e.g., completion). + /// + /// A JSON-formatted response message containing a greeting and the current date, or null if the input is invalid. + /// + [Function("GreetingHandler")] + [ServiceBusOutput("%OUTPUT_QUEUE_NAME%", Connection = "SERVICE_BUS_CONNECTION_STRING")] + public async Task GreetingHandlerAsync( + [ServiceBusTrigger("%INPUT_QUEUE_NAME%", Connection = "SERVICE_BUS_CONNECTION_STRING", AutoCompleteMessages = false)] ServiceBusReceivedMessage message, + ServiceBusMessageActions messageActions) + { + // Log the incoming message details + _logger.LogInformation("[GreetingHandler] Message ID: {id}", message.MessageId); + _logger.LogInformation("[GreetingHandler] Message Body: {body}", message.Body); + _logger.LogInformation("[GreetingHandler] Message Content-Type: {contentType}", message.ContentType); + + // Read the message body as a byte array + byte[] bodyBytes = message.Body.ToArray(); + + // Check that the bodyBytes is not null or empty + if (bodyBytes == null || bodyBytes.Length == 0) + { + _logger.LogError("[GreetingHandler] Received message [{messageId}] body is empty or null.", message.MessageId); + return null; + } + // Convert the byte array to a string + string json = System.Text.Encoding.UTF8.GetString(bodyBytes); + + // Check that the JSON is not null or empty + if (string.IsNullOrEmpty(json)) + { + _logger.LogError("[GreetingHandler] Received message [{messageId}] body is empty or invalid.", message.MessageId); + return null; + } + + // Deserialize the JSON into a RequestMessage object + RequestMessage? requestMessage = JsonSerializer.Deserialize(json); + + // Check that the request message is not null or empty + if (requestMessage == null || string.IsNullOrWhiteSpace(requestMessage?.Name)) + { + _logger.LogError("[GreetingHandler] Received request message [{messageId}] body is empty or invalid.", message.MessageId); + return null; + } + + _logger.LogInformation("[GreetingHandler] Processing request for name: {name}", requestMessage.Name); + + // Create the response message + var greetingText = GetGreeting(requestMessage.Name); + var outputObj = new ResponseMessage + { + Date = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss"), + Text = greetingText + }; + var outputMessage = JsonSerializer.Serialize(outputObj); + + // Complete the message after processing + await messageActions.CompleteMessageAsync(message); + + // Log the successful processing of the message + _logger.LogInformation("[GreetingHandler] Processed message [{messageId}] successfully: {greetingText}", message.MessageId, greetingText); + + // Return the response message + return outputMessage; + } + + /// + /// Timer-triggered function that sends a greeting request message to the input queue. + /// + /// Timer metadata containing schedule status and next occurrence information. + [Function("GreetingRequester")] + [FixedDelayRetry(5, "00:00:10")] + public async Task GreetingRequesterAsync([TimerTrigger("%TIMER_SCHEDULE%", RunOnStartup = true)] TimerInfo timerInfo) + { + // Log the start of the function execution + _logger.LogInformation("[GreetingRequester] Timer trigger function started."); + + // Ensure one-time initialization has run + _ = _initialized.Value; + + // Fast configuration validation using pre-loaded static values + if (!IsConfigurationValid()) + { + _logger.LogError("[GreetingRequester] Configuration is invalid or not loaded. Aborting function execution."); + return; + } + + if (_names == null || _names.Length == 0) + { + _logger.LogError("[GreetingRequester] Names are not configured. Aborting function execution."); + return; + } + + try + { + // Create Service Bus client + _logger.LogInformation("[GreetingRequester] Creating Service Bus client for sending messages..."); + await using var client = _hasClientId && _hasFullyQualifiedNamespace + ? new ServiceBusClient(_fullyQualifiedNamespace, new DefaultAzureCredential()) + : new ServiceBusClient(_connectionString); + + // Create message sender for the input queue + _logger.LogInformation("[GreetingRequester] Creating sender for input queue '{inputQueue}'", _inputQueueName); + await using var sender = client.CreateSender(_inputQueueName); + + // Create request message with randomly selected name + var random = new Random(); + var selectedName = _names[random.Next(_names.Length)]; + var requestMessage = new RequestMessage { Name = selectedName }; + var messageBody = JsonSerializer.Serialize(requestMessage); + + // Create and send Service Bus message + var serviceBusMessage = new ServiceBusMessage(messageBody) + { + ContentType = "application/json" + }; + + _logger.LogInformation("[GreetingRequester] Sending message to input queue '{inputQueue}'...", _inputQueueName); + await sender.SendMessageAsync(serviceBusMessage); + _logger.LogInformation("[GreetingRequester] Successfully sent message to input queue '{inputQueue}' with name: {Name}", _inputQueueName, selectedName); + } + catch (Exception ex) + { + _logger.LogError(ex, "[GreetingRequester] Failed to send message to input queue '{inputQueue}'", _inputQueueName); + return; + } + + // Log the next scheduled timer occurrence + _logger.LogInformation("[GreetingRequester] Function Ran. Next timer schedule = {nextSchedule}", timerInfo.ScheduleStatus?.Next); + } + + /// + /// Timer-triggered function that receives and processes greeting response messages from the output queue. + /// + /// Timer metadata containing schedule status and next occurrence information. + [Function("GreetingConsumer")] + [FixedDelayRetry(5, "00:00:10")] + public async Task GreetingConsumerAsync([TimerTrigger("%TIMER_SCHEDULE%", RunOnStartup = true)] TimerInfo timerInfo) + { + // Log the start of the function execution + _logger.LogInformation("[GreetingConsumer] Timer trigger function started."); + + // Ensure one-time initialization has run + _ = _initialized.Value; + + // Fast configuration validation using pre-loaded static values + if (!IsConfigurationValid()) + { + _logger.LogError("[GreetingConsumer] Configuration is invalid or not loaded. Aborting function execution."); + return; + } + + try + { + // Create Service Bus client for receiving messages from the output queue + _logger.LogInformation("[GreetingConsumer] Creating Service Bus client for receiving messages..."); + await using var client = _hasClientId && _hasFullyQualifiedNamespace + ? new ServiceBusClient(_fullyQualifiedNamespace, new DefaultAzureCredential()) + : new ServiceBusClient(_connectionString); + var receiver = client.CreateReceiver(_outputQueueName); + + _logger.LogInformation("[GreetingConsumer] Starting to receive messages from output queue '{outputQueue}'", _outputQueueName); + + // Loop to receive messages (with timeout to prevent infinite waiting) + var timeout = TimeSpan.FromSeconds(30); + var startTime = DateTime.UtcNow; + + try + { + while (DateTime.UtcNow - startTime < timeout) + { + try + { + // Receive message with a short timeout + var receivedMessage = await receiver.ReceiveMessageAsync(TimeSpan.FromSeconds(5)); + + if (receivedMessage == null) + { + _logger.LogInformation("[GreetingConsumer] No more messages available in output queue '{outputQueue}'", _outputQueueName); + break; + } + + // Convert message body to string + var messageBody = receivedMessage.Body.ToString(); + + try + { + // Attempt to deserialize to ResponseMessage + var responseMessage = JsonSerializer.Deserialize(messageBody); + + if (responseMessage != null) + { + _logger.LogInformation("[GreetingConsumer] Successfully received and deserialized message from output queue. Date: {Date}, Text: {Text}", + responseMessage.Date, responseMessage.Text); + + // Complete the message after successful processing + await receiver.CompleteMessageAsync(receivedMessage); + } + else + { + _logger.LogWarning("[GreetingConsumer] Received message could not be deserialized to ResponseMessage (null result)"); + await receiver.DeadLetterMessageAsync(receivedMessage, "DeserializationFailed", "Message deserialized to null"); + } + } + catch (JsonException jsonEx) + { + _logger.LogError(jsonEx, "[GreetingConsumer] Failed to deserialize message from output queue. Message body: {messageBody}", messageBody); + await receiver.DeadLetterMessageAsync(receivedMessage, "DeserializationFailed", jsonEx.Message); + } + } + catch (Exception messageEx) + { + _logger.LogError(messageEx, "[GreetingConsumer] Error occurred while receiving message from output queue '{outputQueue}'", _outputQueueName); + // Continue the loop to try receiving more messages + } + } + } + finally + { + using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5)); + try + { + await receiver.CloseAsync(cts.Token); + } + catch + { /* timeout or error on close */ } + try + { + await client.DisposeAsync(); + } + catch { /* benign */ + } + } + } + catch (Exception ex) + { + _logger.LogError(ex, "[GreetingConsumer] Failed to receive messages from output queue '{outputQueue}'", _outputQueueName); + } + + // Log the next scheduled timer occurrence + _logger.LogInformation("[GreetingConsumer] Function Ran. Next timer schedule = {nextSchedule}", timerInfo.ScheduleStatus?.Next); + } + + /// + /// Selects a random greeting template and formats it with the given name. + /// The generated greeting is also stored in a circular buffer for later retrieval. + /// + /// The name to include in the greeting. + /// A randomly chosen greeting string addressed to the specified name. + private static string GetGreeting(string name) + { + var template = _greetingTemplates[_random.Next(_greetingTemplates.Length)]; + var greeting = string.Format(template, name); + + lock (_greetingLock) + { + _greetingHistory[_greetingIndex] = greeting; + _greetingIndex = (_greetingIndex + 1) % MaxGreetingHistory; + if (_greetingCount < MaxGreetingHistory) + _greetingCount++; + } + + return greeting; + } + + /// + /// HTTP-triggered function that returns the most recent greetings from the circular buffer. + /// Greetings are returned in reverse chronological order (newest first). + /// + /// The incoming HTTP request. + /// The number of greetings to return (default: 20, max: 100). + /// An HTTP response containing a JSON array of recent greetings. + [Function("GetGreetings")] + public async Task GetGreetingsAsync( + [HttpTrigger(AuthorizationLevel.Function, "get", Route = "greetings")] HttpRequestData request, + int count = 20) + { + _logger.LogInformation("[GetGreetings] Retrieving last {count} greetings.", count); + + // Clamp count to valid range + if (count < 1) count = 1; + if (count > MaxGreetingHistory) count = MaxGreetingHistory; + + string[] result; + lock (_greetingLock) + { + var available = Math.Min(count, _greetingCount); + result = new string[available]; + + // Read backwards from the most recent entry + for (int i = 0; i < available; i++) + { + var idx = (_greetingIndex - 1 - i + MaxGreetingHistory) % MaxGreetingHistory; + result[i] = _greetingHistory[idx]; + } + } + + var response = request.CreateResponse(HttpStatusCode.OK); + response.Headers.Add("Content-Type", "application/json"); + await response.WriteStringAsync(JsonSerializer.Serialize(result)); + return response; + } +} + +/// +/// Represents the input payload for greeting requests. +/// +public class RequestMessage +{ + /// + /// Gets or sets the name to greet. + /// + [JsonPropertyName("name")] + public required string Name { get; set; } +} + +/// +/// Represents the response payload for greeting requests. +/// +public class ResponseMessage +{ + /// + /// Gets or sets the date of the response message. + /// + [JsonPropertyName("date")] + public required string Date { get; set; } + + /// + /// Gets or sets the text of the response message. + /// + [JsonPropertyName("text")] + public required string Text { get; set; } +} \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/src/Program.cs b/samples/function-app-service-bus/dotnet/src/Program.cs new file mode 100644 index 0000000..c76837e --- /dev/null +++ b/samples/function-app-service-bus/dotnet/src/Program.cs @@ -0,0 +1,7 @@ +using Microsoft.Extensions.Hosting; + +var host = new HostBuilder() + .ConfigureFunctionsWorkerDefaults() + .Build(); + +host.Run(); diff --git a/samples/function-app-service-bus/dotnet/src/host.json b/samples/function-app-service-bus/dotnet/src/host.json new file mode 100644 index 0000000..007828f --- /dev/null +++ b/samples/function-app-service-bus/dotnet/src/host.json @@ -0,0 +1,39 @@ +{ + "version": "2.0", + "extensions": { + "serviceBus": { + "clientRetryOptions": { + "mode": "exponential", + "tryTimeout": "00:00:10", + "delay": "00:00:00.80", + "maxDelay": "00:01:00", + "maxRetries": 3 + }, + "prefetchCount": 0, + "transportType": "amqpTcp", + "autoCompleteMessages": true, + "maxAutoLockRenewalDuration": "00:05:00", + "maxConcurrentCalls": 16, + "maxConcurrentSessions": 8, + "maxMessageBatchSize": 1000, + "minMessageBatchSize": 1, + "maxBatchWaitTime": "00:00:30", + "sessionIdleTimeout": "00:01:00", + "enableCrossEntityTransactions": false + } + }, + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + }, + "enableLiveMetricsFilters": true + }, + "logLevel": { + "Host.Startup": "Trace", + "Host.Results": "Trace", + "Function": "Trace" + } + } +} \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/src/local.settings.json b/samples/function-app-service-bus/dotnet/src/local.settings.json new file mode 100644 index 0000000..3a27b26 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/src/local.settings.json @@ -0,0 +1,12 @@ +{ + "IsEncrypted": false, + "Values": { + "AzureWebJobsStorage": "DefaultEndpointsProtocol=http;AccountName=regmanaged100;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://regmanaged100blob.localhost.localstack.cloud:4566;QueueEndpoint=http://regmanaged100queue.localhost.localstack.cloud:4566;TableEndpoint=http://regmanaged100table.localhost.localstack.cloud:4566", + "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", + "SERVICE_BUS_CONNECTION_STRING": "", + "INPUT_QUEUE_NAME": "input", + "OUTPUT_QUEUE_NAME": "output", + "NAMES": "Alice,Paolo,Leo,Mia", + "TIMER_SCHEDULE": "*/10 * * * * *" + } +} diff --git a/samples/function-app-service-bus/dotnet/src/sample.csproj b/samples/function-app-service-bus/dotnet/src/sample.csproj new file mode 100644 index 0000000..8b21d36 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/src/sample.csproj @@ -0,0 +1,31 @@ + + + net10.0 + v4 + Exe + enable + enable + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + Never + + + + + + \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/README.md b/samples/function-app-service-bus/dotnet/terraform/README.md new file mode 100644 index 0000000..49b36e3 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/README.md @@ -0,0 +1,321 @@ +# Terraform Deployment + +This directory contains Terraform modules and a deployment script for provisioning Azure services in LocalStack for Azure. For further details about the sample application, refer to the [Azure Functions App with Service Bus Messaging](../README.md). + +## Prerequisites + +Before deploying this solution, ensure you have the following tools installed: + +- [Azure Subscription](https://azure.microsoft.com/free/) +- [LocalStack for Azure](https://azure.localstack.cloud/): Local Azure cloud emulator for development and testing +- [Visual Studio Code](https://code.visualstudio.com/): Code editor installed on one of the [supported platforms](https://code.visualstudio.com/docs/supporting/requirements#_platforms) +- [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli): Azure command-line interface +- [Azlocal CLI](https://azure.localstack.cloud/user-guides/sdks/az/): LocalStack Azure CLI wrapper +- [Azure Functions Core Tools](https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local) is required to build, run, and deploy the Azure Functions app locally +- [Terraform](https://developer.hashicorp.com/terraform/downloads), if you plan to install the sample via Terraform. +- [Docker](https://docs.docker.com/get-docker/): Container runtime required for LocalStack +- [.NET SDK](https://dotnet.microsoft.com/en-us/download) is required to compile and run the C# Azure Functions project +- [jq](https://jqlang.org/): JSON processor for scripting and parsing command outputs + +### Installing azlocal CLI + +The [deploy.sh](deploy.sh) Bash script uses the `azlocal` CLI instead of the standard Azure CLI to work with LocalStack. Install it using: + +```bash +pip install azlocal +``` + +For more information, see [Get started with the az tool on LocalStack](https://azure.localstack.cloud/user-guides/sdks/az/). + +## Architecture Overview + +The Terraform modules create the following Azure resources: + +1. [Azure Resource Group](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-cli): A logical container scoping all resources in this sample. +2. [Azure Virtual Network](https://learn.microsoft.com/azure/virtual-network/virtual-networks-overview): Hosts two subnets: + - *app-subnet*: Dedicated to [regional VNet integration](https://learn.microsoft.com/azure/azure-functions/functions-networking-options?tabs=azure-portal#outbound-networking-features) with the Function App. + - *pe-subnet*: Used for hosting Azure Private Endpoints. +3. [Azure Private DNS Zones](https://learn.microsoft.com/azure/dns/private-dns-privatednszone): Provide internal DNS resolution so that resources within the virtual network can reach Private Endpoints by hostname rather than public addresses. There is a separate Azure Private DNS Zone for the following resource types: + - Azure Service Bus namespace + - Azure Blob Storage + - Azure Queue Storage + - Azure Table Storage +4. [Azure Private Endpoints](https://learn.microsoft.com/azure/private-link/private-endpoint-overview): Provide secure, private network connectivity to Azure resources by exposing them through private IP addresses within the virtual network, eliminating the need for traffic to traverse the public internet. There is a separate Azure Private Endpoint for the following resources: + - Azure Service Bus namespace + - Azure Blob Storage + - Azure Queue Storage + - Azure Table Storage +5. [Azure NAT Gateway](https://learn.microsoft.com/azure/nat-gateway/nat-overview): Provides deterministic outbound connectivity and a stable public IP address for the Function App's outbound traffic. Included for architectural completeness; the sample app itself does not call any external services. +6. [Azure Network Security Group](https://learn.microsoft.com/en-us/azure/virtual-network/network-security-groups-overview): Enforces inbound and outbound traffic rules across the virtual network's subnets. +7. [Azure Log Analytics Workspace](https://learn.microsoft.com/azure/azure-monitor/logs/log-analytics-overview): Centralizes diagnostic logs and metrics from all resources in the solution, enabling unified querying and analysis across the entire deployment. +8. [Azure App Service Plan](https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview-hosting-plans): Defines the underlying compute tier and scaling behavior for the function app. +9. [Azure Functions App](https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview): Hosts the sample function app. +10. [Azure Application Insights](https://learn.microsoft.com/en-us/azure/azure-monitor/app/app-insights-overview): Provides application performance monitoring (APM), collecting and analyzing requests, traces, and metrics generated by the function app to surface performance bottlenecks and failures. +11. [Azure Service Bus](https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messaging-overview): A fully managed enterprise message broker. This namespace hosts the `input` and `output` queues used by the function app to exchange messages asynchronously. +12. [Azure Storage Account](https://learn.microsoft.com/en-us/azure/storage/common/storage-account-overview): Provides durable storage used internally by the Azure Functions runtime for state management, including distributed locks, checkpoints, and timer trigger coordination. +13. [User-Assigned Managed Identity](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview): This identity is assigned the necessary RBAC roles and is used by the function app to authenticate securely—without storing credentials—to the following Azure resources: + - Azure Service Bus namespace + - Azure Storage + - Azure Application Insights + +For more information on the sample application, see [Azure Functions App with Service Bus Messaging](../README.md). + +## Provisioning Scripts + +You can use the [deploy.sh](deploy.sh) script to automate the deployment of all Azure resources and the sample application in a single step, streamlining setup and reducing manual configuration. The script executes the following steps: + +- Cleans up any previous Terraform state and plan files to ensure a fresh deployment. +- Initializes the Terraform working directory and downloads required plugins. +- Creates and validates a Terraform execution plan for the Azure infrastructure. +- Applies the Terraform plan to provision all necessary Azure resources. +- Extracts resource names and outputs from the Terraform deployment. +- Packages the code of the function app into a zip file for deployment. +- Deploys the zip package to the Azure Functions App using the LocalStack Azure CLI. + +## Configuration + +When using LocalStack for Azure, configure the `metadata_host` and `subscription_id` settings in the [Azure Provider for Terraform](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs) to ensure proper connectivity: + + +```hcl +provider "azurerm" { + features { + resource_group { + prevent_deletion_if_contains_resources = false + } + } + + # Set the hostname of the Azure Metadata Service (for example management.azure.com) + # used to obtain the Cloud Environment when using LocalStack's Azure emulator. + # This allows the provider to correctly identify the environment and avoid making calls to the real Azure endpoints. + metadata_host="localhost.localstack.cloud:4566" + + # Set the subscription ID to a dummy value when using LocalStack's Azure emulator. + subscription_id = "00000000-0000-0000-0000-000000000000" +} +``` + +## Deployment + +You can set up the Azure emulator by utilizing LocalStack for Azure Docker image. Before starting, ensure you have a valid `LOCALSTACK_AUTH_TOKEN` to access the Azure emulator. Refer to the [Auth Token guide](https://docs.localstack.cloud/getting-started/auth-token/?__hstc=108988063.8aad2b1a7229945859f4d9b9bb71e05d.1743148429561.1758793541854.1758810151462.32&__hssc=108988063.3.1758810151462&__hsfp=3945774529) to obtain your Auth Token and specify it in the `LOCALSTACK_AUTH_TOKEN` environment variable. The Azure Docker image is available on the [LocalStack Docker Hub](https://hub.docker.com/r/localstack/localstack-azure-alpha). To pull the Azure Docker image, execute the following command: + +```bash +docker pull localstack/localstack-azure-alpha +``` + +Start the LocalStack Azure emulator using the localstack CLI, execute the following command: + +```bash +export LOCALSTACK_AUTH_TOKEN= +IMAGE_NAME=localstack/localstack-azure-alpha localstack start +``` + +Navigate to the `terraform` folder: + +```bash +cd samples/function-app-service-bus/dotnet/terraform +``` + +Make the script executable: + +```bash +chmod +x deploy.sh +``` + +Run the deployment script: + +```bash +./deploy.sh +``` + +## Validation + +Once the deployment completes, run the [validate.sh](../scripts/validate.sh) script to confirm that all resources were provisioned and configured as expected: + +```bash +#!/bin/bash + +# Variables +PREFIX='local' +SUFFIX='test' +RESOURCE_GROUP_NAME="${PREFIX}-rg" +LOG_ANALYTICS_NAME="${PREFIX}-log-analytics-${SUFFIX}" +FUNCTION_APP_SUBNET_NSG_NAME="${PREFIX}-func-subnet-nsg-${SUFFIX}" +PE_SUBNET_NSG_NAME="${PREFIX}-pe-subnet-nsg-${SUFFIX}" +NAT_GATEWAY_NAME="${PREFIX}-nat-gateway-${SUFFIX}" +VIRTUAL_NETWORK_NAME="${PREFIX}-vnet-${SUFFIX}" +APP_SERVICE_PLAN_NAME="${PREFIX}-plan-${SUFFIX}" +FUNCTION_APP_NAME="${PREFIX}-func-${SUFFIX}" +SERVICE_BUS_NAMESPACE_NAME="${PREFIX}-service-bus-${SUFFIX}" +STORAGE_ACCOUNT_NAME="${PREFIX}storage${SUFFIX}" +APPLICATION_INSIGHTS_NAME="${PREFIX}-func-${SUFFIX}" +ENVIRONMENT=$(az account show --query environmentName --output tsv) +PRIVATE_DNS_ZONE_NAMES=( + "privatelink.servicebus.windows.net" + "privatelink.blob.core.windows.net" + "privatelink.queue.core.windows.net" + "privatelink.table.core.windows.net" +) +PE_NAMES=( + "${PREFIX}-service-bus-pe-${SUFFIX}" + "${PREFIX}-blob-storage-pe-${SUFFIX}" + "${PREFIX}-queue-storage-pe-${SUFFIX}" + "${PREFIX}-table-storage-pe-${SUFFIX}" +) + +# Choose the appropriate CLI based on the environment +if [[ $ENVIRONMENT == "LocalStack" ]]; then + echo "Using azlocal for LocalStack emulator environment." + AZ="azlocal" +else + echo "Using standard az for AzureCloud environment." + AZ="az" +fi + +# Check resource group +echo -e "[$RESOURCE_GROUP_NAME] resource group:\n" +$AZ group show \ + --name "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check App Service Plan +echo -e "\n[$APP_SERVICE_PLAN_NAME] app service plan:\n" +$AZ appservice plan show \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --name "$APP_SERVICE_PLAN_NAME" \ + --output table \ + --only-show-errors + +# Check Azure Functions App +echo -e "\n[$FUNCTION_APP_NAME] function app:\n" +$AZ functionapp show \ + --name "$FUNCTION_APP_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Service Bus Namespace +echo -e "\n[$SERVICE_BUS_NAMESPACE_NAME] service bus namespace:\n" +$AZ servicebus namespace show \ + --name "$SERVICE_BUS_NAMESPACE_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --query '{Name:name,ServiceBusEndpoint:serviceBusEndpoint}' \ + --only-show-errors + +# Check Service Bus Queues +echo -e "\n[$SERVICE_BUS_NAMESPACE_NAME] service bus queues:\n" +$AZ servicebus queue list \ + --namespace-name "$SERVICE_BUS_NAMESPACE_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --query '[].{Name:name,Status:status}' \ + --only-show-errors + + # Check Application Insights +echo -e "\n[$APPLICATION_INSIGHTS_NAME] application insights:\n" +$AZ monitor app-insights component show \ + --app "$APPLICATION_INSIGHTS_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query '{Name:name,Location:location,ResourceGroup:resourceGroup}' \ + --output table \ + --only-show-errors + +# Check Storage Account +echo -e "\n[$STORAGE_ACCOUNT_NAME] storage account:\n" +$AZ storage account show \ + --name "$STORAGE_ACCOUNT_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query '{Name:name,Location:primaryLocation,ResourceGroup:resourceGroup}' \ + --output table \ + --only-show-errors + +# Check Log Analytics Workspace +echo -e "\n[$LOG_ANALYTICS_NAME] log analytics workspace:\n" +$AZ monitor log-analytics workspace show \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --workspace-name "$LOG_ANALYTICS_NAME" \ + --query '{Name:name,Location:location,ResourceGroup:resourceGroup}' \ + --output table \ + --only-show-errors + +# Check NAT Gateway +echo -e "\n[$NAT_GATEWAY_NAME] nat gateway:\n" +$AZ network nat gateway show \ + --name "$NAT_GATEWAY_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Virtual Network +echo -e "\n[$VIRTUAL_NETWORK_NAME] virtual network:\n" +$AZ network vnet show \ + --name "$VIRTUAL_NETWORK_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Private DNS Zone +for PRIVATE_DNS_ZONE_NAME in "${PRIVATE_DNS_ZONE_NAMES[@]}"; do + echo -e "\n[$PRIVATE_DNS_ZONE_NAME] private dns zone:\n" + $AZ network private-dns zone show \ + --name "$PRIVATE_DNS_ZONE_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --query '{Name:name,ResourceGroup:resourceGroup,RecordSets:recordSets,VirtualNetworkLinks:virtualNetworkLinks}' \ + --output table \ + --only-show-errors +done + +# Check Private Endpoint +for PRIVATE_ENDPOINT_NAME in "${PE_NAMES[@]}"; do + echo -e "\n[$PRIVATE_ENDPOINT_NAME] private endpoint:\n" + $AZ network private-endpoint show \ + --name "$PRIVATE_ENDPOINT_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors +done + +# Check Functions App Subnet NSG +echo -e "\n[$FUNCTION_APP_SUBNET_NSG_NAME] network security group:\n" +$AZ network nsg show \ + --name "$FUNCTION_APP_SUBNET_NSG_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# Check Private Endpoint Subnet NSG +echo -e "\n[$PE_SUBNET_NSG_NAME] network security group:\n" +$AZ network nsg show \ + --name "$PE_SUBNET_NSG_NAME" \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors + +# List resources +echo -e "\n[$RESOURCE_GROUP_NAME] all resources:\n" +$AZ resource list \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --output table \ + --only-show-errors +``` + +## Cleanup + +To destroy all created resources: + +```bash +# Delete resource group and all contained resources +az group delete --name local-rg --yes --no-wait + +# Verify deletion +az group list --output table +``` + +This will remove all Azure resources created by the CLI deployment script. + +## Related Documentation + +- [Terraform Azure Provider](https://registry.terraform.io/providers/hashicorp/azurerm/latest) +- [LocalStack for Azure Documentation](https://azure.localstack.cloud/) \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/deploy.sh b/samples/function-app-service-bus/dotnet/terraform/deploy.sh new file mode 100755 index 0000000..2252d12 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/deploy.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +# Variables +PREFIX='local' +SUFFIX='test' +LOCATION='westeurope' +CURRENT_DIR="$(cd "$(dirname "$0")" && pwd)" +ZIPFILE="functionapp.zip" +ENVIRONMENT=$(az account show --query environmentName --output tsv) + +# Change the current directory to the script's directory +cd "$CURRENT_DIR" || exit + +# Run terraform init and apply +if [[ $ENVIRONMENT == "LocalStack" ]]; then + echo "Using azlocal for LocalStack emulator environment." + AZ="azlocal" +else + echo "Using standard terraform and az for AzureCloud environment." + AZ="az" +fi + +# Intialize Terraform +echo "Initializing Terraform..." +terraform init -upgrade + +# Run terraform plan and check for errors +echo "Planning Terraform deployment..." +terraform plan -out=tfplan \ + -var "prefix=$PREFIX" \ + -var "suffix=$SUFFIX" \ + -var "location=$LOCATION" + +if [[ $? != 0 ]]; then + echo "Terraform plan failed. Exiting." + exit 1 +fi + +# Apply the Terraform configuration +echo "Applying Terraform configuration..." +terraform apply -auto-approve tfplan + +if [[ $? != 0 ]]; then + echo "Terraform apply failed. Exiting." + exit 1 +fi + +# Get the output values +RESOURCE_GROUP_NAME=$(terraform output -raw resource_group_name) +FUNCTION_APP_NAME=$(terraform output -raw function_app_name) +SERVICE_BUS_NAMESPACE=$(terraform output -raw service_bus_namespace_name) + +if [[ -z "$RESOURCE_GROUP_NAME" || -z "$FUNCTION_APP_NAME" || -z "$SERVICE_BUS_NAMESPACE" ]]; then + echo "Resource Group Name, Function App Name, or Service Bus Namespace is empty. Exiting." + exit 1 +fi + +# Print the application settings of the function app +echo "Retrieving application settings for function app [$FUNCTION_APP_NAME]..." +$AZ functionapp config appsettings list \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --name "$FUNCTION_APP_NAME" + +# CD into the function app directory +cd ../src || exit + +# Remove any existing zip package of the function app +if [ -f "$ZIPFILE" ]; then + rm "$ZIPFILE" +fi + +# Build and publish the function app +echo "Building function app [$FUNCTION_APP_NAME]..." +if dotnet publish -c Release -o ./publish; then + echo "Function app [$FUNCTION_APP_NAME] built successfully." +else + echo "Failed to build function app [$FUNCTION_APP_NAME]." + exit 1 +fi + +# Create the zip package of the publish output +echo "Creating zip package of the function app..." +cd ./publish || exit +zip -r "../$ZIPFILE" . +cd .. + +# Deploy the function app +echo "Deploying function app [$FUNCTION_APP_NAME] with zip file [$ZIPFILE]..." +if $AZ functionapp deployment source config-zip \ + --resource-group "$RESOURCE_GROUP_NAME" \ + --name "$FUNCTION_APP_NAME" \ + --src "$ZIPFILE" 1>/dev/null; then + echo "Function app [$FUNCTION_APP_NAME] deployed successfully." +else + echo "Failed to deploy function app [$FUNCTION_APP_NAME]." + exit 1 +fi + +# Remove the zip package of the function app +if [ -f "$ZIPFILE" ]; then + rm "$ZIPFILE" +fi + +# Print the list of resources in the resource group +echo "Listing resources in resource group [$RESOURCE_GROUP_NAME]..." +az resource list --resource-group "$RESOURCE_GROUP_NAME" --output table \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/main.tf b/samples/function-app-service-bus/dotnet/terraform/main.tf new file mode 100644 index 0000000..7d0c309 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/main.tf @@ -0,0 +1,340 @@ +# Local Variables +locals { + prefix = lower(var.prefix) + suffix = lower(var.suffix) + resource_group_name = "${var.prefix}-rg" + log_analytics_name = "${local.prefix}-log-analytics-${local.suffix}" + storage_account_name = "${local.prefix}storage${local.suffix}" + virtual_network_name = "${local.prefix}-vnet-${local.suffix}" + nat_gateway_name = "${local.prefix}-nat-gateway-${local.suffix}" + service_bus_private_endpoint_name = "${local.prefix}-service-bus-pe-${local.suffix}" + blob_storage_private_endpoint_name = "${local.prefix}-blob-storage-pe-${local.suffix}" + queue_storage_private_endpoint_name = "${local.prefix}-queue-storage-pe-${local.suffix}" + table_storage_private_endpoint_name = "${local.prefix}-table-storage-pe-${local.suffix}" + network_security_group_name = "${local.prefix}-default-nsg-${local.suffix}" + cosmosdb_account_name = "${local.prefix}-mongodb-${local.suffix}" + service_bus_namespace_name = "${local.prefix}-service-bus-${local.suffix}" + app_service_plan_name = "${local.prefix}-app-service-plan-${local.suffix}" + function_app_name = "${local.prefix}-func-${local.suffix}" + application_insights_name = "${local.prefix}-func-${local.suffix}" + managed_identity_name = "${local.prefix}-identity-${local.suffix}" + private_dns_zone_group_name = "private-dns-zone-group" +} + +# Data Sources +data "azurerm_client_config" "current" { +} + +# Create a resource group +resource "azurerm_resource_group" "example" { + name = local.resource_group_name + location = var.location + tags = var.tags +} + +# Create a log analytics workspace +module "log_analytics_workspace" { + source = "./modules/log_analytics" + name = local.log_analytics_name + location = var.location + resource_group_name = azurerm_resource_group.example.name + tags = var.tags +} + +# Create a virtual network with subnets +module "virtual_network" { + source = "./modules/virtual_network" + resource_group_name = azurerm_resource_group.example.name + location = var.location + vnet_name = local.virtual_network_name + address_space = var.vnet_address_space + log_analytics_workspace_id = module.log_analytics_workspace.id + tags = var.tags + + subnets = [ + { + name : var.webapp_subnet_name + address_prefixes : var.webapp_subnet_address_prefix + private_endpoint_network_policies : "Enabled" + private_link_service_network_policies_enabled : false + delegation : "Microsoft.Web/serverFarms" + }, + { + name : var.pe_subnet_name + address_prefixes : var.pe_subnet_address_prefix + private_endpoint_network_policies : "Enabled" + private_link_service_network_policies_enabled : false + delegation : null + } + ] +} + +# Create a network security group and associate it with both subnets +module "network_security_group" { + source = "./modules/network_security_group" + name = local.network_security_group_name + resource_group_name = azurerm_resource_group.example.name + location = var.location + log_analytics_workspace_id = module.log_analytics_workspace.id + tags = var.tags + subnet_ids = { + (var.webapp_subnet_name) = module.virtual_network.subnet_ids[var.webapp_subnet_name] + (var.pe_subnet_name) = module.virtual_network.subnet_ids[var.pe_subnet_name] + } + +} + +# Create a NAT gateway and associate it with the default subnet +module "nat_gateway" { + source = "./modules/nat_gateway" + name = local.nat_gateway_name + resource_group_name = azurerm_resource_group.example.name + location = var.location + sku_name = var.nat_gateway_sku_name + idle_timeout_in_minutes = var.nat_gateway_idle_timeout_in_minutes + zones = var.nat_gateway_zones + subnet_ids = { + (var.webapp_subnet_name) = module.virtual_network.subnet_ids[var.webapp_subnet_name] + } + tags = var.tags +} + +# Create a storage account +module "storage_account" { + source = "./modules/storage_account" + name = local.storage_account_name + resource_group_name = azurerm_resource_group.example.name + location = var.location + account_kind = var.account_kind + account_tier = var.account_tier + replication_type = var.account_replication_type + log_analytics_workspace_id = module.log_analytics_workspace.id + tags = var.tags +} + +# Create a private DNS zone for blob storage and link it to the virtual network +module "blob_storage_private_dns_zone" { + source = "./modules/private_dns_zone" + name = "privatelink.blob.core.windows.net" + resource_group_name = azurerm_resource_group.example.name + tags = var.tags + virtual_networks_to_link = { + (module.virtual_network.name) = { + subscription_id = data.azurerm_client_config.current.subscription_id + resource_group_name = azurerm_resource_group.example.name + } + } +} + +# Create a private endpoint for blob storage in the pe_subnet subnet +module "blob_storage_private_endpoint" { + source = "./modules/private_endpoint" + name = local.blob_storage_private_endpoint_name + location = var.location + resource_group_name = azurerm_resource_group.example.name + subnet_id = module.virtual_network.subnet_ids[var.pe_subnet_name] + tags = var.tags + private_connection_resource_id = module.storage_account.id + is_manual_connection = false + subresource_name = "blob" + private_dns_zone_group_name = local.private_dns_zone_group_name + private_dns_zone_group_ids = [module.blob_storage_private_dns_zone.id] +} + +# Create a private DNS zone for queue storage and link it to the virtual network +module "queue_storage_private_dns_zone" { + source = "./modules/private_dns_zone" + name = "privatelink.queue.core.windows.net" + resource_group_name = azurerm_resource_group.example.name + tags = var.tags + virtual_networks_to_link = { + (module.virtual_network.name) = { + subscription_id = data.azurerm_client_config.current.subscription_id + resource_group_name = azurerm_resource_group.example.name + } + } +} + +# Create a private endpoint for queue storage in the pe_subnet subnet +module "queue_storage_private_endpoint" { + source = "./modules/private_endpoint" + name = local.queue_storage_private_endpoint_name + location = var.location + resource_group_name = azurerm_resource_group.example.name + subnet_id = module.virtual_network.subnet_ids[var.pe_subnet_name] + tags = var.tags + private_connection_resource_id = module.storage_account.id + is_manual_connection = false + subresource_name = "queue" + private_dns_zone_group_name = local.private_dns_zone_group_name + private_dns_zone_group_ids = [module.queue_storage_private_dns_zone.id] +} + +# Create a private DNS zone for table storage and link it to the virtual network +module "table_storage_private_dns_zone" { + source = "./modules/private_dns_zone" + name = "privatelink.table.core.windows.net" + resource_group_name = azurerm_resource_group.example.name + tags = var.tags + virtual_networks_to_link = { + (module.virtual_network.name) = { + subscription_id = data.azurerm_client_config.current.subscription_id + resource_group_name = azurerm_resource_group.example.name + } + } +} + +# Create a private endpoint for table storage in the pe_subnet subnet +module "table_storage_private_endpoint" { + source = "./modules/private_endpoint" + name = local.table_storage_private_endpoint_name + location = var.location + resource_group_name = azurerm_resource_group.example.name + subnet_id = module.virtual_network.subnet_ids[var.pe_subnet_name] + tags = var.tags + private_connection_resource_id = module.storage_account.id + is_manual_connection = false + subresource_name = "table" + private_dns_zone_group_name = local.private_dns_zone_group_name + private_dns_zone_group_ids = [module.table_storage_private_dns_zone.id] +} + +# Create a private DNS zone for the Service Bus namespace account and link it to the virtual network +module "service_bus_private_dns_zone" { + source = "./modules/private_dns_zone" + name = "privatelink.servicebus.windows.net" + resource_group_name = azurerm_resource_group.example.name + tags = var.tags + virtual_networks_to_link = { + (module.virtual_network.name) = { + subscription_id = data.azurerm_client_config.current.subscription_id + resource_group_name = azurerm_resource_group.example.name + } + } +} + +# Create a private endpoint for the Service Bus namespace account in the pe_subnet subnet +module "service_bus_private_endpoint" { + source = "./modules/private_endpoint" + name = local.service_bus_private_endpoint_name + location = var.location + resource_group_name = azurerm_resource_group.example.name + subnet_id = module.virtual_network.subnet_ids[var.pe_subnet_name] + tags = var.tags + private_connection_resource_id = module.service_bus_namespace.id + is_manual_connection = false + subresource_name = "namespace" + private_dns_zone_group_name = local.private_dns_zone_group_name + private_dns_zone_group_ids = [module.service_bus_private_dns_zone.id] +} + +# Create Service Bus namespace resources using module +module "service_bus_namespace" { + source = "./modules/service_bus" + name = local.service_bus_namespace_name + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + sku = var.service_bus_sku + capacity = var.service_bus_capacity + premium_messaging_partitions = var.service_bus_premium_messaging_partitions + local_auth_enabled = var.service_bus_local_auth_enabled + public_network_access_enabled = var.service_bus_public_network_access_enabled + minimum_tls_version = var.minimum_tls_version + log_analytics_workspace_id = module.log_analytics_workspace.id + tags = var.tags + queue_names = var.queue_names + lock_duration = var.queue_lock_duration + max_message_size_in_kilobytes = var.queue_max_message_size_in_kilobytes + max_size_in_megabytes = var.queue_max_size_in_megabytes + requires_duplicate_detection = var.queue_requires_duplicate_detection + requires_session = var.queue_requires_session + default_message_ttl = var.queue_default_message_ttl + dead_lettering_on_message_expiration = var.queue_dead_lettering_on_message_expiration + duplicate_detection_history_time_window = var.queue_duplicate_detection_history_time_window + max_delivery_count = var.queue_max_delivery_count + status = var.queue_status + batched_operations_enabled = var.queue_batched_operations_enabled + auto_delete_on_idle = var.queue_auto_delete_on_idle + partitioning_enabled = var.queue_partitioning_enabled + express_enabled = var.queue_express_enabled + forward_to = var.queue_forward_to + forward_dead_lettered_messages_to = var.queue_forward_dead_lettered_messages_to +} + +# Create App Service Plan using module +module "app_service_plan" { + source = "./modules/app_service_plan" + name = local.app_service_plan_name + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + sku_name = var.sku_name + os_type = var.os_type + zone_balancing_enabled = var.zone_balancing_enabled + log_analytics_workspace_id = module.log_analytics_workspace.id + tags = var.tags +} + +# Create Application Insights +module "application_insights" { + source = "./modules/application_insights" + name = local.application_insights_name + location = var.location + resource_group_name = azurerm_resource_group.example.name + workspace_id = module.log_analytics_workspace.id + tags = var.tags +} + +# Create a user-assigned managed identity +module "managed_identity" { + source = "./modules/managed_identity" + name = local.managed_identity_name + resource_group_name = azurerm_resource_group.example.name + location = var.location + storage_account_id = module.storage_account.id + application_insights_id = module.application_insights.id + service_bus_id = module.service_bus_namespace.id + tags = var.tags +} + +# Create Web App using module +module "function_app" { + source = "./modules/function_app" + name = local.function_app_name + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + service_plan_id = module.app_service_plan.id + storage_account_name = module.storage_account.name + storage_account_access_key = module.storage_account.primary_access_key + https_only = var.https_only + virtual_network_subnet_id = module.virtual_network.subnet_ids[var.webapp_subnet_name] + vnet_route_all_enabled = true + public_network_access_enabled = var.public_network_access_enabled + always_on = var.always_on + http2_enabled = var.http2_enabled + minimum_tls_version = var.minimum_tls_version + use_dotnet_isolated_runtime = var.use_dotnet_isolated_runtime + java_version = var.java_version + node_version = var.node_version + dotnet_version = var.dotnet_version + python_version = var.python_version + managed_identity_type = var.managed_identity_type + managed_identity_id = var.managed_identity_type == "UserAssigned" ? module.managed_identity.id : null + repo_url = var.repo_url + log_analytics_workspace_id = module.log_analytics_workspace.id + tags = var.tags + + app_settings = { + SCM_DO_BUILD_DURING_DEPLOYMENT = "false" + AzureWebJobsStorage = module.storage_account.primary_connection_string + FUNCTIONS_WORKER_RUNTIME = var.functions_worker_runtime + FUNCTIONS_EXTENSION_VERSION = var.functions_extension_version + AZURE_CLIENT_ID = module.managed_identity.client_id + SERVICE_BUS_CONNECTION_STRING__fullyQualifiedNamespace = "${module.service_bus_namespace.name}.servicebus.windows.net" + APPLICATIONINSIGHTS_CONNECTION_STRING = module.application_insights.connection_string + APPLICATIONINSIGHTS_AUTHENTICATION_STRING = "ClientId=${module.managed_identity.client_id};Authorization=AAD" + INPUT_QUEUE_NAME = var.input_queue_name + OUTPUT_QUEUE_NAME = var.output_queue_name + NAMES = var.names + TIMER_SCHEDULE = var.timer_schedule + } +} \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/app_service_plan/main.tf b/samples/function-app-service-bus/dotnet/terraform/modules/app_service_plan/main.tf new file mode 100644 index 0000000..98a3e4d --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/app_service_plan/main.tf @@ -0,0 +1,25 @@ +resource "azurerm_service_plan" "example" { + name = var.name + resource_group_name = var.resource_group_name + location = var.location + sku_name = var.sku_name + os_type = var.os_type + zone_balancing_enabled = var.zone_balancing_enabled + tags = var.tags + + lifecycle { + ignore_changes = [ + tags + ] + } +} + +resource "azurerm_monitor_diagnostic_setting" "example" { + name = "DiagnosticsSettings" + target_resource_id = azurerm_service_plan.example.id + log_analytics_workspace_id = var.log_analytics_workspace_id + + enabled_metric { + category = "AllMetrics" + } +} \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/app_service_plan/outputs.tf b/samples/function-app-service-bus/dotnet/terraform/modules/app_service_plan/outputs.tf new file mode 100644 index 0000000..f1455ea --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/app_service_plan/outputs.tf @@ -0,0 +1,19 @@ +output "id" { + value = azurerm_service_plan.example.id + description = "Specifies the resource id of the App Service Plan" +} + +output "name" { + value = azurerm_service_plan.example.name + description = "Specifies the name of the App Service Plan" +} + +output "location" { + value = azurerm_service_plan.example.location + description = "Specifies the location of the App Service Plan" +} + +output "resource_group_name" { + value = azurerm_service_plan.example.resource_group_name + description = "Specifies the resource group name of the App Service Plan" +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/app_service_plan/variables.tf b/samples/function-app-service-bus/dotnet/terraform/modules/app_service_plan/variables.tf new file mode 100644 index 0000000..e543066 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/app_service_plan/variables.tf @@ -0,0 +1,42 @@ +variable "resource_group_name" { + description = "(Required) Specifies the name of the resource group." + type = string +} + +variable "location" { + description = "(Required) Specifies the location for the App Service Plan." + type = string +} + +variable "name" { + description = "(Required) Specifies the name of the App Service Plan." + type = string +} + +variable "sku_name" { + description = "(Required) Specifies the SKU name for the App Service Plan." + type = string +} + +variable "os_type" { + description = "(Required) Specifies the O/S type for the App Services to be hosted in this plan." + type = string + default = "Linux" +} + +variable "zone_balancing_enabled" { + description = "(Optional) Should the Service Plan balance across Availability Zones in the region." + type = bool + default = false +} + +variable "tags" { + description = "(Optional) Specifies the tags to be applied to the resources." + type = map(any) + default = {} +} + +variable "log_analytics_workspace_id" { + description = "Specifies the resource id of the Azure Log Analytics workspace." + type = string +} \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/application_insights/main.tf b/samples/function-app-service-bus/dotnet/terraform/modules/application_insights/main.tf new file mode 100644 index 0000000..d397c22 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/application_insights/main.tf @@ -0,0 +1,18 @@ +resource "azurerm_application_insights" "example" { + name = var.name + location = var.location + resource_group_name = var.resource_group_name + tags = var.tags + application_type = var.application_type + workspace_id = var.workspace_id + disable_ip_masking = var.disable_ip_masking + local_authentication_disabled = var.local_authentication_disabled + internet_ingestion_enabled = var.internet_ingestion_enabled + internet_query_enabled = var.internet_query_enabled + + lifecycle { + ignore_changes = [ + tags + ] + } +} \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/application_insights/outputs.tf b/samples/function-app-service-bus/dotnet/terraform/modules/application_insights/outputs.tf new file mode 100644 index 0000000..2f085e7 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/application_insights/outputs.tf @@ -0,0 +1,24 @@ +output "name" { + value = azurerm_application_insights.example.name + description = "Specifies the name of the resource." +} + +output "id" { + value = azurerm_application_insights.example.id + description = "Specifies the resource id of the resource." +} + +output "instrumentation_key" { + value = azurerm_application_insights.example.instrumentation_key + description = "Specifies the instrumentation key of the Application Insights." +} + +output "app_id" { + value = azurerm_application_insights.example.app_id + description = "Specifies the resource id of the resource." +} + +output "connection_string" { + value = azurerm_application_insights.example.connection_string + description = "Specifies the connection string of the Application Insights." +} \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/application_insights/variables.tf b/samples/function-app-service-bus/dotnet/terraform/modules/application_insights/variables.tf new file mode 100644 index 0000000..0dd17aa --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/application_insights/variables.tf @@ -0,0 +1,56 @@ + +variable "name" { + description = "(Required) Specifies the name of the resource. Changing this forces a new resource to be created." + type = string +} + +variable "resource_group_name" { + description = "(Required) The name of the resource group in which to create the resource. Changing this forces a new resource to be created." + type = string +} + +variable "location" { + description = "(Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created." + type = string +} + +variable "application_type" { + description = "(Required) Specifies the type of Application Insights to create. Valid values are ios for iOS, java for Java web, MobileCenter for App Center, Node.JS for Node.js, other for General, phone for Windows Phone, store for Windows Store and web for ASP.NET. Please note these values are case sensitive; unmatched values are treated as ASP.NET by Azure. Changing this forces a new resource to be created." + type = string + default = "web" +} + +variable "workspace_id" { + description = "(Optional) Specifies the id of a log analytics workspace resource. Changing this forces a new resource to be created." + type = string +} + +variable "tags" { + description = "(Optional) Specifies the tags to be applied to the resources" + type = map(any) + default = {} +} + +variable "disable_ip_masking" { + description = "(Optional) Specifies whether IP masking is disabled." + type = bool + default = false +} + +variable "local_authentication_disabled" { + description = "(Optional) Specifies whether local authentication is disabled." + type = bool + default = false +} + +variable "internet_ingestion_enabled" { + description = "(Optional) Specifies whether the public network access for ingestion is enabled." + type = bool + default = true +} + +variable "internet_query_enabled" { + description = "(Optional) Specifies whether the public network access for query is enabled." + type = bool + default = true +} \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/function_app/main.tf b/samples/function-app-service-bus/dotnet/terraform/modules/function_app/main.tf new file mode 100644 index 0000000..10cdbdd --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/function_app/main.tf @@ -0,0 +1,67 @@ +resource "azurerm_linux_function_app" "example" { + name = var.name + resource_group_name = var.resource_group_name + location = var.location + service_plan_id = var.service_plan_id + storage_account_name = var.storage_account_name + storage_account_access_key = var.storage_account_access_key + https_only = var.https_only + virtual_network_subnet_id = var.virtual_network_subnet_id + public_network_access_enabled = var.public_network_access_enabled + tags = var.tags + + identity { + type = var.managed_identity_type + identity_ids = var.managed_identity_type == "UserAssigned" ? [var.managed_identity_id] : null + } + + site_config { + always_on = var.always_on + http2_enabled = var.http2_enabled + minimum_tls_version = var.minimum_tls_version + vnet_route_all_enabled = var.vnet_route_all_enabled + application_stack { + dotnet_version = var.dotnet_version + java_version = var.java_version + node_version = var.node_version + python_version = var.python_version + use_dotnet_isolated_runtime = var.use_dotnet_isolated_runtime + } + } + + app_settings = var.app_settings + + lifecycle { + ignore_changes = [ + tags + ] + } +} + +# Deploy code from a public GitHub repo +resource "azurerm_app_service_source_control" "example" { + count = var.repo_url == "" ? 0 : 1 + app_id = azurerm_linux_function_app.example.id + repo_url = var.repo_url + branch = var.repo_branch + use_manual_integration = true + use_mercurial = false +} + +resource "azurerm_monitor_diagnostic_setting" "example" { + name = "DiagnosticsSettings" + target_resource_id = azurerm_linux_function_app.example.id + log_analytics_workspace_id = var.log_analytics_workspace_id + + enabled_log { + category = "FunctionAppLogs" + } + + enabled_log { + category = "AppServiceAuthenticationLogs" + } + + enabled_metric { + category = "AllMetrics" + } +} \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/function_app/outputs.tf b/samples/function-app-service-bus/dotnet/terraform/modules/function_app/outputs.tf new file mode 100644 index 0000000..3283f33 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/function_app/outputs.tf @@ -0,0 +1,24 @@ +output "id" { + value = azurerm_linux_function_app.example.id + description = "Specifies the resource id of the Web App" +} + +output "name" { + value = azurerm_linux_function_app.example.name + description = "Specifies the name of the Web App" +} + +output "default_hostname" { + value = azurerm_linux_function_app.example.default_hostname + description = "Specifies the default hostname of the Web App" +} + +output "outbound_ip_addresses" { + value = azurerm_linux_function_app.example.outbound_ip_addresses + description = "Specifies the outbound IP addresses of the Web App" +} + +output "principal_id" { + value = azurerm_linux_function_app.example.identity[0].principal_id + description = "Specifies the Principal ID of the System Assigned Managed Identity" +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/function_app/variables.tf b/samples/function-app-service-bus/dotnet/terraform/modules/function_app/variables.tf new file mode 100644 index 0000000..d1d45de --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/function_app/variables.tf @@ -0,0 +1,148 @@ +variable "resource_group_name" { + description = "(Required) Specifies the name of the resource group." + type = string +} + +variable "location" { + description = "(Required) Specifies the location for the Web App." + type = string +} + +variable "name" { + description = "(Required) Specifies the name of the Web App." + type = string +} + +variable "service_plan_id" { + description = "(Required) Specifies the ID of the App Service Plan within which to create this Web App." + type = string +} + +variable "storage_account_name" { + description = "(Required) Specifies the name of the storage account used by the Function App." + type = string +} + +variable "storage_account_access_key" { + description = "(Required) Specifies the primary access key of the storage account used by the Function App." + type = string + sensitive = true +} + +variable "https_only" { + description = "(Optional) Specifies whether the Web App requires HTTPS connections." + type = bool + default = false +} + +variable "virtual_network_subnet_id" { + description = "(Optional) The subnet id which will be used by this Web App for regional virtual network integration." + type = string + default = null +} + +variable "vnet_route_all_enabled" { + description = "(Optional) Specifies whether to route all traffic from the Web App into the virtual network. This is only applicable if virtual_network_subnet_id is specified. Defaults to false." + type = bool + default = false +} + +variable "public_network_access_enabled" { + description = "(Optional) Specifies whether the public network access is enabled or disabled." + type = bool + default = true +} + +variable "always_on" { + description = "(Optional) Specifies whether the Web App is Always On enabled." + type = bool + default = true +} + +variable "http2_enabled" { + description = "(Optional) Specifies whether HTTP/2 is enabled for the Web App." + type = bool + default = false +} + +variable "minimum_tls_version" { + description = "(Optional) Specifies the minimum version of TLS required for SSL requests." + type = string + default = "1.2" +} + +variable "use_dotnet_isolated_runtime" { + description = "(Optional) Should the DotNet process use an isolated runtime. Defaults to false." + type = bool + default = true +} + +variable "java_version" { + description = "(Optional) The Version of Java to use." + type = string + default = null +} + +variable "node_version" { + description = "(Optional) The version of Node.js to run." + type = string + default = null +} + +variable "dotnet_version" { + description = "(Optional) The version of .NET to use." + type = string + default = null +} + +variable "python_version" { + description = "(Optional) The version of Python to run." + type = string + default = null +} + +variable "app_settings" { + description = "(Optional) A map of key-value pairs for App Settings." + type = map(string) + default = {} +} + +variable "repo_url" { + description = "(Optional) Specifies the Git repository URL." + type = string + default = "" +} + +variable "repo_branch" { + description = "(Optional) Specifies the Git repository branch." + type = string + default = "main" +} + +variable "tags" { + description = "(Optional) Specifies the tags to be applied to the resources." + type = map(any) + default = {} +} + +variable "managed_identity_type" { + description = "(Optional) Specifies the type of managed identity." + type = string + default = "UserAssigned" + + validation { + condition = contains(["SystemAssigned", "UserAssigned"], var.managed_identity_type) + error_message = "The managed identity type must be either SystemAssigned or UserAssigned." + } +} + +variable "managed_identity_id" { + description = "(Optional) Specifies the resource id of the user-assigned managed identity." + type = string + default = null +} + +variable "log_analytics_workspace_id" { + description = "Specifies the resource id of the Azure Log Analytics workspace." + type = string +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/log_analytics/main.tf b/samples/function-app-service-bus/dotnet/terraform/modules/log_analytics/main.tf new file mode 100644 index 0000000..2f88414 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/log_analytics/main.tf @@ -0,0 +1,14 @@ +resource "azurerm_log_analytics_workspace" "example" { + name = var.name + location = var.location + resource_group_name = var.resource_group_name + sku = var.sku + tags = var.tags + retention_in_days = var.retention_in_days != "" ? var.retention_in_days : null + + lifecycle { + ignore_changes = [ + tags + ] + } +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/log_analytics/output.tf b/samples/function-app-service-bus/dotnet/terraform/modules/log_analytics/output.tf new file mode 100644 index 0000000..fe2c398 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/log_analytics/output.tf @@ -0,0 +1,30 @@ +output "id" { + value = azurerm_log_analytics_workspace.example.id + description = "Specifies the resource id of the log analytics workspace" +} + +output "location" { + value = azurerm_log_analytics_workspace.example.location + description = "Specifies the location of the log analytics workspace" +} + +output "name" { + value = azurerm_log_analytics_workspace.example.name + description = "Specifies the name of the log analytics workspace" +} + +output "resource_group_name" { + value = azurerm_log_analytics_workspace.example.resource_group_name + description = "Specifies the name of the resource group that contains the log analytics workspace" +} + +output "workspace_id" { + value = azurerm_log_analytics_workspace.example.workspace_id + description = "Specifies the workspace id of the log analytics workspace" +} + +output "primary_shared_key" { + value = azurerm_log_analytics_workspace.example.primary_shared_key + description = "Specifies the workspace key of the log analytics workspace" + sensitive = true +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/log_analytics/variables.tf b/samples/function-app-service-bus/dotnet/terraform/modules/log_analytics/variables.tf new file mode 100644 index 0000000..c399b5b --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/log_analytics/variables.tf @@ -0,0 +1,37 @@ +variable "resource_group_name" { + description = "(Required) Specifies the name of the resource group." + type = string +} + +variable "location" { + description = "(Required) Specifies the location of the Azure Log Analytics workspace" + type = string +} + +variable "name" { + description = "(Required) Specifies the name of the Azure Log Analytics workspace" + type = string +} + +variable "sku" { + description = "(Optional) Specifies the sku of the Azure Log Analytics workspace" + type = string + default = "PerGB2018" + + validation { + condition = contains(["Free", "Standalone", "PerNode", "PerGB2018"], var.sku) + error_message = "The log analytics sku is incorrect." + } +} + +variable "retention_in_days" { + description = " (Optional) Specifies the workspace data retention in days. Possible values are either 7 (Free Tier only) or range between 30 and 730." + type = number + default = 30 +} + +variable "tags" { + description = "(Optional) Specifies the tags of the Azure Log Analytics workspace." + type = map(any) + default = {} +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/managed_identity/main.tf b/samples/function-app-service-bus/dotnet/terraform/modules/managed_identity/main.tf new file mode 100644 index 0000000..af5ef36 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/managed_identity/main.tf @@ -0,0 +1,55 @@ + +resource "azurerm_user_assigned_identity" "example" { + name = var.name + resource_group_name = var.resource_group_name + location = var.location + tags = var.tags + + lifecycle { + ignore_changes = [ + tags + ] + } +} + +resource "azurerm_role_assignment" "storage_account_contributor_assignment" { + scope = var.storage_account_id + role_definition_name = "Storage Account Contributor" + principal_id = azurerm_user_assigned_identity.example.principal_id + skip_service_principal_aad_check = true +} + +resource "azurerm_role_assignment" "storage_blob_data_owner_assignment" { + scope = var.storage_account_id + role_definition_name = "Storage Blob Data Owner" + principal_id = azurerm_user_assigned_identity.example.principal_id + skip_service_principal_aad_check = true +} + +resource "azurerm_role_assignment" "storage_queue_data_contributor_assignment" { + scope = var.storage_account_id + role_definition_name = "Storage Queue Data Contributor" + principal_id = azurerm_user_assigned_identity.example.principal_id + skip_service_principal_aad_check = true +} + +resource "azurerm_role_assignment" "storage_table_data_contributor_assignment" { + scope = var.storage_account_id + role_definition_name = "Storage Table Data Contributor" + principal_id = azurerm_user_assigned_identity.example.principal_id + skip_service_principal_aad_check = true +} + +resource "azurerm_role_assignment" "service_bus_contributor_assignment" { + scope = var.service_bus_id + role_definition_name = "Azure Service Bus Data Owner" + principal_id = azurerm_user_assigned_identity.example.principal_id + skip_service_principal_aad_check = true +} + +resource "azurerm_role_assignment" "monitoring_metrics_publisher_assignment" { + scope = var.application_insights_id + role_definition_name = "Monitoring Metrics Publisher" + principal_id = azurerm_user_assigned_identity.example.principal_id + skip_service_principal_aad_check = true +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/managed_identity/output.tf b/samples/function-app-service-bus/dotnet/terraform/modules/managed_identity/output.tf new file mode 100644 index 0000000..a22e571 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/managed_identity/output.tf @@ -0,0 +1,25 @@ + +output "id" { + value = azurerm_user_assigned_identity.example.id + description = "Specifies the resource id of the workload user-defined managed identity" +} + +output "location" { + value = azurerm_user_assigned_identity.example.location + description = "Specifies the location of the workload user-defined managed identity" +} + +output "name" { + value = azurerm_user_assigned_identity.example.name + description = "Specifies the name of the workload user-defined managed identity" +} + +output "client_id" { + value = azurerm_user_assigned_identity.example.client_id + description = "Specifies the client id of the workload user-defined managed identity" +} + +output "principal_id" { + value = azurerm_user_assigned_identity.example.principal_id + description = "Specifies the principal id of the workload user-defined managed identity" +} \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/managed_identity/variables.tf b/samples/function-app-service-bus/dotnet/terraform/modules/managed_identity/variables.tf new file mode 100644 index 0000000..4f43473 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/managed_identity/variables.tf @@ -0,0 +1,35 @@ +variable "name" { + description = "(Required) Specifies the name of the log analytics workspace" + type = string +} + +variable "resource_group_name" { + description = "(Required) Specifies the resource group name" + type = string +} + +variable "location" { + description = "(Required) Specifies the location of the log analytics workspace" + type = string +} + +variable "tags" { + description = "(Optional) Specifies the tags of the log analytics workspace" + type = map(any) + default = {} +} + +variable "storage_account_id" { + description = "(Required) Specifies resource id of the Azure Storage Account resource" + type = string +} + +variable "application_insights_id" { + description = "(Required) Specifies resource id of the Azure Application Insights resource" + type = string +} + +variable "service_bus_id" { + description = "(Required) Specifies resource id of the Azure Service Bus namespace resource" + type = string +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/nat_gateway/main.tf b/samples/function-app-service-bus/dotnet/terraform/modules/nat_gateway/main.tf new file mode 100644 index 0000000..cc384af --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/nat_gateway/main.tf @@ -0,0 +1,42 @@ +resource "azurerm_public_ip" "example" { + name = "${var.name}PublicIp" + location = var.location + resource_group_name = var.resource_group_name + allocation_method = "Static" + sku = "Standard" + zones = var.zones + tags = var.tags + + lifecycle { + ignore_changes = [ + tags + ] + } +} + +resource "azurerm_nat_gateway" "example" { + name = var.name + location = var.location + resource_group_name = var.resource_group_name + sku_name = var.sku_name + idle_timeout_in_minutes = var.idle_timeout_in_minutes + zones = var.zones + tags = var.tags + + lifecycle { + ignore_changes = [ + tags + ] + } +} + +resource "azurerm_nat_gateway_public_ip_association" "example" { + nat_gateway_id = azurerm_nat_gateway.example.id + public_ip_address_id = azurerm_public_ip.example.id +} + +resource "azurerm_subnet_nat_gateway_association" "example" { + for_each = var.subnet_ids + subnet_id = each.value + nat_gateway_id = azurerm_nat_gateway.example.id +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/nat_gateway/output.tf b/samples/function-app-service-bus/dotnet/terraform/modules/nat_gateway/output.tf new file mode 100644 index 0000000..1e3fd03 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/nat_gateway/output.tf @@ -0,0 +1,14 @@ +output "name" { + value = azurerm_nat_gateway.example.name + description = "Specifies the name of the Azure NAT Gateway" +} + +output "id" { + value = azurerm_nat_gateway.example.id + description = "Specifies the resource id of the Azure NAT Gateway" +} + +output "public_ip_address" { + value = azurerm_public_ip.example.ip_address + description = "Contains the public IP address of the Azure NAT Gateway." +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/nat_gateway/variables.tf b/samples/function-app-service-bus/dotnet/terraform/modules/nat_gateway/variables.tf new file mode 100644 index 0000000..c1c8ea5 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/nat_gateway/variables.tf @@ -0,0 +1,43 @@ +variable "resource_group_name" { + description = "(Required) Specifies the name of the resource group." + type = string +} + +variable "location" { + description = "(Required) Specifies the location of the Azure NAT Gateway" + type = string +} + +variable "name" { + description = "(Required) Specifies the name of the Azure NAT Gateway" + type = string +} + +variable "tags" { + description = "(Optional) Specifies the tags of the Azure NAT Gateway" + type = map(any) + default = {} +} + +variable "sku_name" { + description = "(Optional) The SKU which should be used. At this time the only supported value is Standard. Defaults to Standard" + type = string + default = "Standard" +} + +variable "idle_timeout_in_minutes" { + description = "(Optional) The idle timeout which should be used in minutes. Defaults to 4." + type = number + default = 4 +} + +variable "zones" { + description = " (Optional) A list of Availability Zones in which this NAT Gateway should be located. Changing this forces a new NAT Gateway to be created." + type = list(string) + default = [] +} + +variable "subnet_ids" { + description = "(Required) A map of subnet ids to associate with the NAT Gateway" + type = map(string) +} \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/network_security_group/main.tf b/samples/function-app-service-bus/dotnet/terraform/modules/network_security_group/main.tf new file mode 100644 index 0000000..c649652 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/network_security_group/main.tf @@ -0,0 +1,53 @@ +resource "azurerm_network_security_group" "example" { + name = var.name + resource_group_name = var.resource_group_name + location = var.location + tags = var.tags + + dynamic "security_rule" { + for_each = try(var.security_rules, []) + content { + name = try(security_rule.value.name, null) + priority = try(security_rule.value.priority, null) + direction = try(security_rule.value.direction, null) + access = try(security_rule.value.access, null) + protocol = try(security_rule.value.protocol, null) + source_port_range = try(security_rule.value.source_port_range, null) + source_port_ranges = try(security_rule.value.source_port_ranges, null) + destination_port_range = try(security_rule.value.destination_port_range, null) + destination_port_ranges = try(security_rule.value.destination_port_ranges, null) + source_address_prefix = try(security_rule.value.source_address_prefix, null) + source_address_prefixes = try(security_rule.value.source_address_prefixes, null) + destination_address_prefix = try(security_rule.value.destination_address_prefix, null) + destination_address_prefixes = try(security_rule.value.destination_address_prefixes, null) + source_application_security_group_ids = try(security_rule.value.source_application_security_group_ids, null) + destination_application_security_group_ids = try(security_rule.value.destination_application_security_group_ids, null) + } + } + + lifecycle { + ignore_changes = [ + tags + ] + } +} + +resource "azurerm_subnet_network_security_group_association" "example" { + for_each = var.subnet_ids + subnet_id = each.value + network_security_group_id = azurerm_network_security_group.example.id +} + +resource "azurerm_monitor_diagnostic_setting" "settings" { + name = "DiagnosticsSettings" + target_resource_id = azurerm_network_security_group.example.id + log_analytics_workspace_id = var.log_analytics_workspace_id + + enabled_log { + category = "NetworkSecurityGroupEvent" + } + + enabled_log { + category = "NetworkSecurityGroupRuleCounter" + } +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/network_security_group/outputs.tf b/samples/function-app-service-bus/dotnet/terraform/modules/network_security_group/outputs.tf new file mode 100644 index 0000000..b8ca8d5 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/network_security_group/outputs.tf @@ -0,0 +1,9 @@ +output "name" { + description = "Specifies the name of the network security group" + value = azurerm_network_security_group.example.name +} + +output "id" { + description = "Specifies the resource id of the network security group" + value = azurerm_network_security_group.example.id +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/network_security_group/variables.tf b/samples/function-app-service-bus/dotnet/terraform/modules/network_security_group/variables.tf new file mode 100644 index 0000000..04eb07e --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/network_security_group/variables.tf @@ -0,0 +1,51 @@ +variable "name" { + description = "(Required) Specifies the name of the Azure Network Security Group" + type = string +} + +variable "resource_group_name" { + description = "(Required) Specifies the name of the resource group. of the Azure Network Security Group" + type = string +} + +variable "location" { + description = "(Required) Specifies the location of the Azure Network Security Group" + type = string +} + +variable "security_rules" { + description = "(Optional) Specifies the security rules of the Azure Network Security Group" + type = list(object({ + name = string + priority = number + direction = string + access = string + protocol = string + source_port_range = string + source_port_ranges = list(string) + destination_port_range = string + destination_port_ranges = list(string) + source_address_prefix = string + source_address_prefixes = list(string) + destination_address_prefix = string + destination_address_prefixes = list(string) + source_application_security_group_ids = list(string) + destination_application_security_group_ids = list(string) + })) + default = [] +} + +variable "subnet_ids" { + description = "(Required) A map of subnet ids to associate with the Azure Network Security Group" + type = map(string) +} + +variable "tags" { + description = "(Optional) Specifies the tags of the Azure Network Security Group" + default = {} +} + +variable "log_analytics_workspace_id" { + description = "Specifies the resource id of the Azure Log Analytics workspace" + type = string +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/private_dns_zone/main.tf b/samples/function-app-service-bus/dotnet/terraform/modules/private_dns_zone/main.tf new file mode 100644 index 0000000..393f9dc --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/private_dns_zone/main.tf @@ -0,0 +1,26 @@ +resource "azurerm_private_dns_zone" "example" { + name = var.name + resource_group_name = var.resource_group_name + tags = var.tags + + lifecycle { + ignore_changes = [ + tags + ] + } +} + +resource "azurerm_private_dns_zone_virtual_network_link" "example" { + for_each = var.virtual_networks_to_link + + name = "link_to_${lower(basename(each.key))}" + resource_group_name = var.resource_group_name + private_dns_zone_name = azurerm_private_dns_zone.example.name + virtual_network_id = "/subscriptions/${each.value.subscription_id}/resourceGroups/${each.value.resource_group_name}/providers/Microsoft.Network/virtualNetworks/${each.key}" + + lifecycle { + ignore_changes = [ + tags + ] + } +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/private_dns_zone/outputs.tf b/samples/function-app-service-bus/dotnet/terraform/modules/private_dns_zone/outputs.tf new file mode 100644 index 0000000..ca141f3 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/private_dns_zone/outputs.tf @@ -0,0 +1,9 @@ +output "name" { + description = "Specifies the name of the private dns zone" + value = azurerm_private_dns_zone.example.name +} + +output "id" { + description = "Specifies the resource id of the private dns zone" + value = azurerm_private_dns_zone.example.id +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/private_dns_zone/variables.tf b/samples/function-app-service-bus/dotnet/terraform/modules/private_dns_zone/variables.tf new file mode 100644 index 0000000..8d0c0cc --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/private_dns_zone/variables.tf @@ -0,0 +1,20 @@ +variable "name" { + description = "(Required) Specifies the name of the Azure Private DNS Zone" + type = string +} + +variable "resource_group_name" { + description = "(Required) Specifies the name of the resource group. of the Azure Private DNS Zone" + type = string +} + +variable "tags" { + description = "(Optional) Specifies the tags of the Azure Private DNS Zone" + default = {} +} + +variable "virtual_networks_to_link" { + description = "(Optional) Specifies the subscription id, resource group name, and name of the virtual networks to which create a virtual network link" + type = map(any) + default = {} +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/private_endpoint/main.tf b/samples/function-app-service-bus/dotnet/terraform/modules/private_endpoint/main.tf new file mode 100644 index 0000000..62bfbfb --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/private_endpoint/main.tf @@ -0,0 +1,26 @@ +resource "azurerm_private_endpoint" "example" { + name = var.name + location = var.location + resource_group_name = var.resource_group_name + subnet_id = var.subnet_id + tags = var.tags + + private_service_connection { + name = "${var.name}Connection" + private_connection_resource_id = var.private_connection_resource_id + is_manual_connection = var.is_manual_connection + subresource_names = try([var.subresource_name], null) + request_message = try(var.request_message, null) + } + + private_dns_zone_group { + name = var.private_dns_zone_group_name + private_dns_zone_ids = var.private_dns_zone_group_ids + } + + lifecycle { + ignore_changes = [ + tags + ] + } +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/private_endpoint/outputs.tf b/samples/function-app-service-bus/dotnet/terraform/modules/private_endpoint/outputs.tf new file mode 100644 index 0000000..367ab51 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/private_endpoint/outputs.tf @@ -0,0 +1,19 @@ +output "name" { + description = "Specifies the name of the private endpoint." + value = azurerm_private_endpoint.example.name +} + +output "id" { + description = "Specifies the resource id of the private endpoint." + value = azurerm_private_endpoint.example.id +} + +output "private_dns_zone_group" { + description = "Specifies the private dns zone group of the private endpoint." + value = azurerm_private_endpoint.example.private_dns_zone_group +} + +output "private_dns_zone_configs" { + description = "Specifies the private dns zone(s) configuration" + value = azurerm_private_endpoint.example.private_dns_zone_configs +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/private_endpoint/variables.tf b/samples/function-app-service-bus/dotnet/terraform/modules/private_endpoint/variables.tf new file mode 100644 index 0000000..2b7a888 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/private_endpoint/variables.tf @@ -0,0 +1,61 @@ +variable "name" { + description = "(Required) Specifies the name of the Azure Private Endpoint. Changing this forces a new resource to be created." + type = string +} + +variable "resource_group_name" { + description = "(Required) The name of the resource group. Changing this forces a new resource to be created." + type = string +} + +variable "private_connection_resource_id" { + description = "(Required) Specifies the resource id of the private link service" + type = string +} + +variable "location" { + description = "(Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created." + type = string +} + +variable "subnet_id" { + description = "(Required) Specifies the resource id of the subnet" + type = string +} + +variable "is_manual_connection" { + description = "(Optional) Specifies whether the Azure Private Endpoint connection requires manual approval from the remote resource owner." + type = string + default = false +} + +variable "subresource_name" { + description = "(Optional) Specifies a subresource name which the Azure Private Endpoint is able to connect to." + type = string + default = null +} + +variable "request_message" { + description = "(Optional) Specifies a message passed to the owner of the remote resource when the Azure Private Endpoint attempts to establish the connection to the remote resource." + type = string + default = null +} + +variable "private_dns_zone_group_name" { + description = "(Required) Specifies the Name of the Private DNS Zone Group. Changing this forces a new private_dns_zone_group resource to be created." + type = string +} + +variable "private_dns_zone_group_ids" { + description = "(Required) Specifies the list of Private DNS Zones to include within the private_dns_zone_group." + type = list(string) +} + +variable "tags" { + description = "(Optional) Specifies the tags of the Azure Azure Private Endpoint." + default = {} +} + +variable "private_dns" { + default = {} +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/service_bus/main.tf b/samples/function-app-service-bus/dotnet/terraform/modules/service_bus/main.tf new file mode 100644 index 0000000..84b61df --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/service_bus/main.tf @@ -0,0 +1,77 @@ +resource "azurerm_servicebus_namespace" "example" { + name = var.name + location = var.location + resource_group_name = var.resource_group_name + sku = var.sku + capacity = var.capacity + premium_messaging_partitions = var.premium_messaging_partitions + local_auth_enabled = var.local_auth_enabled + public_network_access_enabled = var.public_network_access_enabled + minimum_tls_version = var.minimum_tls_version + tags = var.tags + + lifecycle { + ignore_changes = [ + tags + ] + } +} + +resource "azurerm_servicebus_namespace_authorization_rule" "example" { + name = "${var.name}-auth-rule" + namespace_id = azurerm_servicebus_namespace.example.id + + send = true + listen = true + manage = true +} + +resource "azurerm_servicebus_queue" "example" { + for_each = var.queue_names + + name = each.value + namespace_id = azurerm_servicebus_namespace.example.id + + lock_duration = var.lock_duration + max_message_size_in_kilobytes = var.max_message_size_in_kilobytes + max_size_in_megabytes = var.max_size_in_megabytes + requires_duplicate_detection = var.requires_duplicate_detection + requires_session = var.requires_session + default_message_ttl = var.default_message_ttl + dead_lettering_on_message_expiration = var.dead_lettering_on_message_expiration + duplicate_detection_history_time_window = var.duplicate_detection_history_time_window + max_delivery_count = var.max_delivery_count + status = var.status + batched_operations_enabled = var.batched_operations_enabled + auto_delete_on_idle = var.auto_delete_on_idle + partitioning_enabled = var.partitioning_enabled + express_enabled = var.express_enabled + forward_to = var.forward_to + forward_dead_lettered_messages_to = var.forward_dead_lettered_messages_to +} + +resource "azurerm_monitor_diagnostic_setting" "example" { + name = "DiagnosticsSettings" + target_resource_id = azurerm_servicebus_namespace.example.id + log_analytics_workspace_id = var.log_analytics_workspace_id + + enabled_log { + category = "OperationalLogs" + } + + enabled_log { + category = "VNetAndIPFilteringLogs" + } + + enabled_log { + category = "RuntimeAuditLogs" + } + + enabled_log { + category = "ApplicationMetricsLogs" + } + + enabled_metric { + category = "AllMetrics" + } +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/service_bus/outputs.tf b/samples/function-app-service-bus/dotnet/terraform/modules/service_bus/outputs.tf new file mode 100644 index 0000000..6fc2dd0 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/service_bus/outputs.tf @@ -0,0 +1,17 @@ +output "namespace_connection_string" { + value = azurerm_servicebus_namespace.example.default_primary_connection_string +} + +output "shared_access_policy_primarykey" { + value = azurerm_servicebus_namespace.example.default_primary_key +} + +output "name" { + value = azurerm_servicebus_namespace.example.name + description = "Specifies the name of the Service Bus namespace." +} + +output "id" { + value = azurerm_servicebus_namespace.example.id + description = "Specifies the resource id of the Service Bus namespace." +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/service_bus/variables.tf b/samples/function-app-service-bus/dotnet/terraform/modules/service_bus/variables.tf new file mode 100644 index 0000000..5f380b2 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/service_bus/variables.tf @@ -0,0 +1,173 @@ +variable "name" { + description = "(Required) Specifies the name of the resource. Changing this forces a new resource to be created." + type = string +} + +variable "resource_group_name" { + description = "(Required) The name of the resource group in which to create the resource. Changing this forces a new resource to be created." + type = string +} + +variable "location" { + description = "(Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created." + type = string +} + +variable "log_analytics_workspace_id" { + description = "Specifies the resource id of the Azure Log Analytics workspace." + type = string +} + +variable "sku" { + description = "(Required) Specifies the SKU tier for the Service Bus Namespace. Options are Basic, Standard, or Premium." + type = string + default = "Premium" + + validation { + condition = contains(["Basic", "Standard", "Premium"], var.sku) + error_message = "The SKU must be one of Basic, Standard, or Premium." + } +} + +variable "capacity" { + description = "(Optional) Specifies the capacity for the Service Bus Namespace. When SKU is Premium, capacity can be 1, 2, 4, 8, or 16. When SKU is Basic or Standard, capacity can be 0 only." + type = number + default = 0 +} + +variable "premium_messaging_partitions" { + description = "(Optional) Specifies the number of messaging partitions. Only valid when SKU is Premium. Possible values include 0, 1, 2, and 4. Defaults to 0." + type = number + default = 0 +} + +variable "local_auth_enabled" { + description = "(Optional) Specifies whether SAS authentication is enabled for the Service Bus Namespace. Defaults to true." + type = bool + default = true +} + +variable "public_network_access_enabled" { + description = "(Optional) Specifies whether public network access is enabled for the Service Bus Namespace. Defaults to true." + type = bool + default = true +} + +variable "minimum_tls_version" { + description = "(Optional) Specifies the minimum supported TLS version for the Service Bus Namespace. Valid values are 1.0, 1.1, and 1.2. Defaults to 1.2." + type = string + default = "1.2" + + validation { + condition = contains(["1.0", "1.1", "1.2"], var.minimum_tls_version) + error_message = "The minimum TLS version must be one of 1.0, 1.1, or 1.2." + } +} + +variable "tags" { + description = "(Optional) Specifies the tags to be applied to the resources." + type = map(string) + default = {} +} + +variable "queue_names" { + description = "(Optional) Specifies the names of the queues to be created within the Service Bus Namespace." + type = set(string) + default = [] +} + +variable "lock_duration" { + description = "(Optional) Specifies the ISO 8601 timespan duration of a peek-lock. Maximum value is 5 minutes. Defaults to PT1M." + type = string + default = "PT4M" +} + +variable "max_message_size_in_kilobytes" { + description = "(Optional) Specifies the maximum size of a message allowed on the queue in kilobytes. Only applicable for Premium SKU." + type = number + default = null +} + +variable "max_size_in_megabytes" { + description = "(Optional) Specifies the size of memory allocated for the queue in megabytes." + type = number + default = null +} + +variable "requires_duplicate_detection" { + description = "(Optional) Specifies whether the queue requires duplicate detection. Changing this forces a new resource to be created. Defaults to false." + type = bool + default = true +} + +variable "requires_session" { + description = "(Optional) Specifies whether the queue requires sessions for ordered handling of unbounded sequences of related messages. Changing this forces a new resource to be created. Defaults to false." + type = bool + default = true +} + +variable "default_message_ttl" { + description = "(Optional) Specifies the ISO 8601 timespan duration of the TTL of messages sent to this queue." + type = string + default = "PT12S" +} + +variable "dead_lettering_on_message_expiration" { + description = "(Optional) Specifies whether the queue has dead letter support when a message expires. Defaults to false." + type = bool + default = true +} + +variable "duplicate_detection_history_time_window" { + description = "(Optional) Specifies the ISO 8601 timespan duration during which duplicates can be detected. Defaults to PT10M." + type = string + default = "PT10M" +} + +variable "max_delivery_count" { + description = "(Optional) Specifies the maximum number of deliveries before a message is automatically dead lettered. Defaults to 10." + type = number + default = 5 +} + +variable "status" { + description = "(Optional) Specifies the status of the queue. Possible values are Active, Creating, Deleting, Disabled, ReceiveDisabled, Renaming, SendDisabled, Unknown. Defaults to Active." + type = string + default = "Active" +} + +variable "batched_operations_enabled" { + description = "(Optional) Specifies whether server-side batched operations are enabled. Defaults to true." + type = bool + default = true +} + +variable "auto_delete_on_idle" { + description = "(Optional) Specifies the ISO 8601 timespan duration of the idle interval after which the queue is automatically deleted. Minimum of 5 minutes." + type = string + default = null +} + +variable "partitioning_enabled" { + description = "(Optional) Specifies whether the queue is partitioned across multiple message brokers. Changing this forces a new resource to be created. Defaults to false." + type = bool + default = true +} + +variable "express_enabled" { + description = "(Optional) Specifies whether Express Entities are enabled. An express queue holds a message in memory temporarily before writing it to persistent storage. Defaults to false." + type = bool + default = true +} + +variable "forward_to" { + description = "(Optional) Specifies the name of a queue or topic to automatically forward messages to." + type = string + default = null +} + +variable "forward_dead_lettered_messages_to" { + description = "(Optional) Specifies the name of a queue or topic to automatically forward dead lettered messages to." + type = string + default = null +} \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/storage_account/main.tf b/samples/function-app-service-bus/dotnet/terraform/modules/storage_account/main.tf new file mode 100644 index 0000000..eecc0e5 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/storage_account/main.tf @@ -0,0 +1,123 @@ +resource "azurerm_storage_account" "example" { + name = var.name + resource_group_name = var.resource_group_name + + location = var.location + account_kind = var.account_kind + account_tier = var.account_tier + account_replication_type = var.replication_type + access_tier = var.access_tier + is_hns_enabled = var.is_hns_enabled + shared_access_key_enabled = var.shared_access_key_enabled + min_tls_version = var.min_tls_version + https_traffic_only_enabled = var.https_traffic_only_enabled + allow_nested_items_to_be_public = var.allow_blob_public_access + cross_tenant_replication_enabled = var.cross_tenant_replication_enabled + public_network_access_enabled = var.public_network_access_enabled + tags = var.tags + + network_rules { + default_action = (length(var.ip_rules) + length(var.virtual_network_subnet_ids)) > 0 ? "Deny" : var.default_action + ip_rules = var.ip_rules + virtual_network_subnet_ids = var.virtual_network_subnet_ids + bypass = var.bypass + } + + identity { + type = "SystemAssigned" + } + + lifecycle { + ignore_changes = [ + tags + ] + } +} + +resource "azurerm_monitor_diagnostic_setting" "blob" { + name = "DiagnosticsSettings-blobService" + target_resource_id = "${azurerm_storage_account.example.id}/blobServices/default/" + log_analytics_workspace_id = var.log_analytics_workspace_id + + enabled_log { + category = "StorageRead" + } + + enabled_log { + category = "StorageWrite" + } + + enabled_log { + category = "StorageDelete" + } + + enabled_metric { + category = "Transaction" + } +} + +resource "azurerm_monitor_diagnostic_setting" "queue" { + name = "DiagnosticsSettings-queueService" + target_resource_id = "${azurerm_storage_account.example.id}/queueServices/default/" + log_analytics_workspace_id = var.log_analytics_workspace_id + + enabled_log { + category = "StorageRead" + } + + enabled_log { + category = "StorageWrite" + } + + enabled_log { + category = "StorageDelete" + } + + enabled_metric { + category = "Transaction" + } +} + +resource "azurerm_monitor_diagnostic_setting" "table" { + name = "DiagnosticsSettings-tableService" + target_resource_id = "${azurerm_storage_account.example.id}/tableServices/default/" + log_analytics_workspace_id = var.log_analytics_workspace_id + + enabled_log { + category = "StorageRead" + } + + enabled_log { + category = "StorageWrite" + } + + enabled_log { + category = "StorageDelete" + } + + enabled_metric { + category = "Transaction" + } +} + +resource "azurerm_monitor_diagnostic_setting" "file" { + name = "DiagnosticsSettings-fileService" + target_resource_id = "${azurerm_storage_account.example.id}/fileServices/default/" + log_analytics_workspace_id = var.log_analytics_workspace_id + + enabled_log { + category = "StorageRead" + } + + enabled_log { + category = "StorageWrite" + } + + enabled_log { + category = "StorageDelete" + } + + enabled_metric { + category = "Transaction" + } +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/storage_account/outputs.tf b/samples/function-app-service-bus/dotnet/terraform/modules/storage_account/outputs.tf new file mode 100644 index 0000000..6e83f70 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/storage_account/outputs.tf @@ -0,0 +1,30 @@ +output "name" { + description = "Specifies the name of the storage account" + value = azurerm_storage_account.example.name +} + +output "id" { + description = "Specifies the resource id of the storage account" + value = azurerm_storage_account.example.id +} + +output "primary_access_key" { + description = "Specifies the primary access key of the storage account" + value = azurerm_storage_account.example.primary_access_key +} + +output "principal_id" { + description = "Specifies the principal id of the system assigned managed identity of the storage account" + value = azurerm_storage_account.example.identity[0].principal_id +} + +output "primary_blob_endpoint" { + description = "Specifies the primary blob endpoint of the storage account" + value = azurerm_storage_account.example.primary_blob_endpoint +} + +output "primary_connection_string" { + description = "Specifies the primary connection string of the storage account" + value = azurerm_storage_account.example.primary_connection_string + sensitive = true +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/storage_account/variables.tf b/samples/function-app-service-bus/dotnet/terraform/modules/storage_account/variables.tf new file mode 100644 index 0000000..ae24d62 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/storage_account/variables.tf @@ -0,0 +1,134 @@ +variable "resource_group_name" { + description = "(Required) Specifies the name of the resource group. of the Azure Storage Account" + type = string +} + +variable "name" { + description = "(Required) Specifies the name of the Azure Storage Account" + type = string +} + +variable "location" { + description = "(Required) Specifies the location of the Azure Storage Account" + type = string +} + +variable "account_kind" { + description = "(Optional) Specifies the account kind of the Azure Storage Account" + default = "StorageV2" + type = string + + validation { + condition = contains(["Storage", "StorageV2"], var.account_kind) + error_message = "The account kind of the Azure Storage Account is invalid." + } +} + +variable "account_tier" { + description = "(Optional) Specifies the account tier of the Azure Storage Account" + default = "Standard" + type = string + + validation { + condition = contains(["Standard", "Premium"], var.account_tier) + error_message = "The account tier of the Azure Storage Account is invalid." + } +} + +variable "replication_type" { + description = "(Optional) Specifies the replication type of the Azure Storage Account" + default = "LRS" + type = string + + validation { + condition = contains(["LRS", "ZRS", "GRS", "GZRS", "RA-GRS", "RA-GZRS"], var.replication_type) + error_message = "The replication type of the Azure Storage Account is invalid." + } +} + +variable "is_hns_enabled" { + description = "(Optional) Specifies the replication type of the Azure Storage Account" + default = false + type = bool +} + +variable "default_action" { + description = "Allow or disallow public access to all blobs or containers in the Azure Storage Accounts. The default interpretation is true for this property." + default = "Allow" + type = string +} + +variable "ip_rules" { + description = "Specifies IP rules for the Azure Storage Account" + default = [] + type = list(string) +} + +variable "virtual_network_subnet_ids" { + description = "Specifies a list of resource ids for subnets" + default = [] + type = list(string) +} + +variable "kind" { + description = "(Optional) Specifies the kind of the Azure Storage Account" + default = "" +} + +variable "bypass" { + description = " (Optional) Specifies whether traffic is bypassed for Logging/Metrics/AzureServices. Valid options are any combination of Logging, Metrics, AzureServices, or None." + default = ["Logging", "Metrics", "AzureServices"] + type = set(string) +} + +variable "shared_access_key_enabled" { + description = "(Optional) Indicates whether the storage account permits requests to be authorized with the account access key via Shared Key. If false, then all requests, including shared access signatures, must be authorized with Azure Active Directory (Azure AD). Defaults to true." + default = true + type = bool +} + +variable "access_tier" { + description = "(Optional) Specifies the access tier of the storage account. The default value is Hot." + type = string + default = "Hot" +} + +variable "min_tls_version" { + description = "(Optional) Specifies the minimum TLS version to be permitted on requests to storage. The default value is TLS1_2." + type = string + default = "TLS1_2" +} + +variable "https_traffic_only_enabled" { + description = "(Optional) Specifies whether the storage account should only support HTTPS traffic." + type = bool + default = true +} + +variable "allow_blob_public_access" { + description = "(Optional) Specifies whether the storage account allows public access to blobs." + type = bool + default = true +} + +variable "cross_tenant_replication_enabled" { + description = "(Optional) Specifies whether the storage account allows cross-tenant replication." + type = bool + default = false +} + +variable "public_network_access_enabled" { + description = "(Optional) Specifies whether public network access is enabled for the storage account." + type = bool + default = true +} + +variable "log_analytics_workspace_id" { + description = "Specifies the resource id of the Azure Log Analytics workspace." + type = string +} + +variable "tags" { + description = "(Optional) Specifies the tags of the Azure Storage Account" + default = {} +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/virtual_network/main.tf b/samples/function-app-service-bus/dotnet/terraform/modules/virtual_network/main.tf new file mode 100644 index 0000000..cec00f4 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/virtual_network/main.tf @@ -0,0 +1,55 @@ +resource "azurerm_virtual_network" "example" { + name = var.vnet_name + address_space = var.address_space + location = var.location + resource_group_name = var.resource_group_name + tags = var.tags + + lifecycle { + ignore_changes = [ + tags + ] + } +} + +resource "azurerm_subnet" "example" { + for_each = { for subnet in var.subnets : subnet.name => subnet if subnet != null } + + name = each.key + resource_group_name = var.resource_group_name + virtual_network_name = azurerm_virtual_network.example.name + address_prefixes = each.value.address_prefixes + private_endpoint_network_policies = each.value.private_endpoint_network_policies + private_link_service_network_policies_enabled = each.value.private_link_service_network_policies_enabled + + dynamic "delegation" { + for_each = each.value.delegation != null ? [each.value.delegation] : [] + content { + name = "delegation" + + service_delegation { + name = delegation.value + } + } + } + + lifecycle { + ignore_changes = [ + delegation + ] + } +} + +resource "azurerm_monitor_diagnostic_setting" "example" { + name = "DiagnosticsSettings" + target_resource_id = azurerm_virtual_network.example.id + log_analytics_workspace_id = var.log_analytics_workspace_id + + enabled_log { + category = "VMProtectionAlerts" + } + + enabled_metric { + category = "AllMetrics" + } +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/virtual_network/outputs.tf b/samples/function-app-service-bus/dotnet/terraform/modules/virtual_network/outputs.tf new file mode 100644 index 0000000..b464308 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/virtual_network/outputs.tf @@ -0,0 +1,19 @@ +output "name" { + description = "Specifies the name of the virtual network" + value = azurerm_virtual_network.example.name +} + +output "vnet_id" { + description = "Specifies the resource id of the virtual network" + value = azurerm_virtual_network.example.id +} + +output "subnet_ids" { + description = "Contains a list of the the resource id of the subnets" + value = { for subnet in azurerm_subnet.example : subnet.name => subnet.id } +} + +output "subnet_ids_as_list" { + description = "Returns the list of the subnet ids as a list of strings." + value = [for subnet in azurerm_subnet.example : subnet.id] +} diff --git a/samples/function-app-service-bus/dotnet/terraform/modules/virtual_network/variables.tf b/samples/function-app-service-bus/dotnet/terraform/modules/virtual_network/variables.tf new file mode 100644 index 0000000..f8c0b0e --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/modules/virtual_network/variables.tf @@ -0,0 +1,40 @@ +variable "resource_group_name" { + description = "Resource Group name" + type = string +} + +variable "location" { + description = "Location in which to deploy the network" + type = string +} + +variable "vnet_name" { + description = "VNET name" + type = string +} + +variable "address_space" { + description = "VNET address space" + type = list(string) +} + +variable "subnets" { + description = "Subnets configuration" + type = list(object({ + name = string + address_prefixes = list(string) + private_endpoint_network_policies = string + private_link_service_network_policies_enabled = bool + delegation = string + })) +} + +variable "tags" { + description = "(Optional) Specifies the tags of the Azure Virtual Network resource." + default = {} +} + +variable "log_analytics_workspace_id" { + description = "Specifies the resource id of the Azure Log Analytics workspace." + type = string +} diff --git a/samples/function-app-service-bus/dotnet/terraform/outputs.tf b/samples/function-app-service-bus/dotnet/terraform/outputs.tf new file mode 100644 index 0000000..5697c61 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/outputs.tf @@ -0,0 +1,19 @@ +output "resource_group_name" { + value = local.resource_group_name +} + +output "app_service_plan_name" { + value = module.app_service_plan.name +} + +output "function_app_name" { + value = module.function_app.name +} + +output "function_app_default_hostname" { + value = module.function_app.default_hostname +} + +output "service_bus_namespace_name" { + value = module.service_bus_namespace.name +} \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/providers.tf b/samples/function-app-service-bus/dotnet/terraform/providers.tf new file mode 100644 index 0000000..3e04500 --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/providers.tf @@ -0,0 +1,24 @@ +terraform { + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "=4.60.0" + } + } +} + +provider "azurerm" { + features { + resource_group { + prevent_deletion_if_contains_resources = false + } + } + + # Set the hostname of the Azure Metadata Service (for example management.azure.com) + # used to obtain the Cloud Environment when using LocalStack's Azure emulator. + # This allows the provider to correctly identify the environment and avoid making calls to the real Azure endpoints. + metadata_host = "localhost.localstack.cloud:4566" + + # Set the subscription ID to a dummy value when using LocalStack's Azure emulator. + subscription_id = "00000000-0000-0000-0000-000000000000" +} \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/terraform.tfvars b/samples/function-app-service-bus/dotnet/terraform/terraform.tfvars new file mode 100644 index 0000000..a1f0ccc --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/terraform.tfvars @@ -0,0 +1,4 @@ +prefix = "local" +suffix = "test" +location = "westeurope" +dotnet_version = "10.0" \ No newline at end of file diff --git a/samples/function-app-service-bus/dotnet/terraform/variables.tf b/samples/function-app-service-bus/dotnet/terraform/variables.tf new file mode 100644 index 0000000..cee2bed --- /dev/null +++ b/samples/function-app-service-bus/dotnet/terraform/variables.tf @@ -0,0 +1,557 @@ +variable "prefix" { + description = "(Optional) Specifies the prefix for the name of the Azure resources." + type = string + default = "local" + + validation { + condition = var.prefix == null || length(var.prefix) >= 2 + error_message = "The prefix must be at least 2 characters long." + } +} + +variable "suffix" { + description = "(Optional) Specifies the suffix for the name of the Azure resources." + type = string + default = "test" + + validation { + condition = var.suffix == null || length(var.suffix) >= 2 + error_message = "The suffix must be at least 2 characters long." + } +} + +variable "location" { + description = "(Required) Specifies the location for all resources." + type = string + default = "westeurope" +} + +variable "primary_region" { + description = "(Required) Specifies the primary region for the Azure Cosmos DB account." + type = string + default = "westeurope" +} + +variable "secondary_region" { + description = "(Required) Specifies the secondary region for the Azure Cosmos DB account." + type = string + default = "northeurope" +} + +variable "mongodb_server_version" { + description = "(Optional) Specifies the version of MongoDB API for the Azure Cosmos DB account." + type = string + default = "7.0" + + validation { + condition = contains([ + "3.2", + "3.6", + "4.0", + "4.2", + "5.0", + "6.0", + "7.0", + "8.0" + ], var.mongodb_server_version) + error_message = "The mongodb_server_version must be one of the supported versions: 3.2, 3.6, 4.0, 4.2, 5.0, 6.0, 7.0, 8.0." + } +} + +variable "database_throughput" { + description = "(Optional) Specifies the throughput for the MongoDB database." + type = number + default = 400 +} + +variable "consistency_level" { + description = "(Required) Specifies the consistency level for the Azure Cosmos DB account." + type = string + default = "Eventual" + + validation { + condition = contains([ + "Strong", + "BoundedStaleness", + "Session", + "Eventual" + ], var.consistency_level) + error_message = "The consistency_level must be one of the allowed values." + } +} + +variable "cosmosdb_database_name" { + description = "(Optional) Specifies the name of the Azure Cosmos DB for MongoDB database." + type = string + default = "sampledb" +} + +variable "cosmosdb_collection_name" { + description = "(Optional) Specifies the name of the Azure Cosmos DB for MongoDB collection." + type = string + default = "activities" +} + +variable "mongodb_index_keys" { + description = "A list of field names for which to create single-field indexes on the MongoDB collection." + type = list(string) + default = ["_id", "username", "activity", "timestamp"] +} + +variable "os_type" { + description = "(Required) Specifies the O/S type for the App Services to be hosted in this plan. Possible values include Windows, Linux, and WindowsContainer. Changing this forces a new resource to be created." + type = string + default = "Linux" + + validation { + condition = contains([ + "Windows", + "Linux", + "WindowsContainer" + ], var.os_type) + error_message = "The os_type must be either 'Windows', 'Linux', or 'WindowsContainer'." + } +} + +variable "zone_balancing_enabled" { + description = "(Optional) Should the Service Plan balance across Availability Zones in the region." + type = bool + default = false +} + +variable "sku_tier" { + description = "(Optional) Specifies the tier name for the hosting plan." + type = string + default = "Standard" + + validation { + condition = contains([ + "Basic", + "Standard", + "ElasticPremium", + "Premium", + "PremiumV2", + "Premium0V3", + "PremiumV3", + "PremiumMV3", + "Isolated", + "IsolatedV2", + "WorkflowStandard", + "FlexConsumption" + ], var.sku_tier) + error_message = "The sku_tier must be one of the allowed values." + } +} +variable "sku_name" { + description = "(Optional) Specifies the SKU name for the hosting plan." + type = string + default = "S1" + + validation { + condition = contains([ + "B1", "B2", "B3", + "S1", "S2", "S3", + "EP1", "EP2", "EP3", + "P1", "P2", "P3", + "P1V2", "P2V2", "P3V2", + "P0V3", "P1V3", "P2V3", "P3V3", + "P1MV3", "P2MV3", "P3MV3", "P4MV3", "P5MV3", + "I1", "I2", "I3", + "I1V2", "I2V2", "I3V2", "I4V2", "I5V2", "I6V2", + "WS1", "WS2", "WS3", + "FC1" + ], var.sku_name) + error_message = "The sku_name must be one of the allowed values." + } +} + +variable "use_dotnet_isolated_runtime" { + description = "(Optional) Should the DotNet process use an isolated runtime. Defaults to false." + type = bool + default = true +} + +variable "java_version" { + description = "(Optional) The Version of Java to use." + type = string + default = null +} + +variable "node_version" { + description = "(Optional) The version of Node.js to run." + type = string + default = null +} + +variable "dotnet_version" { + description = "(Optional) The version of .NET to use." + type = string + default = null +} + +variable "python_version" { + description = "(Optional) Specifies the version of Python to run. Possible values include 3.13, 3.12, 3.11, 3.10, 3.9, 3.8 and 3.7." + type = string + default = null +} + +variable "https_only" { + description = "(Optional) Specifies whether the Linux Web App require HTTPS connections. Defaults to false." + type = bool + default = false +} + +variable "minimum_tls_version" { + description = "(Optional) Specifies the minimum version of TLS required for SSL requests. Possible values include: 1.0, 1.1, 1.2 and 1.3. Defaults to 1.2." + type = string + default = "1.2" + + validation { + condition = contains([ + "1.0", + "1.1", + "1.2", + "1.3" + ], var.minimum_tls_version) + error_message = "The minimum_tls_version must be one of the allowed values." + } +} + +variable "always_on" { + description = "(Optional) Specifies whether the Linux Web App is Always On enabled. Defaults to true." + type = bool + default = true +} + +variable "http2_enabled" { + description = "(Optional) Specifies whether HTTP/2 is enabled for the Linux Web App." + type = bool + default = false +} + +variable "public_network_access_enabled" { + description = "(Optional) Specifies whether the public network access is enabled or disabled." + type = bool + default = true +} + +variable "repo_url" { + description = "(Optional) Specifies the Git repository URL." + type = string + default = "" + + validation { + condition = var.repo_url == "" || can(regex("^https?://", var.repo_url)) + error_message = "The repo_url must be empty or a valid HTTP/HTTPS URL." + } +} + +variable "login_name" { + description = "(Required) Specifies the login name for the application." + type = string + default = "paolo" +} + +variable "tags" { + description = "(Optional) Specifies the tags to be applied to the resources." + type = map(string) + default = { + environment = "test" + deployment = "terraform" + } +} + +variable "vnet_name" { + description = "Specifies the name of the virtual network." + default = "VNet" + type = string +} + +variable "vnet_address_space" { + description = "Specifies the address space of the virtual network." + default = ["10.0.0.0/8"] + type = list(string) +} + +variable "webapp_subnet_name" { + description = "Specifies the name of the web app subnet." + default = "app-subnet" + type = string +} + +variable "webapp_subnet_address_prefix" { + description = "Specifies the address prefix of the web app subnet." + default = ["10.0.0.0/24"] + type = list(string) +} + +variable "pe_subnet_name" { + description = "Specifies the name of the subnet that contains the private endpoints." + default = "pe-subnet" + type = string +} + +variable "pe_subnet_address_prefix" { + description = "Specifies the address prefix of the subnet that contains the private endpoints." + default = ["10.0.1.0/24"] + type = list(string) +} + +variable "nat_gateway_name" { + description = "(Required) Specifies the name of the NAT Gateway" + type = string + default = "NatGateway" +} + +variable "nat_gateway_sku_name" { + description = "(Optional) The SKU which should be used. At this time the only supported value is Standard. Defaults to Standard" + type = string + default = "Standard" +} + +variable "nat_gateway_idle_timeout_in_minutes" { + description = "(Optional) The idle timeout which should be used in minutes. Defaults to 4." + type = number + default = 4 +} + +variable "nat_gateway_zones" { + description = " (Optional) A list of Availability Zones in which this NAT Gateway should be located. Changing this forces a new NAT Gateway to be created." + type = list(string) + default = ["1"] +} + +variable "website_port" { + description = "(Optional) Specifies the port on which the Web App will listen. Defaults to 8000." + type = number + default = 8000 +} + +variable "queue_names" { + description = "(Optional) Specifies the names of the queues to be created within the Service Bus Namespace." + type = set(string) + default = ["input", "output"] +} + +variable "service_bus_sku" { + description = "(Required) Specifies the SKU tier for the Service Bus Namespace. Options are Basic, Standard, or Premium." + type = string + default = "Premium" + + validation { + condition = contains(["Basic", "Standard", "Premium"], var.service_bus_sku) + error_message = "The SKU must be one of Basic, Standard, or Premium." + } +} + +variable "service_bus_capacity" { + description = "(Optional) Specifies the capacity for the Service Bus Namespace. When SKU is Premium, capacity can be 1, 2, 4, 8, or 16. When SKU is Basic or Standard, capacity can be 0 only." + type = number + default = 1 +} + +variable "service_bus_premium_messaging_partitions" { + description = "(Optional) Specifies the number of messaging partitions. Only valid when SKU is Premium. Possible values include 1, 2, and 4. Defaults to 1." + type = number + default = 1 +} + +variable "service_bus_local_auth_enabled" { + description = "(Optional) Specifies whether SAS authentication is enabled for the Service Bus Namespace. Defaults to true." + type = bool + default = true +} + +variable "service_bus_public_network_access_enabled" { + description = "(Optional) Specifies whether public network access is enabled for the Service Bus Namespace. Defaults to true." + type = bool + default = true +} + +variable "queue_lock_duration" { + description = "(Optional) Specifies the ISO 8601 timespan duration of a peek-lock. Maximum value is 5 minutes. Defaults to PT5M." + type = string + default = "PT5M" +} + +variable "queue_max_message_size_in_kilobytes" { + description = "(Optional) Specifies the maximum size of a message allowed on the queue in kilobytes. Only applicable for Premium SKU." + type = number + default = null +} + +variable "queue_max_size_in_megabytes" { + description = "(Optional) Specifies the size of memory allocated for the queue in megabytes." + type = number + default = 1024 +} + +variable "queue_requires_duplicate_detection" { + description = "(Optional) Specifies whether the queue requires duplicate detection. Changing this forces a new resource to be created. Defaults to false." + type = bool + default = false +} + +variable "queue_requires_session" { + description = "(Optional) Specifies whether the queue requires sessions for ordered handling of unbounded sequences of related messages. Changing this forces a new resource to be created. Defaults to false." + type = bool + default = false +} + +variable "queue_default_message_ttl" { + description = "(Optional) Specifies the ISO 8601 timespan duration of the TTL of messages sent to this queue." + type = string + default = "P10675199DT2H48M5.4775807S" +} + +variable "queue_dead_lettering_on_message_expiration" { + description = "(Optional) Specifies whether the queue has dead letter support when a message expires. Defaults to false." + type = bool + default = false +} + +variable "queue_duplicate_detection_history_time_window" { + description = "(Optional) Specifies the ISO 8601 timespan duration during which duplicates can be detected. Defaults to PT10M." + type = string + default = "PT10M" +} + +variable "queue_max_delivery_count" { + description = "(Optional) Specifies the maximum number of deliveries before a message is automatically dead lettered. Defaults to 10." + type = number + default = 10 +} + +variable "queue_status" { + description = "(Optional) Specifies the status of the queue. Possible values are Active, Creating, Deleting, Disabled, ReceiveDisabled, Renaming, SendDisabled, Unknown. Defaults to Active." + type = string + default = "Active" +} + +variable "queue_batched_operations_enabled" { + description = "(Optional) Specifies whether server-side batched operations are enabled. Defaults to true." + type = bool + default = true +} + +variable "queue_auto_delete_on_idle" { + description = "(Optional) Specifies the ISO 8601 timespan duration of the idle interval after which the queue is automatically deleted. Minimum of 5 minutes." + type = string + default = null +} + +variable "queue_partitioning_enabled" { + description = "(Optional) Specifies whether the queue is partitioned across multiple message brokers. Changing this forces a new resource to be created. Defaults to false." + type = bool + default = false +} + +variable "queue_express_enabled" { + description = "(Optional) Specifies whether Express Entities are enabled. An express queue holds a message in memory temporarily before writing it to persistent storage. Defaults to false." + type = bool + default = false +} + +variable "queue_forward_to" { + description = "(Optional) Specifies the name of a queue or topic to automatically forward messages to." + type = string + default = null +} + +variable "queue_forward_dead_lettered_messages_to" { + description = "(Optional) Specifies the name of a queue or topic to automatically forward dead lettered messages to." + type = string + default = null +} + +variable "account_replication_type" { + description = "(Optional) Specifies the replication type for the storage account." + type = string + default = "LRS" + + validation { + condition = contains([ + "LRS", + "GRS", + "RAGRS", + "ZRS", + "GZRS", + "RAGZRS" + ], var.account_replication_type) + error_message = "The account_replication_type must be one of: LRS, GRS, RAGRS, ZRS, GZRS, RAGZRS." + } +} + +variable "account_kind" { + description = "(Optional) Specifies the account kind of the storage account." + default = "StorageV2" + type = string + + validation { + condition = contains(["Storage", "StorageV2"], var.account_kind) + error_message = "The account kind of the storage account is invalid." + } +} + +variable "account_tier" { + description = "(Optional) Specifies the account tier of the storage account." + default = "Standard" + type = string + + validation { + condition = contains(["Standard", "Premium"], var.account_tier) + error_message = "The account tier of the storage account is invalid." + } +} + +variable "functions_worker_runtime" { + description = "(Required) Specifies the language runtime used by the Azure Functions App." + type = string + default = "dotnet-isolated" + + validation { + condition = contains(["dotnet", "dotnet-isolated", "python", "java", "node", "powerShell", "custom"], var.functions_worker_runtime) + error_message = "The functions_worker_runtime must be one of: dotnet, dotnet-isolated, python, java, node, powerShell, custom." + } +} + +variable "functions_extension_version" { + description = "(Optional) Specifies the Azure Functions extension version. Defaults to ~4." + type = string + default = "~4" +} + +variable "input_queue_name" { + description = "(Optional) Specifies the name of the input queue." + type = string + default = "input" +} + +variable "output_queue_name" { + description = "(Optional) Specifies the name of the output queue." + type = string + default = "output" +} + +variable "names" { + description = "(Optional) Specifies a comma-separated list of names to be used as part of the sample data in the Azure Function App." + type = string + default = "Paolo,John,Jane,Max,Mary,Leo,Mia,Anna,Lisa,Anastasia" +} + +variable "timer_schedule" { + description = "(Optional) Specifies the CRON expression for the timer trigger." + type = string + default = "*/10 * * * * *" +} + +variable "managed_identity_type" { + description = "(Optional) Specifies the type of managed identity." + type = string + default = "UserAssigned" + + validation { + condition = contains(["SystemAssigned", "UserAssigned"], var.managed_identity_type) + error_message = "The managed identity type must be either SystemAssigned or UserAssigned." + } +} diff --git a/samples/function-app-service-bus/dotnet/visio/architecture.vsdx b/samples/function-app-service-bus/dotnet/visio/architecture.vsdx new file mode 100644 index 0000000000000000000000000000000000000000..159df5f3bde98492cad7a5dae6b0d807f681a621 GIT binary patch literal 359166 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
^G~_`{|kNAIZ1v9 z{(05q75;}c7}I~&V4MGRsvBY$KL63FhVzwbliq7_v=Gb2t;-r%?VA{~Uh$!aOKTi&{4zBOlD5FRxc(H{&c1z@*P$@RsOj|d<%nzd^6C< zoWj8T7`T{vGvvnme0|LMal7}Z-#)AeG^iWH%y*-;kTTO$k$5vjO?|0|UPh-B0*1@ZZ zDfkABhe%wiprka}N?#S}f&~Btyx|qwo`2uNm%e+f@1EG5%hJIf&e5HEhvlc6bM5uR z3o(2zt95twS5goCG&O+u+vfA+*zsD8SLf<2HOh^K%va`A zm<(tp=RM#L8B~M-adIB|v;Ai0~1*WCu{jyu?{wi1a&-5)QX?rHYETx{2M>SYbUEO0%yd!s^* z+`qr!+fz9on^IPf!wmbup|vbS1poL6fSY5ggg}j#`U?aPJiMFk`}PMM%$IG)O?$u; zxOH3RcmAPne`S+HMw;iXtOfiy5*Uz18tXSiX zAR|NhgwMoyk6VTkmg^MM_FKg3Y>Q{zA7#_B7Q!3Ey~lpjY+Q;V7|IPMVu=oP$KVdZ zRdx^qKOw_R6fr8uHG3P;Pd#fKFA?QuyJmm@0iO(!PC*^5$zsEW%pGw}rN0+4?0C*+ zAyzL(b@fSts*Mg^^P58u)UQ5_b5)Iz`T8Qqw%%m97bIOWO`j=LE8u(a>W0VJs1a-I zgDwf$M#$l`h5dJW__D(@c!kIl^9v_vr5->LmHNYjJEQ|Ys(EkjWEia>{Y2%_@;_#P z+(AN@j2|%BW$EWm)T()Z44XR%sxM~_aIN4%L@>YB^1P-9jlZJ=$v5s^_o_S)1oIpH z6>+h|!p|4cpT&kp&)CHO3D5XgG4|o5GhBf@1r_0a$ZB42e7j0TJnMTxI01R^N`!xo z&)@}q>`m?JlTu@Hf{u>@Mj*?Ey2$jMlB3e+)Hzl$w!i;c`^lrr^L@nfeXYkdgK3(; zg?YE5oad4yPJ~ZO!|poL9I`)PtT79xo6*iaj9iYG<8JJIJz-Z%_I11V2ShsKZ5#PG zNtuxTVK^b;$!-7cWtw9p-mBG$yUV91yV^ubH@;m;ZX@pl2zxbzk0|0)C;2F02GFra|WNh!wYVxq$);&Ew7mf^vRS#gIH7lHElMv)PkWnSg9 zm0*XB+e~gq4HG2koV2iC9=V#hOkv|L*E=~?jPiXb51nrC<&Ja=R^#u_f;hSJ;5D}Q z2?VC%FjRE4o|i;^Q5w>;LDW23gPFmmgLITbywbEi1cqoBASwATT&PH11|v;ya?m+~ zh9-f!1)40gavd#80lL^kgWC^7anmo<2lyS`12$^*yYFsLt(IiK!_TtxC%=#6;+iMJsQ-;U&6j%DL4f?7hv^F(|5 z4_i(TJ>TI$J{Lwzeo8w6wo?X%_-ek;qp>)(0|hlnN}DwIK}J*n zA@8xVc+HK|8isa%)w@%UtlE{xN<+g&+B%H_ErFrmoX9DZVb2(Yr_-g^*HS^jZanri z2Luu=*Un%+Xd-JeJtJH`of;lcm1GNBh`3GA5fJW_pBy$314xtrlU~d&0=PqR-hJ5| zb&Ox69|=1gRQYdGeR(0vg<2Zi!{ec#p9je0Pt8X zkn`E3M~gvY-26os8K$+YFqD_`Y3U@G(34ls&uMCJlLtX@gaG8qjqmtRJN7SbLl$%x zWIYen0QR-J5||nBS?EbrR$ukXMaU-{xN^PC(l?S~r`7l1Z%120CQbuy3oc~kEL`E= zkFjMDq|^Am%7hJ4Wt}!ZZK$boi0WCHnPq&gUVgo{<5DPk;4Uv)&F$iC>OXZY+Ay5@ z3>|0KbaAfEh(Z-y>~EB{8H&`l8@w);Ur)(|q{?G?G+fry9aqr!cR{xi-r2PePnfqs z><9zSU2uK7l&q&x;~-Hiu_NEt&v>jxv_UU}eOuWDYzWavc?4H`ho!#k>nWp9B}MLA zzP=C)M)>pckvG_IWd_eIAw7ES3jN_=^#F~IFuRT(lC(wvEG$t2eTs=#X^qHV2K@-o z)Pn1~YVWdmK)7#JeThZCp)$aPg$Sm@-KF&+8FrEj=%4d^vHxrOQ5eSF zSEp(c4WESb54U?jiwO(~$uNbX&r%=kfPzx63X|L1>|bM-bv2qV)Ztx{zd+gRp(t_|bw0B7Ijv)9b^&-6NN? zulmtw^DUMed4Z_ws%~^RU{0SaKW#@|UN4MfIt0sY@xS=G#x6mEE!nnh+qP|c+O}=m zwrv~Jwr$(SG`8RF*WLXAd8)E9^PY^TxDo!)Adpun}PoB#py0Bvomrb9J_Ky5Q6S-M*uFa z0};Qs_tfc140Hil9?!L-4WRq=n<*(-7XxTY-4c^9;I$Yxp7B8ol7%1~%1`+G&1E82 zU~{B+qL5AIPWQiyY7REBJoBj76Y9#CQNh)VFDI1P zaCkxw9?9bWevWSLkxZ4;h*T;kDWH(Ie&B=F+NL_Y_C~BTNe0z%=IJJv2bX{{fUm^F zva5n1%}JY*sKZ!CudE1mPt2D;~TTi*e9VBJCekT}^hB$2Je%p>VQ8)yz9=xMA zwW@E7kmXo@9(X5Y;@CCPf3sFN7b~^5E0Z)iyp#o1Uy|lm@x#Z3q zbuj0n#@iNjVbETHJ5}-L4{_4F8c1LT43T&sCNmoY{+E8RME3iXf&|tn>lC^>;MD5j ze8^w^Aw`grSI7p_Z-{M#7%-qy1p%;_@Y%()TxPUeyTSmXnAF;#0=m0lUljT{TRj|2 z22ZMR1r{wF2#~{=fnmX&ehWrQ=A-hHmzdT~-@AM?S#uN6tp)%EWGhQHBn{vd%9F5p zO{59R*!35qIB`e~4uuBT@DKhd{{OwRMk7qmXxW6Pjd>@@7bXVT>Y;7)0G)bk`eR8c(2Bp_lJ$cdfajQXlTZe+-uq z$Xhf9W4mWY!Z6WJYqy&u+OCK$!wPb|`lRVJfltU0q71r5)FT=%%v`ibPQa2^s(IuR zc@Ooc6I&5K??J*HsZYj#ojaHeuSOytwKdRAU?x_73M0fn-92GLaHtyMwsPTF4tLFMtUq(0oWfLx40;-}vrf$ED@o5LMgd7E7A`7~CxpkBEgDad73{f^xq% zMkya2^e;~AJRhLoJ%dFtL;&mwgkpuzG3dUTlyqWw{DALTxd2;`HaMoEPCld>mdIK} ziZT(7;LsfTlu%%zsB>;&1wL3{mUwfR1?ClYUB_&=eiB^nhWrGsRB(5_vN7zNM=Y1y z*@JJIxA>cdVgS$3Pb#czLJ;S31VcKqNSME#VKHivg2b)SJ&2Kz9DW)1xJ0ThPsVvc zN!adIKn1}kTe#_AP2kEqR9xi2iMwn#4XHHOQ-Pw`1s)aA-pe&yS&`;7C!OdbqA&c#`V`dLnRE< zpe@Bz606`-xqXWFNH#tcZL;|5`UQu4rVh-p{*|j-kTFsMdOa2@NN6B`K-1q(IouAI z2sdQ6g?D1V;b<<)lydQW^n_&gn&ibqr+9W>Ac%_efb+MTB$6A#vCXvF{W}y-$vcu} zEw8#`AFrgqG9aREQ35~`0f1o2NHwCMcEofFfBfL!5*)bsplRC&IZ&}Rq~|1=k2Z7+ zDMdzS);~a<3IsM%v>1FbQpJLM<<@^C3C097urH)mKmv+1!0txl)(I+uedn-utRl*~ zP;q|}BUc$V&n6)mC{>IVG9xtqKhX;8>&0BLc}nFqbYt03ZpJ5sGv`{5@2y z@e=h82F7eBk~v3!Dc`CR0P-(YM%|3S###c|O(Zl<)<~4Cj2hJ>ZNiwBH^g2i#bx)E z``9RbFc_-;VE5&*4}(9OCF1+y|6j#5eUjT24A1}o0!sf6tHAs}&YL>F;u^I74rxJu z+>>EXkc=!WE*vM2&1MnEG_`Ug^TBG5MZ!MR2(32W_Ec8@}s^mNTT z@6ew1PGL1IiZX$3XR&l)A4}6u+oDDsI(z$tnFt1l>!wbLakh44%b-sNZcH8 zj-Prz_XVkok6W*FtljF$ovLro)cw;r5k({vJVWM(xr4vGRqWer67!`IyK#tP+JD6G z6GB41cc((YqA%`Q7!Rtq2HXzkmjh3FyBox{PeYr0@AfW~8AB00ign$cFLO5+7kxJA zeJ4y%@Wq;saTF#|lWAtV(xDY+N<3e z+LTWk9yz8&J<1m$y`Do3BQKJgAuCnA$RkrZ`%#y)~Rh@g4#a1DMuuh7(1cOr`{V<=OLD@jTOUm;MJK6tOkt(Fy|9 zIPc6U0(o@tbDC)=A^!I(Wk(;Ie>R-U&P#D}JtypFS=hi~>*jDrI`9N1?UT-&Df53S zlrYdxR)Y`W1#T{)A>Q03!w%1t98b=CGs@gl^?PN?#`s~-pD)c_^+GxS@_~G>-tOdN zO|cDbc#7C(7Q0F2`kb>F{)keE&hy-hQn3y_doxJ>IP-zeIq?3>@*-?GuyxkxR%-m? z%jl8CPc+c7olMRLhD_EiQYcPbM@8*Wl`X*>qhYTnOffCCR{->f7ug$S^i~Gp4`?1= zk=}#MZr~R#O^_cgS~p-@**pr(W~~hmfhY`r2i!s~DbYO#k$sm@{tP1(?%^Pd{$L~~ ziaZXTVys)n5E3PTfF+9LnT9V~!*MPqA$GaKP}vXlyUokX(}DZwBUZ)0yMc%k4bJi4<&hcj`J31-wW_nIU(sP@oEal-D%r1sP-em+Jt_Mi|zGV*Qt43;yxJ0 zTd|PaLx8;Zp@h0ZnFlIFB-@3_SUTr2p~HfQOj5TFQjS3(@HOIl2-rL>%Dp@J`I{*_jAUZUPjRln!gE3bIB z0&ndN1*W7@3lsq+ggW4~YOM!aK!BA#viCdBo2J9<1W@Twv?K2$a`d%7q^G)Q`Ntux z0e4fOGn%j}QG<+t#6pmh3!y2R;?;w_X>ToPH*VS05Csknm8TR`qCt#67IJA{TY6ZX z7^PcViBe;}B!G~&Jt7r+fyCqLpaX3FwV-uR2f`j7iCuP zfJ9Ee6`!*}Y}XIm7p7{QiEk#HiQp*YuMe5UfH$c$MNxPDq|}Efq5yBwII%jx!1X!s z2QCTse`CD23H9cNfJ`4D1R$jN69(g7{Rzn~L`dOYg|9c1RTLky%4!h)WBg=6Bpj6j zg)DKiA{Yi4gsVS-G8U?m89t2I5Pqr@_i>Vau^Qd16quC}1NOk z`veM25ziE1WYAyJ7XcM2UzrbFZcUS_baR;x4Q2Z$m@XL^jnWyfzA;^0oQ{H#u=P@~ z6c=MGBq6>5f-g24;aq7SoTY$DY!Eh7g9*j{B2KL+9*c0ON(C+>LsS|V^euBaHNB(? z%`qS~v=<>62{7+xtTp{=0FXL_2!hD!51S()V!nEY4wOJa{*$YxI2u5OAUd8nkx(f1 zTk?QqF0Vaibdw@qE`Y-%ghn0hc{Fx9xPi1Z6l;HCpWVDRRr-PvQ}LZZ=`xA~`g~j; z#SRKvu}=I$DIOtW6ozOE0;LfJLLs!6q+^MUwC5f%0tsUB8x0cuggTlasQAkBj^5>I+ozPULxsQqRS4dXct_m(YdLM$_QqnPiSSJf9Sww zrW1eXiS4aQikC%$<@(<~3H-VyURC3yKxMwaDs@szay2V__q$qpd~60~%xCP>&h?CK zgq1oqsqKzJgo~IN;B#XryrH4FlS-=|1&uMR)l>4s>T~92UZO?g&{5%RDysTc8`KOv zn$T6726nJfvU95Tb#1UbshvR7J5kXii-Hh+^>+A6YK z`?XdmvI-jp6Z9nN=myQm3A1y0B#P{bPjCl4YLm2vnQ~V!qo#Yhn@D*ODq3 zs6_|T&5~L$HAcny<93+9vm0G~Hw(s~PEj;HtU`8S?mTFlg@GEW0NBiiPEAjR{oBPM zX?r{hQ?p2S>#^-&?$l74yNbwF@xTjh@}&ULGd&z1-`tVjJyk^g_cC#(E?`JL=z$G= z5FB8k1}Ae)301sJ#oEG&k=*><(ro9%@Ju0H&ymH65z1!AkSTOB(6`tQ6RLl5!smK{ zE%WXB!Zc=?jFpLHD>oJ>_J!W_n=xW3CRJ<|rVS_7@-B zSwHp5vzko4zfZC996u*Hy+qC`maiDucDL+meZ8h#q_3@ID=$lydaBL5Ez2&1MGX74 zS#24an%V1fS#7V_Ne|FL*PRc2XTC=3e+KR3mt!6x>{fL+rw*sP^!2*|{kJIkJ{g$8D*BfP81XUHC9;imKy)r7hz0Ht ziH=v^A784kDlT7MmLD*r!}}0?4JIL1i(gA$y0c+^Kc~04JRghOm+Z5*dVC!gw(RV2 zH@bXXKNs(lcDY;LKQEVhH+FbmU*bPseLiph%ItP_dcNPjk2ky0>~?t$R&{$l93QVY z+vm-Tx*o9yd8sMzi8 z{rO&=E}G5j>;89et*3iO-jyYu$Ln`*`2Ew{{qJ$}?dNy&VHY|*-q-&4G(Vr;J3V{c z_xbqrNvl=srt9tv*7y2t+xE1P$JNitD4S2yy6d*@YV&)8pYQkbrd{0ZeW)$_Ri{nc zCabX9*zDKf_M=^|PZl1I`*!IjzPooC{^#fS`UWJv&&!eN=gH5;)~|rW?Pcu6YY{WG z@9i>ex4S(HE_L^HJ?gYB)?MrS{+{?f?#KQ0-)RvKo)L&UZ$51L8SOF4e6O17qZ|}di|>5TcQ)G0sbu-C-M)qi zM>&H4!!rZhZC=-IUw5|Rz7(z?vA2b}F5-sz?B2dk*RQgJvS*Rm{AFt1r#(`++icl7Ia& zsp~%M-_O_AquI~P_+{Ddl;8X4KR>^xOBY!rq0HhsVPWIZzXShwu`(5d+p=AX4*Kh=bX^L#+_hiN-~4ZiNHWBA(4cL% zD75vhI7@7o#VEy%#by!5)yEIvAR6Dv+6K;M6?W67?=sY<$Z}RbB-6%gan#$5oQTh- z#v2{Zg$>Dp&I?n`@bA|)JJ5kpnA+O|as-w3nZkRIDHGJa%lq(;C9dU!kxHUoukS}9 z$Jo+9O}=r3Nl5HDy}I6AmY=X>p3i}u)`tqV-~Ei%N1PkIuisBu7ya$*<+%-Wb3G5- zf^8Qj$yPRslh@|;hVUv|mv7gu@5iJmN{ggCZVX`F``f>t*Q~CeJ9r!Dpu4>=w(>_; z^USaMZCf{R5N@kXJ^ASLpRwhRUQOfk^0r624zZhguT58R@94$0&1jfjI8`s86o%f- z2I&0u>pMxeK{V1e#JebaS%vYe?GKtAnpqkB7{BJ=0gw&K#hkzO9jc#S`e#sEobs8dt>7hZa+dIX= zHR+pqyqtLL6NSjkf5%glquP%vZtU0KuMIZwpL85*ziMwK1aaLHlU01z2Z-RN>(AY$ zO;=fAJxMtAs?PIW*RICp5Gh&147}2P>3iwQ{OD;5^GPs!6y+n#OZ%o?ZjM07(G+vv zvP3_tG(-xrtDfLSU+cLEM#E0(@mY_Q#`&xPUcn2>`n>wqVP*SBe*`x4H&MmpV~@n( zg(Ha0#=aBlw%H3?wsi^Avz~~Vj!o@X^*87Fxvde`!|yXltu>qSumrOQdD}Dmj=BL& z7h%ro;anPd@46|IkKIthQYtoXH{ZF#dN5|*rH^zxC!t-YP5WpOEXh;-`x7GZgB5pP zbow~0v8K^DmC*Yx+_%`j=GaoF)?bc}rSZnyt7(pU?U0iitJdt@Uybl+20E7ZNeyhhL3KRtr_#vk zzACmx$})|>#Mk>S<#qnW(k=f^Yi zYbW6QQ4}WRcfi052ON$Mb~gVK3*UNd@bo>xcRaBZ#>Vu_lEUKt4k;M7p`+BF`-$1y zt;zORSXAE)+hqS5w3Z13^GJHf~P8`r)TKkH7{H+^ST{`9S8 zy(4yflMgmYlpijWfCJ<_-_QFl@4cX1Jg2(Ob~&n={Fs^cX=`8)3@#4&Ie?cc;j z?#&(DIcE{qZ&q;|X}suS_4gK0iaS10Pvl{u#FEDvuaeX1Egml8gK@T*7M|^Io zEM6SZ4Tsfh{Y5Q7I^X4lRsGd4+csY3ukSe-6^+KwaBmY(`uQJNO^HAfnkLO{=_^{$ z2xYDm)2cpPxbR1?P5U*r1T6;x*DG4~g2&Y3K7MXKyCtX!< zRaa$mo`yZpzg_6#6OlRxNUAJaM2Ir4=EH#Cx!P=smP(NUibJiZ5wT-#LBH6!!*JMx z0@W-v*2ZL?-l2saQFxhobK*r8i9fxz;}` z?is4hj$mnfSIdW^9@`tJ^3v5A%|Ro<>*oB-_xrxad{4njU$=O7(kk-NA>U1Sk^3xK z%8u(L)K-zZKnEzJ7Ve{F!3YP|KJ5EIZLE8|Sx@*GiD3^Nr!L4%+|H-W7>HhGHJ5Cc zcKPGs33#A3Z%PE2#>DFLc{l7KF_68?v~+_Kz`E@l@W|A+V?$oxH6Jjw?NWeNjsdRv zGDDF1wf1*$YzW{rq8*0^ka}(pdD961Z6)Fw25A7kF)NT)<~>So;hV|c7C86grJGXw zjs0{39|~AA4(?e3z$>U3AdLbae{~X|)&8pNjU1+!pthntUxFT%VID09D5V8K)ppT? zy~B%BGaw?Ana`r}08GAth?U4_mG0Jmigne4>K+U2laFCEe`UyX16oc3i=2cQvhpDH zvt*=w;ualYEdV>j(%@)vkH!&K0%~}y5uvn_nF-*o0#>3^4NZmJ4d+#SM*>RzCdZfJ z9Q?IpQ1k3-8;nn=YbX49!n@wVcDD0HLOn2@xL#&c3L&3b2DnCnt)%pT8WrKB-)rzxS? z=gtAHYz~JENV=G+J_UXL^wwHRoslw#7E;<{1Q0)+TY}$FAKaTtfwACkxKLY#6|)tD z^WUn+YG7Rt#F`bj;OrUswD{}~9U$#2O|voKoLv1mNx2ZhKJf<|<|DNOWtduFT}}+D zh6^~3BP*E;7IKU!aV0hh4~1u40t-bf`e*61%VfZ;ucsRfd$E9lV7wHsd(o{I1p3 zcV4WZsjXBd8S#`e6j$59DoJ`I=7T9UP9j3prFRyDCXtRPdv^BVh%2fIkjxvC{N!w_ke(X*;ta$M!2$S)e3u0 z#D}yQfp2>ii5~thiW-~;Rv54&ODM~o4@pB28S@WH6H7f3Ol`Elqovssd=J^bJxU00 z?QIWO1;Ps55`;7+Qk1$C_E2Q!;_quEl~SZR0JVKse-|X)6#~P!G}R0M_3o=K?^O4R za$YfeKMOFsvpa1>WrAu84`&#jEDGlvP@I?DUBI4km6KK7%fTePaB-K6#3L~X_>KHK ziJSyiC=J}IfvF~d)FA0++_%DXl-8AdY$Xq^(I>_f0sYh`y#mk^ZHByVLMXbdPe*^fO`-U!kzRkAfPY;3p8_MDG(p^+ho}ixn57N)N+2cMeFe0Vh z!5qQ6&2HI>c2M0;#h>y7r@8<;I@GIt06iS=T*j+6)O2otkd|?hp`mTz>nMzehNVmI zsCnT7-)*^e&9D5H4R1@)85s9Ual{ifD7rr>3-pNu(k!b`OTSq66PZW` zs)Br{Jn)+eT;h666H!CpJX~@~-6-dqygST9LWn5|haCiLV+7$5bef)9{1kH5Fb6Gi zzY3?td?qm;8Y~Ggw0~<8yh?D28k`5ErmrzMS61pm+(ZmAuT~Ip)`u6)6DtbW*>ON> zy_u|T2Lx1yXI@pjJbtG@l9_kkX{Pp87qiLxLY$_dj!DhJaauFCzA^U;8VvqvyX0;@%X#*A0z-06hWrr+ zK^jC~ZbrQ<+_^YTE#^ZQIE9KBb(OtfnR!a6<2X#LZiOr8UIoIHB(9%)y!K|c2q(zi zu-A&Du4v;rAkgvyDSH@G**Juxt2*#Q%E=1m!=lIz598bLiIy=>D%w_ zetAy-cD}BIGVk&5$hJ{5n>mk`mHgC6`?R^CY`ajC^L6!{xO)Z%=5|;D)s;`JeBHWS zUxm!7kx`LhGttSX;y0@UjB-+Pl}JxbT1sYKAVP8$tDHIJIg4&qN8fP?4*la2mq#@^ z5wN~Gu%Gmeyiv-g!LRP`Oa{dh`!8<3*!2&nh>P+GixCGXk}!YB%%wXq{4UW#o5!FE9uAV`%N6KP^U#96VXSRSN;ll0&|OnGLJ z!vW;FTg%8;CFiBYYlriLA#A(Lkm^Vd-DxzcALsV61?FE}h|_c4?pb`9-h9hz6fdTHXm zZNW|v@A;T@-o)1_04en#kOaW|V8j*!$g9|tz=)=_rK!fLKXPS72I1cN4TM(y^!&wa z86>LrlqpPpUe(^1Ve8A6&Tq$atr2vvb*{Rk(R_bPMF~>cF`wE!c0bpE3d@ zeV72pzejMy_Yn}WO2(G>U$|>+_L)Vxs4kvJ<%Mgo|1`(&xOh+TPK0^Q}7|R+gHPtqWc!7 zUrO-|_G0rFBa6PQiD~y<%oN7bpGRgoh~7@q%<{}k2(<=n%mp!bh1WfhqsAo*CbUU- z+IZ~@mQo00l?^K7Jgn7KT(du!omRm&ThVahmsmbHHLxw0@8T91<|&XRilDpz);2p# zhO>LBt@P$WsZJ`wA6DOr!o0${Qmj26bAX(#zTfk&AV=1Njk2i79pal007og5#%AZA z1wo~)K~o*V2uX?OnDLuCEpLd@=>ByCbAae(2B9q1a@@W@fC|*e;~^*x0^gz}oB}Z= zPBIKZdr&H97-g>%4nQkBPs3d0pSk|1Zr1;K$k}3QsRbe#uh~m3xIo<$Ikeg0tnOdO zIiqRmHUl~Be>>R|f5;>j;_?{;(zH@NzX3a`K*QKR+-;f&qj0IshsRW3lBQeFPaQQ@ z=Qq?gJ=^~g`&7D0dF!mOq?PX!6}70wQk9r-G+QJ^IhGcse65`GWZv83;ES)66+>Z8 zK#f}Bg7LEV$}znI^r_#33HXWyIcmyp!iw9L z7_eLMow~h{6%$u&P34z`GQJF){7$}lHQmpdYh7^Gaj_n<=-{>kQ*L~#l({0YxS-T@^FH~_9vVQMA&3GY}* zoRORQ)R0mdff|KgMd~=xczZb4xxn3@t~R_?1LUl8j$QaTel$^xTCLS(1Y(p)m`((K zEG}z)%Gh>I$rJD>#cV)q>WR|D*=+3bfnGMB>nMD4{r5$wF`PRJC*pUNgXng)NNG2g zaO6m%VEfL+lhp-s+5H+b8IV~B)JZ9-d4zAGuA;RKiGc2G#P%?4^Iog1*Q3}y2jL++ zk4xv25&`LTm|zo^PQZ_9y30bf4_JB}7zJkQ405TAIM;LnYq*s219wzyky|N(=#uRV zXD1VFx|5=y?7h>t;Hu(xiqzP`b6+HqVo<@H<}j5fZxhULo|*&Od3m}g{WaYA>P{u- zG;cKedyZ!d&HGtWAWaV~iIj5U=5Bze2iv>% z#7THgvFc2*gc_fetDsyTXRI>T2K6$)2~Cd?yPd$twg8+w<1kfw^4{nqy82+q zfBXG6TXXB)AE1@mO#@6iV9Yj-`3uz-L`|z-jZD+OB500}U31lTP|%a>fxM&oe<4$m zt$c4wNR{#$g)~2vO}#cq(W=x)fd)d4Sp$c#tl>_nJnrqTWjlO?7FpYn{UTHv>vEXk z%J{~n|KDg$H5E@YXmoj{ZUdZ2-+=YCdmD$`#a$;=i73V#__v0=jiHnz&)oFH20{;5hH7!Q*VjSRzk`2wf@G2{dK-PFGu*@=`+{?|4UWc`{Q%K-FD1LUT`FomaTtbK&3Z%pvi z6^~-ZQm5J#xbwKcKL@+!CFgjj<3?=eFn;iC4$w)aC1tWrO1gSWH^b0&V<7*I^5yfD zL4nU+Ahw19K4A)tV$EtZKzPQOyqDsS?Hj(XNl@snjY2aoVp^T^~g1wb>6X*Qg#{E zCI#FUV0RoWN`f$FEjtAV+v>gs{1glhivc^amr>!cAGgfASWXmi!)EFS5UR3vbU_r^(jf&-kINGrS2$X%WE?G{Mx@0$i(7)Fz)kxFdQMovpkllc z=&piLX$x@dp2ny0l?eeL91enutzOd%r2*|}=Dn}^j_0^2x0MjfM2s0O*%510m#eRm zpiQQd5;JpJjrY{-{OJU1d@!}S`F@%HZ6JVjCjDBMv)39)Od~JM9v&Pr(s0?HJV%@w ztF7d(E67xtoR#Gs2j!uOROwzwTF}yPLJro?gwwX`3oyS<7MmcpyS*x%~9h6-bEIM(QNB`%&>yHx%q2;gEsF4$h89e6^TB1 zigk_TI(LmV8~RVO;SVk-s-S@cS0#pDjD3CywFT8Sybf<(MLn1zVaGc6m#IEM1Hn+F5A@#*DdM_k_AQTA=txkLQ( zxSZ;=FPocjmt9X%OiQV&w(~?Jh4N0A>RgzvTP>`*B<5{@gqvxa1;MT$0ZTgKx55fT zh7f%D1m;X$-5jbcIV~J><`Im|rH}t47CZojTZfZ0>|S{VMo8;TR%2tYwCl!2(yaSO z!jLqMs05Z6wGaHMZcFMPKop_`BXc-oe0k?xrGwRx1ZxRMfe-96nogi;Bg<%7HG!oA zLvuqSVdKs=_&@?}qXT=vYBWi{mXx7GQi=5w+o|!HH~ z+ZuS-G8T(X#a-RXCyD?GJ59W$7)5FLro|^34prT6SI|l}^gb7ei4;Qnr%i!(4q{?2 zGg*?mWS|gvq@PliZB&WeRRa@S@EFw%kpW%J40$Fad5ZCQ8j6GnZc41@Bi9jX5?k>r+@Em4V5Md3Dt7&1LIh;d+rYU0%a%NmkJ1j;z ziDfEf5YWOwwF=8NBr&9j>O?s|Ssm;^fdqW)A*qvYu6Qs;hX-ELGTh!Q9J^|%j{CHx zOr&+~12<+s6N&8_a=d~fN>(l`2ZbLug4L>t6)ZPC%P}vAvsif){35fbtkw?ju%L$w zuE=~M=X~SD}hzT)0*yxr9r(X6QuxBu);!+bZ8Y;*0fDSFr#sm+&i}p z<2g8UbZ*4f?xGJ#q4gXBWMfQzn3GGdIXOLVz*E*B2DVo(nNS|fKZ+1pk?)zzlyiTo*n zQZXxfm<|J@Wb|QExaLAm(rCx{Mr^G`u`;oG^&yahCPbY&_>c``O_qQJ;Q=9MZ{dZzS!_U zuMxnzyAUF5`9pyTF=r0gDnTy{E%aVp(GQ9gRmG8Us(*?p<|F zt^M+X^1I$>lJrkmM6C2(USw_X>vIZNOSC#19gi6AAXUT>?eYLeR6#eya79;R&QzwV zRbbLnkz4d2B8Ej*E;3FWN*GXVfBL*wL5`5R{Cz>Q87m&R#FBDS3rh!Ypk$gGYBb#X#!azSev6abSCfT-){nenj)m7yb2ScsW38?wNL$o5t`P*`gpq-VNrAX^UMzYkHdEbS)C99i>cg+vL5 zRlC2&CTw{VjPeT0B_Y|B8a?3^Cxa6`tio~ziBCke)W;v*)qBE@V#$x3+(rSj1|Gw}M};9()U!JiFPr-K`Vs(dtQoCX&La7;o9K;rTu?qvO> z-ec7Iknu9|klVAEJvH?b+$P!mGZ=$}lQ=!f`o<`guxzLr|467B8BF1Aw|Y z+Ka-DCAx@1K%r{ccXhdUewPD&s~G%?4UL~WG7^(hFrovJ?z5qUX=q4^%$Ns~B&9)G>wg7-N3>Rbyqcg^Y^i5eYW6K*#1gLal z(!0>!G9Gu0=DQ)Vr7@_v%n97Bj5xcu70+R_Sh+)omm?Sl6h+);uIBBWq%47aqnkVm z#jazCv@mex+yhi^`g8&@1jUX4mu3{8o0Kg(C z2rNfIc=Ss(I1mKMS;v}E?oisC(#rCqCoU93-6|r$HR4ioc+42Y3L*gJJ?Tf>$Y|S9rkDwTnX~v4+#o`y26(K-EWy)xz;Ak3(WB#* z{+hotc{I5-dbI5|w+xCV8)^qO=n3Fo>C@CN@)PpKXsKD59Nu6rho6c|L`=pFs#swF zIdwivi4Edvqng%glKs09z$ih!t+0u<9+U2^%$hsQYHqdLJeWB}X%qv>>hv@{`f`QL zH0Fa|Q`Z9jJEt7IhP- zP)dMG=wftq8%;pYbEjtF4&lI{Lx>};`B@qkVzt5HCi`Fk5r~WU!^8P4nT4H5%gkPg zF~!yuQc!TL{SaATN9q|x;2`0QTs1w$wVWW0O*BVP>dHaX_(fuq4BfTpfGvydVWfv@ z`CpQP>lRV}!rEvvHO9z7Y+SY5)*3<%? z1#1Z!3@*x!JLDiEH#k9nD_IiNPRw(_QD!wj2u$TOPB$)zUv#k6F;~NCjhIDqK7Hkg z#T0G&n>B7_3G%rKny-!rCCWBn>kXFmRwRGOq6Tg_1`f^8HEi&2F&RKWl);d<<4dg<5=b!adXUnRfxoJXl8` z${0bT%_4ETm)56Em=k2`k0t(*m|d$>Blxfco^7pVgzlmKIYPS1nvGK(79>IH2WIZ3 zJ+EO>t-a_BZdtPxtO6`JGv`?jfy~e{z#wN;9&bef>}b4!M@-W!HrJ@vfqNr=QzOcx zQ!2)?_yx@I7X8qeK5?W+q-AN`UBzLSGNkJ-h?+LRozyYgolury0F=5U1F38q@67n% zK=zG_yetxrWJ05#Q;5Lolb1TY8{PW-6M~F=v9aXP_U9@K6l*Qm4YwSRv1P_uf8K~F z^l2j*C>24(gtBx4fu=6wJu^C0B)8E~+Cx0eU6T1vu)=gGFnJ^_Lbc&avE)s;TXyL@ z>;XNG8TO&q0mxvR)bP`9thFjNJK_B&vem9eg(ASt)TEg6a$V)Hd#3fL^Eb8G2|*|+ zGKH!ZK4{gT!jfbN@#k;dxIvw%9^D>`l+LEhg_i#jN2ZaN3oL*F?%m(_@`e1q}S+GcqfSAAHe-rj;*?tm_)zxMQ zOOze<;tf+GLmtEHKPW!OKo0YfvaGbJ?gn~57HhXNOU1b)vE76sJgoNq%F3^Jq)TAMfg0- z^r2JnFFV80Ji-^#smQko9u!x7byzRtck8eN z@{0?ThD(+utfVXt2AJS*pdL5w#Y&qJ9u+yHdTI}YNK`6Vk*l9nm>yf3T45nLwi|xm z>!O||*(ju7Eo@N~QiC^WzoxIULLd`f0d^Jj8~i%qGjUxGN}6?1MK|jfi(|b#y@m86 z5Yveen*E7_rW)*?0oCfjkRULUh?;E6cHr6bXJG^gJmTUq)33kSw(G_o5AyvHdxsVo z?O(n9rh8#w;F%iUmM3i~xoRBtZtKKgYePUewCu=waI`TeO~=3PV`xngVz4A@TlDKf zL@IC9x*(C9gTo}eGu&e=5KX$=*ekFeq_|Y_NQYsHO>j_?`Q^)ST=m~c78I8$#L=V~ z@$ZA@0I2oftz2Q`_q>nH1qgHBSM0+^qGd{Bi;lRGIHets?RT%$*4kEzwOb)S|4& zMVj72_K%6M73Clk{D4T8jum!}>PV3wrTqD*V-ue-li*lMt(if#LC)wrqeWY_*%MBi zMg$fRlc)W}t{*vW&0dTwo5Pp+r5mlOZ8mLo9 zOb`Ok=4Cn#ZZ+1_R~*v))JKgjFi5NyE#~p$*~3_<91M3Em0*Yb@Xrxudd=U8gUY28 z(6o)!9l}F#!Q?j~NFLZqh99QGG7Q5dHcub~9Irc3=P>3FaQ9T7%@V(+BJXP&x>YNs zFB);(XTrzLe;EHb=`P8@$j4U{m&R>=e7x1}nVg%z%jIJKEWJ-0{`Ug;rLig(l^tk1 z8erl6DHFkYO~jASoxtA}*6L&MvgO^>V|tmo-wk5D9x()l$nyxY#wZ#QpOv*g+(VK9 zGA8;c9~h$b0cr+#8)$zmbqC6j9BqK5zb(2!t!tl5D z1~BA6qr5_BxI^IE=X_X!whc7e>kB$8Xl75SBi-8Ayoy4SEgVub(T2!uu<8Y6p5$ z{3t=?Z(`Lruhs~F`#oBNd-|lR!ztYd?{?CmJ&3D0m{_JIFhTRTL|Y1t$yTt-G6om+yuW8ADQ# zJMo0sPn50{7-cYlSXM+%F-|-HIb}Cq^3O|dUo4pKEAjq#bYCY)S%53CRQfSNq(kY}Te&~2SKU4w*^YhlGid`FVMLZ37 zWo}1QPJAsglS&}zJz00YZixX{`l2LDwllO^#QFIf6q{u~GEwDzD{*&g=W2x-q|ZjK z9}eb4rFmzy8YoXe&cB1Tjv{HGYhQ5Rs{K$$8jywVE9W#e!s<>s6pOrwEXf;;vSaW0 zF994qPffO!BFWxnRx=#k5CD!dBr9?5aWKA4DgYNedpVeO(@(It92>^C?vE35uuit= zWYyFL>d{r67Iw}R_9&jdiJ+P+=c&sFMohz#d|*~2?Pg7u%|r%%Ob3e4E%O_cI$(!; zViEPJ=|KKcw=5v11S~bcg0Qq0QZoonwIIdBgggj)^J=$C4nX#<-$Z@&r0{68n2+D7 z$^n@83}R^3KZ4TGtrA^{^Eh9fp)#h!6NXda)N6@%VMZ5|f=0GJP2*}EJltO`<}ipw z9FG)wHB7e<=~44U)u*PqKaT+5t--jULJk<1IOt9$Ug^-8;R^|)4=~WTN+`hxteOQB z%q+Ga-B1^B#?(|fYp+qGtqCOhpf?-VeSvjtR zxika=>)VeQb6fyIG5MIV@2@J_OsqB!&bdT!Fko4iP1-7$19hh0nNas8KEMZYof@l1 zOfmO?Z+yWJ3zL?BbisvT7Qi$5e6^3Vo~-yPs8iYg_XEMoT!W6ZQ{n|s00{Xn)?*8w zgN9b4qCW#v>LioKxFsJ3$5uuM2^s`Uo@a%_LPvPTEXjS;*+04mc{)M9^)M-io1PzG zS?eHaT5Y%P_(husenli46ke6VFB*Z-Ua+K(Ro0SYl!8B&)L|Ng-9WarN4!?aZ(Hvh z7g|8q-ybqRLCKE+DG6jMw5HESZT)rS)D+iWMNZ-0J|;VS!XIMHQOh#LHC~&-LlJKE z8K?NPR$OKFNX-d@ku3)OL1%HQ{zw^oOI2EWelEgmC?@VYit?r@J%2#U#nu^_wzylF zyiONfE4pyNi8V&MSn2f~5os2gBuqzH!2Kn2Y$}wx0%;#oa=&IWE^D=hTT<^>B|pG| zJ3`@!d=x>I%r;zYuGojX<#cO<#ggQ-1gzP{LjlxYhc1}w;f)YS^^M?ED#}%X*0Ry( zusF59y7I%M{CWcUfi^@k#Kvhb2fcr|3+ee=7x>)%QZWvciim(`FVMn9GvD}0eS&#T zBi%0mA#|f~uyqFh69t^#J#-Yd_yd@=j%L4*CoS}cloF2{fgd)>gjKPO6*mttmw_0XN#BE6W*XQ>fL$XO z9h{{4Ef1);zaCmxTZh9^1jx#`O%)B73nq;B#APg&IDlgaF9reVKzM5ikyA4QOHZJm z^ii6xDCBA!Lfk&Ni0JO`3-u~JiQ*#bNOquuB=VtDfq=exGLZ}cN+VPPfPtow*IO&R zqQVqe%>6;BJ4)kuQ`k20#D|93EO@@f)2I}|CXZGI$GC)5n$N{ z<9^fZ_6;u>XLvy(T^KT6P-|a7v86VuxAeDOs44M&T{fzn%T6~D@SMV}i`Jn2CLn`{ zK}gZ~nXm)g!LKtv7_)F(&NIb|CQj=dfZ|<9T*sbv={6WcqhP;2?@wQ2!cI4&Ex_b zuo*=CkI+|V%``XYb#6Y#tCm{N&?mj7Ze^!FOe2#Z=k(hy7j`b3O}U01v8ZACT1nKmoJ0uf z5L&RzCMR~sj6kOTbrro zOOr^ZWEjw;RN#~SSCT9`DCihzT$BDVLOLHKVY(y%6jc(;ff?7p*iW2N0ZPq{{ek## zobKp27@}!(g|+z~^t@C+NUSu!ICY%P*_sY7Bk=5MnlM&T*xXP8jlWd@IMy~A+G!{! z63A+RoXt)hm}jPgU&F&=J5Y1szUA9{%!s5k4PbB`#)Y@O6g&IrO2!Q@)B?53`j}}L zIuZiNPJ1U8RtEY2y@0Kduwt}W+((JvVAP;8e2krTbEy#$qkU~$ON3mw_}MgRT^@Ip zmT)Wt6|Z4dz(1zZVi?x++3|mZ@`z%6K+iu)_MI{f5P)?l+@%xr3MNeP%^D%$1+_wbbc8IQ97hEDQQ1&}ueWq5e` zn3Q(833SjAxbvbY-WRn8Fq*umoB+RY5#~3Mwd$CCE(mq{m>0`!CGTYr$lM{i^x)#loDzj}g{T25hfZRF+=|@_um7L7y{AXyi#DpvP@^d{9WWm>I#@#gO z$ZO6FUZ$28^JA8m_zY=u1pu%|TQFdz@R3OX#ZmUV85=^hj6sj2i_(F9M{AV4wLpZJ zAjb3D)}xmoS<#i%> zi{|k?MKDo-6lJ_7qG4^A)cEk!9W?x8Fhloi5ugK>^$Y?|_#>vpiu&W8**maf60vij zkvyTVMFdg>2R0gbVEsfqLhH_0ak2g+-wfpZM6v%gu=YXcC*6W5^{JPFp&#u3IIK&k zUk%!i6(J+7=EZskI7Mp-44d<53{VO@CWNqcZi+q=wpGgqjC29c1xvBSMJwM2yj zz{ND<<+=mhGs5kqy#ifUkRlOSXYirM8O~G@Og{fc5Kc_9PKy9eafDRVr@`LFe(kFH zBLozU(#Qb*D&mf1NJKry?h%ct&l~`pPCs-*P?v_0M6Pdu)8rG|zs=<^lZXs`gkmmp z))L5=Dxv`9FY1Szz)nT6`$!!CLP0DOVsLYgjq=^qM=Pq#n)@lc30TtAheht@NY&0` zp%x$U?Q@6p)&Ou3W*Y4HWcV$22&aB%$`o*8(G+H;hFh@gOP_JS&3a-i4AsEj2=3*4 zpuK@>$~LnQP8kP^hz$Aix7Kf|j8wG&GwWGOsA7+CK23Kc1gTqMWqDq|azj$IHItDm zf<$n~Jg^DCY#Ta;B8r&#zlFcAYCN%lHcS!f#6;cAO|^uMc;=JFmU3KPkSq|6j_}>+wGWXF%0Vx6XHJzwu=ViR!sKne?LGSl*?aUf=}iPn1F)2!%f757iqweYP>xkdo+@(KRL zL{QFB;(D-+)ZO#WNJ03|;b?;ZL;ADHt9+s6n(C|x7W)SwKs&M<_0g-#L>N(1vY;^*LbwIvt`ey;r8oz6mhpu|6F zq=P-{D#_q5t@L+9&yw)xS4!tYG%ChW$h#&VVKs9^vHB>gygn4-FgFF6-8XrrJ;B{CeF#qq;EI(YAgg+CKIPPYvZ-GAgwIRo@8u!vLzI z0CINO!5jhZ#u*{YJx$bwi;bK}plI)cb7etzz-_Qh*FJwOOuy6yd{ypp3wGmxgf4Wk zw`w#B#6j4nXP1gbbclENt9tQ0fb_{WAne|o(n5oa!tC%tI5Lqb_7mG|?a`|A>9?RSJq4zXwAUrEP1esz#nn zI&*Jmu@{0}SVR#PFy!+Q0%>@vBoJjiXf9hGac8I|!wpk4OIhl9({gmDcU!s5EO=(X zblVR?0~)ScIrG5_;#tzt3^0gD%!QaZSHO=Nxfz-|@I6EIsR|rnR8`nis=3#IX!<~v zNVi*|D7u|^EJ#V8X^?qO8)I@_2Iv- zy)YBN`1uN#RUV9!0Vm&DWJsS49?TSkl`&SGay9m|i=fXP%qaNhgzrFBa7g45460 zahIStd(e=tx{-PBt{VKs#ngqyuQmQ#eKRPuz?Be^6@>*K8FE3R?Rm_+S^srf*F(Ws zviAO3zlJsFJRe6>xWH8jRPFHSpIc{;f=RRR7^aXFp=AcR;PpyQT^dy&>nQE}@VNNV zRW-=N&oFkYt3oQ}lAD^IOXTAFAfG(JXim(6ay$k*U#n!{#B;aU@pMy5?}lmMtM!`; zcJp=)ap@BZNTjg$P=n=`+E3#EA=2Pi_XSc=dJ{Ugpx+=%D@E2pI^>wgO%*%Y8iq>o z^*vj@8R`7_kMt-#@E=`ZQ~&^B-~aN7VEuooc3Vg6*5;9&opc}Ytuts&S1YK0!v^S> z8#rPKIMe@Puqn!KD&c5qsb$F(g%o8M5G1^m0W2)mRR;2?M+=K8hFHaJIxp{#}uwktnI0aQg5zK zOzosu54J@IRaw5&?i0D$8Zfq_s<)H=v%5y!6)yIluMmaWlEjV7?f#3sHtx(H-u=Wb z*INg6ESjIIu21Wp*VYrc*opbm-K)m!&b?Rfo81%BZZh{B@%R!^BSB+I1v0s!YaB45 zpH|%TN2QP=&haP;Y0X12xq$c|44*7L6(JEl)NiI9y3pL3<9WXB9Bt|q!uN24uUU`f z#BZ@jrXPZ*F%O!^_@~4TA-yQR=m`(bA4oc}!OZt+k&lDp`tMP`l*YZ@3AV)8c(Uvt z)|<9-52MDw0y-uFq{C4u-aWayqleHV-3g1^O!OPPZeI6~)6a?~q_1OpmR)S$?#NM= zk1VL)g0vaA?Ob19hxhXj$Cs~Bn}}y*L3?IB+myv^;~d0^Ab9UZ@l;-@lywK=MXY+5M(uzol^9lqY;Csj)qHK31$3 zN0FfAmJHuCsE2Ybv0 zFv8n9N&9Gp*8UI}70zKJ)yFzCq|Z z9st--Iegu1=9eG0Z?l7EpDz4CbSJ&CCB1*Tu%;&UzJfRKGuA>J`_fX`@)pb-95n9)rH+&w%TS?26F?=F0&YI^IxymTVI<>KT35GhLuX}+R9QxGz)m<^D+ou>%Dw${|BoT45*iqZ1u?N-P0EIvL{REJbQRX9`FIhh?DE!fT3Y9Q51${{88! zvoX;(!6&!Zt>{BSpl?bsesc44^qzqtF+os5=ZCBn4<(qN*ZeD&bJkb;AlCL16-RAx zoR>hI6lj?NlS|_uX1I$?OiYja!q8Ns!MCV_gqmjoOX3Z8Q37fY|Gvu4QW7a$g_lqH z2_T-M-z*v6^j>hBdeRXUHEO(h4CaG29u_%s8G*6rJ?^ zPscy`2>)_zA*2Av#XjCFNP==0K>x-1R&8*UeO_@%*Hqt{nP#N6{W1kq!4pP9qlAi~AY6Mq;bbw9Bk*+tDab9hyv#9fHwB>* z8t8?~CVJ93V)WMzX_V-ug%e`zqlfH@On%ga+e+mObr|IH!bKLrV(DfID3LJHBOtn) zPeIW+U>GBi5aH&oPhRp&6zpah(OW}lQlQA;Oe&p8Qp+Pm%K}!`9;1Tn$+H5pZ^mnc zPMCrSWG*OaVsb@6xfJ3Kh$c6>!yKy=PZ(3zG3+XNPJfp6h)Q5==Mh|$Di?z z{svYF#86AsbAA0{fLhEnx1S>1&;=i>_(}v$%A_>#YtknSq{}?jFLn8~JkTCryAoTT z9zr9dLy%L+TL;g-Z}#LEr~EKLHdF;Om*IH74#jg2V_>cl7{Q2pby`OY?9k4mI!q7> z{!@@I!`$|Ou%g;J>h<`-P?txldy~Jw?P=7EjnDFAB<~Rt27G>HMwBvO`88`@9AuMl z1(P*FDdb3-elAp5qTr!Bsf5A;KAk;SE;4e2u#j(G1OMu)?B5euUUz_ZVW0%*ga&Wo zS$_<)f(e*S1sg{4;eZre-^lE;U4^DPSiajBGiQ7-vWkEt`r@)=GOT=sm#5cnZ-iy^ zdx|BrT(N^okneR|C5QLRJfdvOaB;8mc~EXoWlHd@INSloYUs+yh||1wlip0DX~+ z1Te#A0p;P5B4$wuZ%iz$6g2osU6kIF9W4OOp>`iQ4>hm4U7K^c)n{vHfEIz(eXv%y$bF}U%jxK@_J693 zR(1Al$@DbGOHjfS^pQX_E-yr^=}=kQZO?;4*7s4GAz&rqMk!b4PeczSiBB|jN=}h6 zl2Vd1pe%^+EqtS(iR#wN(IkcR^*_=w`NoD3BZdazmv|GMHhn2Vd1DIh&5`lRmLJFiU9eB0O9-8<0zz|4G ztx!sv_?6#qrkCAjq?Kwz&8Y^gp822=n6!EmA(Ky=%Jxb&O7ZD^x&h`ZES4QFnroi} z{kB5l{73J<+nxb;zJP#qFz?7fyb&NMAts+;{Ltv_7ED}lZO__YT_EnZl%u{&zmOJC zql_7asHFMRYuv3+VyXn^_+!z2&j=EXUNk4iz~b){igUN)f|$-veW>RScw&^_&S!El z26F7|mzXn5Cz#i^HUrW0(WDo{Ps0`i9qcqPxv{P7dw@l-7Q0@7lKe&q0vnUZneG~p z_vfNWVRo)UtR1w2f!2k;EJ1v$rHilv+WV_>!@Iz9HmFH zNO=XR!^jEA%kuAeJ7S-lHlC9b7Oy*>v^N*RI?{MZSv_2EMyN>s5(LV0mQf}Y8eNPa zU{D*Z8I*+S)fPE(;K^h-V#-WgAgnYqL1N(-rnb)Rl~)3i{-z(d0Il*rXmHi?MQ$xW zWpbw-`w$G2o8hb}6LPWrf=^Q#amh4kdOBm&*Th>lVR6L;2#T-;o52o4`4UpEg#bAR z_`F)x`ZS)f)SnY#W7PSdp%C~0Sf!3^lz4sBs4 zm?sZBp^EEZM^*iQ*5wu1Ef80wva|6YCgmF5Hk%#)i$<*QA1qcPvy(`${ z^~<071<&igyDK&8P~9#EAr`ZR`sLNph`Bd<<^saxIY|&1Bo}c9pTDui-5Bzx!;vi_ z)v-t>^rIF7U_SkT;x-ow@!F`tX{}v*s?X~@*8NoSb~`ITHu@#xa8+6ReYn!qJ%A2F zj4th^%erdPjjAqXJto%J@X?p>{HYM84F-s(?J%97(uoT-aU4N0+YO*#fS?qvATvj^ zuy#Ac%@0%jgufAm=XF$o8|#Bmxo8&Q|MEvMBYDRSM5uFe1pd>AVZ7v1TJ2&(wgLKz_f`YGEHB|0HqDQ^G+ zS0zMd?BD)xOTr!ZeYv_=peHS-7QO+~cdIgGXPv`v$D^5TO+! z;U@zvy&YJ50y{o1jIccP$Ym9-m1wwrpUQ`o1j)b3U~e$RJEeINz#|6W+JFzbZ*emA z-8Ji0;lHs_<#oJ!&jGU7T^LW!aNL9LYP==Z$e9Zc@2u>_lIt?qi1cJwf3A+A9x*fs z!+SU=Nl~ROW>KC771*SiC>5p8#7JgiH9fsXlKrGtb8i-jo=<$65|2mT!l!lFRwS2( z|8SvK>2Gz9`D`6iSGN_&M*H5-Oero?(OB+TWg0P z@@asgj{dd5TA^v(DtJY=@aqgX1Z)(FQoy}GSyy5CN6T?Th|+1Uo{ISi zTNC!{4Zdly{K1Eomf%X>v;1mfAo=UH8Jd~zX z7I}BN_dtam|uM2uuv@_ z^M)1{`MAahMAt{ngm>d;w9zpGgI_#7bsfjc(1sG4i!>R-DAJvc2PnxbUCG?H5HyT8 z{dYxH`-3Y2Km;WC_?GHin8NFHFpzcvkheIMACJ&JpM@GpuMXq(Ftpg=f&{WbyIU%K zpch4nBO5qEb~`X6mx$Th7l10)kTFjfO-3H2Q<6R7=0(Z+|2}ri8$vXwjj^Bz(ihgb zSmoe(Sr3Hik+b5GJoDOuYArIa-yDu#aUj4e-aH-wn4m5>kQb~>Rf{fd8wsH}Ru-YU zZ2V;T8AQP4Xz`olRRy6{W;C*6yL+apzPi0;G|+*gLp}p2ea5~IrsC+fO$5TAzYb|p zKJq)7+)Otuxv<}E7U91Ya$4xUIZ*H*d@pYTE|I)mMWI_ny;F(9Z(ZN18Oni_aW{0} z;)`U%xX){#lwi!AK@#CUd_G+j9R>Rv<rkkmA3o+~|pUuxHvCynRw*2KHR=0|c z$~dhsWMc&&s+6S~&$r;XySi+2(@=M{0TIT{FY}dhPXht!`-O53Ei`FT3B>6xvRbd;Kh2P@UauJy(%4srcbk!iJI*@HG^04o zWxooZP-Zm=SK`!IdMcbtK@b7T%+3(y;O9;`PUV2;`o6+81fqlCAx zlZ9g?xFmi&wc-OHArNTEE=hUVb1h1f>(}@3c79v}ZT-9*c&)U{-4jluf$RLqvmw)n zYLw_`<2l_IRrr@%8$#jpRgf7lUGkY$nC5M)vMU4*S4bjTnX7yj1Xp#6&V%H2Q zuEb#MQHW+`{5yn#pHL741_En4IN#fHC|*Y6(DLr8*eVzL*JSn{b3Eync`Md!Vzn)e zY%Wt8WO;JP*Tr7t_uE=!etNHEihA;HhLGIqc~uVMn4PtOb&cu>lXfG8)1XSubn5vh6|k;Jwo=%LYomf=!u>7JNf3=zRaPP!t+}!BSR%v{?Unxd z#wNMBZPU8{b}_75qZm%^*WZhcO%m&yg)~X)rTV3vzlAa&apk*qzFkY-TU=co9{}@> zjy}sA8Pa}2C=!5CrKKay=^$*<1@C8*X~NkF;ETi*fw#H3rvCJXF&JW53}|=khXEtn z?y>3GL{azTQ51Xj(wN7rq*QO5@)kQxjXWVLKu>m9NCf+FBN#)YC@}&haMiBePQpUe z>`_R0`1PqSjfclY!<|PSJfT-r5(yiH^a(6EM}-nl8m?Og{3IJf&vpo+r@jJ;mEZjI2n-;`C<0 zpgNo%W->~_I$L3{<{uyL_ve!f?5(}sRK;*++I)!YX+31Y1e$37KVB(V(q08swfh0T z))XWEusvaMln{QfqVR0AKurhOdl+>XID`mL0fK1qBW(b*KUck4#J6Jc2;MmwxUjMX zB&%n0O#w=YavrG8%^QYuz)Dy3wE`CYg*N;a!+HW14B>TAG!OtX2&O)YQtZfS1LV>S zb~cqp-`a|i?68Az@A}81`?qo5xId^3^+& zmr`M3brPGYqup3XcqN2piGOa8FJy4B6Hxla$LI^Q>_dX={`rlgWYU9?6N5g^2#pxX zLO8lTrmzDS&_8(tUe9!sJ>-ZMR_u;$0Y?sr?Dp`J8yN=il)+U_ZJ`t<*z6P!9Ri2 zzm)c4AY@6A_Ww#b&};Je8%q< zi1m?#8?cw8S}@%#V{=&wW3O?L-PyDu#vH`r$=CMDhlKIP7*ebKGDlRS%LcL)#_cg*MxbaJ zH6W1t2NAPMGhULh9B8f`fWHWq2|SKzV;xf|kg|A(rHw zll(14!eO3L;!usVh`ix^(Eh2O*PiTxw}Sk{;vAgpl4*edPPjqK@dL;Bz5=&{x3@-- z^YBUmmJuXDeD4CtO#}wATkn6qate1`UG<*-eD&x)26}Z2pNe5Ta!C8P)4q?BCBX_b z4R)e_wXB7e5+qeR*W=VsjG7m+bwSiyn6=&pE2e}tsF5286RN4oJTdG8X`ZPI&n>wI zwL8snFeDFW+QA%T_nC1M{yeuDH_VGPv<)YN4ZCN7o?Fn;W8@=RFO|4TT7FmTfbbd zU)Y&k%E_!Q&28$MF1o!9Q)-Kds=JbaW!=`&;rZH~x>(K8YM=walfL{IQexrZld%U+@IY0-I6N~q7AbZnJ(HIc*Qh}mdVI9?_0>2~4 z{_{+O3SgOTH!#QO?(Wv&zJTiU+iH^CP z=#03h^5fXQNk_+NNh`EnQDr%{Jtr zKXZQAiZi!I7lyXP)}^FYFP63P?~4<2`3&04$g9NW4G(Vg=#}fq@(uLIRxBTP#mK?- zxXsU+*?q%~XZ;3xU=xZtr7=Nq*gkc{JJ)4{nx*#h?EKMwM?0+?6yjvjlrUPdG4V(D zN$1yrVaIu*g_Co)Sq)tzv7~W2YI)csyQ}uMlZU`q^n>u&67O)$j%U}#s*_h}tZ=UC zjt#FUP(neIcbR)mM|X+k+jsZ)a$7}s@gy&9tW5@u_P6~5_4~o11@C+AxtqtC`dMl2 zk5sqpS6IOIquIMCL*)0c-e_d6TnW!DY1&JzT4e8m$jx)C>@&QsO}O>L&E59eTmRYk z_FezV*Olka&Y)hP=gV1!Txeotp?9|ti~H?om9B|{OfAPNs@&F(`==Rq$7}K1;kh{< z4;MQJpPT#lY+)iz%jw%qB+E`5r%U6R8!vnI_cNUYo@T9r?G`XY9L2{3bN1(Te`WCp z1@=TSowu*d=l5G;^}~f^cGQtvKReU4=Kgs9{9dAC;|MGHs+_KF)B_D1=1&EM#kGzJ zXVv)IN;_WL#B}2;sIk^GWo#=hZg%hInUj>`b<6w5@|Sh{7ytH8O;6gN&qfPv9qP@` z_adyFEIC_I^b8i=sN)|Gm-qYS-Tn9J+;12Oq~ynD?u_lO%(VlX-V1A;%^M1dbuQL~ zmKQV5-vZ4h;XjWao(RhCBkr|`A*sL}w~Kq77B1S|Z|xc8oR2O!(w?ydPCGH7mkVdZ zbe<2`UijW5hMhlN(73BW_rrFq3-GJx#uolen?P?>AjghlhT?{G)$ec_yXMX+GPKQ3 zBeT)k-VA?wtK}F|3meZeGvCkPI9=;1bl%79YSuF%yqF~JMXAi)~ z`v)Hd5L5RB;*0MFfz49L$G_!}yvV+c1U-)mNEKCL(!$BvV-uFzyiOs^+e3A1vH`Vkv zHIy%6OrerPayVG?72E=A1~*p*9_oOa-2lw_y?I*2LzsML-`Pr7rE4wIH%h5B9&;2~ zde^;{yt{obHf;@so_7<}b5B-2RI7<}cT(Nm@hJpapPIqcO^h4i*S_dq(UA3O$FhFR zUH-*f;I&KL&72lC-&*fmkitnw*@2=}4498*>>SMd4HsS6s%(pI;!=NU(7r}Nv>lYD z(QejTt3jPwZ~YRijd($*4#~Dm_$D#KADmttSyr$maYaC~7sLi-=WSIvGH1|!6uK8L z*qMXcr@YN#NGBNI+6Bt3$Os}uYcGt~?AP&VL+G)6%4stTTRcjpnA8x6-t1yS49WZd zR{Q5?bHbSvvOIw~OKyhRiWwSLn>*KstL5hkhr!wcQI@FCQn?s|94K62!Ueog5$z{DJ)`8tE*XzA-)drNr{?aBb}%1#)}1%z$)v+^pFFPByFZv_aPv z_GmXy$(7oYH6ys?1MqvM>!iEX#F!$G+s`;GEJBudM!M@m8WSkv9^fL)B{{e=({+vu^W)_(&}G zD6RSJ<K_XP&f+~iznw>JyXgOo)Bl|*A^DZNHfVj zv&c>76cFMb^GdbA`&U9FM6D@4MGSofGF-qJLJPZ*2z%GDfL zAE>=|e5Huac@BM##Sl4xd-fKK=^3KYmm$n-ZJ|BBfx4ke zIpGVgxO>Loxz4^i8RYZtzEDoJjKLW`LwF;5@aMR2R4jyBM@P8%Wb!W5 z=tT)zdiMikPSN@Bm`$A)k`T8rI~ZmFs*}nC?#0F1A|?q-p5Y+`5NN$xvQ<`F#&30=s8odA~8o&%a*!>D7J! zQ_%iOS?H~KAa1m3Y1T4|{QNlw(Gp$I{;6WNjYa&>QeCrzGe}`Zc)Ia$%lxTUGliB) z_%BT2E?I|26SR)Dl1YLD5!~VYFVjx3MIB@ZRk%B9rV4 z04&=|L2S?vLOUHMAdMv_+#4*>#5cVEo|H0KyaUE+%+Iuw#a9MLfHuP(1u6!V5s-3m zVNMr39t|B@{cRtpX{3)A#R=-YSkZS?|A<&`q^++oxB_J9=zWXUUOfYp za*U9Uu=EoI5t7CsW86ygz%4|G_@Y@%|Fnu=xUeU{5S;ia6cPsgf{50|PPcZ~b@Gew z^0sht1ty>&-eKqqql`zAvbK`BY4kse{PJ!O%<{M1-fjF%L!-fE;B-4&0(#b-7t{_1 zKL9|xNOk;vcYH-q&b5Fj(yB%1MS`4|y?z_ePk?>k`AWi8`cdqZ`>!Vy)lJ8k4YRr` zD*kfx@dr*4g-b!u4lMqzGgm2f773tinOJ<)Se~)m`nz52J?P;Df5|hw)%x2fmai#VWWc5-!KjnuL(O3}Rwd zHwcQ$9neKOT+9G21(hYC(n+BK`3OvsK&jWb1AF9$6v(9@+PZ+S?~Ma@O0N%hS)h;g zkDSF#KA}w9vHZuSo3?*zXyVpVr!Axfa9_$UVeleh0z}pu@7b}89! z|CXumAO=GF>hKE0h;~(e2ngd=HSUVO6Kd2WBgwAf01@)RH0^*~1Axe&@}Gh|iz?KDO`04`%{8M8a$14&N@=y{{V_uxkawpSzFQrs zWRK>TxK~1n1mV5<5o`9U))zqVX|v<2oFt;WFP%*3a8kOQ&jB|1t@@7OSOx+V+G+;? zT^Wec0h6y{raFNDSCJi^eX@h9nrGQ!lCnq`C?f5>tbNw|R__*= zY2GX@Jk6}luBlezne2TR z^&m4i!C0Vq5hGWWC~_(2jWaphFojH_V-77}aiL52-L>M{tX_MIsOG9P7zAQL7hy>K z-;NRQ;}>|i@cM|tAUqIs`|d{9ahAe>rg&;)YD~A5A_MgR5h?{$Mrux#94W3Hi-A0C z$0Nv**kuGszL@;UNMvo*961K|NB=dV^g+aMb z{Q4ZmP}%zEeu(}BvOzphy9WWo=2sCZLUB`xXe5F=3=6AiD!+V+-53m$IL36q(7m6T zG-K0MW@VsslviLjcZ%~SVMnX;QdY|W$w2F1<`hPOXPr>Gtp!M`KPd=`VhE}yYvz9@ z$G8Vb+9y`z$B8bDv4JqrGzJ*QI)yYNqT)qDKGu$#o8;4%DG^l18rsR5qwz1i8+W`H z+#F0PUL_G@ph|G>8m?*-Rjt#{h!Ivq`42v)lRbBb%Ay!S72|@H@)iNfai#P_C zfHRB3FbR=k{M{Xf&H-SoXxfB?2OQHb6H;{aZ&SiR{cTBJBktjN3?LL!#;TNGd-{ww zXARL=sH2Qj{iV6X`NI0Jw@Mh7E@ol075(|In6V?xyu5jh7=Clqcs9GvGk2Q-I?-Hzj+65*TnERR>UENuxcVKY0w2R zC1=nUGgAmsFx6>_YT{%GIvYl;3uNeyQf-~4O=T!rm6$aarc~Jfhp%%A@+4@mecQHe z+qP|c{%yN^+O|18ZQGi*ZQHiF{q5eT8+-3dMMc$HRzzlHo^yVu)OAtcTDA;P{xiYF z@h(q)O*jE3LvfOQV2tM6=i(%mu;V;N>~gpnB*f2Qh3@7;Y()3zK^5R|g-JyAOvKH+n7QZUY2PNX4-2 z1+`RmpGb&ujGQH-EdnOYr%%q$I(9mV`&P<;!WgyDD;YSyjlS4hV-;cb)|b%8`{pDq zCCMov>#Y8qPs5A-twTG6MNs>3tD-t!qa4$(6^rHIpag{#%q;_&FmiI&-b2wS30jeN z09{sCidvRL9xW;=*tmoP%7|GV-&PG=0@FeQOv`{-dhgO2MwLeeF20J|rxcC|Z6Rd4 z5*SqVgN!1a;CeAfF|XsDqr?J6Lr4-@INBhKEDHpeJnUXeFzQ`=^0p-chppx~cyNTr z*r2p|ESbs=xbF=#g_qwjC^G7G!;I7JEGY`fx*B7CZ?R9Ui1#x zqlokD+2!theGq_E1s+z@McWk4m+-sPH7IF{WCT)19o~6JGwRJt>;k-N(>0mY;wFu& znGX{e!2(Oi$nbI=fy!|qs(e3CY@oz#^ag{*+0Fz9eP$C;tEQNc;-u9DkE5?kEozb` zagQb}MEXcNsYE~@$B?X&(bW!_6)4$u#av+9S<^bG0;v!<`h4+SF;qd^6 zVQpZ<{amw4Ac@)OMd7N|*%uUGn7MG%VVSw4R+3JO+kdIZ+StM}4D7s7aABJ`SWvbm zbPteR+xLi%w5{d>hove4O2h6{g2RkOU*WmZbpXmGeUs(xI8Du^z+pT}Z2Y2cB<<39 z@MrXO^z7}_l4`J@YYve5_xrjI1oOWa=ir1}o4*@r%LWeGYm@oFO`8=)tvYvWdZVJp^4kn2Dj>A#o9=G8xxGMT2}B=Z4c^*wTeO@r}H*AX}}l^Cpc$ zPuSk-a|~UpGW^ScsDAl?Knx zc5-|n(d^Pp#C6|~n7Lxe8&Mu8hw{n5={qlRoR{--YjN73-BERaVY{KZSL27kQe?;U zh478J(P}jv{P%Yh^*w`-Z=F0=9>Q|)$0#AstdHc|uVT`a=Q>a{;li^K;Ll(b+jUtq zqzXBw)sxsq%*&7lSky1jFtf1|M_drYl!VbkqB8tv7_2*rgDoi59`WT`V+H&lhiWf4 zvjnhYb}uw+mV%>@Gq!V~TVCxb0EAHr@m4fUiPX%jX~zintzm;y3y*+jC#Rg z?f9;UgXpvz3O9fKQ7uLA1xT)HEP%l>XgNrzrJqRG?gWBk(zP1(20&6>z+vds?#PX; z$@t6wfeF_SG<#u1=Uy4@gR$Mu7 z_XzWi z9?;H_kuy-ZMYP)1kmsQTOv4=E45jZ!V2_a~XwS=D%36lP?lvd29x~Pj1RoLj_43xI}6`z1aYMJYqsPPexU14{8t7;5whN6F@Kt{5P znts`rGk-(Ek9?qbnRZ^sPfZ?)L7{!-3p)qeDPc7gKQ6gV6>m6?lum2=Y;O~_0rMLc|v?spg7VM?O{j&aecX);hh z_K|uLXEMlGg#D~0UIssuQ=9wAm@I-QMznixFlKakN;;KfR0F76lo6PtF?1jLouNA$ z%aAoKEf`m?9I@$`2&DUnBZ?X}GxE>_*&tl4xp|iY$ zNPLbUR58EUklQ@LtYF1ntYw4<-#tuF}=dO_)}DE{_cE!xDeu8 zdJ958N8>(Ht2j{&bv!qRxjYg%A&JOkNFfg1de>QWi8XLgKtDK3)t#3JGCsh5&5s;7 z!GJVBt5;At!E2}R;=Zx^%0w$(mt!ecY~kcl+g_HQfQ&92VM*u%3AvMCYd6vwEVp0L z=pn!^E-axAjeTz>7x%UVjl4oxc&wi=R!<`y57;Iay7-=S8&)p3huM)SoRvrqjD@BN zw$&h_lG7cq1lFnZrphFobPOU7_6W`(7Po{HJ>wu%P3`8Q5D~3~h1)9k$Xf*gng(6*;9@#74o$; znlw&H6e4>ifajkbFRa-mYyvllSVlB!ExbiPDp|#A2Q-T3Bw^Qf4E4+pg8jl)tg z%K9o0ALz}+Sh2D{j~HZk*~!lQ?!g(rPXt$7$s=~f?t#Q7ufY11oJO7Gjc2W9RpO)yhu|GEBQ4nH|T2t zyr7#q(!EV+?pZLtP*7yyJ+KJjDGV^OK>CC^R7&bS$kvJuNZ@A|9^LsS7pIZYzCHG9 zb|DQn9Z8Hq9e|IdBBcp|i!3~qMOF)%C1Q@kCZ*>;z{9VxHN>2$ol~{L>ow9`7Lvdc zXN^hDr72#qwQke}A|_z7TTi|}QlwVO0m{Z?Q`LQr1DX%WqL+HN%Y{t#k*j5Pi(hrK z$1MjhF1d<58I0Jz5+MUdb9BO~CLll7mX65N_|}L3b}U^~^4E4@x2XU(d1o4she}>4 zaKn<(SWhke7>aYTY0-H87oNDFn)^+gAI;_DKS%v#UBUnM|BtTpKp_8%^Cy$aoT&iu zZ;K$G=55ZCQD~YX*oozm`1^fw{Z?tWZvNE%-~Hy-?Zfh!&)RiaZ{pnF=4AjgWI8UL zuwt^0%BIyO8Q(}X>?BVE_VSIZlkIxUvtDDV;_T}Md*H>nfHzWY@mVF2opA!M2M_Qz zM>sntp?+LKG4(tN^&FUbJ|FP_iKsUl%Z^+&iJ4d_b;LuoW!G10?_=EcX{V^X@{J3G zVhIPPh`e$sbvZ#;W_~m0&z(*=wF$JhMu}5v*}wQd@%Heoqv|guAz9}Fygl+k$(>U- z&tX~2S~fur_oNF*gW|-p4_(J* z?aZ2q%*UcXQK2~bNZK{ym)+dYNA2m?rmdXIzHU8PcAaepz}=u*Vx$c}Wno*KmejX1 zef>j&f;+xR>AZ<*RTXQ0=ptq?s>LV^)7ACY$*b5ka+hdTT-R>wDJn3KQ%`N7b4FD%9D&Uss!KwS*HT<}zN(2B;QOH;$P0+Mf-QPzNu*Mnt(~H`hDv9} zo;el|{y-6tcrOOFGSDO(B$uWRR)bgJMUeBsoPfq%-32m^+W4u(=le3jh=PledolB3 zve#GTDGGrTrHhZ6^P>yonPP_CaLfnEps#}`3ks8CeFQtc?WQFR&E>pi=?h(xmcyx?L??lG^M^!?oSEKx{@xv) zq;+m|Vk7zQ;1nzy-vi^JrP~zX+^EDGMbk2#0058OO^CL67yJ4B&sVvX^${FcF@aS% z2Oj)m6hkZUf;j4q1vm%dfLJ;AtR7`{u2NJ*_ByJ-JEk+x0NU&Z5fU45r0U;;F{`n{ zYQV85h}*~a5MW$h>}{Pbf5N+&Hf&X`7iKFnmNNbp{EktIc;8~G+EX=4h2+B7Ia$UI zzXOJjY6roCcWBg^*cugk<>>dD60dVxylPL1R)_j$>>*4Y3jTMU*e>;?sOAtSvXrX}E z4^!x24LA6MrU!tnSMYa+9mn2n>2~N|BB3&30^RJV_0kPmwnhtn9+O3w#43Pc0pBA>})m}NeVik!bIn#Sp z#*nb3_tow-$3{?iq8tNA$Q-D4$R$P&OM_gh0e=d}i)V|3sw3#)8*%0&{%Ntt z!^}#hC1ro<#b^vwDn)w9DyyU)n#U^4B0Jch_RIv!z>QmXW2LaSThkP&F(z~h{UhP2 z%e|V~T`YoEAc-IYEo`@N9P(h zB_n2jMb9KJjaKB)M<)Ee{&QtNn3xyzNPE}~meQK3q{S)b;ie#vhjs8{vwWgn^ldNl zwpKpCXtc0LGX)bkNOVcc% zE@X(>Ja4Vi$j?gJ(Wi1c#8VXX1nQw|c6l+Od+PboIAt#R#1%QDy5j=>^7@JYi@vN~ zr3FgFSC$B@%he=&l2dw|rSWtUX?SuT4Br=z-?h|kYQ`IKHIRG`dKM$POCXYX<`uG? zR}$Sdn^-meDlddwLmZR&HJ^6rdQAu_8yMO)CbZ8oHRXz(-d!w&2G&5PzuzX_jd-Rm*D%fDrx(Sl0-`w<~JA5HFPGlAbpPgs=|>J01B}Oc z$W%|niq}*4wgm}jEW&K%$1%NQ28E~6>+3~S(|~u1mL+4kwI7gML4$LmO9M|0 zlBs4Y}NqCF1fF%E=UqOdDJ>%@~`mIDc~(HVgH)=n6H$ zIffgNPs`FBnSXM*M49L5R>M>R4k?n%Fc$O5tNUlC7yzZU<>fzV7qB~ngy$>nh{Qr< z(O%9?ZXU690d)r>C10F3nUxYxRQq?2OFb|n&b%Qj6dMm*;ycyI<$>x>^=yt+K+Zt* ztPr031R#nyx63#5>JoLv7jPTkAx$7|ex^wai0f#NY8e(A$mOlKZJsq{V(TasG=7G4 zD@A@2(50Q;WE~IFUGp|XCUKi8j~WE<056{+g}kQ8xmzX?$A;aDvwO4sp+owU{r&R4 z<8N};bcEZefq>8+{y!NG?*GBx=-O{+Bo1$5u3YCD5hTN9b6lqhCkK#@#{v)EO2|;W zqft4n+eKGm6gDSKlx!O&@R^}^kSRO4EptdZ9B7%`$CucBx98M+eZ6PR|8XCW8ee>~ zvF9`p>);)4NP3J~T&?)G*^-rJsL{de_x&dLy z;nh^Z;_2y4O~K)H)|a87UsE?9|E6bi%e#;3)BV+yqIbtAN%cLA{5@THBAayi=KE3k zw_UXirZNVmxY~jv^0Ic~X~kEaSDojk9tQoyaJPQ7!M`n+Zt8-@$T_;0bDk(#=gs*? z>2JPSl6~|ix2&u$cAW#SqNl#6gnaSLVOO*?M}uW^wH89_G(5kn-qnhE^LM;Aw>SmO z<4XpyeL{EZ6TPQ6d-*Uh&O=aL}znTOq)lJ}B|BtJLUQC*+!kDb-o-f78ikGqR| z#)ru@M7_#90x^H}wwIfoliB0Av@F6@M!|2lM-%G8_r0wGNJT`%iC>6mCF4mk-$c94 zleVV+_U88+G!+Rr1Pyb1U-yk04w4#{k1`)e1$lG!$|i>6es9YaD0>@s_!&w>6-MVb zYM;ygo=+;78NZ7P2-`c_yC(Sfc%2XW^_TG9RdZfjkBz8bhZ`)WHi5Vl1THo2*JW?g z@HRon^fs()^tF+8&AZ1lmnp*@K`L+(SzO{5>t_dc>Y*s<6>qS|$WMbe&q?Jcrqfsd zTgxBP`-VT1g0S{*cPq@+lq4JN#1SYfzt_ViJ?>8K&!0>gbp~GloouBo>zlbt1oncNhF4<4%KF-EJu6i9K!#rM| z)>V4^{cLxd-=pRHL3MAEG7j;`q?eIaAcw{o!zNzR1KjG?f#e%+-saKIhHHUOpCF8K zf(tJ(up)mS=sI+((&PpUcYHtv8X=0+@DAj=o$+GGkC{xzL7Wm? zQ8(Y5*C4WF@LR2N>Rs15dPiMZDQ1OCd+AKB^~FJl`a;Qd zhs*`+`QgZfP3Du8kCn&Hk&NydEojM(o9whvQRlbQB=RVtlGbE?&#{co!66xliwBI9 z;ljf~RhC)x{MIgPYfCvAB4KQxslLmf8tbIf+2QzIO0x@t7sXXwU%8-Y?yD_%BS@hEvT20#a3$_D5y+N2ZDk9@0ZI83m5{~(#^}> z%OFgc`@u@EEE!OpuXN|gcxh!68?{WbqOD87*GO-Me==qavNeaQba2-dj1;nlz((ct z^K!{~)RDvwKeyg%Hkck_Sa>G<39b4A@O55Ce7+PSi8=fW%;7hRySyjUTl?|(c*=`! zzjqTNixJ*q4k3_>cc)&rwjIOQ%I2NO->ML}b^CW4`ib4okDJFg&gbJ_!^A-OZkMZX z-CHOUo*s@LRxe7&_}{gBpLU;io{e^dvZ~j|M<${r{_RZe;Eok+^r|Ehmd=ws5L}xZ zPdmwgnV-4S=WS4Wzbb+i1|px@Lt|s zJ{#RqeMnu6LOmp7Y5Bt4n;7erm~+tX+v(=vH0d}DvK#4=%j?FoPO2QuI!nSlI(IYb zI>P?1I1t36Ukpp5fZJ8|;Kpu#Ufjp4oLF zUa}yb1yoT^jWP(96?Bl%Clw&T_4!~`XvkS==$>XI@jp8aGNAH_^L!9O^PMWiK!{Tp z9J4V*8}djjf)V+^N}%z|QtP;VOyn&Iy;O8$vl+_98>#r>aAOIvS}NHQ<#TH<6e2?N zF@B(O@f@45n04n*a%IoP`qoabIma9~~&dJyXZlmQI*EqEi2aUU0PN@qp^MP)K6rgVae8DSkhg; z{+%e}2D7Q3pH0)RO?dvaeD!249s6&<|L_>&B)Wyan%O}cVXl<*cETRz&;!>jfR>2B zstl7zK22!5b)ue*SW*+sb#1Rux-S}IUBOdmGZ0HO^I!v6n(TS6Dnq?AolJDA4F|8N z1{y^k1BEqpH>}VSu61S^ET=Cup;)dJq)2o4C^IglWKUP9Zl%}6>n}(QeZ4~VXEi2v zDjq6$O`Z^97n{qEWxUi|*n(N3w5LMzt4Fe9yTxC>F08}ui7i?k_9F(9_zvEW6560< zce8fezmYDCNvKJs@{Y1@TVTw|7Q@X)clZbBSxbpkL@|`v>QSLUiX;q2g@lfl6$1-K zHA6tHLmE+!(`gNo5&*=$h+)*;2*Q~x#x4jAa=@uekLbUrht#f6)LJOxyj)mRC{<=O1$<2BGB zv*Rsmd7KY{Zw+?zvk$>i%@Vs>p-o6uRQe7a(!>n}8N4W%2iRw!wh>#JaFEC2^`K?b zVQpcx{r*1h1WW0;Jjw6dDBAvFQ4F^b7ol2cZJQi!|CBx`NAP>+7lN^F0Va9jm9`1c z>Hb80=_Y9!*h0M!5|Rn}weTgG_~YVJ3y_R)@N0Z0?0BzXx7zEyE6+cPRMQm$%b$or zhwV_1k`l?}Hp=Ab*L?vF{ypS1wYc&V11q5nM<12DMS%`6S(m&(K7lca>=7kn^VDHV z*2p8I*Y}09I%$XJr?hvr#tK6l`lJvnwN^hzq;U>!(abM!^iR?|?s~t#k9caA_?KAT zr*B#1=a4Ip!%SfkY#8)OAt!C(JyHT8uc$>^DW7E}oGo#si!ioG1I$~;EZtJ5{O@2Hjh^OSQ!tpRojDjW)m?-~)n>e^DC!9#TeSSPeui1cU_EEaM&s0WbEQ%^ zmURy1L05RI0WwobAfW?IZ+9}7!qQ4ao%2EcKy!?-a5VixtYgxE=ABk;;a0>S1RrB5 zY&l;4xDTQ!F7FA|*Z3GQm}qbyVC{X!^CpX4loqHMj|610G&<-fgz|7kQbGzwTAGjW zd?Hq^gb+t#kgCjN#%@SysmVY^8oMB=*+5dF5j|E|6?9H7c{{Ag6PO!hD4J?zv+R!@ z_Jlj~JlUlv7BCkhQfgEA3ifu~kVGC75b(r-o={w{wHne{H<<5HKNP|C5Q*nNr2|3L zNN^@3GWF3zs~l+9z2CP|iOk@|fdh~10gq6i66A)`z4GD7XV!t4J@TY5AWYK0@Rnvv znc&y2z_gR7c9HR&f0GU4+i8XU5Ag90B!~DCrRaPp&GF%b42FH|A{~^3_grT)59!5T z%J&`W?k3syL-YoZkDzYr$-YuKWauN{Wx<{b9!lmtnT0Ie~L;16Y~O9+?pH%qy}nV^~JnGw5WEi z+AMH%J-CtrxpK>2P8TXv5wEJHw4e;}wNL_(e4G89X9i0-GS6r9hX7AD!lx?2T892C z5?YMxh}Aa%M_=oP-P&KY3p{P3oY2;2Q0M`UD$g1xI$caRB#|A5~3F3o>*?{O@r=0MoXWoa1c0+u-FBrCX5GhcNI2Q zy!0KrODH&~4UowU4fCi%os(IOBcd#6mM{{J8*xsu>{^?!RMN|WY|R-YyvzWfuZQRa zB(~ZHwoA@}D-J52K|-T|r(N@pi7^H5?W$pC;8~$Xg)bnBl37cI+*2;3c&lHCScW&{ zOiFK1*qBf~D%Z6SN{hopG;|+il#EKQFc1Oe_KimL-7|h-dZv9VA*=jPzG$f=G0uXA zMC16&Ln4aYiO@W_D~Z~nRUf34GH!}WLY5R>`M}}a@sDh#M-`rDXnl-Zxtct$hF{tmIoV^eRG&R&KiU5-(#QE-L4sV49Dg(JJJ(~D1 zrxJvkH&}@KMX}N7yc15G4KZ^TxHyV}9hGg$3m1`B&;SIU> zfpiMK{FFXSTQp^V&gIq{aiTs^1ClTjnyH|YSuFhIn zGWKB-uF0we8K~05DI?dK^|RYcEYap#!|_UXTO#t($|Fu#_bg1H;(E!iq#kV7Xw@or zF(r^a8R`D0ne$*`FSX}>FgrYzR0INxy~H&p_}M*vOlUrkM8#w2X7$RO0l)zor3cwm zSTlfwhUp++`&io&19*xCW|(qV2Vv^p#0Pomj*8@!SVl>(vp{4xdP6gK;nk~0Jq$&O zl4!s%6ONksM%aGbTJanU+()iy;Fe>n28lPV$)PAkg%Dn7DF}>^zvk9K+~Spq3t*ml z0uCH@8DLft)GAYvb9w^UED}73A?M-VaUb<31Hn}Zd$5OY`qpjfL3gmy^^jp4u?r@f zm~#u|L)z$0SVP0Ie{fg~I~1$lDX&=S7?4X+r@t|z6k8LMV=leUw1Y1AQijcLghE;$ zhsLIY*oy~R6Dn+xDZ1d0272?I(tkX?3J}P})AVRU?6@|tkf22@k@u%TLOxl1DU1V! zMr9|bv~D!}<*tP~Y=4qALWY2nP0VwsfqeXt{=fl|09BH?=_>xN9IJHhcjm=)aHi{w zpnJ$CMh$O-db}1S5=Qeh+p0WPL+H*efJAIioJ2%k$rs`aCEz1o^ykdwkT-NL&V4BE+V@3cqpiOaqN zeGGsmJY<0&nQxHvfFQ%ktDIe!lJHr>j$0TGWf){ZBy&R&5W|iBgh2z%QRP{~+`%eB z3Qol0!4zhaK366$qMn_H4M(&gr2*O_Q8!;H*k4!7(#zOhF?A(3mt1eouZzF1`Nawk z@5N&a862pIF#?8uy9#BqC#U>q5${Db?|R#qt8cfI1#58~%tOO$1TQH!N9RGa|IAsp zeA6E4+Xt&6DP09D?&X4f=T|LBofIb}GJiQ8oL#-lWV67xG81;+wRGd~sSkV9&p>O1 zyqSEX3bt$GYGEWfr|RKw5DV>MS;c}Vv$;_xHomW=x7AW$3@}!Kr-++`Vyh|;I6($H zFqKVY4*;{Fg6oqsWP1rsw*s|UR8}^&bX4VQmDHr=MfdDY8e=AF7{%U{&!45V9MSE$RgWO^Htg#3u9a z>Q2gSB@K36%XKu~=~-nw4PB6XDV24y^71+Ca9BrEr<7ocQ@@x=K?l1FgCzI4lDrbB zBNh^~4GQ{B!WDg>#V#S|j4PIc2FpHWb*a%z}1h3 z)%xqPO3QkDF@zwp2YB^SsFkWfU(i#bLb`@DbWsq2q$`XOQspE9n>0s|5P`(wdyZMi zU{~7JWc)1mDXN*2e8<_)is+)brvQ2A^_2yi9q39__QdGmLXq??;W+XKmf!Nez+I^U zq0H!7n#sSAW$iPM+AGyaA(K3&>8mN@$pYZcq9d+nPfM{Y{2CZwd(?0PLz;mEnGEN3 zC8L=VhfQ{hx)hBBDslH42bPOOAY+%8Cjwvhbd$GQW1!>1X*5rI3c=p+W1^N+$9LoE zGDvKtqGHl%BpUkbGEp*h8ijWRq=3V#3UVNud^D$_>L6LM16LuBpn20L@xxts&3CzJ z3N@(GNF&2Ap^#&^9?!YlOf&0mnC3?CTl>K5vxb=8d%H`aE!;s)dn=Cw0zPZi4k%|k zCLlo6ED`=dK5s@R`lkieAX!|*0$gO%Yy;oRKU)wtd=Dp>WWJz#n<*6Tm5`8nRQ_tE z&C#`4&=KkEJ+6n*bF!1UjD2CBdqkSg@yMqg&zxTUo2IfjV?s`mpTnJV&-SoKgCP_# zuI{491$n!}_6M^9d@rSeaocBdMyQe(21W$q>d!#){OW#Gj}GjgU?(OPy~Yb*q8TkB zDvmNRkd#vF4v>}8@A$pd!(>%0mZXtlU9CHuG#i|cw<&v6Q}7YhOzYYieZKC+0Pi|W zWnLzhB#K~5SL??(^bZ>2B-0~?{d82iHDRvOf{IvO?yb(-X%2IEJp!~o#p(Uw(XD;u z`5n**bL%4{A;-!nU{2EfVcWYTMBG{|zGGs7tH*2s{V(=-WM)s!Bak`4fB2|U7Tp$S zi5QK3{xSec*TV$)XIRp`K|Ip>XEdLnT4KfuD`c_mJiarm3k3-g`6BY4 z8{MzQlw(KKxHkYtQ^1}G?dgZ9*@g6cW!fgO$iAM`{q=DGsw#6A6|YW)OIQ zQl1AFR09VPz_ac|KFM=WBlC2ufvb0tNJU&6AwRpZ`rw+TVpQom3s8@8_LJfYrH+0rAvJ_h&BGox_o@yZCs zZi%$vUi17L!V)|r*fCvp-)_s)^3Ey+%fkb%;9Cv(2d)lR%JgiBC@buNI0h4dfUWkM z>Nz_JN4y|vn`_%zhHSS1?|AH^s47;@?+0=|!;AN(Ne0J8Ca`eSR-%tfN70`S%%1ED zX>#*2CnOMd&o_<$wZ(>z_E!bkxQBV&xhyK|MM&UP)^Km((_B zN8n*5&VQ%uOJr~+GUPu6jML~vh&k<9Rjk zd)n!jS4DJ*XQ#P~FO}I9w(*sH(ABMwapwk7X*mnE{?5|AS@WhOrmO}1%CU3h3>Boh z4b@uU`K3jyAi{cqixyR z)pD#CR8o~`pp;+&ObYZpLVqk1;Ni@X;7AJc&U{#$pDTQnjO17gi8>wh`5~2BGe#*S zM|#lf=JCNSf$W3>Mt&X*QEU}pO4zuxw6F(-TpvUh_mzx_E|||e^%8PBiMqVfdRe~v z3@a)JH40$<>Jep0rc_QBbN!e7Wk=Zu=4Ni=m434=H`dM!aUNpUzRI6IXTcJ%du&Y1 z?-{xanzOeckb@c7*4E^BVrH!%dz0o!z7@qFcS@ZISIEOKwAW}LIF3vjou0Vg%=B#$ z7C0bEOA#ON%HAroQTntzVvSb!jFC`Wu!U)q-S(5C_(O@Y9epp}~ z*lQJ{_(`l&8gu}MG~}k*%Qb;{Q=q{UVP8W}jE&Ock#j?5-MWS()lo&k%GF1#w!VwkRxL^PieE~ zpAcO!D{Awv53)lo6};+e)NpZECV{+cXnM%gDO)Ap$jzE7N6W)d8;Q>V2@;SxsPPP+ zZVE9)I&Qll>X>BO8ACfbo7@yQRwD&Gd^oX!<5Y(bHBGfmYuj^)Hi@cy2?Q?`*9H*L z$LjbKo+g1J#}zTnun>{ZI_^J%y2HN&Fr7n-JFMTv68t0x;M&0BUJF$-l7s&-!)H-G=4u{Dp0p3R55sQ*mc z;ZnQ;gdX8g&r+H#SQc<^i89-}TzV$kNtb1qv?Ld+`29YQ*rn+`m&~`O=<>J@WH4Ba zk#>;YYO;(Z`56Jnjc3fsO9*vu58{QL)|)rUppJ(pS-SW*JA=!`*|B^)qI(#uV*Kl> zbEbI+{u~1OJI`Pc_M(jfsa4 zl$LEqfb8rgNz^ueC2|0Nq(Y(A9~|?1yosDy*~!4ikCpf#a099Eh+h==6)m>8@z8{v ztu_-VUih5Zx4${uLB3|-zVr4GFE~G`;oPmxNZ@ARv!=DC$ppy< zCCE!itdFiAW#$z`(?PL&B+g_7e4AACQ~u6nACn+7^1$I8Rh{eOo|qzXC0Gx^<)zJj ziBknH6(HW?$)A)OmhkRUqwRQ~w?>zs%XAY-NF6%C^+3aB5<+ZaWYIvt5T%Zn4G)ch zYmk~KRKZ9JI2-`E%@^)i^jddWpQ8+m;;Oa+`;HuBcU`On8?#lJ`6H-4a2pKAiL(7W zdhnESN4FX&UDBR8vvU9i^GY(ndflwvuX+rO;wZ*~dQ)78hxI$C827egFp7k4gap<3 z*kt|NBrO3ACQj_kesCk>*bl~U{m27*)R7OgR6B_7Uz#;b-q3E7AgZ+8LU6uEk`E0v zt?+93i#i5AciNADjKtYVSFUW8qL%Qum31fWR@cl9kjUXdS^JmS;eMxu7vl3;2(9QE zqU88%_k92UaM_UE?~>26wIyn4o%?Oyr>$lE!^U0G@RCe?Jo+59y^*kVW0*pTAFT1>nk>3dK7@xO`{` z!t@9Knh9wkw3#(y^C61Ku)$UsmN%p8$+x2S(akhEvQw(A7X{Phz;nYxZHgX`M`u25SR(-r;?|Ni-5<|Krhbj;pbM zIdO5_nzjAdw?qHjCrnMN@T2e6?Y_AJOXJfqq%-{U50Lr_TUdgrBv2hI_L))WXd30TD(8y6o$lLrtpf`nLZ)_pwek0_$N|XRHa?kejxv|yohtxT z6rGgYveUkI20v;}<$)n13KQri)`Ud1_<{y($l8(0c#<)f(;YnpvBElW0)+WJXk zvjJ*PLYA&e=F9-6-Z2R(sSnsUtCJ4$Y`ezU%}NF@NW-G<_OQqlGR*h>h^3z{c7uZ6 ztERIP*iWxZyFu79kx<6iCydL-@!t6o#T-I{52xDhZ_m117ee!KDM}NX!GBsBZHw*C zfsMnO;)InR9=DL~X@PQm;0zN-Qz6Ws67b{c>%e3U>H#oGY!C$kyA0HgDc8SY2KN8vs)G- zxd7h7{QHWe+kv}A4rPrUU~4~{{})_X3@3&K0^!I(!7Eb1EF66k&_0r4np7Zx#Q0;7MEiYTYEwZ>=RIE?_O&Qk<-_qQqTa*me8w} zW@BBnYBQ1jl7OUgtmbD*@h?G|y1V__YAsK@T{4}38f@2*coCg+7VlI*JZ&U6mv>Ax zj`U(aZPN%CxRe=F!KS=OnwsAlMHzQ^iXqH#;@G|6X<8m-Fz9_|fBXXkWFAh2gz7(J zsKJc(xm$@&9g+2~aMlgmvVmQ#l;ry`IQnBD%IzfA)5gmgr!5YObQru-9O4~&YZ1^Q zCQ+~t=vP#v0+^8j5(t@5uDD21damDbII!}!L@FEkWPyKG=vL(-W|k)c)PDO0PkDI} zv}U71TeIF1$#5xbtvm}6_vz}9v|*f#_5iQ0N;7n8s!ClnP%o1)i^zsu9$sQrvJO!$ z!%c&w0@<=tgUW{Q$Gw1(WiThNLn6`vcO3vZ)BKXsRRK0zu|S~Pb3+I>2ye9ih4b+w|#EKT%R>-u>;oAMp%FEuV*ekSwIEAf$;F#;hKoQTS0tUP7cD zo6L?6*UfGGb+z7<1L%ia;Gg1T_;Mt^9V z{YI@1o1rYc$W$u)R7FozzsSG}A@YeoNCu8LZ%)=iEl)i!ZL3R&8i*z(87@Cx#s7>! zvGid$5Kj7@#Q@lmEPS3|4O>OinP_5DL<$TTMWl4XvCtsebZgQAGSI(H6&q%$Ey@O`T6;lW&zeg$?R_1gnVbw$hd4vxvvWsmn$YO9<{HDwTtu*wPW#?26#sMq0 zg}?Kr6!M66(GmP{50*O|nQ>j|%TWJbFb~*LdSNQ_9{5?}5oe$PyV2p!xQ4NU2^?pl z7#9?kDrm~6GOEfF+qEY%M_XE-IUI<@0)HPtEtWhD4~zLPn))ZQf8O7O5)e!|8Dp!UPgdl1pxx$fct+NK3SOlWB6>; zP_|!V!t(js_>E+Vm`V{7FO=9!qJ|${g;In+Q|-+bD_=?BXokCXwLGn0l%7y)34h~% zH`sOW`?Pzm-&GjVG^D4L8q#Cg6cEBXK$1x>TAO$D-d~Agsusj7|qyQ9=-Ll8Gl)Ucv6V_IgoI|f_n;$!I&>Z zr4h@}jwlqaN=3XvXsv6~5u`|`I^2>0rV%zl^uGu@r{GSacHPIeZ6_1kwr$(CZ9AFR zw*Rp?(ZsfGo!NVzI#*xqbJf*XUA4NOcRjsc{6a+%UFaAMO#a-=7-yO^zO~jx5Z?x} z1Y-vc$SxxUpQTRjU=3Uup@I8uMvb02x?>R-U(+ATnyDE#mJid5>vj zXUHi65C=lFNL#O}!OoT1K==gz=4eFqtmOXy5eR>?8bU8xBdmNC9&{wZ2DuRi4_v*v zzl&p=06rv6p-5mC@V3x}Cpjfv75_Z(Y>ggb``Wt+%!7ErI>QXgvl)q!pjGxYhO_@s zT&<-D{d41vQBL$&1+91Z`(uC_>dShN9=fQ2D=eSbTe~XYh>qJ?QR>c0_7LFOa-Mi1s6*b)V*HM;IJ`6UT)r3G!OeD=w^s# z!id{T2PKs9EKbU(CBdLEYC}+MnL%&iT5Czr)!@oa3SrD=Rj4qE$ z=$X>#vvi)rT2#Yfqh=5C2E>_(V(^tY_2B;6CI8{Wd5l0B8(orUXY~^t1*{uhiv{3` z_bn17MBi#vS2O&;xMClT#M)h;qKdPEm|PZv92^j6by`l9W2AY0RMRh-!9{SznPjV> z6%6W#*4AM|y`$D?6%fw^Rs5|s-<(jN5}#Xb#vwNbBw7H~EhJ8ywwb(e>ZfhkY1BWZ zHdJDb?+WF+cbQeV3bXgpsS{_?JTA*@6}e>I%*a&^P*>;_0cbDqn8 ziKEcM%T6Qj{h0Pr9o6`>3xNx~P)BYR8qn`!8+*$_p&;|7CLcly*=l68X(E3oj_od& zR(FzkoLbNF*Af(j!Ez(+NzI}L8S=X7ge;cr97@Dk>weTu65l(H?f#VinIL3wNwXMn zZcu29M=DPLNh|G_pNhuJ%nUvL;&t>72whNaAIZVFP*&d77pK`IBR+R5wMttR4S&L_ ziy808LhRRBW!dFMbaFZJ*wj`@6Amol3{kJSjb;P$FTEc0V{sOC9v!8k3e|S1E+Uy! zK8NQ7s;+TsC74~4&eOrl+S7WfF06mIH>$@?Jiz8gd8P0h*_JLlpNRgzKtMk~pg@W; zpkQb~5I|7>O2?&T z77@mhnZOy~5flpeBT&Urc3xxy;a^XHWTy1SMfr#1*ixUl&U}eYUmrPR8;OnrIya>; zd(xN^Vx4(b=Xv!yhPuS3tLGI1`!Y?*K}fnZva~^vcGV6`QZx4}PLj<;Fj$^KVvFF~ zQv9Z2qYF0psODmzYuAn6bt#6~MVl|#D?M7`%KdsQd4|-sqs5@1V}o`eEkFz3=Z+{Q z(0kGFGoj+$7}y9=G0gH{dpyDR4j8z($WE^gaeSChiRhOs4GS9M*?&^$4*A1VWK82M z@iGj6z0$_&H*$cZOr|{MW6Ki8wYw^8eh?fH>2W@G&x^VvzBg^Y#59}_T<4NhoV>U@ zT)W`;UqZ!kC2RIef?71@>~EpjO~Xm=g}&y?&`+ujJ(x9mPuJJKT9Fwcr*v9HBwEhfvxO+#$jd)E_vlucW7z zZsV~imAV$v2`5}U(VtuV7@tGb9R+d`GQOlPKGMS(yqnVI0!L!=1A429vwHAD+Ew-d zG3}yPsT6=JH0<*E)x{GsfTyNqq*E7@T{w@X)eRTHFj7iV;f{lvrZdkh^N{)X?hD_I zLZ2J^2*dC@XaobY#fGb!`}c-1R;;##M1Awz^5eBsE;wCrVYrU+-HYw_t7$~e;m}z9 zm3=+)259dw>~=B8dT)Lr zeiYmD2zjKAS+82eHK)E3)gt4_9MeR%&FnyhfEHZ!vUa@`6{d9J1gBooipX+o*sln~ zintLp8F|>DMPeNwyo%a|K1fB4KYzJC3VSDuhO~&2WZ+no%5$C4O}&txs9vXogXG$n z)Ww{D?x0}jMwkNVujP-tA%f?{lF>Gv6rooC}}AgOa#6)sAU!@N&B4Z@BusxRU?SB zgKejpI>jj@({CeWc_B(*R83aPqzceF=(MAJeKuOrl9BRVCR9lIu3y_L$nZczCjI>+utiy>s<)@|bCoO-`l!*Q5BBeN{()!clGC#-PD* zf_XJ`kh9^wyzOt9K*+}l;O(>082TXq_`ctEaPo719EB?}*k^cfj7iiV$2_}!O`+$j zj!Dd&XlUdFaN7jve*}0x?n?Q%xjnw`-Q~RPj~x^f5)kY#m}{wHcxj(lDR+|0ccZokysd-lGGk+?(~~&z0w#qm6M{3xRsXO*et2{BM6|nJN;g zBy^&ihw|6wx1nP?J&xC$F@bHLr^_cm^OSnY%L+pmZ~*+=m;y&`Gi`E-!P(_nf`x&A z&)fb5%hxw%*RUr9ZT#NFko#!)G@d#IFlS%Zc!s;=$r|K!|6+b!p6(38w*yjM?qa(` z9smO@AmHsiZ_WNEY=e9~e!;mF+xPwQ@(qA__1^uw1*ku9h#2zzeqBCedC>dPc~Qe8 zIH-OY`N&Y{p4%Atx>4x1GN7j)Vk*B<^J$E)9-Ue~+y6Yi{CxJ~vF!1ENWIhjSAVHM zKj$#V(7?WVaFhPS>HSu0>+jMjKi@?#KOI%&J2%6d!X=M26M(3)#+4Bx);Gv_hJ9hn zzoBi?0qz}>s9ruhfc}EhtyG*bcOz%DFl2fh&5+D+tpLv~?8)61rz^o9w<*qKACeoQ z$KR{NV9zw>yq1AY5+f65j9a((XWlI;ANC#1pQ zdLh=`W53eghv$$~up$H8ID@axK<*js=kMM5De>rnWpMfM(-|_!58w;vdpi*1?zO4! z)$+HTOaE#!&K)w7%gUgVNMDiDVk>N_#;=W>J1?u$J*%p^Hg3ryw@>$Sep%GGs_#-9 zJ{e-pVWoA+U=_L~Wo<6${=O0Yj}s*%bjb5T3X{>QfdS!SeYGJ+S# zKV?PTIP>yiu2yc#rf8j-WIaeUom%WSVciwnjbE&9rW<4IWaY&}^fewMcpV1*rZ~)U z(Ne?EN=vf_DNi~Hf>q?t=^#_c?y_&9aA@$N(AGGrdI%>*h|y3JGYbbBSL$h*J}(kP zkBj#{#52ecbyU+U7TtrUxi6tXbx%zOmJ$<-^{@Q1rm$sH7XyblPYzjDh`I4+XqoR1 z^BIMx9gkFm2^#eVEpYTKFpC4{r(>$|Z_XwHYo;MPHRs38^U$7XDJRbov01MYH}&$$ zgFe$rtCA!3g*7ALx@4NMa&t%yI{Bl-38s#uQNQ9Xf0}w>w<^MtaFnF&i*p9*7k^bx=j5=NCja-mV$2@x6bY^ejg=L&v zTk&3wv-&);j%qMcuA&`gkZ&dpmmI3~KZQ=*f{5SI)Bw-!Am3+t@!m&HVBx;9?k)UP z3_%&%oyMkhZd=@4ifN*8sW>7ANw`A?5#hw(Z?vUpSr{K6Wk?C8LO425=8BO{Dp#Z5 zY(Y5>LCB^p8ZVbuG^76rLdMWV(lj#e2#nBA=hL`;Q)xfp6Hd5ITMPOVHohz-=NNqg z{WT2neogxLM@Clo8n2X4u~eywy)_^H@yhF2FabHU#TMleFFR=0DU_Iw;pvOa&3cT0 zD;Cz|q=|QGkyl<>DG#QK6dMT26B+aU+5H(P;VvtL{{30nTL3W5wAU#@%Y9=o-0Jtj zs=r2Ac89W)XO4JH)wymbt+tKs;bXwdZj{l}vsTa9kJor&HW&H$ipG(KSO=1(I9Z@( z?I!G`k+f@$c#FSuZer}W)d;g0WSs%4eu%>TZ?Y%6%(#U1Ws(9TP=as3IdRF=*%&ed z^pi&kC%e@x(ca^rsgH2-W0r+atObL$i7vzz<^xBq4pW_~20Ve#E0I(Pev*IkQiU)v z!c3Z6_z;X-tu-c-jh5jXV`|;RLnaq=U)dyUE3g_xvhHc=P*r*;%OQK$#F(LoU-VsZ zW!jSeaACYglapa=lIpM<+cX5Ikf2#sVVxL>&OKVTIwRNwVU?%{=M4^`#(}{g>Jn{E zq6Y<~JWNsWTNG1KK6Rm7?F|k>PKJgJOsW5~?YTFuF zWr-$+&8CQJMY3R^OY@|8Or&_FQ#Co}{9KX~3EtGqrEKARZecP0f3M8hv+f`wD!UQFHcDG;xFH?cVag*4?#A-39L^Q8(lNpu_ ziGMvZv2dR>Uk(Z1(EYKIlFS*qB`@?j=zo#qL?gHW{htNvwT1P5fpHKifv+;HIU z){19r0-}dx7!zxWTjYNHSnjQQ{}uYYcTqR)`nd#6^OofFlFU{a?ku?@6YGXs(BaoA zT+!sH9WguAq9RG3ibQ2oq2Y668Fa3XwJz30k}>8u zRNCW7?-EGO`!Z^kM|K(7x)&;+nKSo?Hfxv zdj^$e5kxo^vA;nj!KB58GMM_IsE~(A;^~AjjHZJ0;z9fvC!WMIffX$YZsb{7ABx${ zN=HFnzReYK4PgOvbkW2$6J0_V8GT{xY_*VyZ$cvQcIYA>RbC$_80KGha^C~0feSM&1QeXh6bZWZhQmzF3C^aY#nv1BW@bxth7er z$xgya6vi1kJWLdEwvma$GI(RxCQ3L*JG z{&1K$EE2m31tno9SCl70Yx^cn4cVERdzuIpC}K8qOHhG}p$SgT2%}6M&WCre=74R! zprVF}1ip%IhqEd*C=pgFkA+1DZ?eyeh=x=tlCX#O=#yEA zUeVH`$ZM^c`yJ85)4=p6(SKN3h7i`JC%&|vDeobvU4>1MO$q_gJ^=$wS(Ww0TCwzY z`iYl|wufB~PPwxDiW=`=jwJ&O&!p6sU1{EjBn%_-oSULv4^qOwDYI5tlJc1dfF{T_~|X z*-W8JDx%C|vL{Jfbu|7-=!tIZdK)j!c}6nB4NMHW?QhTRY4q!uJZd^NK|7YM$oDkm zt5P<&DY~aTdv-oblUduThJ#bGd=Y4T8+igPBs+D)R!7XV_br7}en|Jm{JnI%$tT2!Emxq5<*J_rD!&Z_E6ZErGQb3!Cr6BvD zIvlEVh{my9DZOBlJm&ra&sciLtAPsns59ZIy0Hd|mzUx8(7IUjA-t8)PF|OaR^dvX zCB`9r&|_3lB|I@LxbSae6}0!%dsyUr%06TskR0R~SZ^F*2rGq@a__2db3$S{SUTcE zhMJZLq3K=L9a%ddc<8c)2CR3=&t)dexe`GN_yr&lER^73_~_!Ca}cj>M5DHIRX(u- zDX>MAq=nrmz5L2%3Az42!tCqOUYx*Lh#tix76kh^R_7`5Iy~kfxd%tKie~#{K9jhI z-7g18L$#sL#H z!{2M!duZ2ZsPSsTQVfb=BoPd)6exGZBzn~LZOgj|7I^;iw5Sf@i3P>ie{Y*cBE=I_ zE1cr4N?mZ6?H2dFOJs@Q5i}L0r#HE^Y~a{<7c}=C7T?MpOD!w!Ug%q)=Rxf6_XV0E zCtnHFsP30a)>y%)~2=;}HR zSRK|PFSA5~)p6k!izkfX0m={URHU+g;S~$+(X7(0Ggv_&O<}~(<4T|Z`pj5MASoB0 z+&XM~SdHm1ehk+>WI~*yLmNl2rbfFL#JnCQjSzswO&L>fam2|f8n>E~9H(#cN$Gq=_)QJCjT4^ZrNml54Q!}Z$hA-t>pD1TNtJ9fg;MZ z3x%sB!fmRkpFO0sdss@$Zu+&GRYFff!a;;ad4|v?FP-Y!S_)2M;0$};5_Tzi<;m;Z z9~al@vb{Gz*Fj$Ld!D_xmBv7y+}WV?077G?GD4z|aVnd*r>4v&@DrB2ohYU{TW*n8 zOaBy!%>2<-+~|QfK25XULgRP|ol~Sk|M6o2R1;!Kc~OHqy)h-UDWq#b3sRstE)#b* zc7F>vrh)e3b`W$dMtEN`GwHtFk32f(VaSz>p0~lVdT-5h7mo;$v%^L?rOjg;w45gr z7fkJti5@=kBWUat99&61QV?iBT#lXQu4qz8rvxa0G{$U{$`P!;T8f?)UvN{>MTcYD zgRp=ke?5UD;wyQebh=;Yp^hc{zO9XJl;a%-)|y7a4mwttt74qVP%|@`SXBJfnsbyi zpHoPT9^0&!;cLtFa+TdAL03NrDIa+q302#;ew>MM;cwWxlT@YLWrkPk4-%zGiP7dG zobl5BAEt~YmlF6~q)l$FF#5T}H(Z6I?z5s5T{IA_JpkhZ(()}7I=4Jty=(?+TS`;> zT7obp=b=lE+3OBfGgl!iF5+y(D zR>h3Z6kCTj8{W|Izm(8jTq$s6AGnLs{_s-rhT1C-M42ksX1JiXXFi}wY16R76_ZOXs#z3B!G(-fbdx6U3rFiNNp5R0m+C_tWR?6H!$L@+*y@0uVSZgH+o4rzY!76I1P` zu@LcuCQ0drrAkmRxi)imbLFwD)Cpm*&SiKVJ>@glit@$dEd*{gOCm8+K8Q00m0Y|> zmA!VkdSFaHmBBMMC8dL=96s5xsp*Pr2^un)U~-9ax=H+&Kkvimjng=az><1mD2TAW zSc4*FQn-MI@{Z!4_he;SQuV* z*;Kh+*QyWp3l<&67ZVZr5_(aB|FsidbbD4OxXlP#Y6U zs81gbnvg~_t1J7pfH21Zq)PGmEZs`G3rSS9cE4@*lp2m}5tA|`AM zAdSMzR4G$L{qXQOv~My28p-u}t;#A%Vn~$PTDfb$x|kh`Z!=z4;?ELTM^1~W5)e!T zmGc`oLv$t;q7_(;5U04AJXr|G;l8oz;aJ%qQ#2lv3`lHwzG=s$jV$s_j zQpOakPvF>~=wv3Asi2HlW^i(2F@YB)scn>}CV^zAj{4~#{B886QU^xpaKG{?S@d|z zg9-s>5wexy;kdT6iK+pWpV8T1Det45(4`Q;fwghX2;O{^l=DQe^6q|br%%b&5wbmD zRCTS|?y7(lO=`qvtZAF$RCF#FCTbFTBF(R4*fAIfv{--545Q zDwjO1tX4E0cGzrMXxKvRbXpo$1Vw%N2DCS>dt*q!1SZZx`&VRHX3Vh>)Q>zh8Sem9 zm%Beq4y*2#@sEQ4sIZmc1ByjBjG?zse6FgH2P3rwDZ$broZ^MB12^r$Xd=K5K&MOy zkiW^|$f5O84N!XawDm88l8Q%dhmRT$>OsJnJ5-P6=NJW$vBDts2(YZ$@xG|Txb9AcyP)E2#Nddz)CvSRq zhDZN?*+0(?EZfL1Y7U30~X4)R*k!0fF#MzvWUw{CAW~6E0 zSTPBkQYUk{^GfXyAC_%g@D2QVYRsG2^%0tK5HTcyJ}8-+pjr<625Mkxqu^Q~>gCv1 z?3|1NgyT7mWfgLWzrtYPi{3hKl`2qg#|%{>TM8v~C7)KPNHq?o!y`sYW%rj`_-@+l z@7Rm@v~Xvyj`{4lTjdUVXf776GVN?%8Qv6g|2o9qiQi5lri8}2UX9WEb|9yT70)20 zq{Kx~KGh2g=k6ci$v%gp0}jH~pZYwBAF%(FeSV2wxEMtS0-Ce_UouZ@ z|DAc#vs2lSMEP$zt8Zr&%PhCK{$m$rlUN{96-dsIE&H465jeQ64PC~SDaXsj%~_Io zcB8m3XMBon5Y;M{RoOD%*R$)~?LiiZ)--`8$$fo?n#kIVoZh5DB+!t|Sb z(XCm9x$p1x^77&l<}AXJMKfkSdTvkKuGNcex{PK*4-d=?j)^NvrVf0A*+sE;f36N$ z2am;oF#X9rW0kt&Mrl^_jdcCw(vO-{dN>AN;>};?rYQv18>rRVjOz3;CD_~4~nk@J|yLz%@lgE5|oE$pVUwH6f=9_n1 zc;@+My7APHE}C|Hvi{qh+<6#AQ=;zXVh-ob-sUV65R)fLT-sLr`0{$M+_#ac_lfSa zV$H@ivBLD*AExwQ9$UI?wm#*z=pg8hoybBly^;)j9XCHOUah@~ugyc8RY$-6guv05 z^vRB{a7;bF^hqvM^By}GR3e_6uMElwCa=6&B8*vIF`CCPn)IZ$U2GWER< zlB`{3v>=Q<942Gj5nLGH0RXR0hqwDjvm_nu^*NxcPe$JG_BJuHkw53L1aq-C=KuJ|DaHjjz4LWtgW!@_oOehe z^9h+WVR$xxPpFZIYG5PuV|!1XR!G^{NtQKDZyi|w;PZfqei)s^qCh>Zv~vp2I!@*Y zWXd%E37!h#I@8t6caz_~cEkQI0Z5pi8){=^1P_siGd-9fhbHQp??riJ#sAS$e)m6w z-HG9R;8WR>k-3a$Jdq(5#t`FWAERy=i4mD7j5mGCVuQO(9Qxc>iFhKv$)b%IDEva4 zdgPqIs2y2ed3bbB=b~yQnO#6ozr2c=h}<^8+^jOgu5XCdl_w)b_N2Qv!-JXgogb`V z#2%PyVuUls=w3Zy+V6n!6Syrg#n^ChCx%D{woh@wlX=5;l;P|+YUD%^K^_C9l+hi= zJ-Q#X@z(Vg_RhW2?8qEB=-XXSMzFUtwxcdZAmimffzuawJRq?ptvjiXv47||k&4GH zNY7*C`mw7jehJeQmj-;Hn~VA8n*rQi6awjnoT1V5g3S&QcS)P5T$UkO$Nq!~v0zHL z=thSf32d(g@NZ)0rv&Ip*&F5EXbAPO9%e|}>RcDv7E$WKT! zY!9Z;?10FCo2@k#Uk2zg{OC25yl8$B`3nX{>|P(eN{dZ@?Tx%S{ybV*ygL6pA&1#= z+h0Es@|{1u^MlaGWW+tdZ_me)ms(3d+=a|PdfpH0!NZq(XCd-Va{3~-deK)__S?BWfXYU(KUe>;C|6-F6i(|yY`Ez{u zu(2Sp=U{U%TV=+RJ ziN|&dVuXCeno1#Ru7VKzVH4RX3)I|hvBKdgHHu;#2WbwF&?5g4u|_=#8(#`EG3}di zGhBm)qZW%~BHaUhuq<1E#dc=?8p2y-$7N^XJBvKTP2!I6pc8+#xUJjGI*O5_8)C~++I_LD`YX!I4xf%ieC?FHO)>RWZV$f0DPy&+TQj=OB_nlQHy6Qi zMmRfHUYvFD@Z$^gFAYGbmk}`Sl(F~^Jeg$9$^{H2AP!9ep-t#RcN-{KM?!Cl1dIuV zZGmEqDqg03-Vh4B5PSP83ldKt7KtZq2v2KisuMYH9as7qs%6KUV<%l1#tH;mUN(uKcdFA|KFz zeK!M0iZ*4fqcdHkpXUK5*zu8Wty3tpu;8^&EV&s%vw?M1IAeZw0-c7RB7k;EwWd3M zN$-5b!?Ta{13%pl5scU9Qlij1rvQ;H7FcbNYc%QP?G>oQF9QCueZ=k$(k-NeWTTsG z`_s}#B^UE_(rWA)8S%Ae(TwabN}7ev%}-4f_}&uHi{jYLZ%x~sWT@IS$)?7?ssO0Q zT~0K4s%3lfK@65o(bG&zwa_vxglZI4H_CR5vN}t|c{GS@kSaF4`7V_lFl!A_w7;`x z8WuRL;G=6gI#aX(7d{Fz)n>@M5b#1?Uz?x^3GssvvcM4@4S3z=LqM|vP~?hQp+LRN z7p=N`2K3&mtfh6kK>;~V2;OvfSf?CbhMx#7d{_LQ(xof~VJrrC0u6P_z8OHv(*BB#exlh+-3o z5g5*;44RCh( zY8HlVxLRCWbV5`O-Dp%P#kIE(;0_L6xvZ}#vo_ELH3P#{9s3!*XxwY=5sThxCrSh&E>vn|z% z%r|#uqx#AOS$I}bQAiKhZKdIO4T|KFCcBdd$3}Cp96Nvz@WRjA&lKZIu%y^wL0N|& zDnMoCXy#AJx*3%Pe;ZYLJr70Oq*l%r*u6p{zOuUQ7tQ=-_wW|ATjT4$LcV>xY?m@- zw_q{`oXm@0h;A2a%N|)UMxKlJI;@$=6{uadeq0k)jVv|3B%%nE45v<~awRn+ao0+z zZ<|%7A?z#S$MqoD(Nb}YCT*E3TXMW)QQe)5R&1aH+eWHh7q5ro7(ysA(^~(MY~|A> zt@NNAscU;wE4N=)m|2ojIiHMTiU4M-S@2mZ~vq6|Hq@LwzW;7pJ%yg zhGNRcgb)(_AXPil81q$kOE_ScDOIfq(3oB^r#OT#2Q=9im1WKWqqB-(!h?KXZo1hu z>^>}-LwXxliQ60EPdaRuVp&`*OK)qZXwWFamm8&lUepH5gF zq$kvJGkwAr$l0t!Qk0!KD^^y9Fo5Fv+3aMtY@x|J_t4cCkLsLSZM!Bv0ijXjDHBH4{f3$f|GX;`f&2zHiHKV~hau<%?`1a|{c{ap zKAKa90U9QPHVAS_DaKCwE5TrbOT^VdMBtvVY(h!AQr3jbGizfU_-ngl;Q_%V`wP+Li%QbE{Q;@5NHEfSQGNv=n`hfdCt z9P4LxL;Y0e+S_rv@@g*+i+;v}+mIS93wzeNY-|$mBosN3H47+(jrb*Z)89Cd)y6mk zsKptp4kOYMZLdHUNKxfr0Q9(PkkiJwVxsk>T%vskbPjH84MF{(I38BmyqJE192}H$ zdkz%VvI6U{5=lWe02WV_^4TmY_5E0N&`@!^>a2TNRS=Hu`tNj0Hk_uh+u`E4F27EV zZy*SbJ6)g%@_r)~xA$Oewzxh00q~P0*y}!W{D-24ok1NseH~pZ&H#6$L&~vQ*l~6p z$>#c+`jL$`7Noh5prqYvPGv19*Q;#M-)uq5rACaPDpa2bKV*al8yo^V2Lap_XS1VU zC!>wjt8u#rxD9+uGtxN|(LiaZvSMn-?g!vu0% z@31(C%ZGzD;|NC$v@}SgiHrIa7!DYzlUp)rCOnRuR6SNqy>&_i^6qw2$GMg4OByW_ z0QJN9yS-*B4{x7Et|Y+jCmAMgik&y?9(NfbRSYQ1U$nC4OoJUu+(YWf7VLZXG`bae ztT%e0K_EC7RDHS~y76BWPU%_+-#&a*3Kagpa)%4&q(#C7 z%f)?dq;2hy%&Do^hz8XiNA;F7cSeVJ=SjrQwk3(*VsSh{`7o-i zEuz6iAy(Hz1LAv7qKt#`tK4?i;N3PaOGjmsUPAAH&TWJN46MgC?4dM97M_QR{*ur1 zZ%(A@8iCFn@+w><3Bwx4EBhmi2d=Mw%($T_3<=8D(vqGr+d#7*m}#!-aben><(M&| zUW4a?qk#Ut9Hsqaz6^Z|vLj51FL5o%+(=dkets~Fo(mj9KpZ?HD`gp^{bk~=nGv(t zG^&HLOEV;VIYLXHMwTR=Y*eKFg=L03;lwB&qaPVfhbOWUw^`vrkB3_xw|j{f+D?TB zx^I|1x4PpHU5}a;t)mTqo+rjZ2Ml70u zrm{rf_0|66kRTQ&c(zgf&A!m1ZYI+p{YL%Mcz&N-?AT_0UtY3k*OEbcjX zmY#0)WWek(xM<7z%B=2 zebJpQ9CwpXk|KIyWEAtDN;`ecnAg$6XY~sva`H5^CE+U4-k$8i`yDPpxNC7}qNdM&%AxnY?L)i_MNUhC-4bof zR6@}^lLYWnD$%5koL_Vt#CmVp`>0y8u#Dl~)|+K^D`8!)q3 z3zBB~;~xj9kqK)4GD-Qclj=KXLMXC=6`2%q1GPnfb4Ab@DL#UyRhC^WS5*N4A>jLS zotSj*^fueeSm-P?H`Qfjh)6ikMAnJ?MecABZFJtgwy;^EIYari^uz}ONex)-?mlef zdlEY>$(S{9#&L!ktO<=t0zGv%k|&z4(>ARO743HQT1}^33;V^nBf-fz4aw!%7~`^) zEZwB#)+fA>d^Rkw6bpY^n@-yOQFXn zlvdUc@KToE?i|EvS(wA=SSXo~7Vnw2jy4vm-j8ieeqOB%2X7Yt7hx+A)z%R7PHPrf zwUAWTUdZk+*rj&v4#Am$qU9*0HM)rr$vO(5ACKUv_#&)uzfK$rZ8_s=#ndN)NkRMW zSu$-;Im_=>$$N?9XubrPTe7h92 z{mH_vHn`22h*G^BXXmpiz~tsmN~*wj%2^B&2u-Q1vKh!U#>HbZsjS zX4f{y&F)=i+aJu~v+&#vmHEW27OCFiB6CilY6M+NC3C!z2$b_7bL1}CP16l`^6<<= zXe9B>f>JkPEhR1A0#XBfQ>($1%z+7_G+9g~0)3n_kJi2oGfOLPei(lW7&Vj`Bf{Kb z&TZG?ErE;}1fN{H=jr7{;M@Vg5wP2@G!6ZJ;clAEgTw8797GHZu5$GTD?Xr=Rn1Z` zDjRmQ0aWO-B3T7JQ(1Kp>&S$1X^t}% zO{HOxjoeeDzkxr(i&H2vuQX2o(y4deDOm4vVR0);5fUNna=DkGb?zHLnx3FtBlaN$ zBT^umiXV8P;Dm%bb(8*EKps5d*7!?e1+H2B7#PE%0YWc71KyQP>?6&timtaFK#$A+$!z>+BycU z3_WOa=IO}Fe8;^3D}*a^(Tq_(o8N!vr3S!YxyT)`E{`@r5! zvI(}_8E+Ct`4yD@YQu1~AN-Qh29>~t{it6}hZClU4FGm>q#taSSUvv zF5IW#oQUQYA?z(Nr-+Zc52`CTTV7elxu(fFfU{HfYeiS4&SGe$l)2R2xP&}3>79}t z_EI(7SD)d8Twi-_x5*S7jrnyD%7URCl#vMMqX4ue?3Gb*5U^A0OrI8zgUXCkK7crD zd0>z@U;pq7hW61@!nFplQp1;7)5C4j%+k(#?n#~DEJ%N4*3Q)V=%j)0*6(~>zsCp` zgs$9Y4Xe6ec=h7o+qF;`67v$qF{u!=q7xdF>W`)Q$RFFWV;miw8lZ&im5#PIwKT+Y zO&J8%`##mj61{ALi*XO>$lz(BK7Pq;in9#+LC1Dqxtv=;f1A6$`GNRPmSA-EKy3G) zB{(MeUn~K~e_H}=9hY@U4F8>~H^l6VlE@S$-_Ao zr?p2_w6xEUIw?tPg;ELcfhr61GVLU+x^^-un&oGVFe2K^>9ar&ni6 zheEw=Dvg;qy~A|#u({RF|HXwT<;ysiBK|#exW`|1C{N!A!{ZRpiB9L28W^aSZYL*; z?5?FM#cO%$gL@3_7r@D-$M}gRwjJ;XYlk8N+GR;!9c$kKByrxtW}V?Ic>+i}$qd!@ zZJYUYU*ebnd3$_^1f|)vjAGW;>GR_PX{!)vb@I6M4{)mc>8}i`L**!?e`&YpM`u2RDw6Ojqf&7y-kh7eiGNAtl;|X1Tun-DnO&=+g00rF z?0gyGfA4tWq}XzIOEh+86T8Y7tt%=|YNJ3F?W?AW&L|Bh|jwr$(lv6IO?_fFN+ z%(-V~zMn5${js~c->&sr@9O7S9ic_zGhTpAwC|=e8zsvEqG~|@qzUZj8QK{I^7dv6 z=H?aeOO<|K)3n5Q5rnpUsEh_gB{ufT$#b5-3~eXFcF{m_Nxc+<85 zdtU2oBT>%b!$90^4sX^^p@Ahl(C~=&!~NrG$pQJ65=`j&$4q#oimc#4Y>A8?;@-hU z<$NlzXS1p8@nu=q+>ps>eN0jA#XfzFzR!v&oFT3-qscX3_`xv9I-{ZXt4Erjy}{c% zhHt(|NnJm$L!;3K_=g7ehWI%_VuS&M7t!zc{`~&l;yT`=oL&`zs@L1+=$3I|P$u%a z(YG_!r<&cq7n*u(pUvL4M;fL-%~MX#ne%*;?(5!TfPt(;Ju+K8*RRGlk+a8Knt)>+ z{@FHos=EWsQ-7Z#wva4(O+S+%T=;kzzxen0l^R4GeTrGVcpsNkowvXpZGLMO`{0&q zX&u_g?wEVl4AKInDkP7K^$OO$Ta&9-(pXhBzIIhAcT7vKly30;gi#8C3_9)O_zYQ4IOg*K-!mN5Ru z2-dg7do7xRl0@KqbtgxFjdX43z!F{mnTY1vrKeZd(#(WUbiE!;-R_ksNtaefJz`Hf zK5u`dmjm;s%fYpJ9HFX?jp6JF&u&5o9ifROq9w2(uAi(76mu|Nz(-cH3=6!%nHw%pa1YyA8l~=;rU1i%Te}$mF12+PK+t2Il>%pY zS_B@ze;e9$Z|XS~k8c)vn*Mi89I{3cm%j{R@vp(%psS?bojamQyl0>}%~`@PSn`J@ za!fJX0Yj19Oj}!umlZml$G#gG_+v)ZB+Nir#$klfVOg|WYDG$%q;UCv(=p64@GfIs zygU}|RGs1RCDDfwF@!R-Ru)m~87c-%CfO7_w97TcRZIpH;&Qc7bdE%qXMdfjo*8@5 z_z0Lfh}D#cV5ko%dFuuyB!f1k^M9}bv|;#Y+8FyEJQhB}XMb#9>_uTK)tyMi`p!sH z#sqQ*`f(WjyyS7%?sEU|=8yNA-Rhkkz$Yxu{A# zmDFMh=1o6){m`Ku6!t|%ubQkkrEe6qy_zY8${l|Zy69D!&!Q~|Bz=)mmAiq&dOe6I zsi~C_id@W=L1N12Oec=8v|88K7ukh4gK5}e&!e$zIX45fjkU~9%F52Fh0((8-+g@; z4M<(B{i601#N};?>?G$D+aQPT3@2b>nF zeK$r=1`2NOuskH<-1R9-oigN;=dDrgQ#8{b>oe?UCsBRyzJ&dAIk| zDfmw?1+Qff4`4sUg8cugRlxbbS_O9dlE~k_^PdRYnXKe2gABq3_><$j5V{5$mnORt zF`dQ0G{Z4}lBBL{dd_We%KN~WTe!ERI|x!8+*Dm$_5kxHZdTFo!aqhE0T6k0*?lTy>muL2P$ zhRP~QS5W89ngPu@jRS^Up&Mv?NWl;--~B`+uwP({5WLPDreTm{#b#hevN^X?v!{h* zvV8yq>p`EBPZ(s`TM{HTog{^}$4UwBOXT~09nyBON!9BY?bw#GsbYE3IR1bPgTg6Y zaTf^6=M}UvNQ)}|OrVO6SoVsS@AKE}vHAv=Gg`{O;r2tXmg5BPT~ClHoIPFKm!Lz5 zn6Cbo5MotKc@Ooh(&R8}QmR?DD}VGHY6S*{Yg#0Q$#q|eFiVozQgVrK8t1CeN@3Dl zv0|Gj{~H>@SrYBkKJrQjD3Y0m#_$)(+!?kl8;os59?|`p@Eqwb+4q9pNqaeEAl0B% zrtj;$Xj$CZ9+@rI;S{)}dlznp5zgZe#yTYwy-IL$p2%p{5YB-%Tk;Xz64~8n^2kA;$|MVK_-$P(&;O>OBjN& z(V>vT-5}U1zwVqfe;+S`cueJu%jIuNa14fgMG&=^5^s@H4Y_eA@?;3JjDQ4>9wh|N z{^U^2(R}lM{R6_EQ0EZuSfI&3e^0pl3<a0}Z!w_Yc~G@X z&{r%|gf}QG7>GwjYT9jF?Z9o@vPg0Un3Rb{0N!J0D)!J!ZRlMzCfk-@dd)U7UyxhZ0yo4T z9r>x8e_3O;$>L8Bd9rgLjwxbzE+{9%$1M0EJKTc=aJ#GDHL4z-A;GmaX!`le98)!4 zt?98B1$)m;AZvXc{mhh1q>$*D!Q;c||3{0UIpb&>zk>@0!F7z*#mBGh6~VC~JAf;? zlt;z!a5YSr)ro}OjJK5^m>MdU>X~($7&Cy7NivJz| z9r|IK>*c3^Dj@0Nm3RXQB%UnZtfY4{c78V*lEsb;Fz9)lTaAXy+oWRK_owKm@*-$nDiq3Jw7nl(oUaL*YZgC3t7ec;XG%JG_ z*M)9u_zVlx4B9ni$64}WYuEU^biHXd{Rj?NMpy;vh+H>mfaL`v#JXlCL8LEHwvZ{i zuCO&gciE=YLT-)2#?{UD2tSV|ad-yJhPW*1h7#N4l?*yvinh2F7=)O%1Yogo7NuAT z7~L*xlwcO6mMrhQ;-kRDYDU+9beq|?BK~%Q(Oee|r8z7|K^I>2mkm@)fSWD%wrq5m zrh`d}jrn|C3`HIoj7YoTq0;R!8s#!@GG>r&jgg0!1h|PN`G+yn@Jn#H;W5G3qP)Yy zyf>W2y}t@1e1$Njp1|-{-w3_M*Q*E7+Wh83po*HvcQGHsKO;gEr4}aJlq-aTDbM0f zhA%_$D3RzQ`m_PHEBQTp3z`PYizNwrO5#w~3JqW1f5+sXwxZJ$LFGxOd)>&wxfpHj zUdBYTR1Vf(%wE;GAvG(ryzw!C9<)Y(4crGqcaZb& z;Pm9rR=w-@*NL700-q?jt5&4>hw{AEBY(>`9j<@*@J;M1W|MTV@*xnu^XwkK+Xe6F zVJK0HK`|6MRez%5FI{qym^+Q`Obh{>o+L8;ulU@86i>VuC@E+Izv}vwQr_vIG(Xp8 z2ruqeRngud4~Yd6W^QiEq$l{P^o;wr)1NJo;fPn)m!*&}skxeTY)Y`DJqu&{-{gKp z0_V(s%5lv})9`{LD#IRGJTG-h?|X;`8q>e~w9>w3zg`9Y)7l}qu~ohQ|Bd*?{6A`k zPPP9V@r%^EsN#qCmH&SweqD~jKOFp@2t2YVg7}&%r|Yh6jGXN?CuD6J#6-tql9oL} z7|cCjQy2oehJOoC_0w-Z47}>vNkLf734hahr4hh`VzTL3nT-sxP@pMEo~ZrUK&6no z(LG}!*d?0kuIqwBhHD^|$k3W{om+ZIFRJaRSRl*Vu2EemrenPd$T{L`M56D zoXW993G)z`cQSN5p_>0&mu9eX{DuC7<7okW{V_w?x(m?@v)D3#8DPp#S6`Yd!5Z7r zz{P9cWA?cXw7;7EavECiWwLb!`V{*((*4K-S5L{2!^(a9R3nI?m|D|X-Ntx4_=CXX zA7|pfjz`O2_x4l{Xz94fq%&H5wnSZMBn7hBCd77-6Pj0V-46(01nrSFP9jE)fc}yH!i%w~q`3yth2(B8 zn9D-RPk#i;IdG>C>VWSyd%beOJzYjIsK}hXC=Iv>uho@bC8nEqy&$|yM(Gd2cR_TW zfZ~IIu(`1acGLLXS*_HPS-16=e&}v$#jLhS1*SL4y-k-MjTREg)JmYGzM*Vu zs;cRe=3tKW6)X+YQ%7<7KRX#|{4fxP<|r+zNgvjbm&h7}X_%JDV>%>`(Au@}ND#4( zb|EI5dcn0hGrtHUc1<#Ac<)h+1_x@AH1*Jd64KC4XDQu|giOx}LugXq<$RoL~|skeQ7kU-C+{!6ZJHC|n1MvU-z z5GX5sd-@rJ!;fM?Hm3?Sby#N#q?M_bWqAZe_MnO_ozWau!+O#* zsb7kG8{AZawB=5{0whQnljwU5A*eM34w%vY z1IsC4T~W*N<~T0?=l8Z%G05^1c1w-*>{ z@Ua%Mm#-cq# ze-aS0!PRBk!z=eDK{m#prB&j#HTTC}D}8!t23sTQ3mz3AF<@9}uB};Ns{pd3gLapd zS(2}>U#q}=ChBHD4)h1KB_^d;FVP$!7KY*l0D}EcoxL)~JPD`9)Qzw<6d4HNT*e`E z5gnkiPBzlS>HI_GK4GUiIKTHY$ORs-^7~YIo6w||{j^oZ0`3QqVEkNInz+46J!sO6 z5_+A>VJBPzB41kpoXWv?<%hj?;~{_YcofF|sM!CPrR$fNTD0`-og1}H135^X7yl+$ zGU*c=V~|k71>VM$%;$aC>8=3A7K*Gr8csXz zTe#pizd=P0@DLA~D2^)gjL%L7wwyR|J|s?AVqSlH_?$r=2W z;oU07ra`gdJG%5eLzK-9xW~x*sHPwJmYlJOxG|FK{z{|HA6&L+0IE?3*@ z5`Ct7^As+g%{u9~!sYHLuBx=7!et3PT^O7kt|qNgHC43tW>?U!A+%Cb>+z0M%$aj; zyX9}Vw$~q8=KqrpNK@9l&HU4jANwz2H_Ly(GA}hZY;iaceHdo_e$R&4z)0-7NP?$= zj=0kM8yD7P6e|Q!*Hnp-RS{NYO{_d$R#PS*BXzi}Lv%m~5>}9LWwJOOPg*>mm5jAI zWzArSab1~rPSnfuRI5`md<%CgS)NJAERS$p*^$^IIx)A3L!96m>Dp18AcROg3bu#4M`L(0@Ri^c6XZK7<5XVFD zc`3)_ljE}e$g*rI@A$#SeId5<-TkKLfaCYB?VuNvs_$etc>K(8zwfB>`j{F{CI5wz z<)i~IqAUq@6n!9VpBQQX*LNBBiRHqo_;2#GMqX7zUfmTrjaN#tu!V6e^QLrFx~^7I zx(y&+bRM(Jqjloz!7;OiJuEIKE^2LFH6t#KA~bI2IBH+!tDP6YbsZcL<2@B9u@Jp? zUALrwx2FAVZrmo% z6F&4xyV&lT032w(5ze2S{W`Nx82b#m_;haEE>SAeloTK|4q3w}3Sb`B7|ueMmz20Q!{=L_&T3f49{LsHI+R!N z%c01p6S~%8oY@GxgsOhjA(D0@ybvzu){MtaIj}&@1H~geHBIY>qx4!MmRxe1evy-Q z|KaGl&A5Vqk^iO4bIVGwTvSB%SG<0Xh9esm3o~}W%{_c=Wo^Vdu{$$<+?DpyT84-;})RNZgBs3{&J*kyNNVK zl9pHlYx{j2iP{rQWfcH)i8v1wA->GImJa??3t04;$UTEj0fILau{+TKtI-SOKz9~J zpjSvj)1nX|^rAQxERt;<7OkhsE)VtmOO316qfkh7=uhX`2l1;Qg?Ig9CLt z`8fW}E?(}9?}YaL{c`NJv6uq9?x1nJ^VCUzz5{LdNzm>4P#*Ulnp5Wf<|y-zP`_STbBklJ&`rqDo}st70=*<;IoJ*p$4WYIq}Xdk=eRvrp=O35TRF$sj_9dGM&70LzA-xxJ+NHqyy5Bs7Hwt|j@ zRb=2UiV!#CulPEjx3u5;QoKcqbF_KF(sIMZ>iMu5c%)Wv!B2982+k@5+T$^k+Dw1= znC4&ykRb7=^DQi}*tL$uNFOx#T7-CssIsi`UGCMSfV1b_o4iGs0z_Fb!PZ8d{dmkn z5_2J<-EdEd%WiSsz^#8%hi94+dyed^2xdqk%R*WMniOB(!qCW!pjRaCxVOHGk;87~ zjJ7KW?VR*Vdv8k5U`1J0V}NlCYzw%z@=?UX8E(Wu$g3DxY9kH9F%p|0K$D;>9UM-* zA~;BTuc6QWx>Pr-f|u z$!#P_W$kmndCM3UhN(bt$40MKK{R%dt;ClSH-E8PPeks|Kp_n^YtWa42<6 z$N+XCYq;w_2w!lJy+6Gc(|dn4_gl9kaR2*_Z1^tNXbA{N;-I{9O@OUf2GYM zcbMy$H3A#z!-D?BOLJxV@mD?>M@`GHCj`FW{91DwjQCm_%8=r$&aa>_80dQB_Y3Ue z1oV2{oCI9Nc@A-5P;e*#gmkFrPl=@5%Bp*wtoFgkj2y>-Gblqx0pll5$4V|kxvk|W za_XRAA)GUOQ7!czq9Ua{Cl0%$!h5&*lyfK7%>K@$?betG*g)2GnND+Fh z5w%5U{>#4iITsSz5CirT-DdBoZ!{sbSI8V3%o(f4!(K$d9NGQnW0ssB`O?;qN8B6# zk8iub-z(aTN-oq2QG^Oq{qz)h|CT?w43TQaz+Ci@!ET7G@<<>7FGG z1rKbdFbrJWAE6yfhoY8E+T?TPH{tW~7>Ok()@wQ0GfjVY;4t{7LVq~| z%YOEy=zPtaE5=fS&Qj};zy7+!Kse^N9?2!JxRST2&MZ5|Kv4I3Aod)XwZHb!cfXgxj*ZWC7^5 zHi;M^xBI%Rs(OtDohRqWG?wPw4xu_Gg7p>c+cev|OAg4H5b{47uEUjp>nIEtnhh3` zrDt3gGzLn?M81GA6(Z(=Z>%jsP_V0d;3a%uMn0dK7w}}VB|GVCev5bJ>rWk0XIqXN zDt+mnntyPuKHW9@*NJa}GUAJkf8$Ct)efZ#Z1+q3@|Vp*+C-j~Z1_MV58!e7Ftx4L zvJv4Q=5~F$^pL-7wU4I3w)6al+Pu8kiaKR6poo+vv_9u-M&fd0I>F zMgWLR9Vz3E%Wq6Ks#CQwEd}3gPH*h{>Ya3H*4O6@_9iF)qX`Szx!GLZX(Meb-XsY0 z#(N`!*-DO0$NML!w8rqEt9bDvp#A#wpH88*CZ|omjbKN`9>#7`?f< z*-SPUOXtTwHrUx%a;k%b7`6}tQIa@;1`Fc@n`V9jgNMEIDTXu_jwuV~eMRvCTCrL> zX`4%PP4B$&vXg~bxs-ShD1}#UWnTPp?=CZZRX5no3hp^)HfPP?s4fgCYmPWeFy9qk zs4ZGm_j)Sb=(ZL(B3e!&KDNAo459Y2nSB-a4oTyc0`^#x^m!AB+ohv=VLtIh6RbHMr!A}P;3A5!gz?QUgbl!7@Qkzjs-;_l z%8|6sEw~sxxik!XWP7|4^~h~3h_SvGr#KeCEaGv;Ehw5P4nplW)hAM_`u2VeCO!r>18P~z!v z4QgYuI>!Fgw|5J8wd}lHyXBuA_gmtAY{#%K)N!)KOcSIUJ+s~&t@_yliz$M6tU+o6 zk0yG0JRUs)Ss|h+{B|IC#W-YLo_!b_2Gdi0RMxxiDKQWWt{*q49;1rWobMympnI~e zxACDQBopK~IR$q%$7!vfdt^UoK_#_LAvkQ^BHlCnnO_M@fu6-3lCa(@pmK3wM)Q2(fgsDYgts)JsU#Saqmj>ezJ z{`>R|TmWxKqdTss2g7fMlaqvY9{i+%VOX$!j{OJdwMV2l)e0eKQSXVsU=(E1u`i4q z=wPcHKtP78Zd*&|8M+K0^A)A!`H?(vIPd`kCwjxGOrey8h!!HvU=Md{&*K@XP^CAq zc2n=-&BkDCU8=Zd!UpOgBoBr&Pjs8Dea`L~vMv&E(k@24#xkR(dE_^z6gTQure9*Y zJ4ai$BqA+gLg#&UEPhu~kCDhV%{AR6sU@s~{Ll*%RZFq)oB}wp+p0`T#Fl+kp5x5s z^RVtLW3A3-B$^AUD?AgNgV18wj>__I@zT0DK1pQ}qD0V=sC2?!!tAJ;Ug6vy@&2># z!~dt`{Xd!9|DC-5J9+J~8iSlgtV2zo^9jCxb|1 z$8Lii(U+k1JKzEzfL`G{kr>1oV$Ks0u=;2i4IaC0MwNN*ikK9+YO0l3H} z=UHbZM_SEVAa!m~$sfySoGaO;4mRxzpHDXB1o`&!t4!?oeLoV%U}rOHCbAD)r ze#F_N-CTBRv!#SO(F_}H%k9qE?!G9%THrroMhTUy4t1xHpN$**oQ zo7PvZYurg}d`orF3dujDBbJ^U&~_`HAnQP)lXY`c%l&Mv-Gf61(w`Y}7})d{Bs2FR zwmX8WYUoz<7+#DkmDi5}B8 z&F{7VaQ~IMpLrjT2a2uk$8V9#a2#x_X`|dA+fW54E@vB>Y_?Ja1#Mzgv{6-M?JBa2 zG_+LhKUS>iZ#K@$=AzrM)vg*xGYFMCPX4lmAQ--Q9dN6?HJgw;ns_oBq(wIJ6$@O= ztGlUlpZR#WIipa&OWm{U!SRTVBD$J;VJf38c@w7CwoYC^!A^My@nns#?6(jXE`>Ro zK~+{^oa`dSHj8GC0qr4*b4+jBTC5x_r&=~l4UbI0YWPJFAOn~f0h-_iZ z{vtA;AO9`%%O!%}ua!Jp5319%j#IuC?^j@WA9;8=sU_lT0Rqoqcuxqf=o6!u{;!## zkJ`RVN+!42-~zcBuk_>C+&_}41*YL1YDS)tEt3kC+M1H{2^blVy!JUY)OTBxvs|~65~%v6Zk-_qDl601{TvxJcHP>;%`!B$GM5+^mQEf zUqBXjuIO4i?tXw<2zcP?zc`id5|zug*a}p;!)#tMKRLmjm7ALI=#4n`{}E2-w)XoSk;*a)j%7p13KK=d$cj|gjwLfV7Of&1a`(974cx$Ih3 zeokvtSN)Kjk?6|cPa`q3yCq;Iz4UT6N=&tmHnM5h3$b@X_}I&KR<3hCYD?{IhiAIu zM@4Vf{bdpffk$Uw%7)*?%==m(qb{1dgQL1UTt}jY{@4>^BqBpKTraDt+Frq>lD!@V z(mwa8vA~DiY3Eu!63|qp@s|%=kgUPaJs|mlq2%QIKi&P8gyHc{{F#{*WBT8J*qFKg zV`f&{M){x_{ma+BS&nGUH zRJ;E0PcGHbbSeXEs`qww!M)k-Q^`(ho|8f%Ywld$hOK9{NIq53w5aBJueGA*DSbVy?}AlP!!OM@ODC*JDh>9pdeiHWbt+?4TTmP$qE` zhvntWXdVs)DcKmG!%kNg?FXQ6zr~50*SVvb#V6blgT8HA6EQ*R39&y(cLnR0p~eRr zS&!+f{>?VLBqsNP$g>FIR_iodgL2&Wr5pSceCKw+#=NV~yxSx9R@b&(N6GaY=B61; zT~!5rCq>^D@d3^GJq!25tJf6hZ*%8U;uM0eV)1~RL*`nt<^*NBn@b5dA|bWxaVu1C zCiO*k+S2k41}W?h`RTK&5M-9S5n-a5GmnlUf|WLq33cWZXj=o2@7s~7mrY~J9kzLJjd z_dS_enp=h=gIsANqgb<~#Zc{D3l49)p)W?~kP1CE%rWF9!|-5Eb2OYlyI*M!>Q5{F zmheVd2_EbbftYHA4EpbT(jdc#ob9cg%2oG7c@qGdar_qle4(dAsydr?3D$R-!C&>- z7-{54QoD^l9tugjZWRt2r`vJNw(^hZq-)C&@Sxw*(x}AWBwK=<%R}DT$Q`+Q4O?RM z11!G65U)c^TZOa0 z`XgpY0eTo3E*skP+PY*v^KNNcL9seSCLgxxQ_~gS! zPA82e^0)`s5r5~JVWNS-S=XVA|X8NO58tR9*;AP)jja53x-%rHQ1e0#^Bxvgxpf6)a)zbd!V|eL1Ktnhk!RXW4|#fD=>9U@d6~30LkCF>9eHof9+pao#>K) z&uM?FXx{F8F@G^!I;@hLOXJD9R!Wv)$$Uupf=T~vQS2zJI8EJL#%2>QEPhP_o;Y;p zUgsiOBl{cWq?5017tK(NCWC#}12wO-S1MBe+OH2pMIJ{jTY{Pwg|}H0WL3SUI7Jg- z)0d9YxT{s^v(X!Aq8LJx5ADU=Uddfuqzcm<2*H!59iWz{F0Q8gb{rr^P$T>VnRhh0 zFa9~Jm3FmyEMcj=dkjW*if+Bb-q{RJRij)@+&uZFV*#lIkuXe*;t4EZV)~18gSRa8 z2an^2qeM-jRB^D;WM!mPWqi0vO|LgFIow8Ad0fLG{@F0*(DjwWhNDQeB;$zeeKhnQ zo;uf()rjR=H5vZ`Z`6oqx=&Km2NdJWA!dG-*bR=wwKj`Y z>i~1L&~6{|SJ4PJc)i92CaxVm8#^R6PB6ys!nsiEzZlQ>rUZ1*^!x;LzTEk$s5K7w z8p2OpU7bEovDozuxVRCo7aw>MBk%2V)|cR}r8#pfZ#{Tr!CVrve_GE@EZ+VM#4BO+ z(K`lF2Ki4lIS+V_@in$>z*+H<>ctaL6EVXAo7U}c3Qq9~iJ9bQy>ar933bdkzmKg} z5Bf_;sK9eNlC{*gfp}0}EP(!MclYD$J37U(B?riMv`w%rC7d0N=3)(zo)j4l2CzrL zMPtu^iRq==Mu(iL!BV~iyU~ON;|!ngydk+Ci}VLQIuRB$2FC#(Vbhv32GW&LwP{5ZM&Q=mJ^`_EqT4vlns6C4 zlDnkqUF-8~%*zN-#3RkZ)L!^B(PS*hIv!uybwuG|U7GOcWM%TnyFRx^D@Vfjk5??l zbSTtj%^n;dqv4O1#aaGl4;wvgtTOZtADU%&MV>%S-zrVzVX`;kjF{{1FR5+Ldkvb` zs<`|N7FO$^%)HdaL(SfqKa`QDOLQP-Nl=EGYRsz2jlYpl;HOkRO~~m?i{Ig>Ra~2( z4r}d|%~^ct9q}XfVpCdShbUO*(Rt|?_d>}l@T1eUhL%z#+GwrM&sMy{N|}CJl*&nu zs;`a6(zzOtiSg7rs+N{(MW~B(N-z4S+z<{~?F~K1Ii*@nXgBT*UNXk7FBa9cPcHTd!kFAD+IhEZl#4-pzbn zU45C~k5`=ZKIM>y#yD<@PtwAc+`he+-k&}`FB6}$r)sw4?5ZX1EA-FRd9!o8-A8IW zNyod}(sgC+0GE#&_s=WWHh$f{0(^h@IKBPYI?xp_V=^kaAAcV?D!bS;^TZU}T(OMc-PZMMVgu({hm|@?DzV;LieEm8 zS>`cl=7eJEAyF|g=Ez1&@z@fnj!pp|m%qb%<6D?*!Gbm6(L@n7uAws%^&x5aS#NjYu%hF`+5G##%F}Zijk`Vb%bTe}4e2b*x3&d3F$75vbi__? z)5H7W{PgJH;77fKwZTE~ZS3lF=eozEKY(U7L$6@o)1iygF~xuUN)Sz7vNOM!Q*|GLf_GwIR|IxB3`nnkMHf+-|l$B;I!XbZnKaXk@GyD z*A3cn5U`DNE9IicbE_PFWY8X_OYN3*T400E?+9Ny2$ed#`nfw033DpP@}D1t196>M zeR$tZ`FY&$W%bF1I`@UYF7BYFI`Tp4p#2Z5BR0%$V{E;-}ur+%awKC zvaidk<HzO-0_yJ_s+dSnC|Zk z9ul7nT{JNk@)8HDQl`IwjjZ>0y)W2d>GW}~ie z^&#NdXg6jLm`v0ammuK?{oM)laugVF^zbu(ho3>nZs2cco9+{+{v$eBKYpKA2bjxM--Mi|1NR)3mAD|H@8@CrP6A;UaNFj9VnI zcgM)mO-(!zDN|5c-4QBRL8cz;C^5n_Hx(p$UGt1C4k*wmj|9ouz|mPt4|F4A$A?OT zG~MaS95d(?`*L*gc4^QnQg|hozEa}F4Y_9(R2@4QK6FntEtVqAWr*q^RPMHcpKM4k zO7Y@jU>OOdA0FHiDl+9GAiD$*;x;bMsLKrHnxHlb$qfCS;}q?$w~sHa@-WFug;s7I zhU-$1ieX_;&e59^F!2AaRqigSJyBEIKttD)1WV?UNg2czrnM!>Nxt>mnu?eGSEIwmsYnY`% z$$5}19_oKHs2-19eo1F5SizY@dn0E{ZBexLt|SG+ezwaqQ?On~wzLfxR!B~{F04bh z0s^u%jGJQu4&*D}%%Qkw+<8nM2S5?xQq1&8rLrR)e_ten4q8@Y#T}j~ZY(h=Q2LR= z888)wVPLsCEr00EAR?5!F~Ge5)pQOvFixpq9bRGRR=J`%x(A>1-59Cf&I2X~u%z&e z8vWyv6tX055XR|(MoEkg?aPVanA0>imI*AIL^4?c<9|aKNxiAOv3>iRNG#5roC8CC zi`;3!{ik-Qwjf(Th=1s_>|-7B{G<_ZOr8Q5wB5jj$F%X$wVf74qORDp!uWT7!<|T> z-Y6L_yM|TDK2iV9tJA5N!9J(gMxf?mQ^l zP=f_xIB$`AcT2#Vg??}mi{2fEug4c!Ul0E>k+7Cd#obkFDl?4=@JCs8swFt|zwdH) zh;26@SRtFC8!kg^A^8tO2>}5l4#?^{mHe;yz^qVnxTdn3X57=0LKfJOM$TZ3LE-=A zAuIFc>t2*aL=IRpOoGi(rKD;@LgCVL6YDAK!Dv~=qJm!}-DF?*Jo^Vq@XNR58*4*!4GO-TJpvOTL{IhtDmWL;4Krd377x~3_L_fM7#8nbVJ9Lex zkEYtbr{`Z1NE3y01G0FkNZ(zwP$&&3Yk2xe2W*l;B7iesGyahL09O|=*VW0Fxy#+% zWuHX&jc|%_?)Y;Jvo`1&ysc2tl654k36{Z0WrFGU4aLyA7hVg19KdFx{6)%aSjoX}^D`^IDG1ENF!m4pqZs znVLp(F5TQVl7EoR5Q)xPk+aLbq|R#9B`%NeVqFoAYuSnEd!fIyDEz@ff`IRdLJT*S zB#Wlw@=cr^w$vj=gO;O!)=soRJJJl*HUyz;SyqSJC5Pg&CR_)3V`G=6(6k~7dcF&QfiD1KAXaV}ikO=bPN{+(m{Y z;>Nmkn}n~1qd%a;D_}6ZAh!#?AdRvLTfx~Vr+F?w!idj`PZ7uUpTgNBXh)?hGX8El z^A=wWXB#q5bZ$L;nCQ#*Pz0LWuYBA19V7vppAN&`FDJM!evN67RxwfR`3IBPLs;a6 zRdQYQ@Qv|=lgRJG~Y!G*w@wIKPZweqdW%9NjM8Xsm!#zVV zztvz;s~HWQDh&sBF;Ec`?c5~AD7^-xppfSx$JvIqy|0!4G-~{so}>_QcaSSu(L58x zcx&e^I5jtea4&dHS;arvI5Fz*W;aAI1Opo6J#n6twTNP_7d{P)E({v-A{495S40cpa)t z{@^7j@q>p~KH`@Wqj@jr8>5oWZSIB;inh@lU0i8?1V3h#AQk!y5VssJ_f`~{PxKLI zTH%1o!)a;1CZ9~ZJybBfRH%i!IF8aO>SpA4CWd8#TsXp2XZer;Ss%NxeF>q;zyT}w zFB=dFs0gXqBc(>?U-H^80@Y6TCVwOPwzN#(IFEkOBE$)WHX&c6`Dn5<5EC02W{TOn zi?1}=^-)>oY{CZ%!rF=TXk%oIH|$sU&VrU!XLV1VigW#`D}x%^z>5HvJu_DLeeFiR zFP++)C!>H4RnzoO$5o zE8M-HWDymKOhL~s%UOe0+U@*T?3kPyGj)O&Q-tn8Q+1LN{l{0vWhLc00#2L%4ZUaSu%91c!V2)3E!0sbLh7Ux=_61HDIb=Cq z+-~5nojLEwEbJgi91;vv{Vax9)~FT*{=BwzNv_HsA3&((cOyQ$=o_CYjz3Iox?tF2>YO*QB4sny_~+giyLE(>ZoRH|vX z+HA)!UHA*dGceHn;BiDJ*~y%`3@pY7bLborX0)E>h$$umMg?-Wyv!G-0FERr2MrfVYV5o|VP)<}U z6PKUO8e-?lo=NSy3t6=1Xil1-In@H?=qgDmfz*%$BQMAE&Vf6OpnD;#sB70vz0#wo z^nr-mR1*DbtB}#)Rlydt!D^h*U=X~qu2$Am^H|}%OBE#j<~%Yl++oRLF(tyC`mqpI zVrW9{{|8&|7$sQ~H0ri(+qP}nwyo)D+qOAv+qP}Hd)nr-`_}uNbJjg~t@|%m?VYhB zBBQEuXFeG*j7(xvFT(Sfzd+8f-cKn#SA=34*~HlB+-3}?(mR8mRI;yQ?5eAXwh^*E z9H|A*oavs!+!n}aX9=|@pY)t~%p%IwTE`z|E!B>Q!6HJ4Jd`gF&VIDI&nMvyVp~`t ztyOD5fn#&Hlm-Ofj!;)^iiwl$6UZvp);NyKuN9tRG$oiTM;z*&&Mn9#I{ zOOSd$1}A@3Nv`0Vx3jnID1atKOHeW;8Bo0Lp};Tfn|+M)@n2;lAnh~GnBY_fy=ZFP zg-_Fnq5M(BABWq4HO-}|OBy!gh2M22Yo{ua?FdHY_P}l|JVZsDVIPNUmQ8sDTjIg( z;En>BXiFZBmTVsSY?)1{DdYT#qx7>k(P161WzJcW44an3#CDyGGM}y88puaW2GF{K zPlSB6__y#^Xt}{AHz4@Wz+R=INno7;DOO`_(hrR#h?5F+$m;}=yh-~9#YF#Nm{dhu zv*FN|ec60h8|nr^&A{4>gUP8w)a;@ls9KMR6~vf96Hs1IX~6c=^^J1UZA4#LsVD+$ z%wKQZu)^D#Th5#GQV5|np7QK*6x1vatJVBCa5QWM59VL?56*CP2@x6;Q=U>NK#F$) zIKVl|o2<@=MTJZ_Au*Kd254ljJ;lkW_ti-Dxsv9^ZIABD)kv6)?UVQet|uy4+m41? zmo%Acoh-Lg%|T(^|MA;Cj;X1v1WT^_m}m!*6MrKW$0UHrLIK~SSxw+^x3T3DWpjJ5 z0Er|0gV~;nFs0@FzdewOXOuHdk)iftGY-d5Y0(aY@Ac9DUJ^l(` zs|B6YynzxQ3oi(1p^xlXeFXXeX|i1nE&Y-=tsefuGHWPlS`MU)Oanhy{dLee z*Ay-h51npH1HS`5TzxmS#}?U%&~D_*k9gUsUsZITZRLergpy7Ve1HfInxS8LdEhh9 zxY_w{372+2p-ym`lU>{pru#FK@FM9~Va%&D%TW^K20h9JyyCuY>(5#&G%tzf9 z-?E(bRbx0SPz=Y*8tb4%Nv`k9rW{sAWYbdg7+6p`SD4!3u44^b4W(ZT40pS=c{bky z@XEFs+E+Yl#M;>agO&G{#1njdc5=BYO<3K~9u_a4rQeX)ZP8GpxSgN;HR8{3*y<~! z$}sw@OV+ee=vg{zvC0_&q(9ntK_$J0b3B_l^@_kJ_G-D^u9$jIU}vut3d$JHV!k zH@h4>+1k+Wx7QZ(Hrdo+7{O(1wNLYM)^-Gc=x{izZZ{4l zULs|Z+THwLsb0hN-fktdUi<)s^q#zegZvqShQcj1cCQpx;tFPs#yaJ$yqJc`{~ndG zEht&m*XX=0SX*~Ft+*;!m$OQ}tLv-%JRULvW{HZLmI?17u%u?K^~H=8tmSg6U`nDd zTL4`kE?w3DdKvtu7i(9pD+GCoTishH>?K^>KR_o<_EMLlhsEz6a=>t_{Wsi{tjpMJ zsSAB{mv0WwnKo-bI2$p`SGX5&3|C7{(j$EsUCj8Wz=kZKCQfhxr{QW~mx>9m)z%bJ z_gf0!-_kxhzumd=?=!csyB#uZK^jx(N-Fcj7iji$z`#MA>R-ay{C@l|j=TR)9P>3p zqgGlNWvenTW8+=GRSqI`>KK)Q6jg~XP~=K8OW`wD^;KL-{egFd@aHYJ8R^dW*?dBQ zPmS8Bu^8yYL3^eLgp+Kn3oiPnu6+r>DYFcEgF%cUEdL`8pnaQ~CcprH|DO4(_l{pT z^?o=pEpX#CRdkIxgswd+PxRM1Bl{ zLqt~y<5Ynk%U_NG>~ZFBiB(y?2Vtl5R2XyKjZYRq(P!$`(a1Vn%7 zSf|S?i;ab>QE`as>SnPj$q5!{(0uipITGN7i8|^|m9zg*QK_#jDc0;3FA=uHTo2$K8Wlngi zJ6&Te>+|z>y%2b6`yM+V3D4Ap;t%73wt%Eh4r>+BebP=6TIsvkUPHo_ z$mcq3#-^5kUo3EcLSZC9D~@?2zF42!Dz644%$=NP*kNh(r4S7QCx_juw8Flsuy@Tn}% z-ajky$)p4ne5Awr&|IrLU6}2)u$Xa1%!(_0&1@a#k@lmRUK5X|d+b?3%CA&|tA~t- zzv5F0oWaDneVaK-RTWIF1Jg$cbmc4pzDyr$ser((BJUol(2RLFL3ZUS=B4?BzgLBM z#@Q-SgteKAx+2$(szK(O?6-#3r*qYMK#)T2&2oBOHzC2Wc|7If(31I@lIP)vgCBj<={7&dG>M_NhT~m-3b3|7y~dNfc6Eu?3-#3`J(8KEUvJG(wdQ zF=t}Fr8buQN?JOs&Y1Te{gW?f&NHyk7{qgejela4?Hj$t|FC-TIyT^8B?$)|S_clQJKN<_Ggc-0xgTMBCyM zg`{jEyQ9_bd^m2gyrh!F;Nj=2;i6Y_#v|2}o6 z8WF`b*p~>fBOCr9jb#NJ8QiX!b%M+k@}`Z2i-a)N*}$iab)pj5)8Q<&r=n}+F&xPPZR{u@>0Ovf&N3yu_fLGb}(K34$!p; z5SpGDYpWq8ec-q~J(q#CQbRsG^aw+_%bc6^qqA&?Uv8}-V0FU!6?{f44E2K)LU~~} zyYP_-%frg)U~w#}RRU018whK)V~lu+ik{9YC$-Vd=GDDZTaA`8_ye@$7unM+v$+ql zTOHyQW6A`y=Va+(1gb~naJC^8998Abz~|ql`j7egRL$@o^I6rBM#(?lQi|K{CJQQ>^ae9u^#K5vax`z>`bz7Z#-k(OfcgB`_D=W zH3WeXwHGK(n?1#er_G8~=*eIJe295M83^G#pK913m$4*CR+xiy?Tq;_*v(Osm}Nao!ehVPQ%w2}%mdB+eJYA{dhIiStIf zB7udiI3U4i3Dbybiw6_v z;G$n00{vd7<=-FmPLx%$l-Yxf1^Yw;m;argukxG!YqI0GCSWMSn&3fpY@7`L95~48 zK;z3=1EHb~7O@I9D=|#T(<(Cs>G@Ez)^#P{o}1a2@VpH&n0HF00fcy#H+K3ft+3aY zL~6R%+d1h*z)I{YiwNqsWETI(SuqD`an)ii5OO$Aq)paB!DiHjm#Vp-1|47nr`;J{ z7xD#V%(S-CkY=&TST4sZL32@{?znwh#FuYIrG&DjlgENdQDEKPDkRz!kCY;2gGo(M z@KAAndvW0)Y9yR#thK$iYP|r~%9;7{AsUkNJ)2>CW?rPlZ7AVWB``OO4=q`%ay`{s z{VHKqiP_=`Z;FJDr+h6|oOX~tcnTObTfo0$eL$6!4va4#G*;HwaK(nvg8>f`<0z$o zylO471!^TypukAtgP~4jV6xtlckJA`MM38)R{1(#*=`lEc`-ab=@t;kD=TT(GhPeG zNmQ*Fuq$h-n`QJ+ z-{R!S5qyn{2|4dYb*+f zkqYCD=?CFZ?&1Gz_cX^x87CaO#Sek z-ISenEC!0Up9WSFNj5>`%kMbT<#gaMwvsV!n|+qA_|#ZRBpo>wx@Lh!!|&iw>_|-f zR@}cO`5qP%m7|q~31rhm^5+G1%ydleTn_e3cUvnmdWfte|kKbq=UN>;s_y}tBA7gy~>&ah*Mr{M)S|n*fJQ1Tsz9mcJ4t;X7 z@bT!Ke7jKN46iz{ccL=*Z6NAmpQd_5^SuUUtSHV&dw3HTmDf~xlATQSEesEY@8q$DrJ>b0+taD;c4 zX4ZToe)Sq~Ou`J*#wsX4;BS#t^L$ISsQ-`jSf_-rufLgAT!FdH8^>-PHii{hZ}x&%;W zq(iJ}v1n%+BoV^yQ3|s{bMP-uPQS3e6c4-YbB$_?dcdS8Wi&l_$JpoKf>Q=m?5{4F zuIN?^KJdb1MMJw6cy>v}Rc^gSm4vZzvB8U=8o?P+i-;}#fXP*VPi69W7&)?)F=3Las`|Awj)5mmm-`7Kq3 z>UHRGpH3X4RQja!eE2NsS0RV+83;*f4*jD0EjRPjZgukTky=>X_!wKyJolO^5(Oow z1y>C5w`Tio=l7~6B=Y9k(nwBlMgb}B2_jduf%@;sLsYaar1?nM+u1ta1oOdxo4;Fy z;{K^$6s9jiYQIG4ZLNr<6b7O0#w8ls6Z%8LG_v$(v+yO1>uvvaP0I&G4iuFr3Dj1O ziq*@x=UlZ3ZszmO&RTEY<%NjtSnM#<`~S(|u_1IB1mAF- z#bKs-!*w3z^FnZe^YrKQG9=IeJ=HDRnrW@Q}G;dxy zx|HO3hz$t{2J{{ljC!?@W|ZI5qrTh*6HvnAn>f!v8oXroJj1M~!84G!K)#$xEx!H8 z7F%TwcJT-iFfXqjKcpi#(u^E1urtYCvi`k(q4{$FJ0x+Z8XK`IB-jYfi0~gIpg~PI zYoU+_g^RVecjdVi5Qo}b>h86W9_aygJ+mtRHfk~E7*gjD#uG`4d3?&y&5jD(NQXbdyoaGilBP1&Bou}@NCfD5SgUPgM;=LMz&IB z(PQ0%!6xp%!_C=H%18qvehM%gsJ(JM4T%MxU!eRJijlsEn?}kXz*iy=MoGE~){qp4 z_RYq;-`5yCz59zK24=e^X%iTJhbkg1MNdKt&C^h43nn-r89=)VGuN!P3{0S2PueUI zf&0cA(omf}BQjnNRkq&JCq~!F$brhF#!VFe=I_rX_%?P_br1j z2=P~AnuFkgGYJSNQfCHZ$9?J=WL|VB_w+F7pF{xsncAVk{li5#AFd?K88!~0$;kE~ z>yupLiT(S^pIB0pkl_deBt$%BkO!soc-s!FJKl?b@2;uC<0NuWnINvocLZKFJM~Dl zT1Qq-`_F#o@qD+CA<`OnQ9#&8uLIAlf1Vk)PHg&ux=hm-#^A%e>9+{|^}g4E3%s(P zr7z>t#!u&i(sOMI!@y2=3f5djCPkh7V}s#$xx2(I!oG{itFZ{%L#$9=CCK#shYFE( zZB1b=AK?)??Y2aMe78nwh}XvawK^E6IRb9Edp z&_01+tLc|#Fv*L>C>|t{FYe{OlTqJ>vQhP{7cVys0#p1ELwS)~I&P3X!|eJR51qOT zCXv!empBm-2n994kS&xgyd0`uyp6r?SSA&gkPSc7{Tbo-?8tgDtG9z*qMtJy8f~2l zCj2^(x^+xaCuE4;)e945zMi6!mc^j)D52toh-bK)-GFljbb=B?Z0VHUPSj^sWjvTW z;SQ$36tms28N?(YR6?lOBgaMb8yp`|Nh6}ptms0QYx9qD|7f%4mti;|S%*ZB+YA}~ zEx%M^H}A{ZD6m9Ulv*x@@Zpjen2C5o;H$sp=Rh%ENH5`k4MHXQyYs?O%J*i(?{2z+58# zOt>@Rd=6vu6p)N1sjvu^hcj(9M#=&n8g77U0Z!<7GTm zjNusl?P3O!fhh&ykqLGhov3=n^6r`j4BH`l#S`h76fbwMn12m@o9yKCjTq+uU#R~L zi)wyUj6~9}`5^T-)^BKiC7~yNG#y|4YZVS#er0J87i$W$7SLD()!TUw@haFDgEr!2G(;V9u}4`g>(` zd+5=ooHa?shfJ;?lBsY2nNIh9TWHcNkwdgG;cP5R+WO^OrZ&-3I2HR-D*B$5+R4c{ z=LkRDINqNl0F}_cq~ZmO_fz!&S$L)1JX>!4G%xzzX{ej#TY55)3rwh^9|aK{^s`C0 zAc?;P`$uiuoqz2!z)&ByIQ{Xc?Q!p2D0hyr>{c|7k)!@c_r3}^0zS}R?R%?FF*;lq z$aC#5Vhd=UD97+WTl_m}yoc*NV2p#Q8dY{OCmD^uVgHi;=BNA#50MGxM*l%qr1aCL zUQ~D$UPD`O;>xe*+J*KI5o8Wnx-+Cjl)hl`Xez`lycqT)O4XZSqexb3nz9js504}- zXhZ}F!J*C#pva;*(L4MT1Bs>2HeI@o+0ARUkpjiMrrV_GVhf@cDO57ZkTwXD${w(kJPReS z-|Qdx7zAn!v2p}(ZRtT?@KrkC=e`^NmP2kTi>hL(Yg2qR^&@pk$@nw_Ufc9m4tT0T0&S#gzJL{T33bu&B zAukZd;7^{4c}N7~dYj;Aj`g0qwt=GP z{S3Gkikk(f!Bp;dgdSm>boqARRjlt^f@e8lL6UKf(UuBHVOvt0)7V)G2zJQAh@q-u zPahQe=Meg%W*Q~)(e<-%8yk8|3Q+BW7rJHk$X~N&9rcm4z|HD{BU&e5yuH|egs|Es zZ4$wQ2$_G}al=%0 zVAL|KM>n$-niJAV=)%HzCmV=zM*@+N80FW?W7=KO+zw<3BVtnjrlRLujnOOlOaQAf zp)Bans4G}^k{`Mj@Y=47u5|Ap7gVU5E#o|Wlx;IEz1b*w8~MC={d;}2bG31Ne&zlz zgdW=M|FdXaW^^Dv&c~Y&mO9Jr1Jiea6zpDrP zAKVr(Y}a08;o=+4ckF{jv(hhWec@ouy5OPvW6dSpxXwoS{*Q*dgStr>qT+5As>o1@#`u~AalWLiQ*%=}Y zL-l|83SOdXg3^XT#h?0wJioVRO=eJ?qC_Mk(l5tZy06ozc~6N(>%EZ75v>`T8NKjG z+k9cRbfGiBf{^`hLiGpC`su*JO^}+K1#7A4Qj)ON@#OZx(y2&u(foKwrM#4b>*XLb zKON)GJtO#>%NreedeCc`3TUbki-*KiArg#D?+z5{qbt3?SHNsUjLbLIfjO80;&Gz6 zD;Ri!CFXxIHuEi908B`!4H%H~`T4}xY2O6fQ0-H5`7v~|yHL4gMe zS{mYC6E8sQXyTh$Y;V0uD!DjWI&w-XIZ@}zPT6)e7hIa10eMNp za8v!`D}Ol(h#w(w+{M?cs4o0i4g;K4RR>d6<5KEYS-0}KL8HPjJ;r?9RMRJRKgaOqj$s8sE%( zP}2$fLT{#;gc959EKLnv5K$?|*+>Uk&@jr(=4YO^J+s!T(>Vs9%2u#{Wl27Jc9OVs zqoUv6O3vj8db|2Oxi_b-A>NvqK|3!=U!F*$ZuGnoR4hu7R`y}CB_ z?-Y2i#4=6J0C?6YaZW)t*LqSyey`?__J4elV?~mtoRQ{i`NUU>4oMbypNaL(6(q6B z0W6CtVQwEgzK(a(puglv?JSZ;r5jM_FkO_^C{^Rj|HD~JT&Vy!t8ABx?(lFPcQ|}> z0c6`Hll@_k!$f8o?OeB^EhkQ5C1VM+(}2;c*zDPtrsN{O^Nd1ssZ!#iP946n#2|_c zJ*ZB+>=+DoC$B<6v&e{J#X5{<00dPoI23F55Gw14Gn7~ncYQx2nsJYYqHW4r*;(tn zHU&6p?DWHbU@IjhHf?$c;pN&kiVm&DqE7kPi$bAY=1a~sCv&*Lat4Dk15$(wx;D@O zm*0i!eg_%CLg^xvowPeT&DH_{8t+MguSC)$)Fp8%DMq2@p0Dc&R%l!n5$nuVV!%HR z8oYioKkuFa<&GKDGNfJ?9w@664h!dj&@G&hTHw!85SnE}tB2|ocX#sFSu|tw0~xl~ zY1@QJ0{M?{wRedS!j$XNkmo_8z{w5>E9r@39NI*vleAkw*Ho6yVQN%)?+fU74*n2L zA3Os=7cSBI{bf1|E{!8g$D`-+er%+yvjwzJ9NY3~Up~O9tvmycdq9!j?x5aSFtyV1 zqy;2#Z>@BZ)k@$}yT;o+!6baJz=;JBi1-a3b(F6s^GiR=_ng~98yF+ikMEF0*kco= z+dxCgoyA6a(FSFqmS^!1v?@JbWm{}=L_Wa|;!10qO0X&L&_xr{*;O@y_Rr0B)H zqZEoI+dw8$M=um2;HZdJ`$7C0f-fI&OMsy*n4)#KP?tbi9MzYplT1ir68Ux^Nr6#e zb4%)xb)o2TGd1>WD_H0N1u7TolCn@zHBO{#Uqj6ThC(?p_cI5kk-g4_84KQyY6a{w z7#N$NY=PPel}lOewLQkPD;Rj?LJ)lNDTonMkFO8SP^t{9x9E|v=v zBe2}!ysSOW;z|Qwl~7Tdp_~d!3DLBHD+?D$d$H$LrKLgY*w~Rf0Xl|mG+|*e_c;ny zZu&E3^Dp<8;}H3?*g2Ng<0GjN{K_d5Qor?a8b^Qgd_Zs8NN_@grG@4Ai4ws+;}i=p zfK2>v*p+eHEABNUXP>m);Y`LZZmkN%1Y>i7y=9dh}h;Y!mpB;+=l1X(%W4@#G zm}b)9Kp2|O!tc8Xkl$b&^;qLkhAG~qdG`rHbw$%i2-F%n9;JR3yi$RWgV~b{IvgB% z?rdo~f7#tW#Bru5iu~Y0L*d}2x!cRFe`g~ij@_pwa;w*3L&NZp23sY zqQF<&*54h#8Gx9h{L~HIEg)yYkCNZb$l&zdPaw74?6)8Ua%;h<`7>ylR<}$qTDgm3 z*<9fRojL2CZ0hSe0xX%H5CykRnK29(Y7=CRU5NhVAe_FYz(gcd4#zwOhK4&;1Dxzp zddE$oiu!)#X0Sp+m4FNU&0Gl-#wEXnp>4u9#u95LDo@=~X_`>d41@U_Vf6PG4JcjB z@%Gc{B2_vbxM#c>;eOVl<0Y`{=x|7^3MJ3yX8$7AY(;22Mtw>-+`Pj94h5(V9Or99 z`@>XY$dZfbW`gt&>-aj&I>GI=12iXD`?c+wSbU*$9oshKfwf>tfWkun`r_}qqSRWP z#8N+U9Pgy4_ZPMh8R15kN!H>G7@Gg6*98U4|EO1>0{e!jl!t#5t^;Mf+RL;jjSvF* z{%Wy`l(gXLNCJyah~S|x8{DxUK{!!(i#kT+W-yq-XIV=}mod_j@HwwkQl|VkKs8dj zAb59Nn@53A0EjqIJPWGzfA|{hWe=L+k7JK{9W~?-Nj&002-;#+L>zq;X10e%XAxGX zmxUq~RfVDvqNHE35veeIcCNZ}*eqFVs8u1eQ4`%qF&*$e#=N4h4oTJVbm`cG%=B4o zT=$?|e8V;GhSKfvPipBm)nJGLrp(pstG0;jV`mCR@@(wTQ!C9S1r!4I(DMP8cauDB z1)l1l>|_7&uNczt!lF|+HY$4RIJomBi2vHKsDd90Aqhnge#<2ygOr?_*Haj{lxG1> ztzc*fJvLfc0P#3c2oMdb%b5B$YN@`Ln+o-J#Ht4k(9WOzo4nh+i2hDm(uZ+qk+I zaZVU=CanoNtOyk=dmuS?FvH1(g()91Mx2rOM~bG4UzMy zB&E~)Dsj5U_PfC(&08eYHwSIAiY&uzIIt)w{abj_9_xj`6hZto9g>6w64qef&o^Aa zE)S;i{&SV9``;n(u{}lGOjj&sXvZK3H zq=`}gF_TZJdXv|U(gQJTidmf_%Oc~JLtI4rc!IdzhVuiYkL6^BE--rpX{qG$>Q_%< zqJbG@SgLiS*pkogPOK`fR4A@eU?v3g;Crwd06|;g&WwOmPiZ^rgH73*+XK@+nEOjJ z4ZiuBZ>XiDlIp#8I2L6pN|kJsurLLg)d-rH=nn{OCh2J!4*4YF*{kCIRUq6vNrbof z4leSTf>SL;nGh(Iu9{WA8Z_~~?ZTW7Hd}p3hfJ%E8^OM+*WPmCU+2x}kh4U|8dd1h z#|KCe97%CdWA)`ZnFwzpl&XDZc(#7lcB@wa=wkx^%=a4yi4l1oof|QT@zSyv4ku!( zY+)#>Q^*Q6=9tBWNPwHb3zRi%zfs6aBQlesq2oRCs-BEBxt}^x9kM>kP^*?THubpN zXruLFJpGr}lB3ye6sIht1LfvE^dY(`?ho^b69?qGv7KC|!aOn77xf%5gp{j~m!fTA5ws?oRznqr#zsSubUs=sX3ngBz!KXmHWjK_BI_!{vapk^Ass z3W%TtNnfG;Kh1#7IXK}N9Kk(9&JQGJ(u@(^*1KHveONYYi=x=B}oyS*0q%^dYcU07&C)?JQB=B=ltHyI$FUKX&1Zk^r7K@`T8rex}_VO?Lvo<`ovUpZv62f&}=d9lf+9V+i@Gizzv4C*Lo zy)~>-uAlo_0N-e=D6R|`+$R8EqeP0sY-{BXOjuU2maDa20uWl5?UqZp%1Hgb+5A6Q zYMB68y@L9lnnd3s7vtena&L8Ev%@qTQdc{ZwQ`rRDCCQ)*kFbZ0HLXz%Z(laV3mxZB4uJE~0 z^ODcbBu{Yi&Ipm^tt~*&m-CI{ z!#ywhrvLHTwyXWbb^jwE7VN!iw_LCL=6Qk_hkU{(&E#{1O9u4YX7g9~!q#d4PZk$# zx?I6tMg<7DD39q14Kb|aQC00>fe3cvpf@Z>wXa-Q@qlk9*~OXpq8(}jJfFs(hQ1{b zv*MSlD15o2W?P_FJRq7nEef;o#=J;FRd!U6uSO$`c*y|c_xirjGdApXR#Xx9(Wy_? zfRE(IFTG0S&Zg*0MDLwmX#vm&oXZfPPgr)HzNOO4DZ7!sFze%>RpLZ{pp< z59azfv-lgvI2@o4pwHOi-yk-GaOm(KgV4Q@pGrciJFY6$Ge0*+#YXt0$sjPTDlak= z2mT-5RCWAmYvw9RmUB4jcf|$ePVEKr%~$OvXZB=-9jW3Q|8xPyo`xEo>Z(OK%4X4g zAK&s!I_i^z5t|i`NN24i~>v7@IszpUij)*J(zs zBN9up1Of*=cn*KHanso(s$M{sx@#ypMzaJvlQCLWt@wB*rY)pQ7Y%;eTr$ICB034qMVUmI7}n`mF!CI-8FnL*05%$94^tCivnp#LwG2rv_RS4woD& zdqjLJ!=!xN+u_)-SP#G5or%|co-00{!kBs=^V8C+ew(jams3+s4qn=DcAE|y+yf7! zZCy)5-o`<&IJI<4x6BGale<`1Kji*;`up**1Nr$F%T4DVtNO02>n`Rh`?G|=&v|ow zu;%?H6W`|V%F$JxHy=Lr_;xEfHq|txz7srWfq9$v?o-yZGF0Y(h6sPU%h)1aSJ(I@ z9Q=8Gbun_)Mwm`{6He@XF?01dnX1?f&~> z@8`P9@e5S=?+J*y*R=-tw>_Owc&q!YN0710NsnIQ|rYhS%5c=Fj=24yz;0^roZn zb_Yh<&HZbIOdc&Nk_oqqg2X+UgDgWnA78TU>}Vrpo)(b#Mag-ZrllW1LCZ*yZ?j+bXkS~&ZHcgdy@vq_v7&R)25usqNCOe zU!q4w-JYKt7R~2>KdVtV=KAC`>$map zZP?PwA)Ps{V@sDrnyhRQ;jFZH6iUAczM!pNDKu%6Vp||laHh$o?U^oQRTT-VcZLb_ zm{5VCPnE{2X|& zD`t?M!wcLdyFGvoJtA9RYEN9#yuHKYZ+yQFw|x1lH2dmU9tv|@jvgOx&&|hHr&YJA zGuNK7;F-}V_5!{K$-Y;wGhm=UxBF@|6XEeaJ3%&mSq*Dv<1A0XjWHd@?L|pB!8WaA z*JKWzRs)k*^vkS;N;*2=`^7b~_q&wBr+;8}1 zH0bppp*j8ZaeOnhq>R6z&->GUW3pGN2%fjL*Ef~O?R9dag%dxF$tLdfoR|+viplzm z?;2`Z+xu#!aoiS9 zszY!0ML3gY6IHCN<$vyLPi1rP@sX;D+3zl6Xgwi<;tyJ&M%Ek2Vol5-A+(7MdwkRb zeSl4l7}pdHi92a5AXU^<+QqT{Jlgs}XE;nVK`0N28)sRnl?d$F<52FMZO8x?xAGg^ z(tHZDyA987y%2Vw1Mgj~gyg8HZf4|GD>Ca;M?_#$$eYt-g|lLKe9UBZEoM9_@h3_95ldGVSl7_FdGsN0T8ZzSwMuTyWHo*t}7m!r@+E&7#i zV5IMOwfp1u{l_o&$J682!z1TjmRkk3EukuI8zr;ZOF@`B&NJ8|Kfc;cHVQ?tE56T95eb?UDH?Y6>Y& zD~B2%&N;Sp`0heG9w5i0Jmgi8x9!i$cl4h>ub@3t{7WsBk;t&F@Pc1)+{!8fswL0u zr+l&Tyv@e=i~q7@=2HBd2NYS3o(+?SekscHM8dWfI=i_Gp?avY=tkUq815P7v`fNs zAN$IHM|%kjb=-G(Ptx)E%anV6sR|UH*n9;aYL$D*P@o|at87stexdRTuOO7McD$S8 z?LRa>Si+Y%N>Z{)ve1~x1esARK~5C^%TJfHD~|CI8l%Y6?}Sa167H&43P=H|SE#T$ z7$=mt4n6Z;CUYNw!zoqpi>w-35nXLMiZ!YT;f2Dveg2@uRTfH`j zbP*jo-_Uhp0mFzPSr)ChkY^b2{1q0Lm*w57#Wi||wWs)Nd985DoZs4l8bT&}D%=l>>!B5!&rJ z1&uO))^`!tp}@-z z&?u&;6m_wj%&Ws#NwGMjgC(#y)$3UIh7OM#a?m6gw|CpkGl2?ah&|x+F9we-Zhw;=R7YgWDb#hR(Y-&W!uK7x8<&-5qbwR|dwaRt`nq z`GEHxx+MQ`c-=4X?`~md$|Rpb;lIA@M-2YlwN>t~O+aO=nf^`aBcOzf<$I1QzFuBX z4Law2dmYuOp!E3g;_3D53y>IDCDd=Z7aGPSFm$MG!kOG1;E$Lm{pM1{H-|Mhr8tRe z1LSVqpYdP`$UWP+wj5?Ibb>-c{buM+35&#*IZv)(!g&$?8qn#PL7^(C!%=rRhvdd~ z4}a=!@`TE=OS;Lx8!+P&jz0NEa5deBfl#klt?WK5%Ew=8k?jLqMpKpXGNP%gXX#db z7tegJ&aXw+x1_g@qK;X1ThB?BSjdZy5UFot_3Gk*tZ9dc5WSRPCvwBHs?E`>JrJ9y z-tQxJ2t7;?Fj#l1k_R({q9Pu`)2Aw2?EQBcZi2y;GDlK49W~Kp9F*Z1xELCG$wlBC zXQFO26Xa>}pbU2Z()9UabfGpVz=;jVGUdtpt9N^sIDJlA%=JhNrOK*;_ohJcNx}@L zfM$5D>3}P7xhjtA7=A(}=yJ*@_W9)B48HcxlO&fD$bFbSNeuGrNIIZe%s>W}xUYQ^ z=!O%p&gqn7&=QhrpsqF10N%u~Q-pnZmKf%W9hHd$2XT`WbjF#5y@#yOjLGSu3pDP| zxL8?(of}KzGS7ufYxlKnU)S^X?i1eRnm46hLd5pro5Sml*F3u8Uj}uYd6vb`aNm&L zW!JiS>#(P@(O@ba#h@fY);*a;27o3{XJ#St??nG1# zx8vllak0x_Dp@HMqCGJfPI&S+Y@^?LT3ASzYi^ z86S06J&+bRFvr$OA{iM~{%x>WvX>gX+C57z{}#fULf|GcuPFyX@DeJQpLXf15n)#cU&D!FHqMj2#oxblKiARkw4D(au` zv)N~os4&+j`Q=ShG$WT-73+!mspZs|ubJO0dEkPODtP|B_Tg(Pt;PZ?B7^a2$ZEFS zv+$X#-ieR8oZnhfie@uS&P{Vv&~7zQ+pQPR?Dc5zB+n8r4ceaK^`$SyR5ES4F}U%nU#C1kKjenkT_V1vloQU=WfC_5kOT zo1&}A7k5@3Hb)SET!*4KC{2>@@Af=e&p>j3lBmLgd#(PI;8{Py7+)pbE-CG7$F*WjzIHK(%t;3$u#6nB6z_5+w?B3UCiMg5RgltQX6KtFClw^OlTA7Vvu-GrC_=E}ixF$HNDXFFf$q`x`ys0MB}w z4*!<6*EkH;_UCLgo~~xUUAG(j;?%mt3YE$-{mMhgZ4<9;MGrZq*YqHKA^=IQr|b=s zt~V%9E6r%hbfHWD&rpGLWJo$3JN0!)2^@$AAOHKnJfn_X@NaSSK%eyO(4*baW8bd9 zO_O60)EiWeYlPDTL_;>S5go*w_1m$+ASW^+m`Le#2~QDjX*g=20jbnPp;zucEcFXG z|9Ep7ZO23c8amq@hd=#VBcfN693<-KM)AXfvbL&Td=GAmIS{U}P^81I6!2oPhZGBtZ>Rm#q^RVi1esS4Ywl%|U&j;mIsd~~mX|HhEVR;4s{ z9T}Cc_V156Bnc5=V)~W+)h)@tf=cP}>1abHLUsb2xD%k-MgC1eV8-Nbq@~;f7^u=a z`eUk*U{+#zOpUW&A&cPD1O-lE8IwN9cNGo{Ozol!6GF0k4)X~Ljs_WfiJ(XLv5`&# z!Jp$kY&@wYUrBgt+JQ6%UXcxHNGt5)3^i^wGQ0 zi`Y-S5kXWJscQ+GkQj3LcO+D{+i5aR6l-jVSmV0`)tmsPlB$L$Qm-|DN>g|p-S~() zpAhBgy$|8|6{%KmLz&f>#~g) z!=WQisn;?gmYZHsl!5;ePkrcI8g*AchWZ1)PxG7agYCnWQioFfZ1kqbY>g_m6(y}O zaJcUiNQSgp5?K3vng|=d)E<2r#*}mp#%qs02J}}QO%qP9B}xpn-u&D3STzdzE~8;v zjW4zXx5Xp~Y@!9K&m96*SH})GXiX`*&gOTuaj0RdSsoq!s~TV0NW)tnvCwLksRh$& zmN7JQBWlz3M5|eTu|~z+)GTWuYv9&hs+y+Ylr$!g@}+6LD1})M02w5D8Ee~O77DYb zXBja*R6iRCB%78e&A*iajgtYjJfyuDkyRsOG-=e)ReKqddxcp})KC!u56U2THo;(& zKpKKd8#LX3kW`<+0w49IdAet))-(Q$E+XPG$#Y}U%&2E&{xX{B~=D|wAP(KC@DQbfmkvK z0BlGAC`(}nG8Lf&ZAvzZa9I15Mu;OP4(bVI(QLfepM>Q9y4jUcGYO4dyXa;EMG=)4 zjE4V+Mgf!uA`OEp6xn8iu@G4JtGJ1PpyHR(XOW>ReF_lJJz+o*gc0mQKa-&=WLDrQ z|{$k6^GSyoFb|co=c)+2BvNdr&6!kUGepB>ITDJU;AltN&;v~Q;GDT z+yNBnFG?0splv-N>H}6p06PZV#s@%Rt;wtnL?Ey`(S1adQyQB9dHtO)f&{kIf|{L( zKk<6_D=R6q6F2%!^SxYB9WHse5k6vn7h`fC9}0R4R90xZs#TI*r+fAACZTSO=p0M_ zcCRuSji`1KAF2J0!r(I>gUBu@CD9nypeY&M!oL_CDfs*GVUU1NmK~`S&6E<8FMNG1 zB<4upZK0NU_-jfGz2RCgOAobZ) z+E$SNg@9V)b`SC&);*-+8alm{SlWRGSk9Ot%1A1hrY`jjJ?c_>z(n*N9vn1`=c^f4 z>wvrRsLKh|5mHRwUz-3D`)HJGV*cMIv7k~Fp2!St#HdStwV{zfM}i_?txJL!hPy9p z78pvPBf>Ihbw-5&>IdO>Cf-9+}6)FWZIjZh1sa>cl0`KG*Zx_*9ktnc^LqwxhDzaI@uxS8?yNU|# zL^`_Lwl#*mExQZSAkYv#d;G$*CL>Oan)aH^lnpUPd7`vFF=e!=)z92X3fj(O*!Dyk zVAlQJmNScLGr2kz)oWC!ZdB#XUvIU!7mx1Un64l0ZwpxO1hBr|rEQK_w_4*yxnix> zcy>HH-(MbwE^w{Z=%Hk~&fJV;&}xk#o-<}72dUF)jniEiIz=mV9x z=y5Tol?0Y$zuPZBu?SE+dXqu1-9)nCO;~oWbG8{@sNmPF9I!US zfx1y4buf`cDPOj}Xwlc>i3YO{9C*{uHbV{9K^fa+fH_x2am|f^uO^v9QZG=@PRjgI zd!M8t%>goj)F|I;MCvF&2mj%26OgOFv?Y>JOuWJ?MaP>g0nBlz#%&pZV%+`SJm0Hk zSS_Qr)N&eR<&pT>1w%s?-~&u6KsF+aD1x@--7Bdn4XA?TFe$x7KN0EYVKZdD2%5O5 z1h6{xSk4G5=`E!nxE!Cor;llnh?6;0WOk4$H%N24G|0dBcnf$^$(_Mnf1&k0dVA ztUQy5>R0~7AV`F&X~HEvyjU3>fEsBJJN8b8OX8bFjF$;GxB`{;?kx7i&KBDmD|91oZl9zDyf>qD}mEcJ*TR+mFi=_rtKJH?#AP zbH5NNC7{px<#O@ia^?Qc?fQ$w9lE5Z)26h>!EJW0&y)8t9>yV5Y zrP2<@SpwTY3~j0*zz=CpXI6A}krNgKi(n=f8;L3%^X$hm1(gy21KJaDwQ!Uf&w;r! z)D|X%Q8F6Iug8&PzZNK+wkxFQNCo6BbJJ6^7i-kRFG^}SDZjWtO|4#E%KWa;ILu^0GDI8sMNVC&)>z zGS|;U3WTMjK#_?|%>^FoO>A+NuylHt4LFK1rRb5l1z{W3J{Gq=f)+U{Jjm=}P|4J7 z4NK)Rquf&}xJPZ3LA))TJ>;0lLtASyxTIb_-y%6oZ)#YnoEqvbDPLrIO}d5^Wh>~} zktI#C(7ufN6P8Y+y9wnq;N?&_ztP`Gmo7i5r{`E?HYxFA@?WX_!|h&rt?A$Hk~yba+h2) zQ7)nGDRq)OY1XejW?X@3aqrk!Vi71*Wab>!J|w6_)sQ(&&(~Gn7r2HVf>eUX@?D89W^5m^xRk12Q$p*?2?nVWCV; z$Wt~o;XuuXgE-Wr}(vOZY+@!E(jU! z^2mIypy{(nmI?0fI7Wg6Mn$_YDRZj}n!ed3lsorgHokfDvupZa(^hqQ>`3u0==-3n z5DwHq^uGWtn$!YcC#V(TAr22c4e{mJR6WCq>HCN_7%5fS`4p{3%_)YFh@Pe5S2mbo z9D&~uT}N57snkHk^p3}AlA?f~BkhFINN}s^RRsow4uSazR}}_^Xw%OG1|;T*o{~IM zzw(&A&jbW0AEJ}=r)X$;B){_LLXlkv9n2o=02XbY$s`D322d*Ono+&NLZw%Ax>w-z zwkk(hs7wo^kC8Yg6yw-JweKaS>!VF0xRJFu7h!W|F4+Nt)2VUXGxZx9Q>}%B#zO>$ zvk0s*8Aig4%?SzMLT`E?B|?sAnlvJM9TLaQpr6Th7@n<&-*EP9hkM{aDCiPCEImo| zcft-cV^55Jm)%(PE03z$$OUTfAq=7KB)-Q(Y8$(IN?A|JTAFhRD@T~2T}eq7spl78 zImT3WgJjZrRbl05F5=b2bBFqZEu)_aD@Po12Q%W5N9q?I)3ae5C>Mm)x_?_MKO8xx zroQ#&sKUarRWyy735O#`FUf9#TrRz+Y~g^%v=0f3H(Fs>IQbEJ0~_d{G0hvO%$+rg zEQc0vIS*W_*d5TAQl`SnIcpl-45hIbMK>)Q2rC!<>^Nq6TKYR-<)~tn{5Pze_-0`v zfip$fiM60(nl}cow1&oL6bJ}~QBNlvI^BEB1=Y`lrGtZpgMv!U^$aWLmgfQvB-1<; zmJZT{2@ZgOeZu1OP}#~M^?c!Rn?p0wm};)S8N>w;_D|V=xPbmnwx?1rHQ$Vw!Aj{VL>x9H_UUNU z10>QPN;kE^Qez4SH0;?rdN196%vBFdMS5n8i4%?TN-}zKj>|37Gt8FS8wO>=ea{RQ z$OrI-yiXu&iid`#!qRkh6;(Mr0L z!61b#6~2`lFnBN=6Bdxlkdrm;1U15X8YDneRTG1q0c^7fDT!t#R;U7hei_ zS51xXjZSOe;?m$$ud`^|>0R?HZDiRo1r~*dLZw*D|G$)FH|x%lnd9nr!LlPQ69=0^ zC3+|{hKUFE2OJBYh-ASs!Kv*yQoU{#W3)iO5Fa($P*ng(3`K{LU=S$lz#7gKKy`a1 zcY;Xi^+0~fi6Z=whb`6>cnv5x&J64}{3cYcHu5X**#vQqHj9^@nPoce{wY)|k=DX1=3np8wITO3v{>Z)Y;2~%bZjPwgD z$4tEg@U+YmQGtk^Gv>S+$n%JI18sp zrl=vJmC~~1X_gR{$+_XXa)lZJ*u96VenVrH9k&8|L_B3&AXI+6$ZRAeB}G8K3=Q;SvE?DVLP31Lp>8wk7aB9<@F*ho zu-~!USw(D}ERCnw57r6_6XlZJ5*H5z`H9oeJd+U)G!C;B4%ribz8)(O4r~j;0|p@O zTu@s5OduSpeURWU0a{o*@f)M*CT7IRdhofz0=RW(_H_W<^!Rjc(o1X5xZCfq^KH z*kC=MY^iKH^ad^QG%nicwE@4EP+^3IxL@PfM!Y0YCRzYj44$P23ya51gl{3Es3zwe z(>H{kI9@zwh#;w?qoiEAc>SZWR3?Z1fh%Xo66{;yOwIJTXoj1Hiz5Nl2}?=l z6jDU^!D1jaX-FDfs=hji(6X^Em=0owD!E`Fa9F*n?3BejC;$km(;ASi0eNn@ zM{7W~24sX&vlk8w{jjGv++YR z$)VsjfO#Z^xeta}MPAHM6M;TKtR&6>zf{`rFWVjS=I0MF9na(+Ih4C#M+)YRrvvDo zP4b}$&L_rScJl}g|Z5P zm$})Jvtbqy7D~S_!H&V0CI82|vH~oaz-0hbL8AfBK|b|ncv#Twb8(@XbYfmTe1l`j zQG)@4C7PoOs}v-6z>pG{kK4Baa$k0%bvv{Ug=UB%fqpnsGygCWsa$mX2J@5vdLGtm z4EssMHkdFsi!4pjea&~meu`(CcsI$W8UeK$cZlClv(SL5k|+qta##{Dg0Dn|FYf1h zt8D9AUqqB~vp`xB$vx$=*ap>MrEq?HgCrK=`=eB|b=U;b;Sn|*ANvr8JR!e&Tm9M} z_B$dwB}joslW~()-!V_$)@yHqUiWvZd=SCPuA&COqlvyJx-A|61rw2Id-_8n!wn@V z?E@c>OG6b-4h8iJ-^#?R1RxM_;u=oc*khx7Kzu|@NDdJ89XT$A&jm4$0_$o4lYS)O z^7>e<_8~llz!Fl9$X0?@3g647M^+L_7R!ZkT2d-#AKXx=QmUV$YY}teXBg&X2&|Cd zLKvw?C~62u$}wy}c0HSbd9zhN7XSV6?D*Hm%h`LMx+W)_8@taJzs*Bo$C#^>C?NgI z=(?WcCLP>J5)UAetfQ(+Z&_YM|ImaNSh*y`5pRQvDzT_Ief2|umm>=F3=O~c94Dvc=@4UR?+ zp6-|aQ4j!VVv;L|H9%GbZgKrg;Qw{o?Ds3WJNDem%7c-ib^8;JD;ztTsGeqe()ve! z=4OC!u(1W#ooiVaF`o_dF3@X}F!LBB+u&fMcg}8+nPE6-2{pzgE@9im!4-NHhofd| zZHQrdzR^MJwk;;zw_RKl;Xe553U^7oK_`@;KSFw>B81fxGU)|pAPN!TCTN8wXCvG( z)du|`xl9};jH&pwAVi6bByf#{6EtrdkZfhU`5X#-#oQ!r1I>guZpLAr@(2Vi^8mm^@8E7>iCjcf~WQo1A z-^zAZqK>g^h;k;T+I-9n7fzU54WtRdYZ9o1R)VL`{PmQr)6!%hdQ0!}m~# z$T37dQ9TC8Bdt`G_H@v}G8`9yhJ>xe)j%!6?Ts}aAMiWkdeZzg*f+O z*{!c{5mLIwPI1SQlA0EpDep3;CVy|V7OlZYEE6JQVjsBkH!b0*A*iPb}WGq(}F2p4zjGzC(*DXj|WWsP#Hcu)h zq6JHqNmHfJv2Wl>O23HVoaW!HW5S=Qc45mz7oYZCJ-Vm4N|cGlN%Y3J=%&MYzFQ*s z8{?wU3)X0~&&@<}sqc`9O3gm zr5a6^965L~PV<5%vBX3(%@gmxH(Sg69VRLni)h%QXB$wm%tUKcnw>7$ZhwHXstI@xQAYS8^p)ntvT zn34F6GU4)#svfRF`EA4&w^3!IihZNeJ~tCa*W4u&rgjrKeq=m}qmHVB76R}G)TI(A zslJ$!bZx~H*B3%DVex_D@|D8wL?)D=iHyUb6^m1za43uwqj?%8Y~^CwWG2Fc1x}FC zuOuXsaH{9#N7R}zfhJS|LXJ={qqx>=ejZLh;bl*-ob?xrOjzKATpy(jZevZ>!3h8m zfU-;}olG``3MSlYvN?xMZP-7RiAG7ZnyESJ2xly0RS7;+!U4HjnqG+N(Sm(mr1*3K z%5>f-9I(}JpPPwJcgsXcaV1R?&osVa%+d-b%Ff{S!Q`fxh`HdJhhk_G#7dAVRe6C9 zy>gawy+A!3>~;YIBoGWHq1quZs)Mpd_JwzvZ(T)I%z zqXi~h^kUpF6W(gL&&-5JyDdNloX|4iRfjqxc{3TW$+nKM)-iU^yH`?quhoT(T~$#` zw`IbBM(I{wi|2oCCX5xlLpVXoZtl!6MrbodZpghLv>IESaA^xpWV$d~w}d$)L^u=M zu8G^xy9NMS*BEsA`2(if_<~QZYphh5$=&B_k#rqL+~;Pa*!;U>qivMe>3rTQvyxb@ z#hLh|+9)sC6os?v4QiFyn}T(31)_kTey3bmqMqnFM;xt`ORmCoad**CPQsa_Ah#w* z1MEuGSi1huHIYIEX}jbYuuJO`a9uL@De9{~R?=n5{?z<)sZ{N>5ehA?dw%XC8g3b` z+eRqJv1OP-6k%xuBY$pP7(2b?!VZXSxp15DU^RH+$8MK*t>wbElnd`T?@U^@O2wZE z#U!ZaP{d*br<0s2X)_@?3MLjytHQgF6QclqLKkEj7*nL*qQqflgg8i%e$ox3cDzy3 zy%g0j@eRa@Nx5^Xanam`;!N6p?U+~)A7PeBee`$I&e}LJ1B2W;CMvpHi9|hNnoF`V zd{G%Ew!vt@UA0x<);6)WUZiX_+~-hbzjZCJuZYfbzahu_bapx4d-|CCY3ZT-V)kK9 zI`B{P-q24us&gM3bo{qyf=bSW#Tpbx zOgdEBlA2KTw~+SN#=oZHVS5ZK#eSwVnW3qK=fh7gPW9-PyHOU1!KI=dY9dm_amC^r zWyn*SXym_4?3)0j2aEH?(yj1oVDz_deF)vFe;htPeDZq#r^ol7AN~01>5EtQ-H+bv zKfC|c{_*krV&z`!ef7oAlWpDbC5 z`1lu&{;~h~@V*-E!L!%TA3y!!2elpYw{A1oi+q!^pRz^#D$ZW-kJ%oV0CBYXzw^00 zonE)%v1}l>j>^ZlmM4o(`Ds@^_`@PS+xqXx?4Hk7%d_9h$CIx?Cb#~n!*}ms4_E6S zl(|(sB@=qGoSmFOn}-*(x94+zvS!<4K5HNPX|bBEvTyzKY<22*np>y&+UqNxT70|= zUo1cI)BJq4I$K;^ot|A@rGM=duGi1+KR$eU_~P-=k1y``Eq%B{Iyyd`f0#eLIGOtm zwnh8=j@3VNu(-HjTNlgv$7E0IpLkU_lcQhftK-wshO0^+?9vkUEMe0iG{2o)y_o&> z?9XN_Nv-cna@R+J_=Z+|mep3QOzXqdZW-DO5_ zboNJ@AJ;)6aTQWtzS2VB8QRg)$L__m)x)Rm?`mlMNt*fZE7iz4B54U_QmLa*bN<3j zLw!4a_Wro)K4XuoImPJ_HGwpy-2BvE&3|A0{k!AK^u`O<@IQ*^s8W!zq@$8cP}WG@ z4-HhisRC-Omr4cH7`V9tI_!8QiBvG@z-G(T7!8!HEy~$owv#+TZ(u`Zi{nf^?sY&Y zMECNpxU{rZfn8Y@R7`7WJSsIbsdhYQRnYkw1@bnkpibL4Iz9Q6CGQ%`DcA1g%I0jd zTB8gKvX{43yystQHB`}$S`C#j9;@tbsi7*_zo7~$wH7tkym=M0h7%jHyj}+_iwULT zS=mgYat%MP9k;AmG?FGkmKP0QZ`IN2D%1;Os9RxjDK3Tn$#%xOnTQlY>~Y0(~CUG-DBikWnzjIqR1(aN3X=;mWe z#RRpZwv`lNCgUIM(l^cs$DmQpZiiy4GBjnbDE>l=X{R!JFrUBF^RTKWmJLuJxT=uI2 zc?rb$emT25t-u)nu~`1Ge}4Af`^DUtHD4=ZeBq|QSjg2aql_;Wa<^hX&rEr<&}~8k zaA~ZoBBNB0R7=nIErluhicB>?jAeVmU}X)zqBSJ1H%7kVeq>b7!d$c}=)Yq2EY%Lz zttjSuuiKZLp31u9WsYR-|M77--}~X?#j&`R_VzC?|NYwGKKoj{-!bA0BPU@RMuKq_kEV zC(%iY&RrBUq?D_ED%V=OsKC;{jYI%SLs2u@e9fq>bq`v#m2$8HDo}SR;VrcfCyqNd zP+Oz#{YhHuZ4+l3a&2i}qbWjj?HHSuxD?`49J=Y_Q>0YA0ram!)073G4cH)|MDJ)! zK{vXXi0nv{Ovc^+2-HJGbpAg4GAlT{NI4y05fS>!zZIt_eJ7~zhRH?eiC$Ma6MCpV z|3H`wwLhD1QiEIv2iYVv5^yloIqW9;7FH*%06SFH}Kwi@?-yQ2pS`#nqVz6t6mf7RYJjLbBKmL%*uWa2>Jr zL6#nTwVYjqKnNuc^>c-}cy?~*qSXccs-DZcDgW$vEoAIBZ>ttd@Srfg@ISZPLH`b%i3X)ZY1EU@{*`>j zY2n%se}Zo5ddjTMj%Vll%j0T=moA+H$~&w7X@W^d)IZu!FDte1(WXW)c^LJ?c6|Ll zTxety1>mJu8HGPU)QpaFkXj6`ZwsG=E&uEA*|VoFj}HF@O!R91{)h^C0F6{WB@lHw zdXNB~&@w}cpvv#)nlYghv;XzLvGfO?K^t`CahNgP3$tH@TG$Z}4-U2;??E89q;t@7 zgXg!^ABQ$O^xaKWeRv-tO8w95lsbmuccaIwFJz@Hf#wjSqd;uooV(I%nm$tWKbX>= z+V-4O2Tjfa9Win0)4PR2;F@Ia=s^$G9&|HntRu0tl9xQ8ColKf!Dfxlx!mZEL)BEo z?<0g{4yWpz&3oaTY3YEb$z{a!!9+37+|g4WtvzLJYliF0DeC{3cx->0qkus4HkbSI znFCCjLzIe&mzksLYs6Eg!+cU5&&R^~tNrG_*eE9qR5-hdFt&+v%Y_9gqn(Oh2?-90kzAcT$^IA6=q6QskEo+B5}| z#0uI7x%IWs9{W=7Y&s?5ZNxUPBKKlBzk_Unpz1Wbx2Nwi(pzfZDnJkh`Em6g=liqs zk6#F`rex1CRET1>b1#fW==(NB+kHEs*B(&0&(e#)O2 zK$)vQl}2;^&#WU-M#*T0l)FuQeaMVnfK5jXUjz+I24?Hjv9v-`Rm5zLw27?31q{b7 zZM|Tmq*oCKOPxi1qUEV$6rn)z5GhOJ#E~(|+?rFr3Vv>VDy>dEho9#(sz46SC<261 zoD=Ii)82qs6&{+7LDE}&iz;3bs!jY*( zf(RGIQZtcT!)~u;s{RXbcaE&8a0|6ZTKUqe3vJ8bf%4SHGoTpS82?AdZ-dQm&8cq; zcjr!})n&gL?jH0oVc~MZ6f?uN1MId|l;Gw;O{Y@EXij}j5)HF-fQ!O4nFA$AaJm`i z*3iLC!S0%KYDF0>QFo5=QhosQ?~kT5?*lY(#P*N_L!coIC0}WpI2%mR(QYRpYz%eh zj>R8)GwQ~`w8?-dGC$}bJmqc^5JidJ8k;ii^FjQh0f4r4Q=^HagfP@~_k!PAzGX z%d+=W(StF+1sJekEqaId^P)hdo9*l%;^@}hW$YCpDg>Kh8Tsn&|{>B zE#1p&*w2(`p!i2Kk1Z?u%hUF@tSBR3@{A!kQK~{SgAHs>2^+cve8DFM+%?#{~}29+#NDWU%r)>13$>)UhJK8G#6ZGx5(7Rg{bt zmNvtcAOGmV{CtHp;0qr z{=HJ_f;y#q?G#TjaH2g5E*#Xak7!wg;`g^DfKu3s!DNbjJ>$s zu^>^eNjQs3~laBXK2Okdt2dk*2Os4^^>V#It?@vX*uig1L1jhi5GZBuaPYuc`@z;1ahJ+H>V6kwIuxU{q z1xp+OER*5D40J2bX43v1<@^vs{6i?y-~+SY9A|&4ofw|K~UGxv(@gu^A zkT*O^M3}+V;jl<%nGlFco-t`MSQs@wy%mRbH6H}Qs{>5ClFrDbvB_o4rm{3x`~MQkJGNgxGnq zoa)tavTAh_*$GYNhBN6;&1e^HpX#^q8k6PVv8?n-QE7b8`^8YH-plyROZQA2Q}ltJ z*=8}I?Xpx&Y!)MRE7tdlNuN^1Y6_0qx>7eeOLNSi2LF}JbJ8QyoN%@=e&{ix)TmqT zP#lXatD_Uqf%*Ehq9HH>|287@EbTl@RamjJ8c;-0p3pNsOcFZH4X! zcVjKXOc6jWX5xcVU`|&R)K3YG2lKP7WvMQLuEA3K(6)z+t>K;RA){>a9cw==I@W%o z4~~>eqrSSTpk4ONP(NGOBqqm!jr>l>s%jQh@sQ!og>?1hb8Gl`rn3spfPL=#w4QQ$-$r+8%{ATa7t)7 z?ompIq7c~72s7eA{ZxdO)H8J)txF#2uGQ6$wl87GEiX$ln%h?1NnX!U zcziui>y5Wn_wF z`A{0B(=11e`@`{w|ITc2YLOQe%UKXUsm<-{&#H+38kKKb8eVB=Q5a;jLR<1ZKAP%< z_POh8hKdI(9if8`Qp3%PyJ?`BnxHn6y#gc@#1B`d4O3{GxT=LTe?>ZR1;nUDHcqUe z*tNexLr)Ltx_w1fjF@xFit2TWNLebsxx9bT%~IWu&!UEZuqpdwjMg14GYGkkX0&#p z=_MR-mmAWWQ1zsmt^$#+A1KmFwQj%(pefbQ2x`K_o&_^97|Ho4Lz6xg77Q}e z$ja;!;nm4#9$EG2Ht+tRfss6BlmQF0#F|gVZK?f2OjR;iiSuT}kzh?95|T`Wv;NKm zc4^#5jF1~IEXjP5e=i(9(Jo_36`@q2lNHsT%E`@pH?C0C;0-Os*4RnfYbTY;>}*1* zG(2CvUhSYm)VYCjzgMclX0Ac*Ji|2@u2&;6#~R1057QfRY)#z5P$tm4{>4!9 z$0AqUltr73pHD9?KP=zgIsEYIY;{>rwoT7{RPr5Ni+o3cev;g-*5n(eH}uzs#_w4aO_BpbWRgk6V!MYcb>1vD(TnKPsV)uSKZi>k?|1-cVX=LM^8^uWt#pBcT$< zP!Q_7<>i|OQqBB&^TbN(oa?AbXeH@s1~g7eVkOFdLL5ISY-5^#Xw0awF&Q`HT9C9x zLLbHSld(#OK>P06w{(cak)9>%^L&A9}7~5epVAS>T;7hYI6Ba52rXS$<=J4qR{-_ z$M^H6(4H*A3JibjK!?*nhh~5;iSUALOe_c{YzyVY{Ly?t+b!#^1e6qlUg9H3zakS5 zR~G@}wqD&2{am+hMU&Nn{9XBwXyt2}P&z$%)gLbP9)yo8J0f*WD3wOB)wO8bW@QQ& z;P>_H=x8!L+3;H24Yk{%tyeWmnU9XKENplw2!!gsXscG;Vy4H_k&$1O2fLn;qrD2& zRdGKXvsT10pA@07(L@>U=%?MFlTKukF-(Af2;qTk8RUhn+RoUq^U;S_4_E(cYGH(A z$3`|0WI=YEP3sL(9I&(?F_^qLDTqM#A7z;inJw56u_y|V!Q$4>r)*)^qyNwha~+AS z3E+6-a~1T^d;Ui~$%Ua%Ila=!8zV2z60lF1wjZi*SFjDs@?z3- z5zEv#ck#uMapXQ#-`()3Er}&e9=@z;hy0iId#=(I6oZkO{8iu4ER0heA)=07xhgxb!Y32pCo1*#_Zrbu?NA1f_oT(3}zmXiE>(^?8w1igX|rsQ&CGp8Sv zHoHePg;tR$4d??DTgUpU?xY5R#3n5$EX&QNl>=8a8LR|>l9oxo4SCQq0SySLd`#{? z?ge7>P#x-4CKhqIK2ij<|@kc~7JDQ=%Whz|Wm6bM`AMZA`oe$k+$$O%Lx zg*J{Y{7q16X4iw3F<-BxWH&#)pFf7yL>U%fxNUnXoVU?YvODm(&|SEht#p(dA<{1Z zoh|0{YQ#1|QxZg@1wR2>5Fsk2mJxMzvCT{z!%juJ7J*t>34$GfHNc2M_~w{SjufR* zOh3%iClMOE&qA6@3d3~S(CI|kJm(y0qOdDfrs!XYwTr3=CKtJJ#z0pAT!?oRsYV$Z zf?L5^dg%phqIS}h0t|${;%y#PdV_d)k!ZP~xeirl=-7!lOgcXEKUmRd@IxU2#3FKy z{T#U;fZ3#pxRmP}F4h&H8PFk!Mw%2vAI^qSyUGcjvKMEr2F*1Wp-a-_>z-&T%E3bn zLl7)^=wMx`^_)Faf|{Yz8G!_ZI8$Co&Z`v_<)B-u8BrjxrDAp^MIIW@X&F_b0g=+m zgv|%@f}AHgM7jx*0Xabqv&rU229OM~a~oPy%vIN*DJEaxLsLwyu!q#x7^B<~1VUo~ zTamzXfwhQUhpPm31{G4Hb3uBfnB#}$!~=5~V4H@qP8O6D;h8Mk%yP3_Ns3kzX85#a zW(G?H#fW-8lnG>)_#`4-&7InEuGQ)5H*PB;934I*kVgg|drici~odO(J$|nL6pOxH8T6Af?td!3IS{NQOE-+HI zV03Y)64?`3Hl=*on0y=DPTKeoA|4CG;yay(%bTEn z(yUn&NFmR;SuT%W^muwG%%E&9krrh$i1r%Pfk6 zbk;IkFF_-Twp@x zB(2O3bm=O~N;gqlGU#27Cen$rT0~A85{-ZDjCiV~+aOAlfGOK2yReC9S`CCrv0eh( zAq@J!(Fgm62-9eit*PQ0z2H6P>MG11L6;r-kg7I>d9@{I!n|7jL)1w+olV$cDVc1G zg$8O7^pDd4s|S%(7}8pEv7F8cduFr&oz>t^a4WruO%n#$7!7DB;RCUcaI>VbwBmH0 zdJL!AaQg^v-;-sChDkfqGBk06OUk%zM1@b)A}X`YRMfU3#v~`12jpihXn-+ zyC9Y_3N+Ka)rO%cb(3~4VnrffiRK76QEQdD5vFX4nDa2A$5@>#v`20YQ4y)viNW2w z6QlYXmWJVX$7h z6gLaB_rZsBc2#Y5DlHMMC3~@PPtF#W2%^@>`p{1g_xR!B4j=Y9R>=}X;*@SRv zsbK~nU*t1%2J#&ip`rX0bxc7`_><{2L`&)n8TM(CCrwRo&ESFT6T9Tjua)ALQ#Hlv zfdUE5lT4jskSNi%q}#S_+qP}ncAw^H+qP}nwyo2)ZBF0&W+q-l{jMK7cGRlKm0#vO zWBr6?-rQxB{}sqDt@PVmiO|Slo6J1pfUMiZ86nBDgPoVQ`*xl8uIqxBVN`QGdgu@a z1nRtx~!TkRKXySoU4l?&09$&DcUZxv=gx_~3tiVxR@AD|fQ-zB=6My>J_?jFjdwdf_ZRUi{cT2waD;^U(B<5h>6ET$>FZpk@N5)i~O`YT4(RHulQ*(EQt zw8XDtistj0{fjMH%$0}--W6vYRQJsZUxT{HL;DuP8zM~D@*0+-PR+b%qj!cLb`N}k z+u8iOIIqS|F}aJ!{nz-ShuR3^LZ_7v2|Eb5PrZ{VD523928|b#5@9?6aj!*oTjxol z_2vu_wdlv(QWulbR4*O!pzFC?S;HAPBSIA%YYv)=XNkZrXok%x$xeiV1i~x9Fcedy zfQmNc(h#ElpdnGWyb`}US!Qy~{*Fpcqj>HO2 zCmNk-cuZInN{fq_Wi|rMOVOM;6gy(4G2e$q5Jr{9Zdo;`7?2`$DH_M{vmLl+rL>Fb z$52)c?Y#QaBJlK=GuJt@rB-z8OBFpIa|#t$-Cm%`3^#l=af=pZS_b!&a+ zuR|&oLerPNLdaEw*go2Lyln~ zVkW%j0(%p`o%boYr_DG&6Ma z8tGX}_^^bDjb3{jBQE`>lwv~zvtoAJ|1cm2i$qw_*O)x7qF_eDSZ z>hsU(7%!z`PjzXvjby#V^T@fSuVpoc){0SzD-?^0#F(>qEzVu3H>W^1v1eM!3 zi`HrJh8y4eX(&7Ijd`qx|EykC6w2<+J{Krs~%o&+*iZ$0CVw+wQM7T%<>*DUAKr?eohTvTj@%%Wep<& z$w@^PqI(Al=7d)fTOBNRbyDbVOki6Qx2Ja+;+k^TX#M*S!~OM2r> z@KMf_4w)ONp#0U_=Hon5tOA3Fhcsj^z_k4q4vHl~l`?^BhXRHYRT3HYQw+q<#A^aj ziX)q^EfU&0iIW&k0bu&r)(^se@%{TXI6nTdT)Y~%t zTpauc5YEncGt289WqM4f+Vd`CE)Pc5>R+~umHrKR?smS*Egglw*1N>-)JVTsQUD-3vHTp} zX&!V$6zTZb+v1kW)9=Sa0pYT9pBTVgl(B@*h)WfSfbQ{3xFcawW4;~J_m+3t3>?yu z%u4o=YFw;MRyLrll;fZNIX*;BJ`;17DOIeqF38Dzjh zw4t{{7QQbY@5Y{=?ey?$Nb%3=C4VsJUKJ3634)^`TQ zr`<9CG@6~=L4Q$aq|rPhJe}mX7crn!f}De?xm{epJKv{mE#ta}?_K>mzP;anTwOlO zjD%lqeV*a(8h}F2;rO}TD6|K*$f+R-*!}7}QZ&NghHf9aBV-2h}yWO=DUA1I5!Ua32 zbLdzez9|*2U>Sn$=LIkI->H=qRC4Dr#4x`%P)vE4>R-6?}tY*8DMy zxXnSpeb?{Uj_G30_vdwgn>XEgboOWZ2d+2SxA*bKXS_FhbHys8r$nu??s#ZLOsKWU zMG8c;-`v~iL9(!PXadJH`ex0${x8GQMNe(7B>f*-V=&_1UdwLqK3;DA841T;LpXdA z@pEVqP?-Ik2N0g?r{a|6Q~yI+vhePP{Y{IOiL$KdzgC;XbGcgdx6+h|1ith$@$~opLLV%6-)NtASM)zbYqPjHOHfNkfcuPZ2=YuY&;+ZKx=HruT6OOlc>` zMT9rZCunpft!AGHPqMoAy_lPGb>;ih9pR3?e)jsw#wK(A^%sta)!pbA&{sPMz`~er zgAAXi&00}oh_RVaA0x4~-mtRO{sxDq?Sk-Z?>D9Mg%RlcY;3kA-s6vtYY6hgXTckz zeSi(t7$(o6CR=P20Av92MC87*4PWA6V61%z+nkZLlbxwk%ik1MwpIRy?WxPb@PLfiLz{5~=^U6sxl{PzgZv0B9J?+#C;Yiw)v<46%`41ODJ!{bR4DN+;bN##wJG)SwM(wq>hKQL8 zITT?!cLI87PcOjUU4NeTjDq#w3|@w_$%_bn>OakyC$R02ju0`q3J3R4{Ma=84p_FS zWG5jfurm$#U>`6-&if6R&O;J>Hj$2Hz0A)RO#k?(baai2 z8&b_YGhq@zDpW&m@9gu?uYnd@iJJ{aG|6()Nus}EL|5zUkK$5FG!53UziAGhue>G` z`z5v?n3GtL@u_i9W_dR~*H>F|TCr*`I$@q!8z@_T6VKZOy4bRXKC~>GL815TEDW^E zB}Cmuc>Z`cLi6%R#CSjGy-!hGi_2QS9ac>9kiULBp3Zzb*KJ?l)feHg9`ML0Z)dz5 z?tcOcqBJZ9v&t(VC~pw}i$C%f%H3t5VQ(nlR(l{rJwKOY3#Z{1 z8$?gbAMi*8E~q<+NQ!uF%q`2rnoW7g!fQF_BncN4z%nGgzeajkJL^4n_m1Vf3|9V- zlOGS~Zzr-Xyh%4AEj2t&Gal6}V-Hb%Zx>xk&UQrWGF@xLghgh29js|?Z>B0uYJGU- zRAAo}Q}CXBhGeqssC{@c_ImtGwh!UL7+gtm3p>J!4sta!MaN^dNg>x5^w<$LQ4-da7ZpNd6WGfbW8IA2A>}JeQKr8TP6^ozuDX*l! ztv`ask;&M(tn*5GiL}2=tWUou-}y72W#~>~1A;G$ zyOL}uR>zffcclIa)_lP{cRlU5hC=(Lz369mL`Cndty1arIXCg+wKMcIUe52FyiBT; zlfkV6P#&F&AanE*PIZS8i?=#WX}QEydMo&ho4D|@)8<|$0=HIym=Xsq5MofSb@cF- zmp5SUs)oiSYoYobhD;V@SLQ#NnbL8$e93Jw+N%G=rY#EOMEC^m?QGi1w1^>IQ6ajq z7QX$9!=3q=h-$rX(@Fd{cpi(V>f40wt0K>Q)Vc`j?}NL>baou7ohG44-v2rB6*89Qqa(&!G1%_N1*+NIr(~S{v#FkSvDOJ|r9=H$1GC4+I`@`!+bnqY4`-1@J*I{mypKO`QYc*^Q& z=k4lLjMZNO)x?u;#4I^}XcLlfXqGgE9ga1~gO-1zPvq&0KoTm_sP(UbQ`vg#`%tN5 zIJ8s9KEmxQe7X(As8*ge=b6*-UJEA~<^BIWv>X2@%vo+G!T6ij+SD-1xrXfLWm3}q zFd91k_9$IuVMCBkY1h0R=;+ysZvdd{^p;-KI+x@|8{v=S;S71EKvZyB+4*oR$=)8x z-{>&&ifoaAnJ@s5TOz@8r-ugI(R!;AXN@0;^@Cjupwt!t5=)j@io`NHWngHh^ArGa zrBF#O@hA99vQ4U44zj!##g@XbX@p70jZlq&utI-I&S{->Lii@RALogERu)t4$#wIIdsYC%H1TT-2%F7P#%Fp z#}u3(!g30bnPy+32()u(b#rmXE83IBjNmV3@uhdKHxkxk6{#s|0|*>f24b3ZtxO9m z5q6`KFA^^AQDSL5HbI*pa6m|gE+nKTJ&Y%f>7E2yWRQd7ug)Iu)myINP@u4b(bkPV z+_|$|ViP@A>T_GcAy?y~21eOniB*h8P5FEi75!^^#hFV-2HHB=eYg9u^|WYz!95w5 z{F!R;J2?xa!@Ud!Z*+?}VDT0Z3wZ%^_8c)3CNT*`%kaRuYWt2#y7+B)p_im_eoZeK z)>F4=I^bDfvAiJHl9o#=DX`KTpl|SOFAW6!V69|kwQVlJ}; zaxU)v_kP?Kc-bwwo`Wb3ZhjDQip=>nG>G<^%Bx0ADgmCmW4bimFV2b76e5?k?>3bLienh zRKl4G)(?CLZ_Y0bZ?-!AxJZ5ip(s|N#K0YJ^mqB^-OgC#LCnx_j+%v_;!*c$8|+~b zEJrAt;D*+Ca5v-bu(adBiYw!KOg{L{xb{5r{UMIOt)KIw#slw^+Uw$V*RQ+%FAr@c zbx=qYCzj!Ietsoxx8PA&i3-gZ=NlYvlr`U=rvsY_?HWOG8Lg=&i7!X0RGXrfr2j=F zdsnjyH^lMupZ`d}I6N(QUceH1YA+_;=0C#WW{OA>$GMi$7V>r>_`!I|0qod?YwX?v zkjnIVsdp1Kikz0+CgAK035&nHMRmxcALIjI0OY}D=xC;8Jo7^gg##iGLwkC%fVXy} zN1w;CF8oC~=$V37rI^(~Wg*4#hK+g?B#BU^C>}va_{{V*;MtHTa1UbF+ojh~j>oc; zju~8H(gVuf@|_@5uVz%JXkq8btRx#xKy<*MzRk? z#Ak?TNz~d?g=)j0x+=Ld8u;OkZkQ@@A?ZaqvFAGwSbWM6R@WTs6tI4s+poCFdP`-uZzoyF~01b-(~8}*l#yYVQ_GQ#2Ydr zUYFG_9jDd1yR!cM^5o+cql_DGkzuQ}Y%L8;7|O{|_l-I+wz z9XF}eN7J81@*FoA75UhhMEgAx+i8>f5cF3UPK}%@wZh?<$K^YtQ0|U3%^CB>>?0FC zZan|Ui!_^3boOZz#TJ9Q0qWg`wO*tVWHzK2PVpnOpwvJ1^6r-)lNT@_2SB!^Xi5d! zh%+r1_nT4s>QKDDC!%P3cda{V)atH2p~d?~BJA7Zu5RrUpAQCS6em0$Q7L8N)ksYZ z76`gHc)ARQ$Gn-2+nv!D5n5+t1X9nBlN)vHSIMQ;b$-7OTW8cq8S~9&runTs8*ygJ z9xxr@BFa3Qg!-_>Q8DDET?7k0n8n0fC(B_Z*nvUKu(MphPrF$>^t^sCH-YzW5be68 z*ukE!%ZWF(IzT8&OB1arxU;~hWv`y^G1#k624)JxtYf~5c*!*B9MX_l!;lt>RgeK0 zgXFu2QWc+NQHchj7H9hua5MH^Ye>pETFW#j>JDxfO3*f2)_kO^yuR!e=@uc6U8X** zVEo@aP;fZ4zZc|GygSs?z^54cm@5fsBx40q1p|7j5R;Z8#Vh5VJq#%yXr^DY4ar6i ztJZAS0v?*_iedAYKMGfh9Yo}O!K_<*aMEHXI_k?JwvYGLw;0MxlzBkxzq(w%?7=J+ zT-njIf+tM5k>5-v9?c=y{2Pfo&Ti)nmC`V09LFGh0rZu~5sfzNG%>IfW3v_()7Uct-s$Rc!ce(>>4)5j$EzZHs6f`r*EWsTyqJmE9eASjE=WnO-)P$TTVz zZwU(~oIR}lO;%eFMj8?@rQt+iMl`#%lG{w3TX0ADH8IC`qlq-cnZ!)Y`r%cW8S_`z4O!%6If!IuccwBG$-Dlr}NF`-9JThm*Cyv#H~S(CV!N~ z$dp1ZNNg==rGeWCu(;v}Fabd|-tQm|$#ED+U0tsIAL&>r z3iANFXAE$M!=)K8Ycx$DX4D4@?15orRu%;4zAeI>O(;?&&l%>3^loe<0n>pcEor3z z+v`X=mS@KyK*gW}C(Vzhhb?36v3aqZf+uAuH~gUi{u+WP5y^bgx4kSglS%?ahXVt+ z5P-b#eNEXCgs*EQl!>_`p7eYNnGh>O&25%o?JnQU`&cuOMmUDh0489z=qhY<7&aQF z(vDmmK~U-XrUWzsrUS4gtP@b`7uNbLVm22>;B>W9*)^&d=1EI}3_;Sy&B{q= zvwu|Q`9Ix;VE9>0-KokCEebfdK^PJQzkM!S)Z^gOgM);3VO<-%<6hG+NZjDy=V#B% zcb-q3Wb17TJhuPo{_0EPB=y2`Cccb#f_whqOf_)nun4 zMIZ-WENO{o3Z6$c2$jQn7e+(b4Ftro7n-y!2naO$y_rNL1EdL@QGya6;cgD;p&nPE zJrg1O4WsxZPMl4zP~m!ESBO`~(2uyRi_i%oxDX{}_3GEi`~me`U`eHwNSKnj>*g^< zLm~@bOq`9dH=`Gx3u1m@?9u$MefGwPljik$95I?ytoE4OB7Bs)DH!8=N}u+Fn>_G9 z9pKxu=ik{d_Fm`X4l#hdKsoCMwH~<`900zW+{P_dRTk48rYp42tb~y^%mqjG!NBR3 z#TJU?O4f{n;YDjxifc35y`_0kih=t8w83i$|Fl3pnG?i?)zvu(aQp@faGYHs?b3TC z6tGvybJbptJ#eXpGqv&Qiha7}-rLz5ZRTm-VVy1o!9p$EV&VnDn;LTLf98Vrpm8M% z-v3O6%2e8(^^kG3&y)+_-FMjEwL_rz%sS2ueS+WO;_A`{k`Sd-@`N`r8tb<-D&2C4 zrAB6~8$OI@P^aOi>)GAVI;D-;eJ>>DTbrwa_pOu;rP%1A7pyen^PhrWhC&H@GR+@m zR474#3;N$9z#vEcgQpfWq$98_y2`?U9oaSMtU?302`6H;d}v$k5Cj*{)INNS-BIjS z^7_x!6FfQjje4qRjQ?+?EDfKquh*M}W9~qqe@3D?HoJb$n!F(hqB2Wv@CN0>J~0$T z7dP);+4V>E>*MY2hu8kCTKJxS%axvYC#I6R3wn81cW*C`<|jSrr8W1{T_wHi2*M4o zXou)%@n}AWCm|49EJsV}rO9*!>UR(4`}dC)Z>}%Zojd>iLCq4#|-FRH7R`p1mCg z5R|d9o5we$H}EOFKMszUJ{VCV{Pa7&*+5jO8X(FaX8!_zpOSiTS;F-Hr}&QfxO={3 zK3e;VyvR{1#Jpem-hJ+dBOIPzWk>$-@cKBs82zku`YkKG36LAbpAU!+bs+cq?S?Gp zrh>A}xh^N@k{jfaMK}vV1C}c-mZlQ0I@pBtn9YdfN`SHTDoW%~S9dcBqI)*E-N40@Z<#`j~ijeZA4ABw;*su>`<#>Jh74&H? zU_{%h4_GLmQD8@OpJTOSU;;3MAoBdZZ;MkFYp>-+Ad&`nhJ^yU{I zb8YX?Sar~Q($|6Rk;P^lPVRq=@Yq0 zNVT*JJNFOd4D~Z&Vuw5`u z9YI!vqRR4Jtipo3s9s?aGp8?veVno4GyR7KdDEHRTpE1vj30 z^J3w_%SZ7y-y6I%zYb)$(r!#Cr5ET-z7B1!{70!^Qg#tCc26eq|F`&2AW8(m>Rgm0 z|EVuq?C&TS9z?{Kgu_KtIFxTf2iQ%wqISnBb5${D6+xxr-oBi`8Y-PUg_?n+l)!K` zbdZ_}J2XA=5+8u!7Aj={)rg8;;M;UTp^aoi0ZlRt4Jd1qxu*&rY0hwjST8o#R%>$z zy$O~%vus3HjtJ60eV#W>QYhlI*BAFKzZ!*f}k(4BRLtvqg zA8tr+F0tU)D4rv&E^!ld2Lrx8t)$7(B>>vz48@1&DT{`vxXFg+Ee*Cn8#YvMro}Yp zUgtpaqLry_!V<)hVOK0l1ZmfJ9Cm_qj3-~7FO_{29)@FYV%&?t9g#t-#T6Tav`S$GeMCX+oFzYdY`oI|wR! zsjMIic_4Db&$qaSmO~TAp>{TgS1pmJ$C&)BRYA%|d_GB+sR+%fTs#_SiYsn2C=HK> zT}Z4v4+*ur=cbuOL<3qa(GpI+mbjQEMQLuukgEF!RzoV$ z0vp0~hILHF4YbHJ02=bS7-OL`u6UjXr|tZz(uhrpT6sYai!+Mi+#m&y0Xra4O3p+& z-d#wkQ827E$fh>sMN;WY>vp@ZD}xd4d;+XGS{O=9j$8=_tWJn_1O(mP8XwhA>@XmNpcKUK%9Ka3xi=0X3>@oB%Aw4#0_!%e00b;Qf)5n5Pdrd`dV!)v zxn?RP1*6l1Nk`FuZG%;sWdL-3ppJz*5BMbjJijCp)G%g ziMIUR^lq6(_vQ$l+KswLQ|4Ul0#u*b7uzKZaz|v}?Z`gt19qRi>YRX`0pb|zea*vJD!CWdHhP&> z`5#j=tul46?+BjX(bm9+SW?cYU_pZj&ZB4`+vA8VQ#0n<9EuWgnLgIFKScCV7Z1DV zO-fm{9Oba8geA8UqT*>?J-Kjln1*L>v;{|$T?C>Aa!_V9hXG|lNQ%r>6d^5If+q$e zTd0)w#9TLLKym%3qVmJTsoDnbFbrdhXEV)3ngX^1rgQY z+qBaGVVtCBK1SB(&#wJ9yII$Odlh_qz&0*$=FfjX=&!2V(&YMC=O)WR>0 zV8{omX@WBZ&O{NM!(vR5O>XiowgH1a_Bn}^l*ZXBFkz<2L#bFTM@Z+4s8yZsooNwadm~vD)6(bOeH73z$0UVJY-; z>Do6kjdyd0m2^My*6MyV4geQR52b5cA$U;u=-M-G+<8R^{|c0}@F$b7p)&Ppk@|>r z$WLiga*Oq#_A%&h&}u>o3f?q{Wk)1f9`KGAho=nk9&az#&q?;3bZs@Pj1t~1lP2B5 z00sdR+o`Ka--qI^Hztq8tzaQVAsjif$0VFs3xC?_VBDCm8+`rEPIBk#*SFrcoxRrk zo7C?e`nOiVtsKHv!Y4uv)QOXdNO{Cw_H-1xnth{lvmR8{Ie81xCc}13 zqOpu-BHj6}2-9YfapQY!rC6g#L|(7fVdG4Pk30Bsu|6)Sa3Es5+Io6f-)H2S&SYpCTuZ3dcxYMiSPV^w_gvzeH(u&0-y4FtzaAW zwLX*^L{OeXRGEq-==8cyj@F*t$OhEQ^1oK4WE<+uU~O%H+tbfWn0iN_`6y(N5LW&> zB5-D|wFFZzat1uwot&Nyj^%r8!UlTrHtBZyuXydfZP_+!L@{8A(AaK`_85m;d!@F2 zLUqB0?a}AIE~Yxpnev1%ZRM!J>kBPtH_F8TBm--qc&x%OBN$UeX32w8~N5U7yHfx)%6b{33RQ~OSO3;*J&qkqOJB!{SwuTSSW9;71GZ2J}lV}&*q0t5`urn;^ ztbcc8jrrnejjieXdfngRt#7|X{uue-Rx|c41j>hB;Lq}B;VQpP|0}0BIOL@r>TUO) zi(N^9s3d#H8q57Nex?*1uQ3v~@{+O99QxDT`SO~RasB_-*-XNd_SrQ-lw4S)leuuc z?;-r}jfd(RJhm;Picfo)2mDgNdHMAg_pP3+vcE2fyLu;FyIyO2VqPW2s*_+U!+}|51DVi+Zp8TZS*=*5E3dGGBK@=4$ud^q z(Ti5%Z_T}ekybYfSGTYf?XXO9z9MLHe4dS68hC){Rt1*C#vdIF9^=Opgcxrhvy+jF zru|UC!xz@NnWCsMLhYFH^ls1kW0SCxaC?XZCHg~m2i$xDThl#h|3%YA=SMH)OB}Oq zC3VZC<;%nKpE&OPL^0V}Eq}hVe-t6G9Y5DyaIt0?rri0Jn&oWF`4`&AVU3IXpgnE@ z#1DQqU<)o71d~Ei>N4J{V5r7W44vWC)-W@JN|J*R1v0xf?e zm2ag2rJ+LFhwd4tVaJ%#7@OxB#UEu;h%A`}qChl(UPmSFUsCE^N{9zr*wF_N_X0Yd ziRgJ#=5xQ=A%|VE%2I+^>cZ^;QW8M6Kx~@{sz5f>Svp0ryXid2I@Q#LH$>&eZEo>3 ziRf=gYELM5dU8siM*dN$Q^W0^uuqsh;I{nNiLR}41!AQ!%=j^WhJAr59*)*)1|I%j zGVP-`*}>&}!@|**1MhApJ-M8S-YS`_|Ei=XSs9!k-Fq&))HB&$woB0@wm}rJe~GQ8 z4$JV$xN5>8s2N@>y6%}#GkfL9W=Q7~N>eZMgh|WrDo&Ck(_0P=O{Hn0tVV2F0h1;< zMxlV^sS&9U^z8;w4VInyy2Rh=%s`ct1eheKl>~k3pbCp`&1}B{ZQ&DjFLH1Q6`>Gq z{dE{CFQh+1L;Ju0%d>?u@{xK)9>=kQERi)r!jj;p>FeH*oiB!OQD*Hp?MN<^fK`@$ zFN|728&UtYOhCIDQdPdnoTve%NApqSK)(PW`6q%bc7ck{4K+B( zM*BQRQXGOlTKO{|L7-ToLmh@vE_mYZXPvwAxFy;~cjur^1hJ_}oCgQ+J;-Y~8Wi#K? z6wTbZ%cx240$GNQAyNC~;C(qFF#Q$J*cZk=*NQxKKV39-__yn9WWY4is}uyqDRg;2 zVlm%71O6tBD599JbWjDDeN}$WMq?s`wbC{hkYjl{`%Kr5$xE<|jCz3jjVY<%u zpB@dLEWJxyZ!c-!LeF~Jj%&GLHwWT7T#z?P%?PbXdyMTdee1jFQ1;fFA@)BGQRz{{ z8))o*$$D;vqtr{SsC&DV1#!0}6hhfiml(R@n^poc;O*^pAkQ-bCf2hd&rxmHu|-(# zFRq{~i!KuR1uJ~G;L@?o8`m3vC#HjwCk6)T=F*8+SeO>l6pf7|hFl?+L2weG)|&xX zXhl-rn*dY;_CmI<%x=mbFWRa|@|h=;*{oLy};|*}^oC zI|D`biZ=rGmW{^;^T%&68B;wffEKLm2wajn;(&C|l?Ej+7~_jB0O28zGfAD^GGQnY z_&49*HDdZv;tI5a#oa(D5db&0%MjsPGqt}Kgw}FQ3@_Kgkmlbt(_hE>20t5Nni)J6 zD%MUraX@7b@$^xxy<&OM1)$5o83{5NYR4fzq^^5R*lD(s#uXWC(9lsn>1CdVuB>xz zEmVHx*H$`~g!)TouZA>Ao=?i6qh&f7mS$)#y4iPjm*?0W4Los24IdZSW+oG6J={&s zkB`^A*iAY+axc+Ew&*R(m~Qe9H`E=KI}nT^Uzs$iR@yP0S#GeOs2>fu^u{Oh^2ZMd zl$hMHd6n;YCy3f=H~AGR7}yg@Mmj+#2Mb09vx`(5O)&*|T=tK)&YJx|k}1>v@PD*5 z!I5*bF*#9x=q{*J8Waf#*zJKx%^{^mNuDJff8>K~wdC@Ga}%M70y1fAc6cLWe$aG+ zP2%2?H(cdJ56f6hB_r zHlnmZbOn@z3Cm0-`d7b|TR@qz6T;pCF3j3e!oUKJ2bOB063J_M#nNgSp>aZ7x)np> zUB#T18U6kj1wo>SWrmW4J-T!Q^@0 z@@>iDY}h!@=4-)2V<3XEw?qg&I${iioTZ`~R^JL#Wt9T|7or2Qvt5tyr3Tkuc3`oy zc$Q&mB%{0^UH&F3Vr@9zqef#jou+C*Q&@Hx=E-YT2!X_~{ig@@a5w$+B6&SPI2Td4 z84*{bX)%1+*-6o~0F*5|Qf@$OMXkJyAX>>N2%s305K$fsMEclW9H4e-u_|r=QzglU zD26h?K8_^k9lLW2ILJ{n=EStK^lZXWs%%Z=9IKp#7**uYVYie6DmuZLQN{zz*V{rID_4X=pkYN7=%RVz^H>;DhrckGEfC-_)XZV8=1OtLhnqG!%+eO0(X|dwQ~BRxlc+2pPD!V zC83M+tgsZJ#hui?W5Otuye$ZKidC^0GkH)Vd`_+skl1sBia8K80E29w6###d8u833 zWemB{Hf*nZUgsd$38P$;YRCTKgvPQ;lt9&Bjvc#5~8#!9huVCXq#z#xGZQHBPRBb+QZ4CP;c(H7>~5;}bZW8X( z7;8IbZnMmch+R8_mT#qRau@k=kegqva*WIXE@sVm_-y0l?3?a2qDFA3)R_Jm&1n(a zWKQDuuDhasLpXuu^dYus=XTljoIp%v*ks|HMVYF2&{lylA4q?kJ6Yp_C` z$Lh)(lwx_$r35Xt<0}0hwoZ6{zlPnFCJ{w`jJlqJ;f+<(Obw?9)||nw{t1P}c&+Gx z)9}<=9YK|5omlQUtd0ls4}-*Dk1{xmQ^yWTilZH82{14JEr!Kp6rvH%{KWAfp#J?zk~pgZbPkEgJl`xh z4c;(={y4JLri2uX6A|7AmW&$3DhMz0O+s1VkYG9(i#Ugfcj;bdOPW&h>*b93KmU+Z zrd1@m>p-;Ev#si!6J&3qcE-Fj=bP=4C(K|HIiyN*NoU(DKrNw|dL06W`j`j?Npi_ys>_Y4cJTQF+KV z(N+;=ftch~aUKl`mAIKgo-tcdHDQAO%KlR)A=_sMx~YDWM7&Q26MeZCNbU!1q2ziM zqGOL*fWBP02A(($coUEZm_B?x9)a4x->v%+5$@cG{u^;qkko1jGtb*I=M~@s7)XDm z{HxVOh$Hnk@qb`!i=A-D4CDecMeMHrgV+&rXiz$?Bk~?&lGU5zRAtHjrU7A^0o-fy31f$}pOLU6?Zg>F zSqP03*m!yn7=u{J z6kVeK2eA9CNukC?F3h|VO9C=9?%KA1g^XF==^0mJi0j@OJ|-`LouqLiVoqc;(lQZ? zNl57};!7@g{5lTRok|Qps{O+3AnOf;qVOg1YK-6gwZ?mgg!<;@DOLHgu$3JafQ~Q$ z$v8|PNv{#tsAzVhc#h;kTnji$0gG#>hsPi7dWgK3piujh;Pi>LYmrP#{JE0l#32!^ zer#f>7aVvV@Pb$-3Xzzt0;z(`N1qOXjum*-x*it{9!%2V(hC54ITxMe;3f>o8WMWP zm3XZ*A2Cz{!%@ZIE~DSSxU)0bnBj?k+eqW)|LX(pQGMWs&5cr7iTA20L1DM==H!}$ z-rL6ijkzIp#39pX6ZgOF1E9s#>lW-QE~DPzC<2B*XvBR9Sj-`Tq>;4vsR2>~A)Z`b zM$8Jvo-luYJ_n>@5Mq^8lIB@3Ja62b;;bPvX6I0J@u=CM;OfBKM|I-L~; zQn-&vpp>Oni1b{%%In34(?@q19kY(qE$xP# zpD8|fmskz_0Ema*YaFpz9VOYWq8Jer2n}mrF|Zbpwr13#pMDrVi96mb3}K##4JO*zoph_P0w`4S z0%F=d12YzO8aQfO1WB3ILSX*hpZ0s$u}QeKPQn7fs7raGNvkk$!; zn4a8#@QS4inh8+p;A`1;0)EtZW}Zh73Y^?%r6it-Y!*qvW0?JPrV%#dT1TPP9O?_a zR(~Xdv$rQ0XQbqxwH>_)2|!RpWK86t<-Duiz32#OcLg#x&rbp~Qpaei^k+$t(+VFO zcUlI3;`OyE-hz;{Or1q3cjL>ZNi=_x!w=H)(;*XL%Z@eQLoI9}T(krjY#PRWYEcoA z`<2VCx+DoaQ38n;(Co*eiXf(l(B!V!1>BQ7wGQJR(Z)1AgsF|-T7vjly*o}^n=r%g zU(7B(2X6L|Sz`-3iGnjjB##S}YL-!i(b$Z!yzvInxqc5Ze@^n@Zcc0i;fjOsJ6X8^9S29`99d5~lCXZaB`QR83o(UW99a&4GKT!+s1O_W z@5>{R_lN8KOnLo>G(Cg?nKSf|KQUQ^*5w=G1F;~z0Ph?Bu@^KJT2*u8ER`C(>t7wA$lCa52b)3C^BxrhMnyZM z2dNl;mgyF@AqN|3861;|h~vI-UCpA$_0=4yKHoaw1!P?0yhZ<`Q8Ciy5Ge}I;T=?D z)jnLuiX_N11a#qGX>VB#@iLI*K!`Wet$+gHH0CE&L(1SGBrBFfBr2%2?@L3{)gq+I z;z|D)fK?_E8DgQ~SbNE&8$S+(UBaJHiWaZoawfSJsP$10Q$y1gebQ6$G~gq}d*7+l z$rWikYUuRkPu8jYxsNhEUiY~`+aTy;f|#}2*!8h*(dl)BZRlf$0ZP1Y#@1k2sqVLl z_auFmj?4|^&7xOUuH*XmJOzW9!O5`rDva> zg_IwQo~_b~(ShBb>#+PQgV{sc?Y+#ENl4!dPljI2m0tIuz9{I1NhbW%DPlN0`!jj5 zzo>J`zR>cV(T-A6?|`LBr{kuZb@>*KGNC%Y@0MG7Aggkw@uzjkD+HvF1a%FbfedPp zwPUs6y)iMA4PMP!OPy5@TF<>sz~v7==TK5g$i|4-r62kP*JpJtH8fw+D@RM>Saa5X-x8p%;Y z<&oC^1Ghj(zZk3S;e33Ozqw*G&Br&3*aUp6{31g!wG@9xcTiLWVnnvpfYopA_E*q= z;S-BLT>WjXxsRVX&QrDWin+Je)QT;R1l?5o)m)&9*OU6QeIga5*L?Xxck5M+90~eW zgXW5E3`@RaX8_5@1aguC(39LQql3ef#p@Nw&$2^NOK+iF3845I; zzw|YMj+5I7ho>6?u?!d;4W13B0yZ}Nw=WpB@wq^U16PogY*HyFX>@hA27035jXCPb zV&@<58dcj2c?vH~us=h@{<^mP5t%sh!QX18~s7 zTI^VLjGDL-0;jOfQUu}++1n?9% zpT1M(=-=$DL^pNOWEp9avj4=tie#=yo3eoWm0rwt<7wiwVF`>jpSpu>Q!i-AG}geL zV?ci6Jso&c*o%lKX9Am$fMi01t)V!`0*;I!O{K6klg~#r0WB~0RTMTWZL#rp@k**0 z^YpfgdGJLLlZ{y)s!$twgiQGO@=Eld0z8zDz=2Ez20C4WeCtpJVeiC>NHarJqtPcN zz$3T`7Q`d*IFz0izy*0hMKG;V{kIKxBzm9Sf|ryRcC!m}GAHW}@O&MV&8zv*+5GpI zVc_U;dKLTmKR#}pY#%viSHgfQmN6}{6qZ>JOhlgIe$@1o2$<0Nb}Pt%;~W};U(o%3 zJUN@QS|37+>Ut+wq*SQ zf+0tW%&WiLr)-kcDljoaS9VSHbgLw~YKo6;&1x=1l2C~Rs;|M+=K9;sSv6*>{HPps zh}w~ObJ#pJ^iuN`^ch&mEL7erbG+?xR$onj`(bf9Td0mhKTR(_&fKX&?#oScR%z_8 zO-oZWXEQT2O+u~NQVeM>KR%MAl0jVD9yg#gN|v$!<>Q-e+$?YQ_H2A}zqJ@e-@gTZ z+U2aqVA9>dC&Y1=v-x7rM(?{psn0ZimP{onjrew`xOW z!~m!vT*eAIyPQ>Q%C0Z%x^nhNFK1>wwh`yIosk`P>02gIh1?~qpg?z-OYCx1pFZ%M z$>5W~kajt%|B82b{`_{*R%6j?igi@Utmdwe(=EEEqoBD!{ZaT_A`Nvpt6=_|G~7IA zHD?gp$XV4>+vTh}Tfyh=jy9?{pcd#wO~yw7x$QX^G1zu?Ijb7NgtcvxrCY)fnPE{s zZ8IA!q1|iCUF*Ijh7N-qOa|Do?0EFwH!nq1nQgb5<2Jzj4m0M&>uqSyeOJLe8q5+b(C- z1R&_d(ju*Om$Q0(zC52_djHBUXZ3t`xs;sW*K@NjyPVZ;bUf4c>th zAjXVWXI?m3UVf~l+%fmoE@w5DiNLpaIjia8UCwHuD|{rEF?$8hw98q2@MdHY zwOV-@tytjgT4U)hXVt*Mpt)4;U7guAb_VQnRw*{I%US(bT@)?GtoFqV?sd*8jDCww z!N#0b#i?(cv#J^O&2v`O%x<2us;5S4&t1-{_-ty=y{?Lp{lsfE+%S)-?)<8fBLmF* zNoal)0`Ye_s}C}qAR<;~ic!mTBxG%uv-HziQQUfkuZ zo}Vty9{ac*?Fjq?b5^NWu|>>NpR=l9#f@`THLAFI&Z?T(&2v`u)Ybt!yPVZe8t@p% zp-@QqoYl6HDwc_`diUU_r$iXNj{9ji^YvVIIjc_}>M;Q=5I4v#PQn zKhd1kN&Rt`@Bt~0msOCnE54|z-@ZMA!xY9y~ zRz_6Ap_Y`ss>u9HI(_L`L;5uZJfza6zRaZfCDcWuf|}G|PWrZLjZNiCiTR=O13kX! zF-TVfC!o<-n$MEiwnNn+#j{<@4`;+<$ZUuxs|Fe8Dv?KRP@8eT~ay zGNGiet`JRSbMn>Iq`uw%{^)sSVjJFi^y_SSa%RU=NgS5k;nKpt`R>`n?qmLbWLDp8Y9BzLA9sY<`JZ+YHl}pRczvud*uOrX zUN%qY!_~#?-$y5l^Q&dkh2Kvv-@oumad!FS$0HfVpZigV$ZOW<{bG7`RMWmt=UMpFAJ+A?Db;);mUuL71RFiGc8B0-&QH8CSX>DcM*{2ma*w6`e5-2 zGxC&`Ah8v^TltiTJ*aVA3c;0=@|&+uuJ)v8yL;!W;=f<{ZsvQafRBsw%KsXpvT<2Y(BQsjs#a${3gr8w1x z9hy5(N`iuV)MrU-As2P3_d0U)^Q;L)Rize-UU+?~_d2wD|2|^xIC-g z;N>{!P?w}nktph_QgNN0rJ^y*H*l`~b9Vmz%x`k)zEM_R|7GXH)k+ahhw^t>5x+e8 z;rPX?Alh5Xj7-WQJ^M}FG-;t_x8*OD77Mp4V-WLi*6Uckx7t1Hvw4nJAt;-gV^ zLl040me0<;X6XDvW zd|9kGrc)QanJ=fy95w#)e0i4XAxS&YAAv*KX~ytGFY)>cf-$BN33+{Xes!JwT6Xi% zk1rn{K7alE)#1?(uO9ZT__)FMHV&(S%}rlHAJZ+qf_;U? z1JJ)h0c6&oDTP-1GJQ*#)M@!RDU|z9(*-ob>p{`)dQY#UAc{DgFQ2?{^rT_hRRo^- zT1BHB&w)@tw5m)rilX_@`Z@X|uPxH;WlImKWudi<79Y5ZR2xvJ*nnypmi77CX#dPu z#GmBB`JW1@}6)%Fwk3aj{foH_~Ant@`)e*(SP^;CV&3L|M?gGY-CgcRdZr# zU`mW1&6NAnqpUZPR%#QsA6A>2+-0kbOXVC04}15I_h0q@RI(z|SX_9(w%?(i)W z1;4tl_uo8x4e-s<{|CLl76-v~=jY^c{1?9@Rxh}5ynv@2YOPZ15yrvir*W!VvMr4x zD;9klFQ9gmB%Q?Hru>WY+lX+vQAV8+9jB=pi%pdFeOVj1EsY|3u)yeMHx(dKlt~@x zE3T5wz51%VgPJnyjTzc#IHe7&WYw_*RXTMpGYPz^j@m-6aiJVm&BMo7GLBconn+45z%ph7{gK z%c7U_-*UuM1@HcAX6KteYrLXUYugHdm5*w#e*NRkn^zuRfSZ^ljpx*17&)&B3?pD? z1%?@Sh*cGr7v0=?G(a{+uN<$W9ZY9~F~=3H+$du_(Th`HlU}Ev;xrqK=)o{a2Q-XP zq*)`5j&*pU$kc@zg0O^R3YUX+=)XsMZLjfGBalwlIJ^j4hoEk+0 zwkVu>!+=rCEuT^~3q+pceq<~QrCc-3^gTr}YwYK;@+r6E)OrJNpI=Td_I^5FEI;z^ z;N^O8xt!s+6*FyF$A} zi5A|{`dbM|aWHo~{Ry4L=%GOb2-i)_foo1?X<$o75zxRGU|^kK`eddqHvP~?U1;Kj zC>L5;xf8a<(MuKh*>DBC-G#dH$-iyPh4`|{S@fXuKsg1+9a@qPG;~MeK3_acSuTeqI_a(Q- zq`bI2F7J&y*13hwX0v4nO_Pmp_IvX_wzp^FoBLaA@3ND5ezNM7%Xh3cdSoFxIk9#w z*1}lw1r0)agV)E#oGHIn+s$4qbp4+oa*!SHoIL_ z?@(T0-YHb1U1V69K5UB1WU-2GQF|G)GXCb;3&p3~;(0PVZQg5|UYqM8hQQiKmb}jP zI+<8-0M|zR$)eR>q+M7(q;E|RXN@+?_NGB>g=O3Ol_FM>DwvSHTH5Ftu8ix!HUn23 zTFq|}%u8Y53XoBgYf zvN#3()jwOj=uUHza!R;qTz zK^Fw??TS_UB4=q~SL9F1uBZ!$fCj=6VB#C$+=9Q*a+z+Hjvf>MD92A!8l*1+{rzZ` z8xOZ<-}i?@n*TvZFajncZv`x#Re&joMKZt_MRUaZ_Rjr5uZOKu#_SQpRyVUTUEHNl z=O`Wbx&|m&phY~Pw2;R>+Gltlj2D?3)=L_(4kq+iq)oLxI!m}qVhVW;8cQ?$XwsTi zby-L5#IsDiVc)-1u`+tVTaWOsK^$u+sP-HsLLFGMZ3^;;;*CSPh!Mp}7dQVw!UrA~ zL?Dp{_cZxK;z#EDYKRO=PYCm*nK_2-)C$YEC<_nihh2B^^CPB4_B2IEM)W$yHh@I& zuaOVfjLeMCS9;o|w3;0@F#m3UL=Y-Plj%u|$)R>`#Mshy5DCL=Juq{#f=p}jUYDK2 zED5Nk<#1a`Cca@Jb_I4j_tNuSwD28E@*RmPfw8r|9G8B!rqYeCc@T+7A*@;*DEW*o zeQ|sIBeWLDFuoBQqf8rRa1!>1x&IysT@H6Z7bY@bfa*c{U}o#n#;|MLZ<=1zDRxCJ zic6l@2psd!Iy&N3UhNHiT}@g`U^P)e>B} z@OUx3yspAjeO;;6W^68+g6Lb-Ym81#hP`)No{NjVu*;%BX3bQ_{Zj&PwmcOgd#c|^ zgU`Cjq^Dr8txm?to?n#$$0}JoSiyPPLkcoaAlQ4ao<8_Y{X|AV272INAxW)drHs?D zw^0;Ab}Sh;7tx|JdK(0EKPIy!=@B^46XU-%c=!R$9QOTQ?2Pa&09PoD0C-3&dU%#y zL-&k?j9Fq5=x+=sumwpD+*KvrCCNHsHauh;u)>P8a2n-IKu!rcG!lM?J&|V0!``4f z>=IKoN?iwH;D_}1rJLz^JbdhqxUBkzF+3i+=_C}{>G3>b;3zjw{|!5hSedpPPC}O; z@sXXaKBZP8{!^OI)Fdk5a0;K&okfx@)$JxAM&q9fpOTOgfTU}2jQh#9Qr_N&>BmQfC!3N!F^_)I~RkW6|+I$-R zaGHH$8$grvN9kzLhny*+RFGyGKaaco8Z!f7%s%e1yu_^)U)rTaQg=Y6KB{bFd#{H9 z2U34=G@&V?be<;JUQH@&ABkwfubYg9{S*!APT8=<{Ps!l?LsLLLli9n-h2K8aa50r z?;wmQ^{TK>dqt?FDDL5SGG@d4394|*lgRfEg)DER3Z-@IX3`WsT==+H3(|fs=@J9i z<)Dmw+-^tmH_88BWGnw1$`pwK561Ypcpqw!nnY(IJ|W)M_K+VZed-RuW97lRh<2Qo|Xt{iNp^ zpalU27^%?xgtZJu^vb@i9dx%av1S8pI*EM$^lz*i+X>H*Pfo%Rxk>1^=)ngN1S0nb zL>LhSl#XH_S8V0oQNK&(5%zrF1|#U$?dir%7qwnBHW7eZ{IZ*A#&#ccHFVPGG!mNE zx!E`c)ekN!|8Js&!VjFc!AA{IjbWRnf2{S8xzR8YPMQqTp5t}F9$MJ`k!kv6L2v+t zcx)6#)3((#8IL729-BUnnjtt1u39`SH?AW06nL0mHRmdW_>84BfuB;)0+;L@bB1UXp@O}w5_z{c>JV9&>0mr?)}cUQk}F(N)UV#@t!hG7UAkdEox7Se2@dDv4&R%jCd#rd_V` z$JIVpX642+G2Kj{vbV4*W{F(AS7zqt< z4dYOB2dItLn05>!qO{#)$^%7h4^>MYlo2fryh?l6JBJb>s}7p@h*bR37X^Mg9;BQ< zBy*AcHRiC<*LZ-9fpx-RhS#`<1!6dAXM5Ph4BI2j0#-5_VT|Amr34a(kjsmfA8;Ne zgrlc;k<&>_Gb|O0rA8v0!<~t(jCUJOBFEQB=U_t=*2B%uD`RcOLPbn~{ube*j?$FW zy8#}R0mm;9D-m&xN>LP#wHXl{!&xGDfUT5{jf6C?GVB=m7ua0@9ln_{3Lk9Ea*tJh zOznhTe`_LxMUS9r%!5Aap^eCFIteW@Lq{db`amn5RFyLeiU+bx88eKU_=NG1m~Z1H z#vPDNkJT|-;jyjsCMpQZjrvJMw>mso9w#b@;3dD0q|xAoSMc@ZPAd@k%+YwnV<2gO-4pqSDG*l39DAugM?YsS<`|=10UiCW0~40=<>;IOT9SuNl$ktK zZz~JcIc+hz;RNNOS=o+)js~uVrKSsz8jQ#Q9~y;TLhhgh!4f0cu>Eo@T0S?5)?gpP zvo=f!<Jp0QXHtx>hy3gbB*#@Pfs~`H2p{XqrA09S zeE=X~VW%~UYtnB+AR~((2xLDHxU73%pgV1)GM|8vo7Q5;?U@*u`|p$7g%#Zq$n%q5 z52?58V@hPt7unG(a;!UW5rRPm*rthXNRueB!!X^G3|2Hc0lLFdAe#@S(Ks$fAi+QA z!eNhCb*yQrQPctX!z+0{ZfoX*54b(@kMYOSfJT|;118wrrFaKb>+xNhmu~=EQof!H z0;re7eAu+%?E!xaxFkA=fFc5rdK1SLscny2yGs}|u^>*VtPI%+Tyc#!4?`8(&q3q< z&8T96oD3!tVi_p^hS=zn%zr*%?HKIIeUPM!z}d?HUCU(+LBtu?l?VqM)P!MG2LfSZ z2*w;i_X8~22&Y_A9w^ELVvL6L_SGXY7*S`^nigchhu5=eprjy$te($2h$_+M}O6(0mD*f0@Gnas1HHa1Z-ff)6el_(qM({ z3Cw*_Wt&mQ+c;vQ)bVBmtw|lB8e61}B9-{~FbM)QppG@nk*nZu1d)+7W5dW4b7ad+ zNd6H*gi#L)R(e=YkMKQmy5I%^ZrI&mK|1pSl=MM9#9)-kUSMf`NF&o@rwY)~TdRcG zZ^8G7ZJ$?#xI#$X%Z5oA-Bh8D5f5#?Hs;RHo;refYN;bO5KSHVV;ky-@3FG#f%*;G zP{+vP7x%|MLtCj#!UQ%GLvGK;H}{vRV{8RJ7r6^34LQ(i?3=ULzX9ySI|pOY{MELozNT4|jai!6;8l_IGJi(#Kq3K06S324hWomP%P z={SEN75Aw(N3e!9o!l0uYyYi2If2=%sWo0<;QoycznGhGt;ep(*r<}RRmRpI(vFK< zKvHaoohXs4fCMp+U{1x8M_9=2LijWVi%*Q~M8T+~hlPpZ>Pw_X1mz;w&-!70IB!g+q!SS#lA%c|I@_`IuzY6HosWNIN#vAK#3R%OJo0WSAQ!)oYg{@(JgstLD1RN0?Anwp&cs>8mo~##qV9-t z9M(kM;pV`XLUZpuwRhKoIsg2AAu9;bni>?^-flqc${55ewV8qu#$5YBu=(s}R< z5OxS9E|qy~z-$tjON$)I0U|8HpwHWaY$Wj$H!>l&tnYauXa+kXIZcEKujx_DtfK2< z{PvU37=N(RZxf|$9OXl5R#8C;iI|v04xbOd4U&)J5yS#^XzzlKdHTdJiHMR+gZ&uy zVs$S_T$vuwa==Vp;EAM_5K>M0G|4%(MAlvUZ9ZRt+04<0>i}TOwxs5Q6ts(dKb+I) zfMg<(8vHNr8@JLhF-IQ*qNk);mLyo&P9Z@;6Fh;G-k_2o@D)v?C*=jk$XQMbiJ_H% zdg=y{k7d0b+tV;5r|cF4CRm~}g3(69Y&r?8VK(#h-Nqps_4M6rpccHbl6P47L6L|^ zY-0fIQa9Q)br+a$wEW|O-q!q5`B&u9A~H|gfAh$^w1fVYza;*HvXI8GoU_Iu;-Uu3d3$^T${*iPkgDHGa*^>>*Zo1IoY2VQY?#pJyIwNoR^g#<27rige z9&U}q1;Fy+!}}lJy}O<*GkD|PfgfhCp;sxtG}A%h(lGPVwT+8ktdvnx4AJ~86x}s9 z9$cJXUD02gZf|FfvOm~+{`A3@ufE#XvpW9wG8ZrGuEY&d{;0+0^Y`i3j=eKiZSv0C zrr+7EYR%(Yh+milX|TqQz|V~-!3~oS9l5$j@_w2vmggtai~S3?!G9`se|BZ!KBG3x zw^2ZCy}l7C0hcC~ch}KpuT3ne+5TZ`MlA7~sa6SO=)2V;ebgaJQ!smBi&i!O%q-TRVp&#`I9oc>xItk zqJ`O=oS6YGFD(b^K&Mb8m2!wk#F2!nMPF4=rqIitxIpTq+a?~`=t=Xidh5KkdQw?R z%BqsHBf-9FwBU_ddjsdQ+_1*SFfqqm#w?)w1cr`WA=bkk?iDo1Ub))2#Qh;+u3k>iBH-VRl-qk#yiSvUxDQjsSBy z>QvFX%=8E!iND?)fh$)Rt?=XJ>1=VqE~-BHhu`XcbF^HX|2kWqEk0K7I-Gxedx0M| zyJG(Fz4wtB8^!lCQ7_k5)04=!ZhdPS3~f&yOjpc&rJk4tR5J5!@#Nb#a_*E3DB!Fa`~74`uZz>f3>PJe(5b@y29_05?5$@RBa0Bq?rc>9{`xLQ``vCB@*{U zMNK{5*1S0?A?pD?Uo>Clk9NTdFF2+D?ao^7fe7%( z0g3W2)rqt!;^0#spW3 z>I|9EhC25sdaui)NWs*~e?wF!MaZNmIk`7vKXiS$xgDxAR)w9VPTJ0T7^OvSXQ@+$ z(w(IaKC`pb1%|P+)IEJbPUQ~OIaphes~xIa3)LM@F^X>m)#Vj6s_s`jv&#J{e%d1I zDe8Vrk`C20DBe1uraXO5jCn0bbptxg(c70+I z-rAr#3ha~LNGbw_3u!BCF4X>49J+*Wli1v+GYdsH#?E8X2Gr5sjV2mY*p$Q_dSr@Ld$|{@8?DENvM{bB0muFgNL`o$f@ckuDFtU2S zeCPfu&qkmK#Wx>k|Fe^jXFU6L#S@PHzJK`qp&IV-_dmWoeDUqK>P_Xh?lr%7^tgEc z{HOBr)sgF8pS6j5mDL)_!&hGPX1>ILA1?dn`SL8=@#QoqOcbt_M!2-w|CE~y^IN+&VMhYs`f%Ly|uVZX7_T6>(JXe>mSGZwYkpQVz1j=Dl=?zokX*` zMKKKc@3V`mN5ai)@!RaQqj!}PkE5%LbN^(+ zs*iBjo}AeT2_=y3+cX=acXsWZ6c`I%?m8yNvxmv$$EOca&1!9}%i7! zP26T;yAXv|AqsZQ$d#)GtJGhT%U0X4gb>Q2Vgv1M{KIUy_~St(QvcOlaBOuqzM2crjQ#xRZ2o)n=a-V|Tn65+<_b=hsLW@Bf=$&KhH;dc?T;)V3`cVkVs-r5VOju@ny*eFYsAe)w$m zp4M@HBZlkeM_(Djp^Y;XnCbUM^nk$oMZqtzb@)4fkvo4W-B}oHq~9^OQ4WnxFVq>u z{3G`s{o~E?!-q2F6F>f=|L*-w{``yo^Dq3_SQfNxM+>z!<#anVufpPkXO1Fu(yQ5x zwc3{BE?X64)u$gRPo>lv?Wv@(mb+{Jc>h&TPyDfdDLvDb!S-gGHRaCv6?0p2(jldR zW>M4$qGZp&mRWPx`TdG{t@H&Id5{@rPouWqfGS)VĤ!+_-DxT_kUB|E0Dm>6*? zn17jq>t!mg61}R~a{Q_Y{f=K)Cg1uhnNYB7)bdxkXoby8Evj5ySR*h#oybuZiC7oI z6D7sVQR{NQHUQaj*Y4BqFBaKJVyv6@frbaN(6{{%w42x~3wNG@P&sPaE^}{y zDr*K4Q4-Zmc*_CeMycHeCR))KQlAJ~1JuD9*@nk+5BsXfsOEI@Cysgb%JYj<`ADoZ z(JI?3X)dwSef%YZ5vBI2;Tm_q^rd6wgj%vxNtIp!H4d1rO>CRckya@^eM)zT;+as0 zwNHg{s*>4MIeToIA|aC$?-LMV^|4L;P);klfzWoG##mYN<5lOlk@l5`vbnnHP`+>0 z&058^J=N1xCrl*Z)m*AUefW4W6&b6Hdq&dUHHA{--+M0(pFS8$+4)z~4>K{3lC6M2 zYwyMN!N=?6{6qF*ej@)B|NYYk+uU}ga(qFoeRcI=FIicgJu2PB?QuER$lIi#%1(92 z`)oE_c8c+hmTKO=_V#RibN~I>)@y)^_B$mav9O3tG_w?&z5SDu`NvD#D|MpVc;TJO zaPMX^+zS={OO+j4%WxRq$Y6UJ&c`?R?_^jznA&Jv6pJ@fI1jN&)|aCk8kbefm9UZ` zT0}Pw!qng?=nAd5x_N!0*35gyZz^$Nd?PXKB`zP|+`p5!btR7L?@HnZt92YAN8Aw2 zsj2Er({z1I4hj`VZyfAyG@6%&6^5|4)^}kpMtY3&Q3+ivbhIV{dee2GZZb3xq8$P= zq8htF`dgC4$dY7up|taEtun=39pDWeSO>t#t!lr}{Pc^fcgqbZVicg67L&T?lr^x}CuBS-ph*iL}6@ReQge z!rILi7Lf~gXk(^ZcC{_^bu~`1@E9QHRbk9bO5H=sIgs(YzC20fZ~gj}3u~es^mWvy zIL|XI2to8^e~C#b3TbIOjlNaAfziK}Yu25Hd#MUiDhg&DoZ*Z-p%_KYGPh?C#WU}Z zM^dexgqCa=^u6*atvr(5P8TQHcuXTFHWofIzqS0gEoRrcwUVTYaTrTaY}z!~K7rmO zNc=H9*y)@%7$ihUhptgUo9sK63+;5cnT8Al`t?ybaALO6v+Nq_`YxkTPf9v2*+xJI z?xH6pFP4*s7h zrT~0epEZ8bRx%Xnwp1OUMo7ydgUOZhrL^!N`kvAjz*GIGxX_Hd#$~q?8X{q}&}`Ii zNiTaQBJ!iMKxkJ(q={1FQ>xyChQ2mvhfj$=(Hyx)-&6XnqP<9`sN*bS6f)EX=QIS$ zh-qsCyP80CX}m`lR?dKtG)qfini8&%8BG

!H}Yq@WB?kcoj4+d;IXm9Qw3wi(cY zixa~4;<=|JilC6XFc-eGCQG{SaiyA6ZN3j$3LBdM#>dYv}zV?k_6>I;dcc_-aDY4}d7dK>(=lj#4? z-nsS2aUA*n{Q&1X=-3aUuw=XM7r-(=krY>eq}7U)kNt8EhU8ErOml=GDcSn;`-`fI ztca|rtm>W~iX1hKwO3SiWkqIWT>f#(O!v(oM+ZhXX_LeLUVBsaG{bjl_8cp4M!_>R z)XaoV`KfBOsO5``E@tg)yPj{Do9cwAv4EJ9wWYnaG*_IHU?VnIXa!T!O+qp2Ex0W% z706mca}t1nE5SD~n86IPw^ffa3IJ3Aa~CXxI_$a2Qu4+T$if^U4yMYQJLwf3e;oO` zIKB*8#S=z)nhTWKN=(w;kfO8$q@nV>c0lx_0@J=0ZFu1njSEgB`NnwJRA9=7+)NXF zQOHDJ$_cblUirrnCVI5#%B{P>pj*86?eF7L7|oRW0Zygu!G$}G`?(j~AhuI|bu!VP z{^P*f9OMU`CpG{H$UKGzf;AWsH4-QaO>`!zBib{@6SSn3+(#J!3f6$7@6Geb4bs z94sgT_=_zFHmXxvhOBoBkn9{&k3YDEq$^gcKC#Tzh%h}}Vl(Hhi8)($&9PrKO9~+LL zJq%r1=38Pjn~-CuZ>o_qOq|&)OHe+sOlB3Y2Cd@2YZ@iFNEBb=KFRIHnZog_4*oz# zYCYjj&MM#+^AL&h;7-U#FfNYMg8X%fldavX3}qsTpUu}4Il&)zrc%>|)_hsU9Gqn_VBpGdp7IYLq1BTZZa@^q{50 zi&;1=q$`Rt!-rmNq_d|-jts|aR~v*F!-42fMG2t&bmbVln=P%YmTSfbZfRy^pE)s1 z#xT14;3tM}v3++tO&W*~ut`i(d} znqP$2SO7Gx*>nnnZn8VhE+02yR&d7`!?h~75kj-J_{Cl&4Fu!PVfxo_9k4-{TkDd6UDC#44?7bgxT`s%8_4r#z zax!Hi#ta$eDlR+D9XR}U2hNVGZaPRa;lK@`E)Lh?Bx|}_(z3|) zIqD@NXHU<4q2AE30_jKd+{uRLMpRmIu@f1W!2roILSPXD!g&RWa$;+A%(4yfj}N5F za2%3M1i0GFX1(8r=T75xE*6 z>F?11efF=TMjqFaNZ76Tmo^N&p1Y(Tm_WKbI$SSZ^4zsvIZIVF(2{uW-Mv@OJryix zFBr>|3;h7cH672rmkarQ!v^jJH;C=j$2xiL*Xp@f?2}t0S9jFI*M@G^75s8k2u2*x zD&CO`wyWVY(k~}qN-h+Z8vT--ig|x7)|!-oDaCLUsqYy{-`3jc7=C%*M_9AxNcpc- zD4p=(3Pie6pQ43wHVpaYYHqny8)F5N@0>v}hGj;% zLfJ}ICuN=MMPCke$VT0qM?Q$|ck;`2a*@eV*uvk2-vG zJg;1mut+ak0qrgbZ;uu}R|=-DC{(5z7*D}R`3%#Hil%SiJDLa6-hc_}&ip&^OowN# z&rLTb&Iqr(Q+9g5Uzm=5z%#wxk{AT7v&26cU&&fqI6JjxD2*^_ZONps8R>0JX}{Xv z$t7BlAusdF=-4r(wereYT&>?To7D4VNmnN^gfPGLFP($qCXsFCE|JJPGWC2}lBRYu zlHr<2dP)?q3)H{U6qcDAMYgUJ*x$4JtotZOa+AhxNifJvE}d3+D@yF67temNO`1Cm zp8ezEZ)md-+nJ^FvoG&{{pf*PNw)RCpLRUUk6_kYao0;tq0`BfXHm6X#$|U*V;JB6 zpnXjCf5c;muHVP7vT83*!@TN=hJE9VPs6;d&N>bA>gg->UI#bTZS)fg(VBDy|K78O z{HD-CUIh6-ALpCc)2eD4p5r`axY2nyCT3B3i#2m=8#j21G2q({R`y%EmE5lDdHpSe zZwUY^d;2>SwVWq*`(JcOjx1eI*3rL_m9w75#i2P;D1Wr>psNYV;Zh2~;G8ur=3Okx z_zc9H!Dn~OB__=0ORidZ znJrstb+@Y~z&OHbSbz)6$@C)EL#8C}s^H&yb{Y#!((^q4*5XicnWeefRqtbPoc4q+p;gPAmoVE%G7FyauDh950RgNRMX*7qyHv zM4+dm4T+``X=+s!!Yo9dS?QEy9TPyvpdp4rBV+0$mo!qbN0pirA?&EU0k=jhQR3-D zo#h+SG?9tSeU~O7^r_3G6v>nD)7%{!Nx|PnhICQyLjh_|XJTVoz--7{ zBp4+VPb{IHt0-weyfQb9vqj|l;4v9~D7CFbwwI(vQ5aGEFs<)?d2Klj z>J4{5nbq`sjU>YiG$Q!n$2sKC$%Mwtn83bh>jk=#AjZ5t;gTg4=4rz}6ah=qAX-iM zhCyZ>0vmF%q~x&fGErKmYq3>nP{Zp`RYq;gTwGQ*)(VR-hK$!SOEE-gA2tgDI9A3b3iiAuaZTQ6685^0q@x8Douk$g zQcK)LKb!8WNnszlg@f-s_;&Am4&Cd06e&oJcD^xtzPI)2g0W__8#<;u{-l4=Zbx||teZ5rtrAnkl;M2cr7v8C2}H8#x>zW_4;O9cnbCDB-$ zMy!S<$FQ~U^NY0ehoocqjYO~1RmTZa{T{5JJ zG!?Q`^4Qm9HVui-STfRP35`H2y6T1cQBJC6HVx*XkX;QKpaSYQsj%#|X%_P*=g*!A z*&n}6<9u6{*3w2}MT#s+N&34~+?R{Fd+(lnasF#*Vj=T!r7iS=;{(~C&6j1AdMSF6 z(*TcDF-h21rKWwl^GzV%{;p20ce0`m(u*=Jtao2qmsgegOX8kHQn`j<0fEJ=x{}r{ zu3MJgxWN;d)tw&lEwiuf%GEtjqA35Cg(g~u_;mO=TOc2N9;&{5TeU^&({a?yf0VL$ z{@6o1iNBj9{^($I_N0>fAHVnu@3I$vbsyN$T@H*q%l$nfB9y9DM06#OcyN-agkx28 zi}ZCz%{sDl{sILAhr^9Z~NDI=f zO<#z1d&&}2(tQ5?69YV}B%!O$niEt^4sJ_w9O&3Cv#iu45>$+CSYTclY|c(IA{6J8 z#zIo-gLbA1XZEgSrAcBDUL`p`;91VtvKAy0!SOrk8^RxQZ$&#;dsM#+xsJ)oM0(o9 zuAIr|EJ!*b;fDi*&}54lzq{O2P9IlwbfW@CCIQo1*0MxqLjr9H$i^fLamQtj$Vgla zZ<;U(SyR%bbiS+iJbi%MkZZ@qgmE>irf)Hmc+)=O$1l;C&hAuSu1tdTy3YW|~sjA55n#2RjV z_;I4YSz%hOZ4Iq)$a|!1fbT-9VREO5QP3xju}1zhyR)h+qy4RRZtN)*i~*}eEr--^ zsVLGLJMt|fRq_5rM(C^)+#^pR!d}boX*oB5m#Wzym2q&KGGHn$aGi({Nx#6R{eBl- zT2MbpJ4z{E?QN%xqYZd1oe78(5KGFmdD4DF)JWDxSxcD99l5m)=t~ObH5Y4yU;qs> zve&6`AR#(J{1olt`+Bg-SqJ3lOWQEoW=-iFw(2zwcx+AOm^9M!W%HS7Ac}pnrhgyS z#BR<6wXvoF#K;6QX_~g7BDoF)rp*ruO&ohK**R^aYOpMl%dQZ$7~N{wA@Ais4RFl@J1dMBd*7y-Euu z22W6VO45L@_QTU3yB$eDZK5af#; z5neo5dMKXA*i{e3v3M414z1kSw!JoIKyR=xWDZA7+{YJeL4ApN!~jX%*L?AhA74M~ zJaMupe>rqCIFqIJG*nL(<=0<-_1&Wf|G#Gt_*e_ClJ3g?8tXUaB>(TpqD(=zlSP@$ zn;*+&){!__l&@ZW!W`I>MOjDGx)A;KTa=xi7p9|y1cr}RoklIjf_%I!d0I5>#SgB- zuw9T^;=e$$9R~d$+OcHjsUWx@77a%P% zSfv89mrdbB_sfW{h;t0KER|^XWf|lM#zGUJ4dgO33_IP$!_&9%9x!o+LgM!MJPeOO z5?^O#1ygAS;1~F2JVw2u7J%$enH;qKZOS?-c6tNKC|LC;U)}%wQ>I}lTOB1aBHSK@ zm{)_vWI)uxF15c;$K?)uEcYz+0~|s!nqByLv%dTN4dM^AxQxe9hm~v7OD@?>a3`dV zvlSR>KOw`2+({ZV!iQe?@=Ol>ScstuO9OjSy+wmOGGVI!4w7UmuVQeW5KkWIUJ$qg z)ZEHIEJPk{eGF)*m=fLc$>b$GiKLxNHjR14m;ekz+s&m1*fQ*ROz1Fo>;nCVTN)Q1JN|HU*(}XF< z}pV`xExY_=3AwIN{Va`0?#U)w%8d z<=KyI4qlrH_|3)7=UO5aRhjO8Roi!;49ofmekUfz$*?>bmQi3T$|gA(mR)@Rqw^_l zreRq`tVswyqNV8@O*J*-U0j%&D@vcF-dwuRTQ|ob*7WY7)P9Q}4(3ZqRUaxW^X16q zrYX!U8)ING$2krawf`XCQ)w)aW6YYgu&k0EWv0W5;W_rp90bXfP#H5uc|FNI)80>` z+?ixR>G1|!?&!<_Nm{f?e>Ya80TQFkM*`Ml6G1W`Lf0p7?z${3#$VesiaWl($)QSD zPq9{OwF^(udArWkx)Jas{U+wr1Hu7B4E#L!8b_#rn;b_d8;}m`8Tpn`a3d!UvjQ_x zR4`v``-V)|uZz=S2ZhCB*qyQtIQ&Dda$*w?PgsPa{X~ zVD98+N_ZJ=={QlEGk`$C%@F@{bO|FH_a78EvP9*~d@7cF`#sTi6} ze--){ZB|pqV%8ivc9|CuB&0jV2jrNOU|d@et>M+$1QJ+~On@n62+qFo7RkY>ohXm3zOaiBXvXt%|u#+k)4A)q9a8eZOqlOH4CF~`iN?& zG0TM7f0TJUrDz1NiII3>WYEsT)$*wJ&#JRr#9g&NqI*S~H7t7R0DVA$zpHcv`>$J@ zB?^i9-X@y9rvXS%c$@*a*SgjMJQn6Dcc{cjk+nZq`VqY}WSa<~8&g<>KPS!Lxe-iP zW8S$_SB>Zd=UP+bC#7LTb?a_sDo~VS5n>m>s#-kq$@bub-8! zFIzXd?m4rCd=b@u9VjLB$W^?M=qT;~=?FQaM=p&Vjqj*zaS|_w)r1{*L?gV7)l9vO zqoh`z?80~l6kZK5P=#?qlQ=enug!7LJ1rK^sU%E>`&=p1ex++WKI(q5Kl_t8KRTn~ zWPhIQPbSDuH^l4Kw`XCMSiyy|uFT2)RDE``KmU3D_VVAPj(!mKXDJ{LD0@u!`H z&7c*%BOcxiQ)b6mvAFznd82=-^pyQj;BVrFM@;hwcc`4rTs_8X6RpnHT0wg0Cd_;Mo1sB^BChAPZ83S|BhJA%&)P7Ul zOtgfqp_v9e43_?|kNCiZmbmy-c0E5;D<8sCmH1T>vBH=lT7@Mg4b!7{hcY38un!e> zstc5bC_tlPpJ8OAH_*x6a+z@<=pZ1?>q#iv)NLX4H8+ug4s#d|J&-YoHL0s7Q|@h> z$8a*`PH^>6D#NaJX~*N$CzG+%d+fuuCr&1#s~5P58vkT6YDhNnkJZ*YnT*bfwQl8y zVKNp$=G3R`C|M8Ub<)OWQH_HKh{%B95EwIsUSwRE>Zihp3Oa1hY3oJ5F~+%C=fq-z z$1U_)$^3eTddPU$4M|-YX$h(Xdf~gsquer3-eKMuuIy+XU+LwycwC{^sm_a5iC0Wv z;5Y~Byl54r<$^PLwr*5kf(g1gv<|9P>AUZ1$AN_r&R{W&!|J}O1pb`n5Wa{2uQByQ zgr1fHax$%lZu^uH+54ZA(Wok~HRYlp9Q+Sm1WClTZ#vMR$;++gz=5XhtCCN*Yhf{* znMnmjC1!^4&OMg33hF=$XGAR?)vgFQz#&>gA`Yu`uTg9fLT3lwy^e`8f-5KqlWto~ z5RnNUzB1-_!4ub2_Ei#(-8!(2(bD+~(-u>Ti~5i-xj_tfeDwC;ub3ywKRrJG*W2cw ztf0gUsYgn!CKN3(D2v!I1rcz9l?usNSxl&5mVEB{l0Y~kGVN2X6*8NEjS_GXn}``N zE0;&^LXpyJZbP7$xmXw(zTv939H?xdJe5mDpI6MF+QdP;0Rm=SK?$@{eApf>X^8CYRw}Zc(|KT(K*z=Vi ze0TQt?fK>F8hy;ad+Hv4^y1ksdps^mSO-QvczyQd)%mk{l`rpp{pf*PNj~hrpUSHL z_x$CLFBDLn&Lk+&{=wp)a z+-~|`&n{n{y?$H$LiXM6y1Z(iZ9IGZ<5%~qWzS#V`QcHu=vS{_*jGOK$NAf*FZ?E( zZ2c#m`CLc`=6^weDw6i`9IIUdj0IY{yaZFv0khE%)N`(ulb;h%kpFLE#)U3 zM_*zJ{O-LtyF7c!z3v&*D=So6eDCbl%O{sFEibjl$&gw3lXJNUv*~UA4V&F?_K=!r&s6ydi3=2>w98A9X5<-6{$?q9q^Sf?j0-u?KZ`_R|tqBq|BboMk@x8fl)6vl4B)y~_oMB1G@ zZqxdCqP5S=W%=Pvx+l2TKfiqQ?b*-&b;+J`dDQa$>)ES!HJ!9{=Smp<{q7Pjt#4Cx zQ@*|U3{mm-Cy5bo`0f$BP%~Tzx?^-)ALWhc=zUi z|F1v)ss2UnIJh?Yt3p@R1mu#BxH4#Y}qEtO1K?vu%F)clqVtvtPD;11IaZtay!7-7Hq2*#V+T*Cm8FDZ@Ho3*h zq&fNB$9KP-+wZ<@X|f+W*r&>|`uFE=P^;fuJPTxRy()-(foN#ZwznuUQG8=kM4GhTMoOh$S#_0XUgpMLB zdZ5h-DQ@WtVSYKN_vuDL#9~e35Q34UURJ+-bUk{1$t>v^>yehq6r=@K6BG_3jn!jA zdcSs$e{)4olNfq)N-L}lhv@{qQS{vtGdd|L`t3vjR%s|lEy0|YruHU?5msHf;=4|Y z{=ClM69I8j^q+rPV;m7|rMf)CwDez|6nzYX9Z%6qn_zp-Ev#`;^q&qX`cR!+UD2ab z`vQV{EBf_h$B09k`^qRlnYLuqb=kr1iu%?>7*zCF1~jRi(R>zFPfO@)RrEE1G(&|( zrSM3KelZ~%hCnK z#g8gKdH4wuzusWhN%0elaKVlgy9!a|!#(`@N%6}B>W&BAL^6gHf2iKBtoYZ3?!J2~ z{;ogQs_(MmUox?ID(&586yZ|lEJ;X;4UACyOMbCqk|!xa>*lxD<>9l+d_{{&>3C1$ z)apBrr1*1WzlINfW5wS+Q{&0+t@w*?ONxIvX`ubtV!b1&<^=6GSw%bRI9;>He}eCu zz-b$tPnxlu)$x0T@9AuG^6Iam+yfPMb>%MEyFJ5D_g3y*pRHBVC*}U>5PbhZD);W0 zUPZYV-*!^&ACgypQtl_^{+By~~-%VDu;36%Lk{X(9 zZ1;ie*HZpNUq69z=gZ|jo_n2>hsRGOnaF;PbYGL_UgzX(m_P-By(HEw=F5>h_YV@X z-%WN*W7~2vG!&)pluM&?o_l_R#t1-d|E-F`?lCYx zWA)FUKNSHh{1}vSaejFPgn0g^oV-)0{<=f;Ok+7Y^@lt4p?15nQ%}-#qxTy-jGbAyTY7yt zJhmdJ&W)UObgX%s&77A9B}7mD|CZP7N^L)6khM&XqzZRIhmetKdm#Nq5{nm?`g`E@jGp6sgW8us4*(Z1T*I5F#W3-4#{t^_A!yExU*kkNrf}i?g53 z-?&;A={(+NSMPnlWNI-LAaklt;9w>!*MY63WA}8M#$7JqRT?SNJroL@rIv1?%<3cU zgx(tjpXlYWblrk@SIgb24ZV!#TW<7n>T)aGWo6VTeLP6Or0>MG8IRZfvh9>&8y2K^ zpF3;igTK-4Z8Y)`mT2FWzD-^y-hx!`dqLt$XsFP^50R}kU=xrO7OYh{~`^crQ+Tlo*YhGqsyC$N;?4g&KrHQ_0zbLbb zDmTaBa$hL#zyGySNIog5`I-MVS*iV5%$N7VUkX+2FT@ zq}Q5LlqkzRBL! zD-Gp!%PFP4NY}dkRmw-Yc$%y<7(CiH{U#^W@)jm;zkgFJD8;Kyz4pYNhuE%^G@t+Y z`dP)v?mn4+S$siN_SbphByT_eG?Ux?wM*ZhzZxiC!W01l!Xj8~b~N81+1A{IM#jot z)e@$y)xP)c$rtCpmI|3hyqHp62I_F@*Vt9k*3d3~x0ZqSufAx+V)klxZ5o+tf2PtD zH-)N5MqMnYO9V&-e3j`MRX;8@TZ3dwq`Z}J@M~b%6_XO&ji~8zf2FD;d$l{Bnl7UN z+T)Qcs)rMluOE8q_O(Gh`+l!27Ob&BAF%OG#X3#W)(c$iX`MONDwx(3SaGFf7zssW zRH>VL<Fv(g@4t5A zJycf?A2Awfw7TlNprfv;Cr;|>nCi-jNc8}SH|@4`brUva;&_E=mBo5gcT3UYlwOi_ zw8Kf}{#X{(mA3f()2*bYQa6bQXrHOomHU~hD~6#lmu(4(#ZdKG*jRBwuB zZr!=}sQ%i_XhK2T&lUG}x+Fjs=w&ORyV`3yIh4$NL+v_|f}u4BRBUDty#{@DA|`Do zL*nQUD3MC=kcb*@WkebWcM%D*kSX(Xnr=GD*sep-dw52KYE_Qj_3rL1Pb2HmFq~VM3zxqRwKW zjTYSDAx^1q67Q6qwr8p5gq*0ZIZADc59qFP!LIUT?1F6S37i_fXz3b_0Nm#z&%^v#m_xg<`e9?XLjJs)e*6l>g z@(U1C+!^o$#I6%N%0Pli(07OyqJ+|U+J2#4bz}kBV9rHFDz7~Bsw@Q8^lA*f>H#O_ zl)ICPME0R{7Z-|T_6!6=NqKcf%Z_?bNJUQ) zy=s+abdZ^>bqt{gS$K_}VvfV*OGJ8hj3W8t2M7V)~Q}%lk(Njzq0i{6J=~!Da zXK|rOXdi2#>>vZF9g%?ff&{>h+0hDuCfN2FJ-I1xLu($)JYuGo5N{p#gLtL*%d?Hs z?akTQck5Y2=2pIi8D)_m7Zu;?89(JsPiwX#pt(dDA(ue*oG58XwO^=&(Sw*~88W9= zGOkvR5tJ#5JEWw-BA61yeBe)*rFv0Ls%6W0qzMisw75{D8VdI;ZRi%gxx%2~USp6~ z+B09rpB*Fm0#$(ysD&8q+uW(N3yD*XmB6G=uplSvlu1kSP>&J=m(J2l>f@;+V*rLd zZavD>9dAG&=pk8!` zkaF)S5LR$l^!A6GSUUPeB*+h?v$#+s$eq(oFHU=$t$-aCX#VV&1k{z}9!KzLP3=-! zto|KN7o9pc{&Q3wh+n>;PbC;Cjmx%9<*GaoS-zStWsDIT!FR?`aZq}Xo+c>&pc1pP zd=bg=45)DqY9gEwE==zRF(TnBMo`>3ktjdXI@wWnC3(ms-1!c4m)|;%i~(sI>|0N6 zzCno#@=aSg;BWg#eQ<7dJ*UVFE8c~!9Cz>4V~MD$-`j>f3@-f8b#=D)?b{1MrfX2c z()2!3HAaLEB?aF&XM#!>BIrZe+3J`wjw5f6xGu_|*Q%bw*02O!1baSJRDU%)9`~IfVywz9?%2a?)1ixiO9S91^FZLNF z8w}KfR8H3`+2a0#6Vr#DjC$WiRp}-jjX;G=?5o^|kZ{aOj$n@2xF9{G&dx0p9)kLZ zYGggkM0r88C(3vD&ZG=&xe3zb&hDU+j+aC?pA@BvFBG?pbQ}zGd@J<#(1i-44u=w6 z@9_w;%vvQMxLJmf6Qde02kgR^_a*LM0C*T~%k7vzzrCEcI;wiA^UWN+t{@ zdK@iaO5ET&ULi&{5FtFflH($!h&(AVkhssZZeGTLAEK?68=bOIu8zJ~Z-;UYS^3o0}|5of-XWMKea z{6k8b9qY7&cRx5ka-^~_IR=PS;no*MpJ@qq8(6JXCOoo;4!phkF?!;(SsyluFk{5n zBu8zAKjVB0J#oredOa^CT=Fh}(h2F2zuou^IpJ2CL?+RJWY^1#kl$9WeBkn1?DZkX zN4)6@Fs)>5^d|VhocjNCi)3;Us3GX%xX4VqsWP)aY3eq_<22 zBGPG2-r-6REBlNx8~B{$0h0(k2hbw2V+=QCHZizxKv_!i3hTt8oY}m1u}81U3k1+! z4`;mWLpjdkR5~5X_!`O^WBF3pL8ZL(9;IB214}mC;gCx2sM5HiN%7o>=-To!I1E{A=cjQ*TTnUi9%qtxiej+OB+Aj>_*yF|#iW?ZJ(DO8-czPL@~y!M ztR)#=>jE5~uC)ULe0D`kc^5lY&PkLPAdZ&u?t99VhtBn(dRad?kzT;}66t{E7_FpQ zp*Q*Z@X!lRdLo@v0t_?UK+r-;&*VKh=~ici&h?>$*9(m>&a9^Tz>Tvp{6E`}?M?l| zTpAwmU(u#}JrWvc{)RZ^s4_-s(n+wM;j@uRMDd6*m=e2TmTgz76sWP!D7!^ptZci_ zO^d!KXE#rIXq?UP{ThdjJQXL+TFOB;@LPyhh=E{{KJeS$CCO= zU;UN{_ZW4kPTBm))mawuxQnd>N%BrEnW?RsRHWhtqS`BlD*TF8sC$P}V# zu$LiqDbN!#Hn4|w+!AUJ8rolL_m7H zeI{}C4A7Wp49`eYqUwY4J@%wW#*kY+(F%wU07x$|BJf}ac6p_hb{;7A zq>sAHR#r#$&%uN)y4VoB^>_Yw}E=XQe(z2U1W;~{)>_!m91`HhAD!WO^lQ*r(A|+BBV^WN;I;&17 zBydRgA}7n0YRcSA6_k5K$u4c4l1(_rRO)$OT*;0;CnwxqvPfwhN_M`ES5J}59+Rav zqC9LuVqR~~neH%b*Kxm89;O{GK=I^Qr?Aj%9KY=^q7=uf&0KXNpD%=!o`Ibz!=tGbQW8pTqSky(_KP7p&#RgSm-!=w)8u%q=$OAdzoEa$Q@6joshj$Ptl&3en)ijHE6Zc z4l>be3M=jO6apb8*#=LX7uA8j{G6?(2wmrcNv~HL;X7M_@`2l9G7xyEz=GasOGy?a zTa%sNge+%wJu=3QwT@@)$N(aV&FWPrah0=4F`+REUMzm#96-P_q)KkWZ`RRp5?2{J z+8Mnd%GiX1kZy4yhcb5Nl~xx&=W9=SWCKwMKA80lwImEq>FQM_<+$sbD2FAcl#^&I z!R}6?-1@&xa3;E)<>!&YmTo#66Mm6aK4^>TJ!QHhi_9&bj+kzLgbXCB2++ru_$ERz zgZmP$5}}0+OQibPxZBi3YVbW}QbQAr{3nwX;|!@pIh_GeBv>R=imYpYU71oTmk!jX z;K5yzL^(hSP$wl3Btc@$SvFA0Jqns=1t+5Li_8!+X&!rDk92KKsgB1u)Xei~LS?cnf zoN_BFBLj?PX1(8AqB~#53yjF%$qE#lh|`rMmdz%^PC$g?oyG7BXE%+}^jecE6{5%AvtS^0H+pOI4yAR-g|8-W$R) zPA8!4mdzP;8<+?$Y@iZe^~aY8e%*j8K4f3kJLZrhqhmp7pDDm`d#sd;1fd-pDF7tE z6OOXGqi2pNwNlsJ{FZbwcd(FlTn66h-jhf#C{{gl?ulU6C~^XIw3w0a$`liJ!1-ihq-l+#cFHw*nAa&?lEqJv{dCx z5jV6Lv}dJzOxHns=I*R?kF)MM;T~tCM|MXRgLCd$A|16)Xa&QWZarjY*iTNR`zSzs zvzCP6Ws(A36un~Hi6+uLo4WTT(vg`6I0BC-JYE*DS4Mhdhe*XqUmbKJUB*`=3?7*w;1a!;za^C-Rg6r)YH~V# zGa#jP=CT2NW6VVQe2vM4XR-p8<$OZYy?J0CNt6ff%>d<*AtKV#bjFPNn--IZtS$9q zl*N0omnbI;W0Hj(U$&I@?_fIg%ySP(=MYw8WMOI`2I`XdoOCBXBfIEO!t;gvMGAXx zQTJ%~*w^qYd!d;?Juq*ZT$Rt*Pv!xNd6caMGrFx#_OGUPLbOYPG;+<(N0kq?G~ELnY_*Y0OSo z$>{Ul95)c`*&RfpysmUFHOiVqWumzZ^12eICJ;eT3vMKXXC)3fCW8!osVjvtBhDRG zI&{gd0a5|Pq|U;(5=o?s;ApF&-S(tIFKnS6y1S<7l!Ff#IORyMl}f4-t)#_Fv90lW z=-v}Y#A#}7O(J(u60N}W3!F;2EHIL|KA!xTOIf>#bZM9kj)l=nrAyrD(%RER@O1gM%954M%WZ16H4bo#~YMV__cc+y|=YB|^Z!jgm4&QPt9dkiODCs0w!f+C! zuRPSyR<~Lfh12D4z$|NgIU!Oayv$x<%QhOL^tQ>5(Y{n%8?H+Eb^)2Yu1WfWb%d zg&lh8%wOoeq3zA;esV5U1U51DtK*E8^zIf8kRI74V~|>z%EAa05(FyU=$Kha&u~vC zoLbT;cp>Q;Hwh_K$9+4bI~>-JvQW~ai<6V?gi2&7iJ@em`H@iW?Lovg89@{& zNCo4=Y1oDuD?9VZPNC4p_E~Y#D;;{lmQu>exJ!9^;Gyn7)4eL}pdLDkoN`LAM~o0m zkeKw~d&-Bt3|qN^)u$O3L@q54Ceo#KI3@<68MxgeNr`l%AUvoA#_oo;q;pbWB%8Su z&)27=%#%pR*l#kvtHB%gdlJ9n;qfu-khqz3w(S7vk)^_qNq%gN6}wbR`mj$+K_B7d zG#SQiVIsZY#wF673iT}>TGH{b!N_E;HIlXRpL5c!G=&GdCfcEd=L`9pMbDe=Qc@6X z_SkWG=lPQh&=~oFCyypX4yy57K1Ut4Gh|t!(g$6hMr~&8Dbk)OSUOn;E!V)5UOpjFKMma^{pV0n0w&o@?`9fOV~1ZQ-8-4q3*fxy z`#OlA+kxOx{I7eTA8Lrlgc-;@Lqbesdyvd2(+TyfoGs_48sfX)z(@fy{w6II>Z!-S z(OAQ9XrXB=ash@8Z?PWz}2ykK}prr`mR^ z`~Ce}-#`4~*7P?2`Rp@$HjiHZ$^h@b^0Enla5a(oyT`5gYOjF#mWQszwf%|@Ixo`k zP*M=|5$4tbqS0=M?5URYcKoUrsgbhBfaGcbH*np^rF4=|R|2;n)QxXWg96qHG_dfsHvQ7*r|cToHOYBTEASk!nks z<3lzYx!`sorITnWrXwPZ{~%l3UL?)I%_oZwoR`cLj6?e#C7cKp!@6)inEi#+anGpc zpfeMu4^9r|F57EgqjWPnh6p<#1sk+LKg%;^!XsM)e?n>>kQf56gmjbXNFKjr9s&l@ zfWk>0C7irPHcxun%di?hM^*`!kc`Bf!Bmj-7$24_rCde?kROk1=0K6o_8BFe??7j#M7m43zG{T@{J&C>ia$^KYD9IL`Inua?)89Cs`U+5e>H+ zU8X)?%3rU@FryS5hL)-XQA|{zbQh!O8CifakL?Unii_gdL;0*4K|*tPdO&mQGq}3m z>%JXQD^K^DN(meX^eX5i2zV_z^r6IR6wEOCn=K+4h%NwiEpK@T0)s82m!2`m6A`P# zsWOK@(Tg5OjU(Q`_}M@|yelym`AVR)aE#=kWW8t_dhI79>bQ#dg80?kUztiP59P#J zP73f3`(725i~wNRCl^?XWg1){f34@5Fzs;^+W_t1^Mk1gZ0Y4ivx)W#b;l%a5;+B2 z$8GfaTZup53;r$klguoWiMsYhx`lvV0C78V5y6rOLPa~6ks84XBd(*nG>JdBRj9}f zB_`aNY(i)v7O})gU&0RrA<QxKVIVSkpm1J#K;fGGyLz!LIIzJnR1k(LH?A(+jASPgKj`y8bd z(Tdz8Pz9;@4EAf3P_7A;O)}dVeqH)TmWfyRdqgzpd-z&$;xpM%@CsL)W?qCl?MjJm zf<44g@SCLSYdXR>fhz+5s45JYQx%Ut#Ra!ZDcvwVa5`F={0-9Z9Dga{WFmrz5_w00 z<4HM0MF|I;#B?D%$3^E@-CBC&WbR9DB>Ap%kR{vCevgvQ{-aW9?MN-2G_8_n29CU| zpWW(8DKfre(yP8wO0j69GX@GvD#bkvsFVt`Q#pXmgI&i9~fqLd3xU<^*T%St&-jHJaG<_;(UD$;(BQeGKa+4tm1!phRF zhM@B@Mgbb1J%r=4$VZ9p(mGv{J#HOL1Cmu z=^3+*mlA=;GU0T{d6euGvOCb0;Y#>g5)YTS5X#=2qH+vH5{OvB@QpcS-=iE8eX-uB z#4!jFLC7>#uYp5G5%auaQ6? z!<#HsN;wuW_zoM4`GvT3?@`JTtvKY;I6&0+7_|_(UnL!`q+_CYtPbT-B^_W7_YGk$ zKtrZqlypMSOwz#}mTvi3gRn$;!3t8+B`+Fhlv{^M&;UXCsat6hR+Sw}c)d_-dPX6# z#c@Mqs3yEJ&@ma($UTra&!ZRT=Wi!CBmYMuK7^^@DY*z)V~;FC22xJn36w7ee)g(1 z21H^A_79OrOhtDcvIrT>iJOaDCyx(UJpMASFFqyzg?r^~oGe1d?U6$j#8u=%_PX?S z)N5gb2;45o+x7x=B4k`23|U@@Ukpw@IzlFz8M~u`9AUBQhiQGMdhWjd@l_K^vS0G$ ztCv4D;wAs<=33dm{{H+8@u+Vuo<(nBcLZ9`e#T>O0g_~O$leAv|hj>A>zq1mMd3><@C0uEDU@a1C0tJKKZ zLaUICiy?~WGw@vVc_*9tR64NeSrI1W;F$*tK<%rbNGp3th>Mb{-b*$9&oc zjY2LXMbaIwawCK4%W(KS5|H3wP#pk*=8(dDqoll?rmY);%&sa^?R$wH)0_%;#UAj_ z-IpEkyEVe!w~~cmcu#Zc*XZXjxiIN`EyM%$*YFpPCJ|a=pz$rVt!DN? zQj{sl%S!s#X?Y989dK_*OZJIquq;Rx8;xm*za*!DAP--z9~&EuCC}(mY!ey3*z9_0 z4Zm{%IXL7fh`nHClO{B_Pxu;tNidwa6NJZLstZc=B!pND&Js@c6fjRd!$QSbMGFWP z{!o2UqL+Z$vVXWc7!389M33o40uOS~ai|KVbMT#4s=JA}3X|xuQlRbyCV27_usniO zSwYOQx}E?}#t@xE_*peT#2V`}2_B0R(TR{H)o%vz=1nk*aC5_at^=P4wuK zc7*=KgRX?TYhg`zXbQ%u$6sUOG)1+pC%~&lTk%0k%{e3BL zguJs`(4`FdPSeHc9mti*B7rWqNPd`+A(#t+DzgV0N@FSZcx9|OkZZK7jxREbCw+Gk zIc$SPLfCVQN!WSj~(TbfagLw?;!?NNUY9)lGDD*2)#&vK(+fhz`pXp#Y)# z(zMB)X}}rYjXrkyKDA<(-7uQMEn}Nihqg%q;2AT=E<;E( zC$dXD=GcxGECaakR!1Nv(0dB86Br|g*@7pJ0%RmRh7U1U*CdG^D!_w;=V%cp%vs-* z=rJz|#cT4SrsldCmgv!ml26B}ukT6poq;tonUlVqI-;6Pt(BA|jbHcB6F5grA~T2w zanS6*2YNKVJRyZKwM9L89??w)Jfq5CH5BL}%n>nmGNviQ^@snb}cqC(_N^?B; zO%0xGKxZOwY}Br!wA(Y)MAeTS0;c{^qNUbOUAL@2!P{0*W4$qW1FsAnj3dnkx4N1z z8+NUNd8T02=hUT0MDbAyauAPP_t^oi z3lCZn&p?eJph%BWW>X(YR`zWoVR1o@LGRn6Obv=^2{&&7jo`Nj54=~-GWI`45tYbf znKcKm!}~y<3y#--Ka`3ll9_tSEg;uW!V;eR9GgG{TIms$BVvDFVdu^&!LFgk6=q}9 zA09rX0d>oB4-Ri~Da_G?oMWT|j-z_?O&<<lkFqPVL024wBd3B|3`-9BOYySFHk~ayJ}aUmUbV9c#D_ z`9uO%q#*Uo{N70sboPekawC3J%tv^Q^g#P9>?1Ols(Zn2YsXL3pT(Z3#U6d9+kkLy z`l@{XJEsgOgE0pf;sNzdv5WHLcn$GjZij@YE`aR}9@bLggwweB+*s_lV#6BGCeN_* zOjX(xmEwhV+7dqYAemumhA1Xb^AZ%AIOc)Fuc>kPH8|q9I3{lreY2vO)W$-cy(1ZO zC5h8_0ND%0m6X>1Q zf#*Zm3!jZx1|c>3R6?i5QS%e1JH;QUiwWSI7pX4>cW>3_^^wF)C|A{|gpf6*$X*j9 z$IetOhFVz^xH74hxbduc2~H}Klsv=*+@19S_o@;KXJiis)g=dR^>E>3;uuO7`iV&7 z*t1-Dw9QN-ZfRVa&=n}c=#X_sD6WT2%79Wx%ZXFBU_X=v7N_g~u3FqfEAPWt(uHKQu{{Mz=rE-BXW)>4?~4dM@A@>TGZx+}Mg8 z4k@eX83iCFYh#CZVNDi*<~)-0MulK59H-b_Vwql!5<84a!!jgfO3?tRyDPvO#s5G; zr)Wq2R03BGHobxpZR&%n1W)LcC2;;JC*TPxqv|sOeM=3YkMMPgGP<#r&~XLwE$ET@ zo`k+x#nb_)*!`&bKB0MMnGpGpRExxleJY@{yM!=Qd5tFzDe7_pI;^vMxp*?G0bRMiA>X`fIiPdo)U!nh+IlRdr>q zcFM{X+~3~OAcxm%@dZ9sp#^X_Du|4u%R1bHvBmdE6$V-ffX|%nMfLK201fJPEF(?+R*IaD(dP&S<($Vti4AtHyF*ge)@eN7Ub zeqY=J95GTT$gvAV@5~f^fE3>mDBOdx!OJ^xW4Q!MP&}AY1=4ke11NnA2tHgzLQ?(J zVe+J?U4WOc%qCBJN4kCfgruDjf}4?LVE7wGif=9D$I_+ zAfRo}6#{k^2ZcDef8lg`r{2JMermBdh~g9O-*d5dC|Y^WI|mcFdC~j5P{B|G`iKZ& zC2#zFLgLQmpgIDNe=}?_SKU=i=oe%)$rM?<=s6w8JN{cEXaZJ3=PYdk1c?UI+ZHBt zD)=$PG3CkE9ubx`^bflV5mH|nc_XlAQY4`_p|@CaoMT=?7e9{u9`m>NxMXaeDC3f}PznLyMQ^(zuX(1&6XtYyP9RrNC~N0B&% zzou7>vh}S780ALz!Q3#b=~v+sCLBde%DmvO^$Vk_5;aSJ0;}758>gCnIjRI_h=M8J zJ-sd0MjVYYI$DSk-d@%?mGmPUaa}d^27?11Z+l_1K$y`q54}?UZX0AnZ9kEs?T7h& z`{nl~{iVI&`G2FKS40JfWofPr(R_4GCk5Tzz7>Oy4`eq9(4ZShx>HAKrcB61mHQA} zzyc=>fd^8p!ClkXVGhMYNEJ(1ojxRni1gH-rA|d(?q8PhaC12n3xQyYMNzAouuM7C zInZ0N{P;kk97`DYj~F&9vS?EPWjqZ&3tkqLdYoW0%u}VhUmjrDLL3#!NYwgGYN-Q@ zjUmf{(6``tP%OX_ekY1fTd7`#!Ez4vR#iMc5YoUKCm=|<2K^GY^$C{15)PO`?BwQ2 zBi1DcT9!gcl`x9x?x!SVK*w$6b4nn{%z!QHi-OP?2ZR$;?MkAL{Ahh9u+wfqZ862V zl+H=0oyO=oUr(*vh0aEZ1A6^-0L8^pO)|C+vKu?5K9fMzod7d3NI*GWj!u0lkm5Qi zUy%D&pE;1~kJeUU=gaAu>y4gNkq}O|k0(*pozEJ{8tGzS{zv_MfF-Jmjkcu%8Cl|) z-2-g>Ss?SBb%seAQnH0>OwtsWUZ&>-$EWk}-~srJYfT8g(Kuo-5-ge%Q$jfd7=Ee` z2&~j-?!3Fd%a}6>OAwW+5;@~kNRlJ%(5n&jSdHqF>LUrBvrT~we9SFqFwzB?-1&T@ z>rzf}j6HOj;K`7&Vw`VGDg>8tY=9>)r+lwQB1!Dn5l`@%iigaj)J|%^i~EA~ROG1; z9Y>$@O)$Adj|iY}k9;LLbL8g*LEX81EQBg4r9}yeDQ8r_mFSg>RBn{IAl0wfLxCQz zk+sIbo+e)FwlXn3_(pogIYx!&dyE{Tux%$vx!v33nt)VkNFyzN@22s{af zp70QF;74AQ?I8l9g6TUYwnc7>_q{zW;SkCawIWD$9O`u#*pEg&4O6d8NtYfNIJ!PvSmWz^@&{)a;xa0&3i>uPMr+8_s3pE=Oh zKMHJ$ZYu?#YXh+SFP!VPD?#lVyXxPT$~mteOSCu+h<9}&Q(Et2JJ8mjCA4iE9!$X) z0~ACDjRHA}A9oE$N>Vw1RuMxzg0?gXAPopTU7=)Wav=;h;e7}WkEsS)<+lK-X@f{# zuK^jf-Rz~LuP4=F12iy#@&nRADu=#P)`QVZnd@PTAY)8$1i2M6Ra~B`JZgz9wPJKu zm}(q~&g_kAo={;1<}C>ws!l3t6F))XL-O(rv5)#t!dJnVqOFwE>#E@T%s9wt%4r&_ z2bK~&XIKG81v?Cne;l=_LZD!}XpDZ$ET@p*HX(J?3-*6qa$-j_acGGHYOc1Y z5)wMy7#aw~e^>i{eN7^#aC8`D>|%XrAir78i2(2HH1hO1TnCrIx%E@Y_E?al5s^Ex;p_kaz)R(3$hDlw}z<$ezC*XU#jaueo*NcEXW}DU}U! z0KJ?%prdf;P8yq7Uz5lw_tp$!!ZDOkxH%foG3*L(k0B>=WTK=Z-!IJfMQ=;#MDjoSA3>XpP4OxPgTJcA^ctF3?@_6#q+RUP$48o;188^ zr7exRhlc373O?NnKUo1?`461kV|S*})+X%Owr$(CZQHhO+qPM;&5DysDo*a8VjG>k z$NT9WPmk`=zu{Wf;yjPJnpw(T3~EdV5($)!n6=93fqdc~XPE+{-#5~JU2Rz(7-3u6Xi zCZ{R~yAJS_5A-2Y$Ojk{HwRr|3cwIuis)2C1`S*Cf7?9ysG1t2E(5ytup!+b7Mb*d z8dx`QMwMvlf)u*`VYu(egL(c#<%vj*nMCs*r*5K$I~{eFVY6lIfI&xE7>Wb0D8g2! zT9?q7kG436vI?ho&eMp{*eQdhyoJt8mw(eb9NyMpgfRn2U|)AHNruHWh(;r`t578m|HxVx$JUwj1u!n}fq`>l1!KHa)kJW}#SM2f z1pHWvPCrX>7)pum5kv)jL+vRA8S`)S_4J{|W+6lrlP=V%Vo~R?T39!8u*Dhm#ud5K^x+%+noh*B2#U1)F868(n?Hph{!R49QtigeLP#D$0G# zT&(q5w(8O0BqAvy!NvgEX4L-RBHxV2x>{w@L0ULzC%hhr%@>fnxg6EsLj>lU?bDmI zpq(_^HzR=(fN;M|!a*-Bs4K~lj_I5VHUY$DGOjrYwJDDb(p;=($S_+-O3dFHoki=b zIWU!k{-s(;s|iy<-X+?J&e-m$-#D*bJM7A}G;8HG@#*M}?3g<7B)?u}4k>t5Hj98H znz&-Atm>H)WKc?ut=@%PQ#ymwFugijXVqRghNmG+ZW!n#FIc{i12QT_Ldqt8+p~Q% z7;X>Zl98K*stED2woj@n5j8FfNW^qlW;|e{AX-Koi>$1G@8#=9aB7vGvGkx7DK3UBL{ZORYen2bw-kg(>O@o~51YfC7) zvX{sYQn-NO1TX*x@FXRzC@4wGFaOU3eLsSX+;QuY~QC_sbPV)N7#egnuFlEFZ!iNS31E2E-Wa<76mmu8|-KF9GG53)#`q`iUz^7$pU zO2^T4ry6X@s0+mVQ07C?Y3qRbVFcRETw(oVm53>wv(b!yq4E{&8Y&7!YRG|#{dO{% z)HF1Ho+CJ%RPU&cROq4$fCN{_3Y_fXUAT5IZtBUyi_;d#_HvPA5$voKYDC6WC56Vn zjpEqk5g|WeRO)M;R1>nIvhfs%puL(77SpCw}p9@ORAiYntqqNx7t$k6$ zmXthxT7Yg?020l}wgL$-|I|>zzpne4F<3*+Xk_#MxRz|_&^D|)xelp|?2dLXWn?u? zu66^GT)GQN)(t(2b{V+2=!$Kbq%3aZP(Zoc;go6QX~P~gqjt2N!y;wz)(^dc^CqRx z+>>)%aer0;b4jiZY|;dtAy+-T5{&f_oJUnprlk9?me4B}a5p*gkXD?&*#K9h#{%}n z%?Jt;bW(9}(zPQpHyJjm18W8PP?BC2>Y{s;tve%iLl>bF!BR4*(!(YseS3A>V|!*J ze^^wWbV@EAoY4+=rvae8RsdVRCi+rOhdFb+7y@jKZQ2wZp2=>$P{ZcUWYdLtPg2R1 z5y?;c!;sUnaO`yS0C95?$2C`xhq;teW@EJ3VPN+uXne^KKjcLdvms-_QE2#6GZLBs zTt>vx=MJW#bC1O4GG1r)*_veWbpiK~-d2E=Mw}exehvorPw#atD2#%Fm?lteV07tx z($ypJiD*28@>R6R!k`jKHI&YcruG~%Zfp-4Nbd7#R|DpqXo#&d_HmqqBzEa$1TK_l z5y4psk}r%ZN+{Vk+$mqt(4m!MrWb8zm9 z;$tkd9jx>7_umi-YUZh8D(dY&%_WFZ!RsuZ=?kJSM88+7XNLIu7;zarW&?koB5Yvo zWacd-e_j+)9IHlM22X~~VMaWkbTbyWLY0{MZoD&VeTSXp<3~1O6+8B(!q66zf;aDR z6{|5lvo#Vh^6BrQ3|bEkvl&HEoF|-}A*BK9k#b1>8iht4L`Dv)=ML;eBz%MU%}cAW z+yb%q-U-)0b1dhDCvZY!rBJEP-2Ex_GbomobRR+;*d@oOf${N`SrqFt6{_(VSTT+Q zI1iY;+2%i02Lg!UPpN=`JMB(|=6{|9LRe{_@TqFfo zvf<+6!(Wgj0d9mdtq-6rs*SN{>V*vrQz)FJirX>e`?-pwO~4qJ(()|kt(JFW>=u#Vn{cmPm&Mq;HEIZ3EI+A@b7q)j2B9v7r;dg=H? z(_;NY11b#CY-_T`wf@jwPCI_dpt*a@@7GFA!hz?H-{*m!%f5mO9fI%2f&&0Ww>H9# zzWDFwgVjL4)NjYSn4NDc>;)&FI3^JSnOg$;%Z^M?hhtd@XF?QPR1@^vs=FGJ&`L-mQ&f-Sc|h7n%bO+Efjvv$pF!OsT&tNI zWWc_gCey(N6B9{0#@P^!@~L2Obg$j^-py30%gbcI@5UD@SMi^Bj2zNMY^UFk*Wd34 zM}-Fdp95bfmT%990iU&ryP|)=QXKRIY!np6q_yK5BNm-M#X1;~u6mcKJS>Yd$md z`1uu)Jkj)owcHoxF-->mpM)NO23Q0<-}(-`MGoguT#EkYEW{Z&*Jho?`~K&FFs`_H zh$Ioxs7~qfar1KAzD^56K;KXM^3BlVSUjQngiZa756e*{ScvwFb-L2kARu(8b z=c%N+o9@sku(G==%PF@P`1aB_QM3J3H{(Z0I12{_ecb&ZL#}bF>7U{U(eih*79OPs~yMK zbqjiNcNy&Qsx+A2-)_H&WB;=Y5{KwUUkz!Q zVTbq|ZHJ)`+k~Hx{cAhK;!_uH08e(^bXrkOGS8$`LPiWhUF&5b2Eux@)!&yQZGYb;(ymUgnI{JRR*Q++l!|~$ zEsxLAJ$A{1F}x|;=S2dpxlDgrR=e1Y9)9~2a8N`%^uPUfzW#Qeksf{9n2H1b_PY-6 zrR!JFG5n~T{QRa)o(BYD$-%-TqPXBJpld`#Okvew(%)Ks#Q1kBs2S zP58xDd|}L#UaO&tf?=b1i7xmWN(by}9rYjv`dt(CKIi@^ z{3K^%kRM^Qq&h5f(#}ludm3C2slzAP!dbnYN^G2^ILCuPzywbj-G1d%pQL~nwXF(> z7UKR*Aon0Vu4#`%le^qvj>1kS|7iZ0Eo%8Ji%?55#`;egrcy|}GoMw}5X~pz&cP{_ zuRKlSk9ond98Y~h6;ZszU4n(az5AyU(aFQ2awT7}h1XLkVy#K1`bZ+;Y-?#mtZmzr zC23*zyc;gxIblZwPhVGNuc}75eXvr8VfP5Ta7YpP7^zyq0zked#9CS6df^v6^ntjr z?Aa#Lgc&XNp}2c+{i#wLziQo(CpfL%X#;ft8X9W{ghC&9A}V;ODn6@Mr9j#qdxz{Y zxfKwR;x6Du(Sv!&7QYG?qJ_n_gHT%(7+U|2o<4Y~E!|K$>^@Iv@Wx-YPa=fL<<sB(ojoJmR3=bW z-@eEq4txz-{4#E$7|+_*VrTa)Il#l5!0<&9Q^MWw@7VxbR=!%h1J}R3P9Rf*-;xRVl0Tcf=K}NosTuPic5z9uI=RfL9TJ8?jrkR;}&I&jP0( zhT6*!iO*mc!U6;Y`@7q10-MqdY--=9TiAwtG zK#LnflmFaK9c`ujnRa=XtITDSf&4Zoomq6<(ZeAud9x6d?OE$A`r7pNr?QPlS&at~ zEa&auSIrqK(x8k_-!B0=tS!pDT1DCZ2Z<87of41z@t!f-6DJ;$up))gaZo@Ptr>ST zo92eUlyF{32nCDl9WF7fbUjA(R|R#@{TZm$K!-U-SA-u$eR7tisAA)nXx{890)(3x z^gd>%q&%!7seWF9k;y1KM`<@dHkI>i*Ux67S}{UpnM%T%0+45U3m#~kX5_Q15~no* z#Ch3-x{Y8$BtCQ~rBoN<5M7NIY(g}4yGF-%_K~G;at&S9!U(v*r*NQ6JL3*Hau7#p z$wqK&hwBov6`I+~(HPfQh!^jKxo=NBd@5F8C4P(f4ZskwtE#hVbH>MA39vHRRNy4W zxoXk%gRwO4h|5kd6&4y#^)``5e#ke?!ueM{=sx}}EKjjnIT5Ptkc+pHMpzk)DJQA| zbQ{xjmPY=}Rkd~Fl)zV#y>1%niQuMaW+ceBJu-4Jnhx;-_Z@S!_NEk4nJjj6{TEN) zS*cL^W+Zw&FP`?47yKR2sgXAzq==853bLSd-~|`beabb_=ZNnJ^MbcWKPlV^pKYfS zC>c1hS!kYt-=uIWfc<_an}7AmI^dRTQWc&m7}$dizU?Mdi@f^GhMY`re)!Z`)C~mQ z8WT(;K{`XVx62BTaTJdj+WG8hzJmAcf8Vu-I6t8+F(mSYBXr;xdqyCyK4ef1Yv&;Q z7zZK(x>3!P#Xx^3^?p8nV8v;q#!rgOrc%}Nn5H5W$pS8Q?{j;pyy0U=H$C^N<}%7r znr;SVJhOLdFE~5D$vAKyH(a44Gyaij*z0$HckgJ>C(JyZ^s_Hgk7P{)Fd7EFzWvUC z_{No!|N1-lgLWx?-KL%ly!R*uK8`3Bejh|82F~mXzA0}{&wsrbN@{!t*YC*u3wRen zypXiV3u?(Y$>?jW^_pmX&MMXW6sigxW;?)_*k9nvfgW8nfeD#D_rz~P;|+&G?ioTm zNXU!Z%^DWyXKjBe&|S+GdQh_EBDUalZu!?=160IBW3R+TzX`&$X)!iar1;-#n+FcEdz*a->q*0Z=lEs#NKF%x`aT(GoUq7dN z)~;fiUcZL7-enci{O%{e@QJrd`MplB8t)UNQmO3$oP3EF3;3Ivr~$9+I-m zs({r&p=lg-+a-;XX3^{C{anXkxM-Lk8pr?V)CJsAnuBb&u`|=9<5diVP!eyN-i-IH~OYTH1@4t6)Z*|&Eq2Un9bGH`RHpG zbgB7l?oZK~vE8q|Fx#eZH1|NlB!0sK?m%k?JuGryMss)>G*<=7J%PqVgL@dfE4EX| zHL64eiL#TZli=pwv&+Gfl*&AEIgzsO>bqwuVK8r-OD@Dk`+`?k%Zo>rDIfYdf{E6# z$t#w*`;P?-vp>|gy*xn~GY7+CNYU7ZE;|HYQ6$U4C+`wB{eZ8l`NqMtAv#jO&do2ucR zvi-p1&~LFGn=?lj^jc{1k{QLouRp&YIAuRu=LftV85;vWR|yS1CoF#XJ{+b7ep%vV zuFZekJ!%@>E}V0oPkcR}H!2uBl;}z~KkbswA9@;Af{Mxh8ThB3+>o=9rM2CZ00GR-^<)5SKRdc?*q?=mmHc3 z60P<6rS1$U!A;)Nd!r5bl-@2~F{YzIz~f`HvP5Fn*w&otYvK&%$HDjKZsV8J{pj=E z(CyfgLP5RdH%a2? zO3hq)r^&6i)})F~>h53zQCoJ|rg|u6y^j7WXP46=SSA80E!D5gGukjr_Gucs|~SOG{So8p&;Nvr7D5e;BF^3^&Jk2UczWoSj`NaCpy*ze^G(*O%|4BoUAz z$RgC$fT1^;ZmJ3d`>@_xoyCC2&=^LwxWaV0+xX~KK^TNh1cBDuDEemC(r(v{yX$gc z)y3UK^4gB%6Uoo+o~kmk6vlay2t26XDCqy5tcSzAcbx?VSfNr@oF%{A4%FQ4)X>IS zp~e5QX621O64WqvyAQ#2Z{xr1>-Nb#n}$MN%8cTvM>tzCUE&|RO{r_;b8FtIrbSr= ztA+MW)u%$G5fzl?ClNQAM{G-8w|ZB8 zHzUYxkPI1ti$c4?;T{8tvD-<~U#_h&tX*PHA%y5Fs+`4Mvb!c00;GBXuhbwuW9>OS zj|tBLa>OPOi=2O}Mo2>KGZ;Q`OGDUj8xj1(01v=DuqTeNm1UJA28BdZG~Gtu@qi+> zw_KLp^lGkZ=q;aN_qo0Q5VA?OBOAR#v}qYFO{E8~*h~h6n(SdZlL#%^%;oTGvzTjC zHBFduo3X?+L8TPP+%YhU3NYN@f~9{3XI-|3WQ~;m`f_9ks}>P3VSH-3{j_CLoZetx zaely~dD4IBPb@Fnu4=mMxzlSt3;*ZCV0WD&wfrOEvhH%!$Xf?ZeW!|!9kMNeA4`fE z`fP~0i_*SkOW9ZZcjae=>mP>L`*YTRs@( zpK6?XoMeooPqv7dO-A{BB!!NL32sl5j4o=q^bGDJk{XOmiDvE61r+y`j%gGT;DB9t zLg8V)DLyHGR)ZgUigEZy#R985^Fd`(zoKGQ=i6hvitG4LqWrbH7D*w(q0$rj9~5h0 zbqnxSxw#nXLY5rsEo5l#uZ$=12+r~xR-lq#BWTz8MQ62|t$UB5Fv%m#fG+qDx7&`j zvUHSf#=c@TrL)O=;2sVv$8SJINrz%?`gz=HG<}2suBN_PiyCa=!5-m&_mkJN+u$hR zLqEL})n6Pr$UBNS`>RC}OzLl5-9DzIz^n5a`SSIN94F@DRGboqWo?JLb13RE-HbxT zPKsgnfhpIW5-BVLr>A~pWx#UF+Sm)D(y)V?R(1v^p_Et%qx%fKG6UaVMD4Rjlc4s^ zbU|Y&^3nC7R7-`j>sX=S))ir<|v zgX_7SLs3>Wx;i<|V^2<>pDouCM$DdI_^piW$d?L=uTw7C`Gh(B8 z@SNoYX~K?_twSh-OFn@yv?xnCt|fH})n?a8(AT5x;#e#i^l|}h57Dko+ke5yha5yj6rv1wgt zhaPMou6xenp4Sy`vsvD^5SKWjqT>iE_VU}X0Y_*{Lqr~Ti}gFYt!Zc9Ynauqo#Zzyxhqw8QExIJ067x9bd_Qg&KhG&RTW_6+H$?Yz-?=Juox7LxSI zoafr4*I=l9Fx?9($T%h3{Rd(@UNgdxVhRni&xb^~R_7eJjM55ulIr)z#(D?UfQxD_7UEPXZY=UVGe{#Maw4e(@lVEe=;Ir5 zm7K3=d>gETc2{>zNQd7KL-v|;!q{sPMe6078>fn*eLLH8CV%?UErBU*s#o$DsYez) zExDin9M}b*%3oaj|0pLqLSqQpb`Bj`>=$!8mi!y(mdn;|Zk>gB{ZAK5|jFGUd5 za(^K0y1qxFvG<09M)-kHE$N(86C_GRN?kafi@_7Lp`qDc6K*BI(s&wNrWPR{3u}^1 zr=tCeH&D4T`D)Cfn8|8pT0^lHnnP?eYW`s4aZEci&ED28?BYN86#cCmQ4PMHbswUu z)tKUS$RGxosU036_1qkX0Rp=7+}sN-Tva^V799jE-REiFqMEIz)6fXgnX*p(+xJc| z`w#85H-x%jTl}UvsgRT@$w8y+1a3v!+gwVibN9|1#+-RVYP)`Gc;-rE%&f>u zvFMq}yQAPw@;vuvlU~~q{eCKAW^2Kt;6dRoG!}}>foqoW-%%~F)Mq5b=B6@4*Cnb9 z6-r%h&(MlN)&cMOJ0!%ge(z(k;{wP>4wKcjcBqy9ISD8zl0Ty_U6-+iU}7Qcb-)%# zC#Yehng%6hW_PDTI&BWd%l{eVjXjO7gNiN}lOLj;oTLK#-rFT)<3 z-tdKVJ>xB)P#i0~OHZtQxvHQiPWW%9a9;f`z4+i<=~VC=KV~5Iq*ka zQWC+ChHPUyU2*r-uS+Z~N6jV*7s|F(xN7R{*(sx%fp?(jwrGg4Aw?2jZlP=IZF)%Q zEjE&+tZEM9&*djZXU^gR_N%$(wa2G&tpyJ*XTvB-2VqK^)wC!Lah0QKCPlRL)aOY( ztYK6FNLj$CqaXdaIuRLE+S)VO-7&u{Am33wZ|_5karjo+85Y9JeM~3-mlt798W4*# zAr$alz<#&Z6;NZ4Ku-A}?#Eb+%J%0Jt!s>nV;l?Gf4_{IH^DIG{jkheU;ZCPk;a0au!1Q8+4>9>)e|>YZ=EfKtyL((ViYni}fW5m{?5u zyi3tzStx+QSW@2R=klyx*SX2QWivc=t=`gt^G{K|^ElOu(|VOEvo*$&I;Q~@yl}e+ zga~;0;IgBJbRX>jaNZuF1sQwBL#xlTF32-h8}vJurQO$W-?c&7`AT)4A-6%a#;L0U z02@x2c#OFLCuMMIfe8rB4jr@MikCk{u&>s38~|)*MX)~DkO{*+Hua!8jo@UT)aAp* zv4&P5g^{i>_~Q$L!UeT6x=nis$JUn6z={hkF^og^uMvXpYYwl+oUOh0 z#^}#WgVyow4GYbO2akVXsk}xEzd7!eb%u0O2^~PVv}Nz5tJTUbBec8S9YLPoW2=OK zG%eBA7{yN>t`|Pbp6h};DmGNxTuwWI5@NkMA9DuL&xvG&8}d+3Z`XqQ?|@Nx2LD(GgmU5XczedCQqkm1;T1~c^ z^{wkaDXwh^v&in1Nqnd(rdYK;h%(Gvsy0kQKeVoj^(O-_t{&L{4a}78AC}V4E`bdM z>msP6Rz4c=(d}b4zz!n6W$~f^G$1=bq(JmKj`-crggi78PoA(`YJUc`>_XInbsUD#gyR&8ou*&m@_w$X6 zQU23xCqq%7ZS~@YprS;8w#J{&fC=+QvmPBaPA-EA7|=py39@)3CmxLRkyYt)T5%>S zH$R~k1hpg;SxW*{7QEH)kBN#(vnJjD5LW0H5-8;qaB=pb+bef~id7ua~W{_^Sl53S@rWyY03Y=BS2|U?06?I zT3>}M+vSSw^jgOEx|YW0i(n(0fCCO8<4%iC+i^dIna@jT{Dk@j%%NA|wU#A7X~sg% z#w<=5s0-tf*OYW8Ha3<#1&TU+xUg8KF8&#iDwc7^^T3bMi8LmwT({!J%*tZSKjB21SXJ=Q(vC zm1KGXq&q+c9@|RpYzVQ16l(Z~W`qdq8+M={tvkn)$_ul2!p5Iv&}^f6KL*M>Q8=`I z@TqV)+1l|9fglL(hhOsBZsm(x6e^;yUM8jm*Tg`T`NleejKTG5I;9I?;$|rEb2{Ya zDCIuZ6}MAhJt~${jpwb2&6xqAMPCiVn~}!#;d{8j#waT=3|(fiebVyG!AB4I!N#-pL-7K&HO}KO>$^;88r2;MjDsWTV&JRkUs#p1=@D-$Rgn)sPiN4ryjLA&# z5N-mW{FcO5G}^(|FXVT>XMs6_WOMyhiiH@-+6E=$bpGcJJT?}7dWc>2HJHDkl$ng1z1l`By!@P)-E@skqAsDLmr za*Qr4&V9MKD5(VbNsvKS=MS}Qw{uh^`XB~2Vdg|vK_36K(rGcIST;$0y?@JmZaHD7 zeO3Ha(wiCYv#UTd%`~q}Z%`lbW#oz@AqPulI1;P6me_~uzjEua7b`nA5Gq#id3No!hBaOSf= zc9Q+!YL-ucSXLsBIyhia9?xI=wA#XyTmIpx>K%s4=#%cibWVQ-k>B!=^X7}A)<>%? zr$&<)St6lrUtYe7E?2b6{3h?qPxx3V(PrU5Pu7w*Pd#X^rab^ubZ`BNPYj(T{<;xm z*g7OaLEEX+%M)@;&-=Grkl&QDc(TQ)hSgp z_|XHHQj52*-KJWmE^Um@MECHXsjpITk9nmxN6bSBh1S@IA%xsNn)Nq0R(e>pyK-CZ z0y|SK7ls65KEr33tl;Kl6dRdVn|T}`uzmq9z`P&&KKGXKEG2Yy>#v6FO1utq{(Uj` z?r0j6hu5;Zh~Z>ZkU}y!TqWM;adCUQkGc$1o-wr~TD*}4d%s*%T~OmjE&j&1QCg4b z-GM6D;pBgfs_X&dcB6}1fJ4VcIBb~15U-FqZGfINy04t}gte~Lteb7cZ*WK(aq6xkOSqWVUoF9Q1)8L$%q~g2t4ADJi{7DlVw1c0A-3^^Sr;<{v zCUQ^T<2iVOC?C?(D%W%_W48gYcfrI4BJl(RgK8cmQpXs@p!G5w7i!my6BahFiU3JH zBiqy8MTL}gH!(-6!tY-<(MN!{wR^LWEEo2qNvs8o6_&T&6`B& z=Zogr91;r%?ouk6G#TE(GLI{^W?vJ#pHnDaten$k{+BLhxUM4XMswBTkmyx~%$CgP z!BkW_X46Hvn}Xl7p3sG&J4WQfT7sd?FXl-{x41ijZY1QC=uG6 zzW|IcgG{>r*GdoYb>@xzE;;t>aVx=(3XPALIMyWU!uo8p`BSa`15;54;El_Ct^@^K zEiWxd@^CvwFoP#8U^?ijY^zlzdSNZxHbo~he}>4N2T)JJ^~tDu-8>ZuqQ86)3u@2y zc73Mdgv=1&Qce)0>iUlAQYJ{K5Fk{$K|PU_8YpV`lXYZap>7RgO%x6q_5Hw9$2csb z9LDtWyZ?!pYt)uF>?)I!^@kB;2X7*Ha>U4hz{+Z6nS%Si7SEA%-Vy8L4(hAsz)qwG zReJG!`i94y6lTAaFZV0bZ$i(Iy^c9@2uBJqU_ z>-MxKqD=II!{$4y^PhF;TT+5Gy`kEG+=)!(+)cug73H-4!h?|+D)TwLR1o#KxT$69 zOWpK=<{AiebPqE68?1)@-TwSq9^oaI6})9B6%%cP7{krDV-s~90$K`T_8~7pbJ0OS zh{-JY7W8rbp>PN9giZT7!)Va&{rbw;xI^?U=>K^w`0{w|j=H-5z6syI>5si-(J;`i z?{)iJ_;E-%ANcH9_;nUpDDXXoNcf#G5cp6kllz~i!^VRg_+Eu=sn1PJQNMUnrM0^) z3B5n+z02;&S){Yoq*3FY#5I)=ZkKnliM#I)tCXgBo|pqn6~hbVL^=bbieU4QEo^K3{)F^1BE<$sHkJ58#}!x8@wRj;Ti z!nrC1=*5Q@bnqZiTfb_3{i-BN%liVToKon=+{D6eIa|h_NZ27M3uy!ndeth7@YbHe zoLH3f*22$+whg85eJR)=NoSe-om`kaH+J4~27hleo2^5uGznjq7Cz46cv;%+DONoL zM;8Oh#^%aMp1r7hOEEKQ87g<_CnqpwO-%#V;?>YE#p&;!heaXMQM_~p3|tvlvS&&{WHh*C=;Rzpo_lV zb9^hfb__;V(O7I>`$S!vJRJoJJm8>4ydEPNXa49 z0qlXMYk)g#JweWpx`NFC;bR{$O&3Vei~#qbO~%mSg~7Srat6PF39g9mcVS=av%hfE`PBxW2S8QA=LsWv>kz|h|#*FilHmrVxQT7P)&r*QEXqr4fLOf z(xqy?xQekI{U}%d`>gz)H!zZU#s+1)=b0#+Qv@zlFY;$^eu`yb)La-8~ZiAb?W}s^Jd4YP=l3iPHPDL#nkIq3^U*L+4+b z&!(SMqKh{fW$gt$F8T8a1H1G}=)}U-eDs zRYj4zl_aW#S0ZOFxRwF1*ew(<=x0J=@q=>jK>CCXOc0L7a*Cr&qEk{qR9?CeSw0f+bgL>X zJkeAzk_@&F2ZYsUun9NXg!?qSP$c0rBQ7R+0&mq_RLk%Mn6a4$^BY4hTdDf=l!RXQ z>dAML^nVN%TXVdBii!M>5SG_PY2ZjJ7$}Qse@Z62c@?1b`owc|!pry75rA_;qq=0A zkrb;R+X5(!YAv-f-B^2nYLKAMY>>sYv+cx=g-PP7d5;R;%8lxYv7CsDDUbs({ep3} zLyDwZcM}5lB#3ILerzi-qD;qcmCKQNjP&6>tb2GSV& zqS;)?JnfCDIK=qDsi?+i# z0}i`VQcQhR-No2jzab%j-VP~zQ@vLoaX~&J?l6>ihW0i#I@NG4Nt)HvGcJjgjw2vz zmvi-AHR7U?O*Fzn6A{Z9E(MxP4znaJzcpN=7za}ngVYTkG(1Rr|A5)mXR#BobTMcT zvi3y1#!E~kQH6muT@{+=eXIkziy~&E1N@tkosoY{m6y6vt!f+TOkM#e& z9A)>w{C|?81X1_^{JNZ?uM`ypi996b6?8`FVG~0lGAbZEIY4JIC_U{8OKGQ=&c(DF zi*q9fpIM5VMaq-rWm4UT>If`V{cw@Zou z7<-aK%v^m%{E=%tAp`_&7!yXVjWX!?OVs{xLlij5E3kd$tg{dlerRHh(AKcjKCs!; z`6eZ2jYW`(4Vaa_ zK`_MtkPJyD8rrCzi$&DEDXfxID8X8YC@oWeiXl^H5+3B1Q64DmKb9c8UgOl{1l2hb zzCRaXYhsB4){>`+e5W#iR`YGG7Tu|UdmQ0UFn#XyD4C3&U~3GAri%hwOmn-7E< z78`i_C#eb^wxt10@EFj>^T?@9k6u*p;Oj_~mw6pLwdPs>rK9kG1vd`oB#0m) zV8>M?|F7w&vHuMn75@J~M_D;?a>$=T{{QGG+W(P`YWXi6MR12)lNejpEsp>i7J~{t zp+D|Zq6B(;WV>lv04l-4a8@9ylxH^eJtitJ%P7*8)6QGxpM|J3g)9o>;Ymr z%A|V(P!5VSo46r9KFc9n6b1K6y1}DA2;)A_Md3dtFZPl*SXt5I96{mdQNFVle0=1O z?q_Y%pm1I4P?c0mt!_(cDZ4!<@Bulgk~V|5B|^x-e-TO?&!jA4s%Wp0oG0!67i6in z(OUb6bPr5OYL+#UlUjz8h#^P~5huwaQNuP7N@#Oq2FimPY+CApU%tJgA+Pqi&R}## zNUmdZx#B(pgVt-0&c22l%6T)rFvPWF=Tut@-D>=YW-_u#sCZ@m60k;?Z*)FPDF#A4 z6uLbbFqqjtom7xh0XGx*L_n&ehaq(1rqZ>WzO-KY-YYofr5bv zz~Ymd z?mq0NSz_YxL-EyAcR0bA{C=YDC_;^=)Z5jPrQcCdj#!T-m1m&(X^RD%+TKqC>}f-3 z(3aZ!#jvQ&XQb&%+iio6l-{#{^L9`~ex^0zK1qqvL;_xIx%SKuQ`E}ImWg{?Y9cUf zTL$^p(U>r~OKlrAK$kb5=8Nu0j{fPCcN-$icUkl3{yC4O3~n6HC<=0gbBtj+^^kou z6#ENWQ6Fd%o3E~X6gt!SzN>lNaV&zpK)%5EB)f*~f0Cng{s%cK{r{7rT510)NAZXB z2TXd`5VnOtL)IcmlX!)0=m*a$CVNRv4*R6p^hCtz@ARET@nDl5Q|wl1NSQqRqH&9o zW&Q=k*xO)v#oW&cDt$x2#MqI``g2)h0bUGtZ+ZTc^kPY;f+BWwU*I7};TZv~;ChCc z4Qs&BT{>A$t$}xZg~fzxRrj=1=?d>|{E5zk!Bgpxioql%5iPL(q`qoF=Oddi1#p|; zL~Nd_!xZ96k13TrV+55jQ3tshRSe;-2>xH>DA@l|j$*T@K<@ZScbvkY8M{q(lcN0* zr8F0!F1sT)omJ3R6d_C~oz8{kx>T_w_fDr$(@@w*za2AyLhZAGZn(h;wMm=OXt0BN zeiV%rvvzw2-R6Jf%1VghuQ&lID4v5j8H%r8-%o0ZDNqJ7Y2onjLR~WhwwfcAc2t8p z9(In|CeQeHMAbY}#YQJ8Qh^4a)ZGKptNejT<`(1eph)htYP3vCwOAogC36#|pbc_T z=mJtu#8M-Gx*%x-DHex26sDptMI#TI0~9eR-I=# zvK6y}s2q1=&A(u1i+c3`74L*8JTQgqA+0J{iTn{?n8a1dd7$dF&s;Db zp*Iyi^V)9;N`MhIuXfSAwAy^CTaYhvlZdHFkHqhW7AZYJzIha7Q2EPE8|Kbp8mGVl zk6fs7NNyrqPcd4Q59pe};_11q6W{bbCU8|-K&bLpuijwonyB#|1>UMRHho?8LEZrwtZH1nF8Ej2A`S|A5U;ZoIR$JRN= z1cmB5Zdx6eH;9;lIv8ELccl~~ybxC9Ra-;r+NP?}uovJi8H#7nI)?e86^=2uUq!_7 z#BlC}c#N@2sczT&aHbI|;stNnzH17CA$C?&cHsUbchMZ;#bpHW^oDnScHMY%utcY; z{(ORR1!D@GT&?m1)zt`E`R=*r;#|M+#`}AZReO!vYwc09YR=!p+1odwRkM*)r~17d zk}qdLJfYM%p-&d?2;^>BRO><%AMMsVwq6nz5CqW|)d~2qz;UdwmhBtOP(ZHYMB6a> z>!gia-03$tGhK)UDezeFEeJb>I)~6c9ZLH!R%MNN{`_TxhcA%`G#I-xkeg}o5lG?F z1K$pMBAm`Y*wC35^p4SWKb@HuctpmCGyZ|u42XB3)Q zOoA3nb@1SB{X$o?c*1rQsPK|^*4!pu{$6t5H3fZVP*NZ(k7~r)dN%Tb-glUidCq&% zsawT}PJYxJ+t1{PPQlqRhfVg>k;#b7iy-LW^chnjNGi9hN2oB)jDQnJt`Gecz3R4# z)EU|li+GA(uCoptu`X}TA~T?sfm7;O|ACFVKuR_|x^zM#EbL;q5z(726cex!u&LW; z8}11H;SG4DIkdSPb+9}+fL}ydN|?F!T67q|Ez2))sw}7Q{nfrWt?H||5&Dz<#EJa9 zm*&W*!0VWW(x8OH`A#9Ovh!(az*U;IOL@EIWp^+CBSz<^JTEE!ENI^%YR4Y-Ciaga zF<5@QaN*iyxM_vO=}Lg`F6u{{Doah>7j|v%L((Q^@vhx+`Y zPc@KVC?};>lyQQ;Q=#Vd!IzIFiF_4>%|KIcpzvkL2G0Sbjga7$sTKEED!WL5P-{XI z4ProU^iI$?=`k=IvB$roVZ%j*sSVr;%b!;%PtmW<4Cquwo5q7Q-;P2-EYu3{hFW_8 zmDGcRkRoulzb!=iDo&!2Bq)@?5O#W$L}tj{Yr0`4K{PVyNxm26H;V-6gDQ6>nHBYJ z_;Oawn{%5|4YVcx5HH9WI%d_Bs9Xq`5)Ht2dUN{j8kCV@YC^6?;V9;a=bp&;Vqy~K z0%%1`c+kY`vJz=Wyeg*8#O_6h|5=RUmn|2AELj^)C_R}njWUXIq^JA*yBNiy;1@}K zJ#hiw^g$i_JjKyZ3`eor$4qJ-E=fCo>%TYu>~i((ZK#nHbju7tj{$`~8Ag$p2?X1{ z00F9E!Nj_`v1vS!7Dy5*p&XWJM@c*y=X|sX*;XTRFMb~fI=x!l1I}}Z&V+I7FLmL` zGv`E6!Zw84CUs>rqDDW(N{Z$`&c@P%lB(FHN)$)zd=^UPDm^H8C~rZ=yglf}?@oE6 z6dGMH{Y;v=o-Yb2*CN^#pUHl6>z{kE&Vw$HlsK0kIFQI#z9n%dAwtP2p&fgodX~o* zvpk})r$?JmgUsW^b4H&ot;p2zn`)+i#!t(}0V-u+*zHhye@(4Dn95>f`2SxqYIXMS zVwA4|;dbpHrL5Q*rl!U6iqfYV<)033>e*d3{LRHMDf7+*D^X3K5`L7*mapQ;6p z9sx72hjGTh{p7Nc58~@}oW*!gRhJ>?wGucf{eJe@wm%SUvO9wev7luoOG50}M$d#8 z+WjwN6xKhHQG{P))F{P2lTn=io{VZ;`4=)u`X9-tf&Yn&O8=k9C~%bQZ+8pM zG+{ZQ-uVASMiu{`$tXvQl>Z$WmHDq^6#ZS3cEFt9ZbIu?>P%xg{l6ijaIaHnpm);= z^H?QyVmK_?LnC$CXT8M?GDavsXF(?&%26CzlP(=qmjpHBNp7Tl#!&oKytsrhAC8Y2 zyN*DB$f3I#V2wfH@)aXBj50Ny#U1ZJ(nYL1Jntn8ph+!be`fQ?k1wk5A$WjiC^u!M zsq;JT?x3`iPBDQ~H35yfrZpO6ZRo)6LxT`XxU4N}1_QHGCVu{VG76~#+a!uAUMSjf zn7u#`U=v!s98MX>_(3f#$i)AZ=cZl!i!^y#-a^7z@~+^EHdHP}j3>GZ8Ec(O7TFLK zbkqjRxd_Us^sRmiIgwUw>S?Ad4}1H72e&_?4M)*uD2%Z9IPr)-lCp<471*kn2DKmj z<^~3*4!x#h@HiDKxM1D19E#aGBE3&eY>9be$EJGp(3Tk(-Hvq43x`!YP3&0rJr1KS z@u^0$AIeJzkwO5V4@{dad4#GL`>Nyzyn8UVQK;=P8~}V8zF=K4o@B>oiU`*acEpiT z#SdHbC5I+vM3>&05VlC>%+O~l2^Ehp%J^C7^N~d>=BsPADwq2D!kbXjflZbQ^s>yk z%P?u0j_d%T8=u(?1i~XFh8q;vZFl%H<|A!o=;5V>!5yVFGiKj-u7qj>LLrjT-fJm|c}$<0*hT!t8&aWm zmBYaoDV|A!1wlZs!76nO4}E2v+=Hv2tXdWmRzO&s2Re6kq;=Ed zU%O|n5EewhAIs;h^R8k*<_W^zOpTzfS|H-9iV?rf<_y<#{U!G>m!t>Kj8$7EHLHT# zD!1)~_=x?_VwCj%L5#}!ON_#{y0@&^HUBxsYMXFD4qri)Fd&`BSuR4!URf?AA}sI*XOAzaeRi6X}SB2jaZhZFN|DOLm6 z`*A|b`t$IQ`?63~xmrp&i;7CeqLvwR_{^>kF6(OSZ*VX=|3P&j{-05HO7V!yqH7T8 z2?KD29X;(?#>HdJm?|uY2`=XB1}WDuSM^+I$i%|d(X&?>-cBGk@rki;5aOr%A&i0!1QsX2S5rUwv8m-*nv;;(131Vz2^a!L2@rO=l1a1V+Z` zPX6$+n8O|{d?(rC&OGRJRfThsf*m#zTPdg;GTRPn+MLGk6Efaq#LVj^(%Xsb@vOUO z=?GO-?7bW6M&(^OHxp53g=|i&1HR0yfQ-VJhTP>6B_SYHiLViOCQJ)af>6Cabl+9x z-MR&B#|nmH;U^vXezf~`)DJI^)7_dxQ^wBc`E?A_509=Kh|4iTR(rQhyfaP}fkjK@ z`|=4F&TODC^V=mWawBrOi`&^xm!g1EClHII>GEx^8V+z8xm(|9uWxyWeylC1kTD_1$z5@aV#42aEQ$PegwK+K^vSNkwmH+#kd>?zn*YV z+4MgM{#@{Nw+HoJ*xS>YKpF3jo{zq5X9IVNSV~0^I}Q;2wsZ`Xn9|L4H;uDv2sb~l z%h`50B$7)l6mdRS@Yov1+{7S?yCqQbk44AI3Lb6?KygFk+O&-yG3|h{c?|#b%X9k~ z5nq(uyWgot3>h~fukMPcN1EzFCM)sBq|rk2XhH2KI;}8xgMaT0j$@%y*u%Y_a0f;o zF1gqn8|np^BKT*OpHBU(Sxs9e6i$`MA>OLYL|3!Qbs0l+^u&1{idG&_Fg4>W=-b#! zRW8S-y0k8qDd?hda$EHuq54J@t-75h|B67K{|Svk`Cp(>rvFWNC$0{4#yR3#YPAZu0kp;6vst!uw_UW{D`F)-BaE zrQ%;3)LV1VM2L$CMaco&oPRBnV$77I5|##9_RtWUvK zSRzS8D5ozbiH18uht83+u_%%yqcMg`ducPpU9mtz)IPr$3b>@0OVRGmc2N*nvwOot%;DsO{b zAW2Dc{NV=)uW0-R5;FUB?xK`9`B1WEaFAz=3N#XEA$-bP(AlKKxTNtF3_$St9gd(+ z_fJXHGcILvs`4C(qdOa2Sa~&SSFV|W3@xhhDBWZ;LV>26@uD%uxL;7jPEb-g?2;BP_CLO)2Ng6;n0qsgT zoRz-TNVr1`UuUw8sVzov9SMx3Q}3dvv$kD{mu<+oxe|_zCQ?(NQS#KR+RX&PD5ZnU zTKf=k7SFEXDufIxLiASsEV&QQJwXn1&0AiqpWU>0pL-#1pNHi~?=i_ha1cF^MEiNDmzzu8 z9_-txxZ(R8ACJqT-e?$q9 zGTI%`5lY=nbm`YUiSKtHC(t`ex+V#rXI2o3@OKo=4Nr#0+pmB?iuZSo%Hq!rLiV5kRHO1^z1*h$ zXO616{kX%@MlkJl&Hl@yI{)&hsQz=0>aFYik8Whjo~Oj!`+G!6%;(Fy4U4natNbVA z1NPuWjPB>vdBo+`%iEr54tLkn`5pr8=iS-ijMs;NS<{~4@xwDr*z3h~_tW9vU;5I! zDmj$QrGwA(=X-y%?&lgAZTHLaa|*}1uJ_y7{AJhcgG=`xqIl3OeG%a^WoIay3to2p zL@Qy0aD=Bc{y@*0ZWx>NhR^4Z`a{KA7w(_IX?wglfAl^YxZ!geelCV(@~(HYqqmQB z9X{ydyD>4kT`ja*QdU8r4%+TT@s&O*WdNvsN@^FP;N>AuR{nddbxp3jFTPqWqLo2ES{L8hH9O z_9G2b)HcCzfP0*7ar>C*qHIB5H4yA|h0pZQ@_f284iZad%%v1H9(@j(;3V`>tq-2P{nX(*etI=re5+o|J^<5!**1-~+p zQ*0c728~}NPNKOOl_mssIyPIg+Kjg2{iLMQz_Zwf$ zTmXN@yOJ=QghSdpEx%YRmoL_;>2IvngKIl&w)gArri};Dx(ygq57H(Nx1nuozM<)* ze`Kw&|HfKn1j)Jn@z zBuC|R4W~8$^j8q*N7)}7tMPq{>R?{6Lc5=b&JYOvmsTXtUWQ4ZZ&$;z@O|~ux}Mi# zJ25a=DaHEfjEQy%EtTV%d+omZd0~ zbxJE?Pmrk~q7*BL>nKoH)znr6jIet-E>OspVrIW@_m^W>FVcN4j7jINUL?(l@;u?0 zx4J6#S#LYJJ5;%mQBP_D6WH)RhF=DS@=r#Mkz*G~U@e0#7RKxpoNpoy{SHP`W+Mnl zs4|NDz6jQouf6ynWe3|urM4sBB7I$uo7&23dqU%yNsf_uk~+$Hp9fmgs-6CWALN_c z3u%bYuLvleQ@#zl*d+D#_Yo{;v7@%b6UxMZA!Myq#A-&Y)GFykgk4`Q?o-x5#15(J zeW9r`dLus_7nyQk9e}vV7QAqLb~w2-b%C-DWBLmN4KflX^~yjm&olE1Q4BpZ*m@|x zF@kA;BCS0@v5QKRUBg~)ISO&#xUAMd0v5QKh>KOSJSoP2eXa#Irt&LbFGrt!v{2Qf zp0*!XM9lsLZ%OP7nOy=u7yT7FYj+X@iSIBLhR4UlyQ5KSFG9O1M;Y&=&TT2FVwYkX z`Z)>6bMD!Zi(*YzzH0K$O;=Cs!F(R|m0m~|d`JeYiW{E>C%{L;&>b#Lc-j$1kSH;w zrB(|-=VKr)dr5jx%p@3upYJc2`bW_>Q_`Pv^Giy=mzvC}Nfx3iZ{KrsQk>#}9n?DB zTmOzA7s%Zgp03Pj<2%3mVK0Fqzv#}Vx~fz99fBCL)Y}Zaf6p%-iae%=u(h z>3s5#JWDqPuwpJ#0Lxco)YC6jJxzQUzzus8Dnr?<#LTD9h8B3w&F`WeoV$vz_A(b$ zLWW-FI=($(`i218eD2UR4Ah~fQJ!HY>3O!`+|-kVATI{mdi-Vl<;&$D*3WlD{h}|S z4RvZL#776KZ3#+DD2IiOt`3AWkf#ru%Oi|3pnzUF)5NX|@AjnS5WfASaUw5JDj^gq z{$A=gX!dS0zB>ah`HbyiZGg2v(Lw zAa-YJ-e{;>=NvmGh#YTk{d8n^pURNj6I9x=G&P^c`o7@9S%Y9)C7<6WzYWsnu*O)V z4r}2wr-u0hnyw4F?O2CqHp?5|ZiQwwwYS?!yklIA_(&|u$d2k_G~RVkYf3_Vnc%#I z=f$tKHcr)y81`N#GM|PSNXrF*?z9N4poL_CNIqzS8pI-9nsZ>3>vykjG&R8+@MEdD zzD;4oJd#vo%aDmuGZ_fU1AEHXQQ-ZkoCVe(`D9?`DRtL2Z6vakjYc@qDaLj&4om(T zKWrhnD*!57d4`5QiAYYWkZm(PNHhztUh<6FPw62D(6upO6{Nr|TDx8)CcrYkGnq_~ zVg_fHra3>h0^L>zsj9!}Y`@O4U`{HeTbH&j5DJ%sR>e~774RE@#&YeLRH$FuIYM@) z(lVL8-ku3^#Fas|lES~s0alTS8?9yPiMMpr==IK(ZpB`?+3>setNhRyo zJ}yKO_Qh13C=-f@<<*eiMVQoCdr7-TYF5kKx13|$*$oXmi7Te~(l_ml0xI|uMksF% zr2f?w|1QN^+325x&oFljar6}5;7Fo}@k=A39oAo$u8V!AfpGcZ`>aNc5?-)hI5$5i z>(6|h!XHOh5V{wRH+gR*n<;`d*q$#=C&`bBK{TRDyGp`B@6>YSd%zaK$WxVJLFuv7 zMSwoD&1=(*Mc+&&WsLr^t)8^5LjLSg7w8dqz~LXO7MD@3R5l$x{@V2w8>fExEng8w zMG%0Q(#Cm}990>;Im2?4VJhsNe|?@xOr49$>TEg)=XYs3XFS@_H{hxnr$MMJVMJbo zT8Ls)`TQ3tf#I0}{vL)|&neFNx6rHEiRp_Ox8hlsdtsogSgb=v<;_q-F#h|A@D7Xd zDIp_*MIj~)Fza+C%#(p6%C?M%r=?XF4hPsgKr*wzg0iHyC=Rtz20285b|q^~Rs`pK zNGP#MeFFv%+xF_xV96B+q(5h z8yBJ_Ee5qx#jSJno9Y~ISTWh~%+F%uki|k{kf`uTUbE{Wq6q5R(u9kpK)=N!x=#?3b94fa)vt&E+JQb-*#erwR0 z{*!Bv zam%;AO`s5`pm~P>oWMhj8qe!}UV#msH^I;LUpiv?!)*0(W0x5&1QiEqUn$IjRs6B? z_Yu_dK@H?klbsP?HT=co*o{<2Y$o?edK8$$;;<RMb9MDsj1<3aGTaKSnX>Uto1peh2sT$TUyq zosGddQQtDb1wvpT1*IuNr4I{v$<26)kFj_ahKENvFE8WWr&K{16H3YPzBAN#DHy(t zsOfflJKv-2{+!(NiClt-@%DV7{q%42dYhot@%;RXzg^wlR<^pIKK6xmovGXexxbd_ zJep+Y$1i)$-Jfq2ydOC!-IzWYHy=4&FBb?ghKf)qbNpeWXg>Ebw7PE(F1(T5^LRGM zF1Rf_YqXPbiPN1!-~`eR0~Sgk9T)uW9#{HzB3&uU0l%Jxs3Ymu#}GYVy^at!s6*6- z9Z04kzjt^1e5or04t*z7S|0B|s~v+fNe;>vyMxkP+=g&4?l;^HSV*=tIURcwT3h4# z=vlM3a>sGTBw!{bPQzE9;^uxFD5SF>Z|=eE@Vq#8(Xzb;cYE>yfp|MR)i3PKD>-MZ zn5*#`<26b8Fdrv&8;zJi79I7mn;`Wl0jMt@bWD&AR1GXOm}2lX>!$OLE9w{9rwV^a z;`lv}p9e^8IIT2vDP#>k_rE6$=BCfpR^%NH*C=8sRP&VwDPbme4yh&b>BX@>aT4n( zTL-9HGmu%u|3M&ruN5N)QRw_7693$8Z&RkW6EQYU@gWbUmK6MiU3h*qn(86RbDf>J ziPD8E7?=dc8 zT6oDbDPQr>$K$IACifD$1E=f(ErRaVtxtjA`(aql{y9}cscvY+zoV#D(qw%a+*@!3 zTb#Jq7yrlKuu7x8G zJDo;gkqz&3eB1N$XFl*L>k@F4Ptf?@vh#}0BKOG;{Pwfl&IjL< z`$p}K+aw*2%4)gz8b$3+oxS(>$I&GP8*#B1q!5>dBep*DcFWGg^qc?**AfFc~t#>^Qd|SsI=Fl zmIs}1vtFAXgP3SmWum0FTyK-Xy%4u^OfjJk&BU4S}YzRwGajasNB1vsXXY@`Xc|2=!cn-KWf0YMZ8&?+S+5W!jte0+<|w66q} zm<$EO`~*wD9qq>_0k5WXVWLfYN>kMVqlo#pBo(U;@A@`OdOk$;uGl?7f3-d7Ku!pr z1#?ivE}4%RfpG~1x<~#z>U}8Kd32(~jLi3mSw+FKxL;61B96d^{7Ze@MJ*_ojxe0Y zw$?sTcaH?-9IKxLk3SO4guFOQtJhu%(9Zr6sY>>bOd+s4sXG$(BM= zDQ8Q!ifGF7*}ge%*A5)puwRGXoiks{4!S+%$;4*NPd3s!5f%G#e|b5aq+aV1_Ax}R zjkj;8iuju*eR0(c>fu>}xFfX7aM}ZMW#spx$OH()<7N9o;f!`!pGs=IMWUBb7AJ>8 zj3g?J3|^UVwlSjWGvt2rXJTpiNJJduFOcD0B`61yd`D$l>SAtGqgJdS-%LM99h*UwKo`~#i;9`DuO4Z3&QAGDreHa_V4CgMH$4I^JT9f&5?iiJRm#6Wsu=Zh zI|8TD|J0;9{eNLnt=IgsNd+Lf9Pqt3;m4(y0;-RF2??is#87Ehtwl*@>4Mxk_S1Nd0ow{17A)bDf4WS8WdVZz0M%r(@94ARABx zElLlFbmUeE{VImRln0)0Ge^&h(^fKtylef!)}s}WTh)8%<7|q^)VTMJbfF2UA|<(! zGP%)2NsW*xAPNE#&b~<%f`US|m41S8_5!+uB<6YR1mOe$oT@HPyGv4d>&^#&M13nz z4du41s1K%v;r2E4v$p0N>TMyKr1V=7W44zI>OUVEnUgm8Veg%?MeEuyr7HvxljrCT zu?^1@9RkDf(3ExxY+862f^8r{=zhjVHv3$Cyoe>^2J0vO3jf#Ivi{3Wvf zB?_;RCKYS?FR1DZ6+j75OZu9nQ?t2ItJFpyali1A64|U@rNdxPTkwIxu?2l2 zr?q0Yl&d>-ZZscW()NgK+(D(90ry}!r$TICk0cG}B67G4XM&OX7GTU<12maNENxZd zOR+Hh@%f@PD746-Vq}eF^MPH;=3w*S^+-92ICPEaSWvrynE|UtwmZHz6pLuqLBdq^ zt*&K-2nR(#af60*dk4y~d(=F`>cxubj?jD9ocjzGm*;x;yza92mz(v3HN%yPMLjH*Y7aou!^kDD1Ip3xUAKzjwR7kIA)%VhTuDfe3z&+f;Ijpg~ zmSVuawlm;GfXnVLvrtZfR25#Byh~X=>|yi+b_XgZfW-cewF`ZZ5)m0x;;Vg%+ikYt z-%TpKz`cZBbl9tt@cnyIXFz7c2!a3r<+)-gSM$$HnLB%O<_yBF2UJ#Wt4PTR%}^cv zkk}D~jJrTd;tzF8Y6?qq$6e1hN-X0OB=j4y-a24`(SKS)u&G@lK{l@140f7 zh-cO2<7!cjy$M;d)7LVxEa0EucntV~)5K?`;#Je2?O)_xleBZY?cA5L zcXl|UxfdyawNoo!VlYQtSYh2Ehvjb>1RDrV=~uE<8Skz-fWp?xJ0WI4eQbJv(F}S) zZ-Me)H?{JX@dyB^;mT1t2Ac;`>>zFTh@Uq@M5jo0+sFi!aSw+ob*&%pl;68g1HI69 zVvI*|Rs3{>eesNZ`V(@-pJ^ApW;`-_pM-rK26DYcyT%Mp7V(QZ&@nueGpPdE)5Pp z<=+#jeILNl?!_AOe--#~cj=`oo4*HVn23S}+MPkMMMm7l?k7raQP5SlZ>pO}ikH)W zQvG)DSD_NV0dX-26fz0a|c>&xd*Wxp5Gn5(i|m@C#|%&we1I$Jrx!g zi9?F|HCuN4OQUC0%I@EP_v4aJv}-z`bHc7|wCEBbID{Yw9M$#n@aj20#Kft_A^$#+ z&@awMeFAH%41t+@0XZnX9dPe1`cda@TwrHxV5MRk`EOmS?kW+&dXgKA)}DI9oRJK< zF}Ni9cF1))0mfP@U zwqnXtpf1(148DlJ!Hl$pZFI`aqVf6z;$9IFK%X#?eZhP~?5yx`lD!LVaES8^7vq;T zGN7%mCV5x2T~TbN{fA6&tIM(1r5gAEu6Y<^-oAN)?8$f4Tx+UG zzTx*Xf<|&h`zEGg%_(Pf4kt*c2TX+yb67^`ewQ5$3k^|V|LbqlIh(~jdLkL zte)i@zY8|If8F;QN5ETB4UU^B$SkC{#yy+{G`N%32KiXs9+qgjztIJH`XY^T8`;gt zXZp6(y2-O!q3!O{imN{uz`GA-@2|h#hzXt?Vw2x^6d=lINMeuZTcF{Xo;BN)ez=xu z0{81JRu%$QOAfG&%)O;Pl*06f4W#y@Ah}|WpI|OCHXrVE#`w#iCv#VNA;fVg>`-9wHhkR0{LJ8>LeWUL| zL<~ZhyfmUVjv&f_Ff>LPnq2A>b~!JVNIy7b{DwMY)8r~{Q(+xpV^d%HiL(p$7~8K$ z&TkfzOESPetmP@*e%10<^=+>7#H9p+^_=B+n)BU81dhsz@-p9P8|ns@Tp8kepqJcu z_(Y}DCLw?2j=GZQcvvSsrRM8!SB{!FP$Am~_u@>2dwVr~9WHSYNJX(jM?VPzn^dBV zyOWaMV#rt`(%Ng-y)*Z)k~JJ|cnX!EvQn6q%PO+CNo(kLMlKLG!)A-gQY$@R-j$wj zQ$q_Pec2l>H?05h$^TfC(E9 zH&eZhz(9HN`v;h+e(vAFR40&6F9hES&Ic*>`!BLrpAzS^p<5HU_t1e69ENenEi#-e zH-iv8BC+%0%4bmR`a^pqDpm}O;Z@SHs|;dNj@i#~X}>Zi4M%%d%fydLy%eZ0rrKgB z*IZHBOo3h!2DOz21jVZmLkqWxf-WpAF2#>Vq(A{-qNupErz=1GHdhHw*jkq%vSysT zgt1(jc7=5GL6eO06&U!QR37m=Z4}r_CxmMnmzLNF@>nj}^{=L234Yi;Udfg+l^GbF zP_kNATGiRVo0?PJ^`=5)QB8~eQ2fcShW@f}E`DTS~`q`1f?V>*Ea}u(v!E#~D7=+PI z%~|DG^|Im7tB*=S5b8)lCg8;gt$O8@vbMHW6A644i|1X+2vY4SmLg?$i-@v8&VL57 z4_-Ro21CP*4`}GP$_ujMP|aCzYQ&vnji9ABhlfdY1j`SEtjF2f$0BPQoz=rC2bI^- zA{}dCY{QFs^*7g`g0EhrNo@dA$mWB|nmQ%;VyW6Q|2<1}c7887{;w<*f4z|WdG}C6nh_veNLJ#}3)W5P+nA2bLp15u>fLRxRR9;O`D1ey21A|8rFO;&K zsy#bYB7PU}g)=!zku9x(W$K;Z{g#(hHYlP#WN%{TL74Y=0mT)ZtPsEZT;*KLmJBD7 z{zR*J1JcCeJsC>7Ltpvy9FKGSY(0yu!Gt+r6BnjD+cu&E^zt`n%XA zC{C}qT}F8mGwvEU?mq%o_qi6Vc|Y}7?5HDkIJ95HQ@oqjkj%wuEygk2fZMoON5(x- z4q5kf7f2w|S{tj9OR*b~IsOPbbcInMom~~5272QY0doi^(`DM<^$S{A-IpiIvE8N$ z{T;aasu(t@aW=vZkgv}EctY)Evxgip&on-?Nu|N?=xAA^@z?>*)4YP0TMfrk)fmK8 zT>A2=s7<=)XTgwKgn6w0bKq+FzX7gJ-M=o9Ldthjl^rPLK;cP^kO70`iDz{NU2OH) zIf2R|JGCFp`wraJM>^=uJoQ!i)O-bgH^st^Qnpw{t(7O>*E16}Gy&ul=8+ z2;W|m&leE}R>7Fxvd;g}7}ltL5Cc^y*n*s{Oa^%Kp1W7O9EA!!`tQP3q{j@w3)Fbv z8te~}=C`*DMm`xeQqg+X_;$xV_BawxH)Ok}fUq}EhdjQx!N5-XF$}?Zi^`zGtSo^7 z*{phlIjS&kJxQ?HvX=2S?%h0*nXlM700>7|hLfaDG!jt?kr6ij=xfci`d;PEZd&?t z&V+<&``#W(yP%(*UTm`G99LZ8NQ~c=4lD9JQ07Q390O`uWRLJsb$Wbdi>hmQ5c^(= z*pZ71y&ryba=qNjhVPOZ&0Fevk4fdEg!FEWhX&58FyYn&L-8Bbdry>Pc?R@762g~# z%0kajtQ%{-@q2iWH-Y5;}5GX6%(6uy1W%JC;yp~|_3Tb80vBy1k-Jpf?!Z~Mo;6Ta@5tZ%Q z&XkC}xSl=~j02#T=S|KODf2nD8g9FqVlrq?q9@}oJ;I$7SblDmd{O32eL9fFIvA zZHl8LUl!hcF&R$iw3?Q&UFl^@7mA2OM{q&%s%}A&7hWIPcmEpR#&&T3&zEMhF?lG`ng@<a`1<$8bU73;0|7_C#ok#QUC*?O+r(o(^Hjw>6`{o4|sHNYo0K>=w=J8`X2z z7KK8Q{)28sI+~l8s49HK#wi)_jga;H1Q)M-*37&H4?5FGk{$<1|1H3>u2XEXceErt zhK)9f0wd(BOJpW2YKqg2yY1t5h2de4<)2&F_nvveWcefGY`V$uk#$aq`;JxSnUAKy?6B#Oo!gcPM4<6pHMUkr) zL^?{6T{h-R)w+sB@L!+N)tr-fu@G<+NyB1KtCVOE0I3)WUXJ1s>Gu9d-D*6ByR9G> zoF3TfSUVxY;0(!=mx3cW)80MV8u%yv38N!z(RvA^Kf%n-J zjwu*IvKe?<mzwV1|(Ymg=I;p#c8jKcEx#^9^bZr=)hk~ConQchfIkHSCo-U!n`M%YGwogju-BhhbcOSkd>VA=-0~?+-_b zES?dy7)9>;=bg69>~Ttfhr&aijVK(X$Fgb(!G%J|%7=vMQ3q9K7 zGDGrE>&8-E$qPQGU3k54B<*b!cax1?F!Pe4u-4d#!vHln+e#X;SVE1s4B~R%@M$?! z6h3xRN0wu2)2DkHJfpOZz8s=_imm?T6PTRi)&NzuUD#W~4fXEC7V(Ez!Co7Mn-?-a(+69O!jA?j6SlrhDwf9ZVlETS}y`uy{97|2=VaArfDdtN}*? z?qU9r%7-d^_N3SHsKU)8s9#F2i}#?84|qvqW}@!bObrs#>%QJ)Ip?Q-sF*(bb0J;O zg=$Rck$!y&B`qO9AZ4jpQ$UuuXB;{j@|I%fw?MGEsEd`HT4I+4^c;H1s&Y6i8!a>j zmY3ZAjaDmAWL0Bx%fH3vgDBbt{UTF?Q}jF+tfo8hvtsf~GSkn%rIya?#v`VF3Zn0F z=~>J!1V*i0aD0GyMj!j}SFcH)TKK0$s{kenKSY$n^Mf3jLpsT#qiz)6?yc9`EYsJE z@QGNX`kGMRn${0SG?RLO2+sNSAoRtwTJpoWi_fwof^-e2a*;7izZ&`OUp@V>Qiim; zgxXI9yW5U6)rep6(V0;>3lD0UING#+Exg~T3{#x}3P2x^n?hN@s|iZ?8VY_AUOItkCl2;7o-szmV%d;@%*Oqskr_H+MxD;ycMdpjE^cTC(t>(T!5OSYHX#hPnCO{t5gql`30T?2FUp#Krf}6}nAesFQ8_VcS&T4tJmaJpm>r$|8ixhr7RK)9*AE)1 z0Zm4QyraI_6!rt!fWmG?ibsOirB+?s#=eEad)ZH}0*1btBmkGTrrGybgS+#Amp{(okxs6g(IQyw3; zHV6toH7g_cB4kIqZEMzt)ESI2agmgfR7ZmjoLV_v8f*DctyQm`x%s|hGDIT;Q`Zd8 zlFE2<2$D`lZqN%v*RDM2dv7UC*W~zI-)D=LQ$3$A>w49r*uL+*t1a?=?0;z9$ani( zyFHSw95mDFZ2DZk-QqDC*?7L~&i|S2T4iu?g5dSOw()sCsps{1x>@~xOKVDb`bhiX z{CPKsP2}ZT1{B#Zc#^le2qFRqFan034$h47b2PS|&4? zTo0x8S`b^Jrns`aE*LN|P+~_!3|bC7X@?=chwmZ|x+o3f$D!Z~?Mv4upTIDbra@A! ziIC+oh;6HdMoTs$;Mwd=nTK4(Z$K^~%qxAVYOmKCE1e>{hkB8~D!4`Lj7rY~jmCFI zc>rJKA)E%=ODT?)MztxNydtlOsyiO7X!W^rWO$V20fzofoKF#qFS018ngKW&n7tIF zN2DGOT3F(nuz)wQ>xf5_b?}X}6gQrekc6~)59QaMc2Hs=s3Q~50vd_4RaPOzEbXp< z>92yUkil2_oF@K)*m1Eq$KeWqk(?JMe2yqEG8b$)2;U4qp~WUKF=d{qjeg{;oMEvm z<%oW=%vbdc=yTm`6{=fvUgFI{+|fH3tJjW79WwZlq2vSO{e^^AKdUClHTMJSqi>d2 z;3q6ocTm&f1dmua1BsiuI36dBjb97M1)TXP4-#B5Nc^CPA=WPKs5$;ff6D3bp@`uq zV;kz4&=4(4dp1Y#R;w=nV2?VWQ~OIC1#6AWGpd^yLuMVS&ya2rjKm#TfEwHsip&El zl`Ka;Z?`fZ3>3zvw2ORJk}v8E?*blN(2I1|ur0190N@BH7dU2lnxb0V5Yh?~zf+@- zdjv+|dWKTN?JcXsH&NG?^(8Y5l_7kq#KJd-`r7c084NoT8bLnAH`305I@`u9Npvl= zz&hs+%Thz(eksJs!CBPGyspuR4XgDxX#Hj8$;>s?p0r<~${U z2}a0=5~)T)=5$X*2DR98`<`rnnlJC4JA@ZJU7t16^n<)7!Npe-$?Pmz;KSX-_=Qs2 zml?;GPbLwL0a2C+OBQ36jXE|aSS6mKrMBmUXD`3#9yE>F?? zc5$=48@?Lp@G9&M{L3?RM+(8Nc}IG82z%pSV!7iq@pvXikcR@fV`sg=b86uQ54(SQaN8ZyE*Gy71Ku8Tgsx8pMFH!tPd^q zNTGf^{&fpT>JEO$Ir;R6AQ*OnN+GT-J5$`GWIzOvZO2QxcrtMwQrSTC;$uKRE$i?c zVk!pxwW_qzJtm(2Y*YLax@hjEHPWw{;=?x!fstj>^7~;~^it+4QwGEUJUOU92Y-G= z;wZzbLMiQHQEW11TVVCs4Lj*wL26)eB8eu!o7>Xqu$`;?Jt1LG zCEnL%tlwwhEVZ8k#qdd7Yq3`mp5|0B=M+&KZ4^@okp@L6M)7f8`2Ia$CqLNwRf7G5K%da$RS$kFR`U2rCgL7%u@j;4g99 zez56)e8^FziY(VcRw`Y)51`BEx2eZQHi( z4BNI<=l8!|J#O7w-Bou~_XpVHoU_M1Yp=29oX?9ILjXpww5Y=gUT5~6s52WrjQd}s zv3C9^G*&wf8LZRo5zo}2_(y4K> zH1J|Y?s-|wL9u+2W~u4K5zvdBV8IwMZTmOYR(QVfF`NuBV;Q2`l@{bpb&BTKlEW7; zLLm`DlCilpgihIK5>*EMeKewfptcNLHFoY*$hMH{YYB?hs)>zL+-kV<<;BC>#+J*_ z|6uV|!Qk&H!_oJ`)|{t#MO{w`qI5z}PFx;M;?D9k1Skf)Hax08+TV$a? zXYB&3WO{*{32Q{tpE_SiErqmv1jB}`O5@W?OP_UDQv&jLavh?PsCk701OXfFEiHU^ z{-Ca#)i6^en`O2k%;Bt=eA9i~zSE{BRxSVq(l#r9bRQIe7D z!|?)U*67wEM@wOiT&Mz(zxa8r1l-i1(!@!O*v77Bo+xh)cxqd+y_PB5v||;bdG$`? z)nWB&BB>{8G7iBbSgHlG%}%Bwtu=(&WYPue*C$tHBYiHS7tDN^H*mjxa3b2-3?YOj zsy#%3ASE=_4P?|(zzRAONO=|rGhxQ4TrkwhGD?Kwix(MUqp%cN_$_W???mtQkmjj0 z7W}61uYkzV7YhIJD5MrZ=`xPO`JIS*1D2%pnC8c?EOJ8Xt(PBVS4r-o>+cQgS=ddP zhggxy4TRott+vf!v86>J`bD}#QfHI{b8^8z45y~QKPD2HPNiEsD8wQCuQRBpc}eX&b^}SWIsnjWq2*i5m<=Zo zN5acrgO)pKhr;m?kxn20Z@EO_wrMq`lf-Al!Ire#l(9mR-K|YWlKR=jS0NZSR&>e*-aK+GaJS+Fl)d~ zH8kvA6wjK!VmbXf*ljKdyky4{gOWYTInT|a`&99yZ?!ZYC7S%Puy%E?pv@C_LL)X>5l#8T4kaqc;>IWXrO;zTe z#fR!uNko8v^{S^Yvhmq`;aSlDlf3Bb6~qOSDs*7A*x_GUAtQf6HT$RA#uO7BSu?;L zsWWaP#?h%Bv$CbA68-XAM2U(W#jITas1{X<8@Q`Md8GqcYNXS^^lD+SuOD=GSRVn? zD$AwJRzXlAO$n`{9dpe@>(^#>A-8QJPO1nyDzNFotAA!99X^RuYWSux{NH7=xzpz% zzFuU~-~c=x|4vqw2ViAyuUrS%aR^5H(da`IDxq5gX>`eDbotx|W}+7dbZDtZjnJ`# zd{0cT@}u ze8-e8aXXXCY*C84A|I}f4f)S&g@i+!l@)5f_#P56J+CuBC{9#JNJ6n11Jp0U8d)eh$Pukx0;#qRQh6xW2hCnU1MwU zM84HDh=tE+N$tU&WFyEPC>}6mVw@+fPxeOYwvE1?vUx{}^{W*>4fvq(w>9`AF5+oC zwMWX+L8v-pKD{A0m!exS3iLzg2{!`df2^f26p*-<8%rplkF7;A%0+2B?8$(C`TX?O zUHpDY!gw?WL6IZUmFwf_CPocgoA(eif_hV=3uv-&PcHX0JETG>xmms|*J|ds@>8-4 zBAkS8NcTnOH|$qxES!Y>((Yj@r%`GEqpEH1YH=((O(~Fe2%$>-N62!r9h{>oCy0YD3>_VamBUAP!MXpdw-fBlzICW!1okW z_0vo~T0@$WSawmK-Mo}xemRM`pa8~kA(e7Fqnb*Dc2#LZ>;tEB=tpuVTEf|2i^e}v zqzh853tBoAF$$AZ_|!U6eK>qFg+}B^0nk}c#hPeM<h_kB{G84fO+e2q*qR~k|`t!(uSuDsPRMkuA{MZi*ABx%qJ0V-< zq4vaSsnX4;xnJGc+HJ5|(MUWGZlq)UYOI>A|tCDzrDd}SoWnRbK<`QdYDxqO!Ez zze+9_W$s~lov`#J5E~D1Zl|h3G3>7ZDHzDV>PL(IS*at<-eE^aOp_?fTJ*zw20twu zRUzh%;XlqWaEc^A7ThIxm3BHBok0y~cYfD|Qd5?WL_txRF7>6Iqs1=Up!y|L{6Y29T8=kedhM*tA zyM1U;%z{ELvs7^fFOCZig=9&f7U;~2q!uy>K=XdH3)s@G6qx-6P}h16?y~H&G(F&w za=4=Z6Cq0yvJCG{S_@H})wH^UJ|K#@5BWfSQq|F;{H~Oodnsa0%dp&$io1cM+Cw-P zJGF((rIfp@Q0@aP+-+=vb&&r|1o|hqaYVDSd`(5bIqN-933Z8OC4r{&L#81(UOeo) z8RZ2N@0Z77K8%0BX+HBCb3>+ZzB1co@#NaZ zQTMZwD@fl+L*-|BGZw`!A=Gzr!Y!cfb=$=VOqCvAnp)HtQQ0z^IM9>B17Q4M5x4n` z!GAudt;GxrH6|~pe`?Mz#!$o03yv$E6qOvE8k5A9J@p3SX4+z4DvMzG&x_O!Bnfw1 zg|ktFMJx-XlaXT3+@e_6OhB2Q8)Y0RSpRYoyrmO)T!ILNXYmO>k0gQUbsOMqwn7!2 zDu2o1#*(-1V!gqv96Ihc(+KI}-MxqJ)#NTrxeaHup-q0E=Lha09H26y^sUxHna6R? z6|&WAt;ntD&EkfO+OEzjez=bw*IffZJyR!0zv{(=bXCY6%*M`@By2I`=d3x_5T$HT zxq^w(b3HQ726Y(@c{YFJtcr5`fK1su!RCo&EmDUM<@+G7OK;s^yo5vkEHKETAWcQgR(VLs8BW1b2h*pQQM)yV73bN>% z(QBEvV1l;w`-RPKK0PMq3C6%2{!X2H;Y<(k2{_6UqkQ)oJPpy>k06UDU3Z+O!WzNN zKX1yHK8O;KSwNCg%z<`IDXR=8cTY_Jvx)L)!3V8}P7`zh^^xZ^-B_gbJd32K(O2TN zOG%qc`<>^hl0<(~6=6lv(;euK_a3d%{#%$d5D%OJ= zph%V{P9xz^C~2{}IZg-tKI~cQ=1gX+QsoxP-1B~akH31F5H8)UBn=sACs}&X__k5s z1${$k-8TO`O8=)s7N7*3NZP80U}-;Nu#w-)d1j&bhlQdOlv}#Fd$gG{SA_Z{tKCf8 z#TYL=0`4Te`A5O4&rY}jBr+l$?VF*Rq<6;d`Vkg5!-5e-mWboxN(nv=3fL9hKUKH%&SJxv1USkB($rh?2MftA7Dm=Y;+j1Vv(kXMgKo$#z1 zc(BcSUK71&9AJGz$$nKp)kym!K>JZm866h@oWh# zPF>2SY$!Rp(W}2&lvRg%mVS2*?{WEu}l5uElT;c=vZ%go}y3=H`JvM;LdU{f<}=@A_vv=UErDC8M0@_<7N91~NjD{saNLWQ!wm6%zw8Ryh+4JRkDV)G?d>Md!x#Qwi z@SV<1%u`W5wQ{6RQbF*PFl4Mple7{)HWR(jo&nf#i}PRPSV^l{`@fsacg?tx9;s;_ zSMbWRK5USGfy%t3ui@2ZJO5ZQV#AM6`x{Hg3Ha}udc0P48MxlbkeBWLum&lajPFFQ znf11?oq`91Iu@V3Q_pOS%15ZUiNI+lOw>ueNy2*iNQY;W=kU>1Bhl2kxAOPHYJ5>uT?e zlEFZ!io$I2DWRg7b1i|^6{Mh1K1XpI_OeJBCB8x*Wbuh_6bz&5j8$8cQD+14er5vE zX)B@mVED!B+k*K?R7a(BDa5cY!4yuGmjQAe`T~#=D<0O}lKDzk!w9F-lI>ZZ3Pa?! zkU#1Xq0<%2Lxm331p_6dak3&s_D1$3;uZC*_2BTLq_6~U{*<^x>A?qdxf=$yL`AAP z!85e4IX_6Sl$D8weAjbV=591I3KwAjIh1AIoTYmu4`;ka-#$ELxc6|!jqA({Ay#@y zGnLjEw(J(HcmPs3UQ+NguvvhI#$BO{oq9!cuzYlr*{!mPAT1W%wvdE&ip5Vt&A~|G z3;%$@SdraqCexd3oD+83=%@0DwAnc;ldt&8!3!^I^cWN6XcMg z#Sa}Urd>-gL*;Asy#yfmb2_bb6&XSkgQT)*e@>VEEM=Z z?&&HMxllE-Feja0ExejbDR{H5)`?)2E_fLE6;)OPo%9fu_J+bGcVH4SfiJ^A&wzzN zMt;FVjkwE02V+6#k@t^>jeubBz~H)pb`q=z5C;%7a06qU?L48lng zP|JQC`@AcXljmVRWU2j^%#$#sPi-g@I(Fa~4{YkRkw(0QFg!@!62~gicUH;Sq!Mp- z4w?LZ(epHMe3!*o$!>WOUVD=WaJ7=VQhiL_m7vXWkw23@GvXVZ8?masaJ+R%iJpS*fs!jg0X8zr{bd^7#c2v zF~-9cc((Cd6dC?l=Czs?7^YlQ!+Q8Yb{1>MY3>)U5vRYl?tqvtP*HMhi3K@Hpd8x5 z4;xUc97J7C$bxaDedCoAbPpPe9=zQPI+4@~zm5-?J{keAtm^dt9 zi@xaremL#%eRz+}{h5yx$EAYDiZvU}c zMxdGIt?Tr9`TcUe-y`t48G79#v}w!qO4|m!fX!;r*S&w5Z~Hv%y(;kgen(RR3cF6WW`N(0WugyXn?p)V1Y;o(>k#{+>Bpv33A;$D(EKKlzXv@ z19~a^BeEKN1wq2b&EOKF@od`&i=WxJa*a=*kojrsb9uxqwgs|k1?L{&J|khQTo$?< zrz|k)z@qG=Zx8#s*`ZflbYYlh>TEqw^k8p~eqYb?C>4K3I{mH5XZ0~QU>PqQ)0wPB zPoiVLwd+DA%}~dsb$x@G}_u11<8qL4^Q2?esz+8tjn+Ly{>V3yTN zB)obK*bXPjW3o8UAfo{|L^f~76Ssv zsxZj+;(biBsS~^T03q3YE4yQU`-y;Rw<31*Ez=NNs4nk2n0;EG*$T$;EH=Z01 zAmqEiVo|{ZRq$CoO866Z*jr>4$Sr_~6t)j;>@SQ0mbn!<;7m;a+6mN$fS|Njx3$BF zFKY&{V)p+M2W@C7dlSNoD>45p#tKNG&dwa=Vh^F4J)f3R>y0EGJ6X?@oL50E3O8*W zw-#6VSu92(91NbpxkA|k;dQ`VTk@QqCe?JOL??lhvK#-H79_t!@}_?Y6LqL%=K<5N^4C9l5TWmWQE2TJ`lP)gg^Y;W zJ497Ud0wa{pr}HdxTd_04o~GR?wv$n+KElJ9?5l?8= zVITMWz<`$!rwrK5SWEwI%S}Qj?FZV*5@bY3z)iNF^h&Q56XZ#RjGL|jjvV@$!${6z z+ymwencOPeJHR)Aw#)QebMV~Df3ClUXLBp_OLC3m z{H|6!Iy;l0RAd1g4`tWVN~QMyMaPQ%AIFOPf5)*}{tu4TPb~7(twuD`zs$XIJT{^&fmo7CH=HPF6}dV_ zG!nU~l8&A1u(8|%W+^LPAY~V@T;3hw>o7&0F$Qfi@j*7l0~z!p40AZMEG@-Jb?7d} z$kqLwmj|srr3c;?M+nNh`Tc$M_IvI5x6KV=XA2 zR(7I6H&N48+!WlNnRpzFfcY1C@;jOUYk?)1(rd>L2@SkObCeGkl8^>R2%i!ILcHaO zd(4wEQe$Nx9BI5*Aw^953jXi3_Qy)oPrA=&URA75L2xy3)WE%S>?2f3>%9vQS2qo0A2I!>Bdu zE5n>976V!8Gj{XQ=v+sNt#bX8j#)8l`~yd9gN@g9JMhu@d6$!|gauP%GAZ!VM;rR{ zS$Q0_4Qx`W+Lvfi$Pniip}@fcZwhSBf*D-s@G%2{6OAXjD1dqpp9{N(Ik@Y$#6@TK z-^<`>u>4T%0chs+@C5p2HE^I{CCk8mOKi}aNfd-EA@?8%Py|@Y~#qaWO! zqi0qqW#aI&(-FtgQOVfhk9mR--xZ3W;kV(%M(N(>m+Q#J3Vvl zu{9x~G!9vhB_B9$?j4Ef%wGN>tH{ z62E|fjs7AiC4xbd&mQ#y7v#NwXtB>TKz^Jcp(yV?I*eQ>u$@DQ@}n{Bo`PFBXZ2*U zpQ+xZ{hl!IW4-t3_oYY*!-%08YVqe$U}pfr&`9jnY*;Eo`*c8Oj1pH@B*(R?d0rH} zdYgqBwCeu=TII0D`axo&1|+LSqz;Ps%*y$UNi=`cz8~-IZ$pW%zn>dwzC8tgpi?FwNXu5gR0wo>-=^4i{bWDZKowk{#*9eli5b@* zcQ&n~S?9~4-a;%npkp#6uw9?PEL2UNseuknEMH-z9AZ0*7MB2&u&_CZRY&89a&7DA z7IG`udf~iw0;-IecnmJ*aAUz)K^CSU#0mDIZ{c{$cLW?02L51qitM$->qQ_KbnC-L za%TCVk*|*C^V?jTVoWC6B$-qCE7JJKDh%QEXgkBP=?`MNI?9D?Lm)k0%dg7g38u)8 z6mF3F6x&)_8||NE(|aGgUt>m!a+WJgiUpiMi`WWv{Z(PhSm?Z>>!|#DNt|!oBzwy@ zAR0DI}ktF78*ISYyd3U6UO0J%pCE8fObuFo! zeKds?e)4;LU3M#p$2JYGO{=_43}Aj7&HUv3{@4pAJggd)M;kcV$NYX;uHk>b4`s~p zsf!o>&2=tj_e;!?3A+6>LM7h{%n@=~ESeH9H^K6~5oAkc|T%7`dtLt}X zh+%xYl)E0)pTwO2(ExVCVU;lWOw)Dr{|UJA>UvVt>l%4U)F`Xgue$wuS~sySYauHf z2^*k2lLo(7c}i5s-IC=^Z_oGpGme>mkqKg#rM-nw?vJ_4ydzk#wxEA>Ce2adxQT%P zL0j;#JHF;XDT#WI__i21iMgK@hWLrrsiMK^L>st;X z_h{j~#w~AtbF)8P-s7hWTBDt1Smj|GrB7roA5X6Gn3mzIwolREz<0|D$wK?>l#*3i zXj)XB#fS(L!v{s|5~>zBTO%d0Hn|FaAhjD>hc=qpRw*4jWRou+ zmLxOuSs!&9rEN9E`JOB}WO&4Q;XH8goaqc0^-g*P4rz?%Ksc>afhuJ^VZ{55NY-Sr zVDJO=FwHRO5NQ`60jzm^{!s*$o~JHaPqU~he7^87*fR_iCsDLUy=WELDZXhKNoX{1 z84RCiuBZQpuq%tsBNBz7wU$7K>e?o<%;dIrmEc97!S!+6BlnJ^hsic;mqjCuZ(3|a0OA$F#)u2Wl%ap>L0OL$&30%U}8kwIx?ABZjh1*u?mZggQtM@fsJvogWsFyb5gs>X0$i zq4&nLTZ_@$_BJ>A<*_%Kd&Co;Rn-VYM)SX|_K7pX zUX#7<4P+kuUD^<2R-rAIW;=7Uj4Y=@@Wbb%b9~d0=Oyv+lKT*GB=9XoJvef4ww2us zqc*UIWh=o?;AbFj8$s?|^YD$JMv6^yD6Ei8Had=jyqowXg2}8(BkfZ!Itn`GM8g%o zC#!obfUfRv3it=4x3}FUqf}_8@lQjvjug;YB=%am7RttjA>*U@fDLsogx`@9J>QAW#u;%<}TOZKBu7hUbX{YT0;^m>+Pb$v57 zM?*pKXvQOe#{xs`f@z;sM#jnK>fRIGa-R?i6_u}+dEO_&wK)HQ%P1wEDWP^h9>iKV znJu-`a@pHKEqM2VKDAaP_g9z+!ju*N< zX8)PDV*0;%EA`%RZ5sAtnQ@1QO|9wACeDm)QPg*@Ea|om48=MTjEr^qBP>_*>vyR~ zV8cGubX%de$ntq4_%GRB3U9?g)#7u|=8fNbgK!Rpy}KBG;j9>~)Domhc}iRZJ{JDQ z>cSv$-Nv2Bz(p|?x=xKkpP^OgIFj_hpT;XCz^fiGE3I5^0FARS;&JW$l)kFbLic#2i-EOcyJ}%gpwJtF~LdB3QdR{v$sk5wcocd_T;>V4g;E?WEWZdq+>~J|(9sqNu$b2^s!vTSNQS)uK zD2BtMD}~~h%wJKj7=7oB4Z4q=AgyN%P(=yz1-@R-xavD<=`Iv=poaE2T*N&Ux*k)9 zEfS;?A_%(V zJ0*!ovKEWwQQy>y&}DHa#l7W!^)6ajk%b{TBA6xg1%r;4sA{yLV^mEZ?G^puPfURj z#fa^TO1TciGrvWiX33f_RKeO_Ax=^9vV{bFo$~_mc+N)m;4{k-_Mp0Yns5Bb+Rf7OatBEYdte&Qs_t zWe_;l4Z-~2#<*~1^?Z%2Iqqdd@NS=zAV+ofC2PCPtljUCNeE)L2{D&Mgu5EM1-;nD z;k2B%zt1WP+~9xV_)P?%l;%CJ5;oc5a->!O+$o^f=3E`mCgZ|&ukhEo*6LJz%P@Aq z&VXTo{7|8mq{gOu9vj#y3^o+HDu_al7Wrd!7^OqN@6`B3&H10FoA%Hf#)}je`+`c)2G{c?^1vtyOnN+xHO)(55mcCw6tgqqEQ)0 z1>WW)pF5%h`WBCvI(utz3Z`z!Y7FxZ%XyY&CD#xNvi(+TpS|%!bZ=?z%*0h$ZQcG!0lH`;@<%emaf0sp8cp@S`tNaT zShh)ABk=)J9b2{K`_*=!WY?kh*{A3O+>=^szaT!7io{L7JAd3w)pJij*XXJvHd`D0 zvK^UF&D&)i4l6_kksmR7bx@o4ltF=m!6%F>1;s8rm?w`NNHW_tku$5%f&2P1obLuSz6qKxv>Eg1Dj#b)n;EYq#WZ2{vHX>`u$SsV zM;|I1=JQnu79C5zF-`>6=YERm%vF9;$8Lb#3qd%&%#pHlJ$PT7X1N;=-}>W3-;NlQ z@PP4Fi7FlA8c8|>VO+n0*G6M?vg7Ahw67O)`m-vQ7KfqKG&+wvR!7h#5TyZv}ixG#WdR^Q2)$u zJ+*t1Ya=6hqz<)S;}MMmY2lh``^I9$kOCpSKO`$#m}!t~eJA`rpL&)fAT~YUCF>{d z+d~n2w=)`5kCRu_4|>Q2ZyUl{p6H3T#RzrQ?+&MlA+4III*!Mz${gB%(5wP|Ih1AO zF`s>H8)@;}f%6UXe*3vONtERuuI#L?f;Pse2;7>ZhPYlg((8SM&%ea=R|U}mYRr5B zlY@lxelGuUns;m>l@n%hgMGY6rrN~!c=(;L2jRDz;_*Tr>fI9#!{-q)rAqB`UDPaYQ z5PkmX0Qq@PvtG=0a3+WkLoiS5cz{H%n3X6R2Nuqb+2T(;Q=DlWOqqWZIf+DZ6j+vR zfo+|bYG()1bT7x%Hd1@`2fD~YxgRJ?_a`TbNaE9i(}Om<;^3|(^S&y`xWg%^n#7RB z3KF>RSkl21OVV-FXhCTu98-E4KHfFT72vruP=%OL%#9Px^pUEwq0n0PP^3t{mTuWB z+)C!VNHw1^(`>A$_W%2fx}BY0!tA5mwqrD2MP)dl)sUg6P_(}PNpsn>ne1;QqDG` zbVHoj}x7F1#2#1h#^wsqeUbxQMLOV{s!B$ zMJ?wYQwjRiw?@M7C(go%l07nzKXl41c;RugpaM(mAP0|3lwYy~E=5wy#48VUJ!$Xm zkM3YIk{~c#p_vdRHwAhF&{>~9qzrXT89bxgnk^|g7x(yRaXVQ=cE}M3z7Uc~)S_hd z4u_+g$knUA;lzU5n2SY@$5{g=4zvX)>iHc#@jQPZ?vciHI@qhnX@rConoGJ?J#)|l z?5uAoK5Wxlt&3F}l??QR;DzpsQN)>CQbOKmKnmOqF}7AJPMCignQu_`pt&h#7sJi1 z$SYA2U+bE!b=SK^^=`{$uvx%kZ)b2I$y<_1x*Ur@?C(Qu*Bn#y?=pf2>($m2dTP-O z(^bnnEB5U!bDk(Na!=+R`>3Q153$}$UE0cq)bFNJ1pX%t)k_*nypZ2&(DikkOVo2I`$ zOD?hc>_^b~b@h|eUHE-$jj;X{Jdk0HY^BE1+~wq5r4^*BUapy`sXZx} zR#g(oqMaGwv-00$OL6`>LFtjl{2(}r5dh2@IZ9+97ozLfN5s!(7I zNl7Nk6*4IpDj7CJ_sNiZa?3m9t&_aUa?q5pD$(%-mrE1E$RH8hfZdGj9}x+dddR9? z&a7F4tfT^_qUKEgo62hdk|*qe-Djq)jfqGk)&OcAdLAC|%SeW`Nj zJhv`>16(D;m<9P}E{bMXRC|1a=v-bNvg$xvMv}8zlOYN3h~3l`_(sRhA&3fkwg30X3>1EWCKRu(t4<7Z^>l{hvme# zen;{hnr!KBJFVfz8MybN`RlE*E`7&SDl2pc*I@UCVhD#)ph4>}9Ciyjz zq-Gzz!Uc>|DZ?T7PE8>D2Wb(I#(D9LuiS~D;S9^mKm6zd1|f~SQFQD3@SUlYCTD+8 zz#1e(N=23-obJL#korhxxLdShG;pj8*a*nqdfy%HhH+7BElwyNb3}x~Wg|lQH!UTj z@qLrp-JEn7gYMr$#UY{E@g>!6uOGU-%ZLe3&4`|{QH)5|15Ku*TX6O|c6v*Juzx2c z!z@&d^vpJe?CSUXS{ho=`W(OB4&5e9Y=YnYT<-JzsWQbfWYBeXxEtFGJSJxa-)HI`@k90Bt7p(fy!sM8D>RpN zp6!QQfTV6Nu-@jD0 zDv&b(@X9Q9%rI0@CbWN+HoJPlkEv}%qz(BX=xa7^xG0uF)HJayE@8U77TroyjEz_R zf#vO1<<(s+1iR?O#zKu;l3B^W{<|(if^3mUTvNwt`5?dW((t`fPe@oEgD;os5mb+F z>M;+Sg?8pBT^bq>@`2`p4DN-D`+|7e3T@KikwZn41xXL6SbOUbn+mQOg^|xVjuNF} zunZz}`!;_>X+MmE)0cwj=hk6Hq&K;ywrkX#Vu(H)>lP=N#J?A>*a9MX%60_yyyX77 zc%=pque7>;T&J^KIxaN(uMHfBs-W7Y9S-q^I|ltQmd+5B7XpY^&R@ybh)>|ZBR&gx zCR_^ayyNAF3o%7EBo0XW$&rKBfSU4Af8dR{Sa|<-C|8W{DHsf5W!*qJGeDNnJ(YR! zCnDpf+jD4)`;ayDsimm31(N9~=tNBT;;Y3yyNu-%#*KNowd_f}#&4D=YFurBicBt- z*x;wEev>Cd8~MdGYTmDdxBK!dLqxB6;9w3R(i=EY)7vb)|A91v`43L2jMbS1Oui2N zUd`+OMPBtW+(7fOPVe|N&d)nAfHk}lse|(TfFJo6c?I?ld4(il3?Q#m{~@oQ&LP|4 zi>}dqW5OtW5Pw$4dlw(YboC>bq+#w(zmSi})rMlh_$HKh7f%b)w$j4$p+jus(-8cQ z03{GGZC!nsJ+-jBh2g3(+=Hwpd4VP_Pz;FV$^huYjH6`JjoXs>>jU&1hY=++MYqN?TIHx$t?VPRTn$AUk@UF5~SAWo%Tgz(xnfcVaUs zK83~~RCoo{2+|OW5l?9qFX2hPxc_|xrW9-~ZP*--%gZ~tSvpAmni+szE$$$h=f+~% z$fH1nWagDV{R_QnxHTJPSC6l_{0F^yOV{`Zy`ot72fg~G4JlHs6Cx$pJD!}9(Xof+ zgaamj26qHkP+S!VjV)45#~|A9AzoUoJ7O}5{Bf_i_;g(GKp-Ixgs4frR;B4?3VP&1^Mp;osD& zOuuTXcn%S3teH}>e7enLB$t1wSFE8IFT{6sL0+dk?<8L9ZcONjo5bD7e0q@aq}lyq z-2E)Urbe`-DA2+9Gex_rcUg4gFtLYWOT@=YtF$I=x%3l^yVlgu!j8m=KH6gI%xF?X zM$iK@M~Z-LM5@)GYqs|Ykth;57J^HH#Ma>Rik81Nu}4}v+}G5!m9n+&SX8G=S=hT# z(kX-4#x&@19+A%>g35{r6&xuA!bmP{&-&-9OD0~cRpeq5j0~wc7nThI$q~(%5O2}^ z@(X@oRl2F(tlT|+!T@b)ftZ1#)oR#7peR;?+xYgaOmkDZL2s}LyWvN}4(s9x23T~) z=jjWs9a#RK`db`mFeeX{k7VKzl8|k~0OlT~mQ%hEytxRG>S18zeVs+&Q(yX1hrpQd zZu4I&1nehBUaj^}UdZr)zRV{t5qDhBqHp)NqsS=f5fN#_jqHouU%6lG?~B69I5(MFR1Z@^6EyA zhy$rhuEEAJL4Uie#RA7;1$>H-p{Ow9hY|}99}P~4RVR!<((A|m3$hY$sHu-;6&>Z| z(^h4!{sTL3?(MQ@Z5SA4r*Y@XE9iy%-yy3I%56O21he5Qi$qeL%Fq1Y0%h6j<}>og zlFE2vB_))MX16R~?)>VvBZzK{;SxR`UyYs%W2dJj$Cw@F<_a|=Cd-7G0^B^l%wku2 zaQvL#`-qeZUrx_^FIwLN1mkaaA0wOl_viH9tu?^&2pnahW*YEVybyh0c*XE^riTE- zYV==*6}~0WH(GHz&ROoke`D$%qcdsRHc)3`+jGaZZF6Fq6Wh+jwr$(CZBA@WZ0-Ab z_qW&D|NBRGud3?mtE!GOsWc&k1!nDmB=P@eSdEK^!KjdB95AAe2>nBaj!66s+8lf% z>OVK2n9aPAj!S0Qf=_)N!Li#G!4PWxXD2$>v8;|w624w#X>rMy3@Qa~-T9SOZtt(h z;zP8t1j<2S+>fEEgntSh>P6#%YEl(rI^(J)F?h{lcg>faM^CNcdLer4>IOgJz*#jx z>}koIi%}TSQv!KGteaScN+gLCNDsCBL)*;Gep7CXuHL6e6wRp+S9$L_)Wszf`L_`J za}tl%lqa$Ve+FP}pyE~Y(r(ATva;ctwl65XbR4L*m@4?29&`qUpnCZKxo4O#}q5l3HNN^#xxQKcLS+VQhX;=u zM1VOyfCpj2&!EaZ38uaC4+;-!ioro+ekpjz7pD4K&I|m-gAaL$Djant@gH?ma43T> zcDYGbujmYKgGGDNAey^`;CA0fv-SWlEeJ?6b>M}}2_xc$dDG+)w2!{Uf%<8_5KQK6LB{9)YKrqR1=^Mgf%aX)7}>yl)!qS3)IzUI7h&P;3${NZ^Wpj>G{ zqt{W6YRyJ|5fsDKiHm<6qtO1G1j&W`i4>jYnnq*?Q4OwaZ}>;mhdeT60j+2iyaOB! zPpIauH*Acb)D_t&0LmiDCvTAUBnxAoHcw6T@9^^)dSh0ckfi67x2yFAcT2Z94>3+@ z&o9byD)p5rkj%ZEhAi+V2M>)}sfcJaUc%b{6suo7Th3A!He(p$#QyZHlD-;RkefQt zD(QS{3YIcVx5?~AA~h>D+&yEIIa7@XW9#f1q;omZiIN9QhvuM&m^iT3B3Vt3-Kv^& z(_M~d$<2MJH_2Qz*5I6sI*cJ3Y0b0>m&)jnMj#}%1}?jUXtue=MyRylMVYpr)6-Pm zG2twPvJh5r&>C^s_Qd8QyUQuu0n=%bbD1;xCoCXKfLq+{QwKVAxzFsSfjv0(zuqCd;uLz2pE`h*Jdb$DcEInfxi=xwvt z8_RWCvqAGb?Kf5$q-rV9-QsEM#wpw!+z|BDDR3jxA01ZYJ;9zL=Z3?I^kT(F8>NoC0`83c!R?K)% zf!capCX*8VpoHNHlc;&G0vY|YsWo7hCyuNTBq7xp9{Zv;vnbkU6bLZxexBxYR7jFp z12R^^J$!8kTaGF9-%Jr>qT~}*{O%arB>Os-?rbk2=L%5)H@qxKMs0Mi$ z_=?=bPtPe=I+|o_Y=>

*kN4q4Ji3S&q4Z>zO*}$L7Gy%!MDLifnIE1g;(}{qx3u zwAmj;O9@vNcwf;~3LH#Vu~wAATa}W?T`wik;Fw$GCjF&;>L2;jG#l4ur1E~{6v}w_ zRXvG2&r|y+Z*K104!5L~8MCbtV^wFknDfXtIJKx+PDOnieAdL}eJMmdcnBXao3~GNG0q}K+ z9<1$086B3o8=1!Z?7Wi|+9y5K;rxW#L-Z6aTe{UT9_5uuB5=Mam z)g7@14ySRDq%}hE4HD4Er|B4{$;*FEz^;O4Aya=8r|=)mjXS7(gWt*BLhT#CbDoHu zM~-aKz4P+#x8*w~`@jZQ(Tkn2wH&UcPYf$iMTS+9E(17n*ckey#1c?L*Zeyh_}988 zf(CHX$MQH$2CH%DyJP_(X9M2E0Inxmb^PWWi<=anQ{{{zhK<+oFK^%SGzeZYSf#6| zc|9C>Z_^Gco-9F&v@RoLv8cgQ6ZD-~`tTu)m#Xc%1*7IFg_12sroY-^32;fJ^EYG5 z{)LYcok3?BThgzw9Io&3nix<1UMs3vV?h;6sA|T^31U+OiMWSeC{?WkGT+o0Nk7Q5gN$c_^xR} z62W;5N$r)6O%|Twr&2{K;t>tWnRwhV15G(HeWOUG@k&pce^ze8n7FAdpx={V8BnyT z+5QC1$ozAP%4hjGi|gzupZkB56>alF)NK77z5|Gv6{n3`rm=7dc#{fEzvfOtPssje z>ZT|sS)xig1w^{ZAEMNI3YPe|)D2!TrqeOaYOa8AvaG~w1g;IN1TYcoe>kyZwkA+L zi~umi*nmzEYRDp(D);h=gJbH>D(n8w^B72`E~5yJOJg!EkkG<_v9!vnX}(isZ})QR zh+_3p0QxCg*1Bg55v{?whSaUg8BV5gygR4CkedfW*L%n1TV4Zf$egdo|0pY9HY|{` ziWG4LQdY=4w5C`%|3_J^$!(1Hbgy|Tk7-%!{}Rhzf=;9IN*_c_Z2IA8TFmGc{U2pz zvR+yr7z{NK-3_2$;@(?e<%7gC6<4ad)1yo@U2^dBUZyHk83Z(>6DB3ja2y7ilq1Iv z!n?(?Ve216%5^jR`w@dpgnqaNd6=ADfP}oC89or6)ZEQWB(FX5M>t}$L?yr(Uay~a6TN5 z%=s7GfUunJCJs&0es!HpR%4CWKyvevX&Bg^p(_^JBcz7*f0z~TZZAf_hyj=Lj1n3U zvtswj5Dt}t6bRug;l15RH`EOIGE62CKAlYG2?I6Wjl^dvn^CsX z3BMS&IheNRBA+o{Dtp|y%D+E3GL~Xtpff>qe+>XJE4;9YB3~w^IDXPd13C&`5jBBs z$DyI{FI>Il#T9Kt#tDQsqIN^7QvGoGG<#Ays=I(*HKeF2=_Oil2sO7F8-U~6QJL^e zUqJXZ{`RqPpae;D460F(o17Iu=`9{8Tv&Pr_Wy}p)iWnU9yibMo#&udH9KD_ULVOE zRz{}(_I;bKO#1ShFHx@pwbwki0?Ul8DK9c`ZG9fzohB*BL}on|5BPVeNUl86lDXhR zh*j5@Pjn+#z{Y8j;hgrXUa;H=86)#1q zR12zuA;k_K<$sn{;NWl3a2w{lrqX`1{z+oxShOs7C-w4m297#eq8L~UQtD6gCY3+K zBXLI{k93^r=qz<}*L9~!$>*lnv=;`?s>9PHln7l8&_WArWvP_I;xDXqgmI z*rC?uIIv07tPywrLJ5n6{-dm5fs~bj_6XLxurWZ8f^suikl=RyCCae$Z@^!p1Q)67 zLS|GDk|=ANEAtQ;itaCb2;kjD%Q;D&?P4m0PETP zBl;{R9>4EHZrMmpftFR?|12wn82O`}dZ;x!9V^gR@jc0aJ%jnIG}H*3y1md3kU{B~ z<0iLKx8mtDIJj_WweTzlX43F@wNq7S?pX0xsaq7N*>&>%5T7YJbL%1m=JvZ+=+$;0 zW@UE1(2quBJoG=zs;0>pfp;itzuPjLv_3JWEl^#Z*95=ZRSAr%eKsX0ikGb5;MA#y zC{gAi3GT z)QSNr$Rxxmt8+B5pf-{+!A8Ek6EeXSOW@SRi5TXlN(|hWlxidX({DPz+11?|b^|+) zklLJdEdGPjf>Ssl;zv?M+Hzo1u_TBE$YYZ!8BHRb;at!&EhlrSr8&k9Xi*0Ov5ym? zr2gh_hS#^_yo_J|xZ-iXf}E0Pb5IMOj2Ti+*)}L9vZ#QTzx%SolZnX^^z$W3Q4_Gr zF(Py6%?{IO(o=n1WO*VhQaW0rNK(8qdO3gI!;rYV$)dt-$g=g+Ax6#Kgj|*7wlrAk z4^O!UiT}r0{rr!!@?D~Z`xA7Q$8^pPj zme51FmEHn9Bk_rx8_~?anfRCDuMy0SlGI&s9X#=BJW}hO4oba&oE7T-I4c7r9%t&9 zfTtP9TH~FcjWB$pH3j?}HcYbn{@hQWK5d{qEt_K)NF}}>Nrs_7&Wg$=4lHeP9Dy4) z^t^~a{FW^y%h~RcF(ig4m^iZ#5^s!{oGamAQWy)YY^hw=Qw4)z%%yry9gUk*>#<9ZDEA z>JgwvCacKKv#!KM=y8!1xi@>-O~&F1go}@BOy|eHYdJ114tMp1dCUB>CLd@Ohob#bT_9FhIXvgk}L4*Ad{ zYbtlQy2mIc^Ju>Ey_JiBo>f={i2!e42+*@S6lKR*5aaT@-&G94qbq}Z%<5Z659c0@;QfxqRD#E6V;F@DKML+-O6>Tbf3hftG! zWmg-9ZexokApiUomv{o;hQS`Bc>y8{2s@o2vM!K?B&K(WR?5C^+`RyR8W({n+ z3dFR5avc`N*%W9*oezk3gHlo^MmY|!3+TAc?pb}mf1Rn7fWmX9)%S^J#0Ll16x~*t zw@kzhg27L4-iIM(iz!e>gpd50#L0rpHkq91ucLPGgzumSoSN~$$pp^0;j-{(2Ddj% z<`+ia`YpAk4W*v((agyxBd#n=xjh<$0Vh=ehXtg3c$nSzZ9p#5DcEbuOqs|iTwtBr zCsrui^AX1>=Yt^~v)Iub({4#7X;{HjxCzZ1jWVJm4`5*P=jgjkJv#EFwne=%{vK?GYzYEL&lL{-h186_pyK(#57p01PHe3NPV$8N);H$7K+Xy@InAOD#zPB7L^?A@aNy_=Pumby2u7^AO3hiz)eN3WLVs^L zePjIZY>@LLQ;h~kyCxsMdM7!x>TrijOMSt9@v(4ae9&({(`^&s4DvC5Axtk+h+;Mi ziC5HuW6F0yC)74WDvryo31;PE?b2klupT!mE~Av&*qcU2%ApkW_I0g6`8T$o?mkla z)(WuZW*eBM7$##Rn-Vg&cT)`~aqgTf=vW0M>>#z5%w7F`4W`=T@rz}FO=xLEqL_cG zIRPSa3o2o7$J-n&X&R$4j?G0Weq4;9 zn7_0mf2a@=)zcgv&bwuxe&Xah{Liz3l(885qnGrdnd(LQJoNlxds0P$AHS5BTh(cL zXv!A1&&YSD^Rp=J%^b1nhwyXJHib&du|xTBlA==5$|;6(oisSNpD?T=qLZ(hrpg@{)zen_y6Xr`}S`JysYNaAF58b^cPhin=G z6s@9m8dOJlBKIbnSgeh4eonS!Sbg7wo*mw8|UwGAL$q@eFk;EvFU1XXzNP z5z-QRQD&y|G%_&*K{BEPHeFGv5cTdRy_CsXq1a7A?8VWofM_0=q|<=IdZ} z*y(&foUXIG;Q(3Mr<(FHCYSm2#+Q1T%rF-h8&Si%L?pLTWFur2_-e*{kLB_1rG{oi zi$qS~w%#W@X7gE~*XpURd~BNx1|k5u*34mx1HL zKi?QMPUnRm&@DppWpuJ?KOnOkvAj<@2!X1V3Q)De7B*VR7yykOF|gMJAvo*-b&2u%XdBVv`$@yo=j0FVXUPeMa-ek;txfuXB1nKtxBt=C6bH1f#+$$O=;U1q@odo#QnJGB zBCEkAp@~eBK2YWStM2w})S7l`oP`APYLMk_P0JGnJvW6@!MbB&iMpqmo4eVaQ6&w+ zSDW|N^AfV~xnYX*n>6p*rFviGFG!JLAFg=?dN_R@+dB<5&j&hZdp}=1mqguW==454j;{84 zRzZ#Y`Z|5Rjoh02e)D;MZl1mN^~Ni<$n5&ODYd=pVzQ||*8Q4?@`d=F@m~EibEg)I z;mVYjjG4~)vC{S4%Yh;E2eRo%VUyp;`ji(}H-ahtj3ywa+uYN_d#f$=Xw>LM@XNv3 zko#famlxMpfpAQ3K@GNDckAL#z-Q&gzfOu&iW9R{d~fg1uYVu4os*Hh^3T#EBG0=z z0bM(y7R;yp?L$6~_Y$+S-<=xsmcQk`mR%9wYEwq{Y`N63$G#%(IW`R>*44MZCfV9z zzrT!1c|1{~zCj!8gkn1{Wn|KWbw3`39NY|3ef^Sb=V_VF^yyD(6_hu}Q+dNyUwWF~ z75wz2S~-Bo)pVf=WE%KnhqDa1=Ghtr{V_>CwqH)ht7992~*nyh7YFL&Q2j($oU;=&LYi>MIQ)L|%XDhKb7<^jXe@wyZ+Ey&L6oh@E! zed8T1owXm5THautFRmh;FLC{NJu4+PI5uKkr9!wJ#j1_Tx`4ubycD{6E6A1s!$lj7 z${*2h9M~bxiALl}y|02FHC?@x)}^LG(`&5j`i>lT9JBb5Sh zR0!&g|CN@o3XB#fNcd-p|Hk*BO==b<^>EiF$m&Qc*9g5mx{!l{`eRNsB=Fi*ZJn+$ z4b0XQ#BKd8=XN9LDNk~HU0Qu7Uw9{brOO3v7xJ~1=Rk#9!YP76F>k8Md)G~pfoXKr zXOC9X<8r-4*F8=h`e#rqfV7L}n;ecyN@NjtLO+1AbS*H3f9$0ULDtksON&%-dLc<4 zGdJDEmCs}oxJUpKo4^S{ed;m7fFv(VZ9>n2GBS2wjCm!-UkyC8rOx1T4%g>4zQ zT`+4=LM(ef=zLF;gFgz?M<2mS$a8Z2K+9%-eXR7HWf?s7jY3;Jc{@vKTdH!QsZQZt zpS#Y=8pfJV3ZKX+h}cdT!#Ps=!X~3d2h=ORn(P(mTooiY-4b^aMw_cOKbB}f>XTL3 z=XZ9z#4E_|;JTjkyJu0dbFMS_Tn~i;y53yNJHa79hR!0fzb0t8-J`)=L`2j)uU6=+ zBnk7+Gb$_BPAz5Xj)dDL%=22=H3h=J_8+1Is312dN#$J+voeCF{)4Ve`>Z5T=jB5O zQgfmxU1$qc^!PH)S?NGgq-oQJ`v1Nzw}cWHJHoc11Ww`4K$hxF)_2{hZcHr1A#~aX z5z@pE|!PlRR2g;6) z=3Uh21^5TuSSX1}OF{6#rchf2w^eL3*vppNMHI3vHP!cV6P0H_aTbv@n~l6i6O?5FBqV_~q%WnbPKmlVx+^9=vDVHdVCvr-^ z>wbx{(H2GVkl+=%U}SeIcdz_W?O&_H(3y+fR=LCah{yA4J@NG05q&0Bg#8k|G#)Zf zg?ZPIeAEo^HUPkN7Ntnnp1>t!%7Pzw!Pj=v4awUk)OcHnuB5=MZ|m)k|4*5e_2q=J2%FjC8CRbU@KYaG_XO`yYsscQ=^N~A`J z!o$NFz>JKNNwQ@cq;s#iw;zOF^INUBgVi7$tsHkjAyO=IS13Q6Rv zMD!+&`K9JP#JDFb!mbf2V9UcOKclk6SEIgxo!r9vk>2x-Yy~WaF`T4yDW#Oos&q(I zJKtO{cL4ZOBW12cOm<|=EEaHoF8Qt3BAHgJ6?7=>x~ZI`m`QhItDG0LFzcYlJtbFX z{##z?P(~`kYw5Lq*v%~&+D>i>t0v(}=&$A^mAS<5;XIK3ji=OdQHT!>_tPU-d_bXg zm~ul2ug~Qfq+3s#DMDMAA60Ygftj$B%L0lgU53ScE}m?T;SwK%ZYtQ>mD?JPq^2H6 z^-4-4ynXfv_CeZbAt^(cNr^>Mj*UK|()1m!5PUH+!DxsZ(tQDOv7j{2{D0&XDUiIX zq6y7E1(H|GaIw4so~cF8*h=fb^u^z3t?1IXfcm2+G1P{1Si2JVc2Nt#_V(rKsPa5q zxDMERH76!Hi#LVhbY!3Y-xHVtzsjo2lYs?Q6<_nUmSkIDR={7|C#tOEapn^B7~CJl zd}kEwQ~@21@XCXH7_Pb--z^!=EpD+;g}lESs!KjN*}C$6CO{9-4OA$l{5{BX9$e>| zh$=B|g~@R>coOA)T3^iOn{o%Srl|ZQ|6E&U8;!)}4l9-PRWm-10R>zn*vSq%wzd}1 zr&?P*Zod4$@w^*5MfVR`h#4ge3v_)bwzIKgegW)?I|{ZEB_=NA&Jo-^VIgT0yX*ga z-%q99dPnPRA}|UIPqbgPV=lZSBx4=c96qELU=#`x0yV$q)+jK5p z!5q4DSlZ6(FiWW4Re91+Bbc;8ollTuAtPLG2`$4#&U2Wd`2x6rg$oM2I!aeq83^St z9>=U+DOj(sn3nsO4QmD!a%8q8OS!OhM0xhV>ZTy1=Tt!S$^zjgfyS50s;8Ctp{dYYy( z#_T}!N@x>^UhTsr36G-iI79yM6E#MXrP3$>j*+8tLqdJbiheU-TOS55l*eYSWxUE4 zoiD_Jh{YkVvMC(<8l+`8IPnrrP0T1blB_6;S~#{5tQO}($B#%-U;ix`SGL=``W)Nn&}G{`7b@uhXtOO^RHD>V5PPE~=w*4s4UrxQn z*=(MA+V&sO%~Wq^?j|fDtOXua8NftMA$$6j{L~^;x*VKkjEapBJw8-R!XR#KG!_R2 zb1gw8(b2)T!@dxY#x!^}ny}}DcFRN@d(s?*N|+_azj?9`znL&u(*Lyww|`XvJ3oA_ zf)aqR)6Zv>Z@d)T5o~j#G!IdDk`4YHMEE&|X=%vYA{T*=R-FHaFoL>3I1^os=BpL! zF&HysR^mc!SY%r6d?Fz7nmY6(|32362J(pYArC7CWES8N1|3 za&|&g7Ntc3kejEoqA^SPnt`Fe1M**YmzNe^tTv?rU-oy046!PDm4hEgw@1U{I~&SU ze;-PlI#+W$obf&G}bChMm$eeRjv{q*hd`0cvsd$e{hj-_*ReQ7kxj&GgwD&qZBYS+SOD*NB;``#YTtr#e$KC3BrN$&q^rUmK<*bKLJBzYL|h=_%XvVpTw*Z+ zgZHWL#GQbGWBSa~tfFIk!u}4X+X^(w6Y0i=EUC<|(VN>>mA-a69^ijQ^X9`BxX<;c z&(%|7`gr-P>glJp#6_w><%L%0F|(uJqdnvMY@*;f&ElR-K<+}gCYlr`9 z@dU}X2qYMO1jE(+-)8Bmvt0f6w%vBSRMt`Ds8_9z2z+r5I?fR*mW*g+JFS=L{7!4{ z1~WvD$}e~^%h~Tq*7EK712DT~JNJk6tIlWJpxN&G;Z^CJ0& z0Svy*@1wz+^vq=tfByEjxxxF%0~x>7TsivO+3wLEoC409rs}J*Ziif+fBDFCx;qen zTKA_nV}6P&T_^%$LHXHlugUkkX%60!`QfpNg_{;$^&n@&9!KbNfTvu68>*YbG5=!jO^{>SG)pum^@sx7a_J8rmeYmJY` z-QoVn(d%>S>c1@gF3w&~HLHO_t5w@UxMqECk1Hc6j_-qiXNmyPP5fBBtQ^@QFQe#h zjLRP642?<0zvheK9mpcKj?V3F=d-w}Oo})|XX8hmxdJNz&us&12zO>fJ|`MiloFZ` z%deB41aj!xw}9n|_d5j;EhhaIQ#Z-ovT=X5AhD+e_GtECwk1w2qnZhpk_g);owARpe^t;~A20!^w zz+~0E298(MKlHui0dZ(d$tRZbAAT(qkX-Y|BSPgpT3xw0M71)A-eOMoW>}*PIf=rQ zDc+a1U+b^K0=Bt1yqR~Z8E&`AjZg`ZcTOfqRq8mRi&w~lecC2y1T#M+Jq-`E3kY9Y zsCxG4t|YeR+&^v~4Qa*BKluxmThYTW-|eW}{GkuN-#!zu?*H}Edd`1;U-^C5*LOaR zpS`-R;>T+`e^|Rs<1fecba1|+?3{0GLB(EF0@OkaG4F>M${>%gRC{|1LO< z2yZts;#GETI`S2lAM8HL96Vwtzx2&8!yh{PfkcD3^AXino0djH{`+w6i^1z;1AVmq z@UwP6iy>}S=%7bGhm#vcLzo>Up^9y7)c4*x%7C<9JP)MlX&9%~wP;^hIS19T|Bj!3IniD@RhV@a&9| z!{*hZPGpkU%>>JWOih_d^mL5+(#km%G9ty0co5R|nK1f3M$c?>5YkEO=*6C)l;(8|*B4_C;Nn7Ol->8#JKxG7|8*A#u%6SWpgRCZ;@$)A|vzzf-4naM5K3XaZB3e7* zUzWX^jTE*u122ec9d*hCTT+@=p(T&#Yt#Nox3XP)E(&3K2-nWG>SgJBe|U3a-Lk~h zau4g2q{)nfwd7x}5+EV%0N_t*21*Pa)gveRujt}ai}f&lBgAFyfoI1aXEPoKG7wo4 zJhd&XBvaAmgVcQNtBXY_`*s(Cd@@pc7(2DpE$Du!K!_WJHT!7&SQwGDa*~lj(lxiT za8EwVf#hSK>RCfQXl}Z2aw{r^Yv+~qH=n=@tzD~-5@cVWDPxoMEvyH zLde>#Wfi9O(@dgyybz7atkV_2M7rX)(;Fw=j8Y{~4qJPqDbi=tjMOM#%rQn2+23iz zf7#wUuJt{euflR%w|`7{8*SXte)kZH(XX-#^0@jk;Ol)9wCy$>Eo|p_J_$~3*n2(- zWg5y@p>h0K%rr>|;z2RNw<1yP=yf!@EH^P*O^h*b{JG5B^=Agn?l%o89d)P6(RxQa zpmKJlvFpyZGo0|vR#%g7Q2vg*v7Htxy_(zM>#}uwbY17Zv!i%K+--S-F#TU8pyY~| z4@4{sbL&VZrvWK)cv;rO(?!MX;jfaCO75i;X=`1A6e$h1GwL`Q%LZuz)bf^1_3hsigey_lOK=Zu)w^qMA;k@$N9bkyNLk0z^o0*Uek2h%yO5EaT(;0 z1&PdN5J(6`S;sa9Q!~s{0|~IJ6O}zcb4mk0*ZN4JjklxsW4~k$Obs?f%-ceu%7`}%pPs-a7Xoua%|35*c^?YZ7qqta0z z;ztmn9kNggdL40*Uo=jcFvZpQt{%bdg!+m`mJ0&eK#U)hPC8Rm zJ~YaT95u)!4lkaDuC>N2xwjr>GUAo1D*{<~^CVKU@(74>Cl3kfUO}9$zBM^p2?woq zgo~7{oYanJ1SY(8T+7*4@7RFW3r?1pEjleM>xYy6jlgR)C@ktD;=RI;+L%^veH~+% z3p3rQ6AvyWX)KNK2AL=5Z@O(Gn&UO%5vMQ*zV`Na3TLR@?$Une4AL|=FZqvskY=bB zf-sU1vz^bI-Q-3Eev)qLd&xI7Ri8R(Kl#+2wE^M^tJ$qu+j0{O(;@6b5C`nkWv2G1anDDzRK9+(SGbsv!N2;wh_Mzpu z)hsD8c&GHH+a7}5PFHb$ojo$h0I2fWNF@NU_Cs~@pc{b@M06&H2+srj(Pd;QA_V96 znwEoB@PAcBQ(}4UggBc7-8?K)LxwGy)EsaXToV?2LofTWl{8J7m46R=2z1B~$oyN> zg|a3qEY-FO5;tMRS1^*PdW2IfzqvIPa;~2pkGa%VCJ~M=PBG9=MNb|eR1kC7GLY39#tb@$t~`II%6J^o<_UR8na44TFZ3fgPs7k z9J=~ro9a62~yM7Fu$wg9CWoAK{8r04jI+aLU zsA_7I^@!r@P+5AIjq8k5U3w^Q_pNQjF|4O8A(s3h*X4;;yGl` zz1SgmxRZ8K@;ecOl&_wOa~(Z~*VhW61%Cn@F1=v`YK7Enm<++hZL22U*v^1Bw|DgL z9=Ey-DJ<|;VSHZf;olhU_QjE%(C8hILGKPDvhH!x&4AwXP%q5@Z#+O9nP?~8?L($% z7SW^{oB95NVw3tZk2I4#$y}!u4hD`U_XOp&>Xsr}-zjoD2HtDMZ!cztEo*t$J^h^C zoejRs+^_fZ!&Aq&_8|fT6ODCEh=(XX$w4D`p}Vv?p+ACrU%t2aZco?1pVVHT_v~SE zHJ-X#TBr#$TqfK*VDwiV&Heb!QDSc^|2k*$IJ^RAXv(e(W>}z(f5i9e{ocVS^8p&m zd+WErOQ-i|=j)qWPfJ^U({rT_Z1i;Sl&C^Fh<)0-eNObFi^QINf?T}k%e-OV6&ekD z`tQ!r&RVeU8$2In&*BRbMi%+18^lhY3gp0j?t9z;S}d?aC<|Uc7VPJjkp!_)U>*7?0VlQ8@&t{{?N}nKaR6Sej&3Gu!s)!szKKYb>SF5L$LmZBY zE#;$BSf7<;0o4BxI=}>`9vI-><13SY-MZ$`1r+WV;eE9|Th2D=`MKOI?tNVhjt;l_ zZuz{vWNsA}ik;1f?RaQ;Aixpp|>OR$Q*vv$qnzk zQNs-`Xy8{f`7yz6)rl_MbmwhH65=89hOTEYX&;AGmdi9;UInjZxz!dQB&XaL%xSi% zU3)@+)yuoJEx;|{b?4wK9=T01=c{OD|9W|UwEQ}HccQW|_D$D5R~L>c`pb%t^`1yw znh^C-(MmJNJ>3_<5{)oZEPZyCZ+vZHVXUJ<@j2;Q)PvY>OqT?Mu(hZ_?Esskh=KG_ zCw@qrKP^YK(#66K+w_h?mQeX;<+53i!5PjCuLV1kre5KacYX2lZBP3|&zIGdQ_D&N z@wZXx=H%#|ma!NJ(}E!FfdBCn=?~n>nYz9g&FM=FFMc(sA4iPC4|6;^xitAOk(`to z>ZoT(pghsR{pZM36tj`*@>0O`+2z4AFzECg`(O;Jh#+mQKh!bRm=egC_yWfWZ6gyA z^)cnChf+E3DChiB1&oc-@DF$He%@TuzvDe!o*c+Wa!Bjaq*{oH?i_u@Cz|elPeaLA zEP5))x?xFl_;U4y0~v6YmTh1%^he63TIrX}W2l)u#wdPi!-o}K>~8_;7|z#L_%F?k zl4Kfz8PgC`%^00~?VPi@I{h4^?mIeeM>sQZolJxXo95;P%&Y929Pa^)+}wY90M(H{ zG<<+?3Z>dNt6Qf`oLpq&5*@(^pCBQQa^{qZ){^p7e>C*l#F0~N{`_LGWJq~Ar!4Wd zj3SoAzFz}jcjCZx6ceCXw$D|VP=2rP#i0MMmuu~v;cxih*629xm@t8682pgk)~y?I zvuJtdQno@5ns^cKKlBB&(J{WsTlVdsSgUH^dOfRwZnN1Mfh{>Ql8^PqrZlh9Dzhz> zUCju`Y=@XGvF$yEy^)gAw`b`Cq{ahZey78(|!`e`B^N45xHPeeN4# zFYr1BJ{XPJ?5dm0h^vtwPHDIO8E4`hYBuRnCDutA*G&!Sb$FbxFzFPeThjT#Hv3ED z%GT+!o{Tn3F0!s(ti~A{p)(C}ppL4Hh5jj&DnHIHv}H@GI8e)ySsM|GtTx^cTZmb3C#@!`mGpwPPzf%OyMcuJY&dm&IQ%qI(h2;tJV`Uy zMofdhA8VdyJXke7DOK2WzVzHp3+V$@WH1G8qbakS?e@#fWrGWnu8(>uDWjhSUK;q- zPOAMCUN##@Tvs@sJ=nWDp6AJDfP>aVPD(z*L;cCM>M0FUHe{r^C}6_STS~B&CPNxK zybuw=w0>E1z1-KMHI_hLux!*V_2YOnU*}ZV<7ESFU!;TDW!hO2iWRZ?^ee}nbZ3+1 zWVj=ejP*e)Y1_kfR>W6AU3dpbeiL~&ud?&LcWT94c!lZUcI1)^PJW3+_t`o{! zgFM9N3&3+xSzTazjyoPTV~!4u?@QdPss~1n4cio;{k9wc15}!#f(%J3)O0)DG1ADS z{R5HVvkJ0R`d|>!l0K{u3xX*)8X$DB*4X(!$Oa_Eq#q1$lWv&gPbE+D7g26By_zgd zVICuhPAS>*@kE*kVRJEAllt5#IUq@`3hXRAO;e%`M9?o8(f|iS=jcX+=_hK{;~O_> z@S%=?9Aw2M=nZOp4H19aOo_r=@!VA;t*g3CGOcn}XEH-SJ)NA7>;2`|+kv(@&j1X= zh~IpqBK5AcR1-5O8!5kP`$MMvQLjN?={OeBh)9IO-S~T}eY)!t!%;3lK${Ym(+4=a zA`gadd1S7f>2;R(9(SqF`LV97ol7WJ6X^HdQhu(r+dnpAv)Nw9x4iQxr#0VbY|~@D zWx4*>X&ffm;_nNtc4p9zv<3=?_pdTmjm{r0PYP^~a+(2RyqJ^B=Q?d~PJeDo?(r?& z>sW$4=h2SpO*SLkNRwa4AUF%F*(_bnx=|^@rU54_)UJ zrAe@D>#}Xzw#_cvw%KLdwr%4t+wQWvY}-1$&$w^*?5E6;IY!1ytcaE0nz80I-9q6L z`zk2U_}{V_GjWn+>7@+z(;Kuf1^?If&~D^8hMGJc!!2AveXIQ=tej^hfHGd6)MF2c zTJ85Di--g|#dHHEIUVG4ovv-r^;~bdrtP|5ot?!dy?y%mUTE4u2hrK4MG24|%NT*6QF^;0`>2uW@ zzQj@BDpUn!7ZcJK*+V|RD~pqqj@~H=k`IJoL}6$@D)Y>X?HrX>1wK4itO>_CkqF$i z3Ay8bNY>r43=j0g5W2*JZ>Cr*L4Ci!dZR}fx!P}NJkurX&I)t2;bZuNb;s`QS=+WT zMiLnq$=I*FM4AKxg@2Ko6s<(zAk5?Q(gz7XvcgG?wz9VA$=SwLpv#UV2RDYLVVi_e zn1#m*cSPKi+OBFvWve;v_H5_wZ4Htfx}GP;eVHAOp}M6v#a{S^Ep@`vXewRqtFVHm z#sdQLZrx=~8RH7z+d0(td{%WwA`;mZhhvNv&h40r zoOPJ_rFtd3j>!lO;{>|X88i4{bKloGj2MdTrlA8pgt}_ez_p;Km_O7!UD`Eu6kZryeKs5jYW^x{nD2dei1hTpugdh(O|82M=VyX~6U^~|9~*^?CX zb?+NewK({lSItB1Uwn_-HZg^CtZr!f)@+$n$i83X(ARWtix|v7J&D$J&BuVwX-;s5 z{6wfVMFlxTUNpg4q)rw35&qb@#*kBIKh18mIVPUDFNSs$aS8b-d=9)^&o_tYSDuOlGbVo;af*K8n;fKw3C&97w&ooL;+Ko_qpwOKTfkLXhP z@;Gq0`XuIJlU=iFWSPBj9YH(6sQEj|AY91Ar?SxW5cPEr%@avd_-8qtR}#c;!j}jP z{+;LyAV7n{gdI8)-018fqCKR>?Lz$K^ot(k9!*7OY(e_+0mS;NzyYWYB9N4_mR&bj z3zDt;4g2w4yVCde0kt?CPTamCN=;*`$*m)G19Br))0CYk5-IMl6?l>9p4KB=*-YZ! zXN`oqLigEjYvxP`@D3g!Snd||?v0hqA&!91ebsuV%d-;R5q4V0njL1_ zyV^n}Jg;u=#gdPa!>a}AI!z*Kx+#p4Td2+<{R1r?*){YrJ6rX1KC#o9)b3-7`-Dy` z55w_I`BL4&wnuGaV0U6fr9&|a;)%c-Raj@ZE>%@m@Vu77RJ>4w7}amI zA0XBswnDQa>k=@ub2zIH%`f-$1_WrX2W4w`LwIroC|@c`%|4u?_w?A!)POjPj&}@K zQdL@n&D3g%-p=geUvjqj1?WSF)kQ=SDaULw*~O+VWrZy9o$AzuLEkM2;s>whm9@7p z%FuAY+-q9Yu*h>+UbD&|_CZb?8ws$ z^3mIx#uGGQ(VN5>^lm;c`}?1>Bv0E5Cni~ovWLwE>~A$LO;_c$HD6^CAzZ(W+?p*o z7`{e{uF^@93Vbm2Wf1DoGk8&LO0=@RTUT89DqO-|1z0LyPIRsjK(t9gxSq{r>tK$* z2wV(Gx^g4{8$<@w0*6o(BBDT}hGH_j=TO0Dr!NPgX>IyCo5SVX{-f+TXzjGXCrv#I z`(aTpX>8hOGg+o==5ioV)HRRnv@ydzy=+y_D4Gn0fceFZH7dY9cMN1+L(p4_b{rc* z!3bt?B(`F60rALK8Yz%;pFI+muf``$T1jW}=jYH%{QM#Bk%128R4YfUK0${h*Q?XZ z+qOyQ&~^9c(elF=CZp;Y>YLTx*ur(mS+KG{=j*YK-`Q0H;TZ;1LsQY`awq@AeK6vf zf1P7Tx2PI-i+TO&^u6)R(Lf%1GTmhsVX9X8V;XYN31|3B55|>o)~v6n+CR^0Zh$(O zpgNXtCA4;YwdZNyA4d6Ovlnd7>-Wkj#cIBPGCAJ)wXdM8&C@GK?flIBqnn<~-J#Fd z&spXJ-@RD1XdOHbVcD0GJsWA!ujod1q{dHceY8busgTUJA%_pm9r5)1C_fF0?0CS@ zij#xN>Lh`A(w0n#K@W0TA@`g`YZS*nZ*idx)nA2_t>p8+Mv|*3Kf*~2H`j$Gfi-I% zP(c*_^fY0u*b?ZN>_EJ>=2*$?*g>M=X1`h4&5tW}GAoQxjkMY495%Y3Ns9fx?O@X^ z)I9j9=~SJ3#;~JpJN@PPXf?%Teb=LqFMk$GO!imj!y=vXMo<_2xKOk-AjTL?S0J?Zm@f_!A_MB_U4!dMCT zZRSp{UMVwNLiMJaIARIbaUfA*xIL}JPHVnO;Y&v6;^;&>n7?3pc$`Ba4BO@Th0%T_&B&`!m2|s@ofvp$Q9~*1FE`sNuJ} zDIu)~m*9(}+!F(EzLi+$rGhMcnb}&6*nBMGL~4Hv1{4ibRa24^6#m(N(Xgy$!9hgm zfle5v|H*OWKRVk+eZafUgipLk*E}Lti>+J#mvpGnmDxfi4M&RqmWWE*Q}4}h0<8i~ zRD6?_3(ot!aFoojzg04oZ~sD!5wxZ;L)R6#t?1mTx-yf>eQsa;%cuO>fw&qD){HkQ)MmbpldqiFMIOTypjg@3oDXSwvE}=@tEeHFk zNwS$q$klYIMa4>~E^ap^i4r-@*UNtU4QlL9L30U5HsN2yT{iC`zwN-4M z2aQA03L2tQQ+4c~tT^n8g)VBcBhnKD&-HPL1uDz<8X3F*!bvb$~ zC#DDFc*?LF3;{`*zwHdChHcN=H#b?fq}KioXO2L{Eqq&==p{vG4oBr+Uf9baZbQ4e zok8(oLHM{8i}cr~V#Mb|-Vd`Zkw(w=KU`CQ4Et(fGnZ1>)}nff#+AS9sm9OiW2b4e z3_*EEr_D|MtYF{rSI6Z*c+$?qhHK`$-gedKX?>s?CcRN$7K|XH{5OmDi5Bl1AC}Z# zKlZ-!j=0XsBHfewp^5UT1s3XiC4bMS*SGELp4C}IKd&z?0OC@*I(?_LQ%-{Bg@%z2 zUWZW?btD(jg6hu28d6_o&+o|!(-N1WYTev^+hrc|=+=JZTDZ%LSog3HLM4P4|6r;H z=Fh0a+tpd?Qf3NzMiKWrD>5Wvo2&C9*ZWevSMCv;1#;u-4Wn`k%Yp zx3u6!dNRntrd3mXc892ARpe<4=yGW-ltkf@tp3m>T0V2G9+7d)D3Nj5iigTF#e7|y zWMqhjh^0|YoPO!Kf;pjV>O#6AloVeuroM#}(;jFH`q9?u7{3#(l#xFP8`9dv0I9hu zxe?P&or=o_oC#TU_u+87sKiU*SwH|7^V3O}E~)7p-1U zu};xu%}u0a4LzM_w!ey9%qff=!*%+`JO0QJyIANg%p-ItvfMTY5x=j4j7pSv&b4YR znJ{(h-Vb9rGrGcrTI{M8GmaYkTuYM*kkY;%-r>6qb2 zyzo`3e`U*cO3hbqMK#$ZlmkGBuETJ5oTYFR#`50)JAtS8(-C4~U5y1Gp1ZP)le8>r zpU!in*|rA7e8<=*yoEc(h?qW=o|651Wfej1L`yh5vrQtO+sNx1+dp)F>hk*deIX)8 z2`90Cpanl2Z`y|ZuloG{8f|E!aA|^m1N0e~N(;hr!lmKHnOm|@JI)R^s4|{1Ok+Mo zgvuTK?WopgPc$B?ahyI@Cziuey1vwMXxYhwzQUs)X7gzr>-bF1qae6Y4vHdKpPWl3 zhVY%RVZE?at!3z{83$dI%lfl!VQzl;T@-sb#N=`+p7i!*`2Q0d<$fHzjr?5a<#h|% z=%)djny4*W4e_u9X!}u)*AWkR)4S zsPxLT9G4Z6o}OEMi+$v=i%L$&YGWk8it8n-Ru7f!;UZnd?G+36OAbh0*#Qb7a0H^H zGZMmnGvP(&*4ZM~vD_-z)T|ZVX6%x3`aE85B@WkWkBgdNeR$4Mu;EL@uf^nD^CyQs zxVj$~8t--9%|icKXDE!&rc71-Ja$Bw6U(pLM#@=?Fj|O=$ka4$$NVEjXKRV?D8G*D zBJ#VHlI`T|IpkP%Z7t;Zk(?j9>3!p4FRpJ<}q=EH+RU;sTh7Tt||XPVzDjM%-hr9{`o@=MqPBZ;4I_!+Mv;g3D)ey zhu!eSKKCKW{2;-BLir;cDUWFq)`D!3m*FvqZ5v6^(8;OnjTr#!FIPdZ9;`1lxux0G zhBIxm=0X#a5iR`}l^ zkBqmslv@R}nBpiw%howW*1s-@?tDGB{6R`O@Lxj_Kcs1<)R#xs+KIm?!G|a3TF_FtNF8 z>U;}7ACao`EjHyIZ54r8!_IjuO$(8LC>Qj_c(2J5C65{N2TzV^VVgqKHY0AiH$L~w z*@wlG>b8^o*|@e-(YNcZiFu-TQQGrus6F_({AJpKeMPJ%RLe7>CuZ#B;s`gJp||LI zu&$lc*?WsKj2a;q0AV)^~w0;J2r zGTLDO_TQD)QYNP@DRy#rUBl{i3Nvk)P4tDPeMfwRMDNnS7RO>Cm{6w|8FJn{ouu-w zHBQE&%U}wmhcXQFppUKcF#|iQNUHzcHQ5a-VuS9CKj8k}0(+2UiYJb*j4-9C?AFS# z7^)dXoqlLQ@zuYz?dKCuQYce#O`~`#5ti^$NFbkM zKc-E$Tb2?)zH;W&YgIFQn|rRvuwm5_c!{|kGksgL`fy8Auz_?4d3cOx-{Z5-IdQAV z4xh`XUN5I8sJ?`lfMm3-vUpfbZo{P9z_j;3An+BR5J0Vc;4vghz7)N2FEyy)qfD03 z)pWD_27;_L0E1P`PwTU4ir-3;r2I%>;R}bOY;6`Twi*klewqUf&U2l^5TaAlO#uI)+Qd7AGG0?nv1SqEYYVeSe5b=(r;@mu@}-jgOQB&F z>_aziTH{7UKN6MPS-vjsl8}K};W}lGI|C|L=Fc1P2EODE*Oi8wZCMkqX0+HFup-cx zhsW!&q3+WvPe)F&RzD+;J(x>=x#ziuDpls2e#!%H%s5O`3A|k_CA}5c@odu^>;lv_ z;Vb2CB7;CDu`1O|Ar{EW?Zjd9g4l~LF|IzLL^Zu_V~N>cLAZqX1t@T7YhsqDm2JrB zdnSoNk-HeNYNnz)>3-4C!&S~o!$OZVM`({sLeomfrtr6Jo~%2H7B>bf`>6 z5M|d&giVY^pVLNVbbsabPZDrNswVt&QJ{iQp0J#KzW8wPlR@|BGWfGUn+ z?YN8!7)4UL){0S0-YO)}2CV>0l{^;P)j6X{builgCcdaHakjA%&(;N$5a)Ixc4(I_ z$-7B9P$aOUUbnJNsjnMWZ{Xt|yS5IWYhcnoSluqE z)pNG-jvs0kZy|?C?Jv&qz*-p*SY8;_Y$bZaA!COMMBR+$gX_zp-os^6mb;!&%)|{B zYsw_~Sc2wJ*tGJDoN?AH(k^xF-j*jFKS5oVgL?PL;GfbkSJjgo(Y8XEoe}Zl@ z+CWGVAY7WKZ#4&f*-+CkT432ccpAQ<%btm!yxv&rEL=tuO|5Fcxz=a|V=^`L4l{s| z?$uMdg$zx*d+|0l!bqe~i78nQ`(XBv8XD4_WuQ;bU@0oUBd-Qq4j1ost8Z1w!`zPR zqoINBu4;PX%{pm)dLnBjheqLP{c_m+?vJ2nxj+|VbT|_MLR%4^;aszQwk%g8$w?heD+;HZAS@jOeqazX@VulH4}QJMSxs;)B3f6 zr>hq3?u+ndHZJ<%`E*<`Z+50xv3GYMzH9b{pnBa+|NH*@?K>JX9+y$cPrE$=AnWX- zfhW1?nu16N@8yGR|IsqwK;raeMhX=Y$dgF%0!ge|c3XMlTA`ut`Bu%khD?2q-pGQq ziTWYUq;IiL49(8f_{X>AdVeF>RfQ;Ad~tUYZw9HWNsoVr2FUfG%kfbm$1_mD$ZD5# z2+9g|&K$or)@`l?94^%K4ATZqpeA4^T8V(ZG(x7Qs>HKhd^3Vvu60f!~^ys3x6Fz(blTrsth|$ zbQeE05_32&r{j(AbyZs(}5$y4H?`W?IqXqjMdpWW@H9D86 zrk<3kPHn5h_j$cnVhwFUmSyh7yzg)pxCoy0Aj&tC_h9XNSM1gr(f4_nd0yFGyppW% z+gy%rmV3MFvc!HI0jtw-z`o1g~}&cxl~RrJ?E(b^s_I~u~D zf$+ET5y2m&&*uMC&yskAfVWezQ!0uVA0G~qD;3ycl=M<%E3zn%behrns#J5Mn2^(B zNNWHgYqM$o@*=hR(z1q_suV2z9PX5j#&l6k8X@S6!^vQRSK+UwH)x`h=qo#&rn`Gn ziHK3=hfA59uD}m;!_<@1h9X42C_vt(Z(JfZTPZ&_RhWbCH`XK%1tg77efBq-j1tEE z=$X?M1sOlbQ{+}7;H`2Bd+ zI7lPLgI?rgR%fdyL@k+elb(Mo>tMrL$*z{Nv#q)hy}h6(WjB5$ z3%+%`RvCrwbcwcW(5zAxFx;pj&OFoZeV$#x#kHKsRPW?YV%sq9en^Q&cyfli*dX9L zim%0^mM9!lyp8u{{CHl1*)ya|*~7c)KJ)Rkg}W`)+r6LL{dw{O3hdy>gRB?>xD>_hu`~Y~2*SON-!aTDWL=&2D}v$uI0O z-X1)Cg@i+x$R}5J z_3Ji$V%a^?;h5>HoVF!cCOO#= znN-ZocCS3RblHX%j^(+CZ-gsKGbd5l&2hVLNRz{|qsqn~ce>2sZ;F^jYG z?$Evk$di*Z!`5ziGVd6PHdogO(1z|}eM<^CrK5qDx};M>4%|!cbi}<*YrgoDv0$5K_?d`X z>#e7U#+^8QIhVcW4QCf2hdyDB?QRWbbvoy*di{Bw<{JWISYy}Y`R?nf+AM$f*?YeK zU(EUYJ727!b8oQOcUaS}?#U~`IyH2yp}%t- zsIwfjvbOg5dt$xdZmJt?C7!UGvpj`aA^M z8NB-=Hy8x0i@0IyFt{*Z#EqOn2l;A*12m{3!Iz@^p>!I3!lzal~jg7xdkA!x~(2)Hp~a4Aqh)3IJ7GXS9=+VEFrECxb7?ifdF z3jaEtgVdj$@Nn5rq!vs4*h2Z6%?m>uEZCyBW*mZi~BqJ~-{Xb%~kfm~!U=1kVhX z5K|jo?0CGAedWEinCUxR{?G?7!IIIdrkq_rVNtl!Up~% zWw6HUP$!b6rf(Tf@Ule4$TLZ0I!>6}xb)F&GAU-W97~WV_FE5~&*eQ&&NTP#33P@E zK5PzLtd5m$1@G)?y|{7i%cnr)Q4IjLD&=}7ZX?su0!9o+#m4&lVYkGEbs>h4_r(&-&xY87rbeV`z6>x?FKl$$0WAmT{MDE3>q zxIj`g68E5{Wds$wOE!s&VT_z07Q_3w!-HaCmWbpl%&8;{@f~rbY)z^HW}z$4H_F&b zAB!iQM`b}#K-Ko(LlApbT5@1|1Li?k_mFRyH8e5oU;=zBd~B1{?(WWqlvC*JTZ;a< zw%DMLAy1<_Q`lC4>uI-_D3Z%e2dy#{vHW7Fvca}KfLa$cG#p^T;=qn1ZL|R1gdM}pKsX^{e&1WuH{=sy zVc27IX7EW#-!#I_YkdeJj94PIw4^y6#{2LjK^J>$bw=>j8Wj$NO$e)ejlB9wdcf)3 z>SEmdST3%V;2>uCo(z6tGRgqM!$IqTmt(56BN}^C$x%zpShK9$vl|ctMVm(zAz>!2 zFT9nkb*I4dWf2s^P-IF4w z1A|Pa#z$``Rwj3`gK<^Nd<*E)iv2!RrJpVYU@*RbNQw2wU!k1xvF8pdeU4i z{#e~f6oE?PL7xvc#>Db9D`am)1!J&`Ws;6CrhtRv7!-LGe1B!&UI7)s7L{;ggEs8x46wxc%lQ3s)E!}$iH zDHQ1f3jw?G0*YPBK|Iukf?kHLAtH%4bP)nc)rYedcdoQGoTj~TGRODy_*KyVZxx&f zLzT8Thx7h(_3xLR!&D5s{zd02s?rQ^MlAv(Z`p-AsnQDci{#4AV! zjZTfa6R_(jMNt*ZoxWo@P+)XSx5X+gj6)sGeDfg{e>6Kt7c;1+h>|dW6aRFZM;VHT1GiYEV0E>r0b!ex1<>~6GE;C=w13$gY|74j6P{I_ z4A|T8(FBNR>T~=uh$~u#W^j9JX#OvjN9Agm+CF&!#bkVAe9&v)H%2P!J!Zw?6YL$k z5~7zyfFTwNTnqpd2W^oUG0}QsqeRMa;#XgoHK2~&PDN2LkK9EJG0CdIxs^^L@Kz#> z!q=X^4042)c>%5fUJ146CO167HeWY=8)v#>u|4HNixC-FAS?VoqjJM6?jFla#M zaI8qBBAOy8Oc37Cn)x#+IU7+4(XJr?yNwMg2?O5N3J45boGpbM^1|Y#Q3MFX^Q(fn z%oy;g%4N`hm%QeHBr1gOd1VnxH5mkPZsCCkBe z#sI`VZ-IrWGfbGUTQ~415jlS?N7No8C_zFIfT9r&?)sTg29^+@H^JCM{zj+*qJ|jn z7{;3pD%?{eBHV&_0$@hpRv`LslP^8EG%M(kc;h~T!2vP!iL7Yey~6b0N6r*T@2S(B zO_pNb@fp%&$vILJ`4ANZV)39ICFX53&n@uZ&yioJp?kV4)4B*N5}s6Tp3TVF_Z-6< zj2PbD@o^frq}xaTv2uM0lC(qkTIWU&l@LwpZ>`wkRK|*jBL~A$$_rq@81_50=E~`C zGqQ$~DYk{|5YGZ_BOzGF`=b(#K(r=FQyL4G;xcNkysHqYj*eDFt0!?} z&?b%h<%vVyt!?b)?+PbV)dDdTu!y{awTZmNXv)w1D+lA*)$Z6`{Z>D4PRC3G%ipT^ zyw6$0zY&HsDVujGlcq)NFra@(#KAf3WxN%{Nrb^rZfbg8uu@dX&{>oU$vzJi_pu-x zrWuU?Rv~0~(?o|+-qS__TiN>H0brgU&m#j0hRAIljo{((DWCJQBc|X#F9vKJ+OneD zn|$i$w^ic|BISsIm^+>2wmS@tXcVoeUNM|SGvtRrp{#t7rS>kyl`e% zl-K5L6?(qhU%v3NwIw^%LAd@zWoJ*6WUaERNS?*TGjv+;kBJ`Y@AT-{uK>(KxMR-B zFts+k-2a}JX$-}$pT^+mJG*BJwEaxQ6L_|9ZW(xuQTD{PNiuReQgBTDA+z@~ z$h+5U#H#e3N|84E#gBOUt%%x}vWhm6se6s11UXKG5s*voi9sbHw?2urp3o zAMP5N0dJ!2zx!i@!}tyIf1xQYy&IOfe{VS8{yUmt`45@`s4F>aFd_Nn1AdUK5Ys4P z$x;$pNmTJ8YEeq@=jyy&u3#Ip))Mh8y9@+*1Cb>L%Thxi4t{L3#R=Yf;jBUV` znFl}*Tk%YRDT7#gq2^d%1#?L*ihjQJZg8sM4ux*vJj&>NW2%9~wbJr7TS<_~G+R(4 zN)$<^wZ+IN9WiKfIBt&z%Y zWFnl(hSZQ{)Z*Oglx2y8D#5^=!7FyM#ks&+zT4`;fbSF7{pDI#F{#t2n?_@X=)7ZF z#3}iWox1gA_Q*ea&R-yq##YFL+F}HWF1GO++-n4%Yj?0`ivId++)rK`1kxAL?Ko}S zk7_2M1hT^@#@#uE*Enw6VwZzBtX?EB8n4A$p)~_YfK9fE((bc@j0N|!=TH{lBB*<) zM{^lk7#>ymvek;ze{X?0j))f4W=Cxucxd6dcOB_El>S;Mg6ez*&VsTjG5BB^9i3V! z@E$)tQX{!pIuQ&IG`R=N@eiB{4G$gy2*1La{1aR;3kGIh&EH2&!!!l(4S(OCSlXH_ zIzgU_Fs5D zXD7}H+L=!uN`xp{V%@SHyoKw+|3Vf-+2c=xtM6K>HNSNE;y7a))LbkV^7V4=9-unW zT&!4Q?UQh>Ia^{Pd%swLGLftHinoXdWa8O)ExR*ay~ZA%YP_85IKX-PHrtEdTAgS{Hwv;Zi}~oV+_R;4H2%{xm=F|D z53d@7|5gf7BiM#2%E&i@C9$S6^PO__}1P~Fn#k{a`WBg;e>GYAtO~N94tLR#@q?Z9F&)S zYJbvID@lZal~NL#JjParlDI>rRVO8&OETy0m3L2X_88PAjJNpgTnW&$XIsdz(*&M~ zJNifj*(|sFlvMW%Lns}CXFHuZc(ScVO#~{|8aOzF3*z&PYsM&e!+9S&KK!M7tE=QZ z!X6iDJ>UGPqGJL8P>Vf?lolS7f15H!H6`zW+?_JkmVH5Nn%RQ2_5xLJdy$X9A@7a`+^Hi7#Fal<7VilWkn^U=)2 z)vU7ZZ`TGE_8rWAyngk>t z#2Vk|#G>cLw)rek+Rj^g*O)(}zh(mV2B<~sTil6`hAlsTnpTYaVj>^p-!Gg=ZCR(P z&2c$g3~ZXI*TxNK_$1Id?!$N?^5hhz5HYwY&Gu!myQf|${TX@*}l*DUA@hRb+bMgmkoZ?KF306CsEnK%2pG)#ME3qWUb@=4y3W$d8L)R zevh>~g{2Cj*%<4wgfkKdtARoae$D z#xDeN{E33&ZNLV*9 z6e4<`C6a1_;;zeYTrbXM00P5G<@AaExc7bRI6?L_m-Df%^n)9*iN#rwf?7^vgfNH# zk|vxmu`Rx4^Sw~%$ZlaJ$Q7yK&?Uqpl&Patrcj(WI|88t~rZ83l`!UCm4oGA=3cs7uA@8xmt9V#JWoYIc{vOrq7=6TK_dyZz*inP4`` zCdL^eKy)DgayI;wxXkrl8gI*b3K4klA;0T}$M~xM(n$%MY0bInk`+KpG^J{P>bL98 zH}=evTZj7!Kg=GzGsz@Dyl`0Gx{jpw_ARNQV+pRx>HJiZh^hj9)_I_i z+TsHh{vHgW*ZyVpaMOmqS$5^I^;TX z3$OxDH@C(RS)k_ii_)e-D(b<|pNy@hEE;iSCni|yp3 z+!nq6s5@Wo-7Agp~@uoaIC_^B6eQy>y^NB|Wt3J=I zo@<39tvC0JL&tjh&Dw23)W5ELat@SND`$>5E+_smw~_X3abd+uPxbouA3k^Wob`xF z^A)bGs{({^f-O3NS1nrJt8b5eZ{@svNF)fQ#(ZgfszL5dPx;wQ z36rS(STi8?>T*-5PkU|}BJXH_nC$!LeqW3GxIkoVntsanT4>@Sr?o;MTf~{$q7(Zv zCfo4kA?LSdKI>lJwBHB-|G`&$v5tuJAda&hG8qNQZ3hp&eB$KWk}Wu7gTA*`2DQP1 zSnj_5yNFF|Fz4DeX&Us6@x~kkhdxbfO#2u37fQBbbOukUU9s_E1~q=TgqZeN6pzie zTx4D9@I>Yic7%y_xH{>rJK6;m8ptgkcTgz@QjGeZe1HX-(KJ}5Zjo=dVvz0#7Mn&6 zbs?s4Y`{#?TxYoJDpfX-W_3a=ec9$fSDg2yRMRg=nAhRkzGG2|n(LP~pc_wXUDRwl@{W=}7byKhe( zF*>pStMc#D)&hkJ>C-5}oj$?R;BuD^O@teyxa3EQOoboI)shjdEUhAey=Jy(OP_rA z`o-Dp*}`I<{GSsHkUPhXzN%h2?oUw`uk>y59sm{wyP@#jpVrnnlzT;10*&}owQqKt(G6Gm@o zM%INn+JdV#fg`5TJ93@?VMZ~bBF775X^ zHkZv@K`oV}-CUbg^>!@8#@xEzvPG!{>CIw@870VCBfSDf++Iq}d~@Z?P%H3&DC(P| z$(3ytFJQZ`5p4cvoGn^h*%=gs)Ai67YO()e?=6Gd?AnDpGc(7`%*@P=nPO&UX0~N! zikaClQ_K)^%rP@FGgo;I^gI3DGo4P`nNHh3x^HRpOEVg+z4qFdIttzAL38+7S!0?& zg=j27R=S`^#Ph+m(3~sDeu z779Rz#8v|tHA@-Vw%4TX652FpNx(8&0!1}3Riqt~qitoYtHzyVsLJ}BXd!weKqgs7 z=``Y4Vgj#pHdnSxcpfh_(VWt@4X2Ik-HsUBeo)~)=SN*3nO_PXLoH$p)6MfWwPoaK zaVc8r6!AcoI>gxU6XAi6Wz{B4ffvKFfYxocmFaek{dxw=bvjYsdnlUb_9IdYsw?VC z=({7ERrdFNLOj0yD~XjQA`=xnE(C@QNhsZ8B>)uP2!>39BYO-2$fBF~#U4!lBtUsMr|Y_z3*BCf>DEiE+MVZbO3oQCFY%^^wio*mn`s z^-)9<66~+hUmqG`ts3Pyx>p(ZpVe`RDxG6-^XMvQyUrH-G}=kyYo2xro5U0tyh7Dt z`V{5LS^wN>%dRHJVkfsv>I<9rD~eA(Q#B^}o6lhfPx`94rZO(Q*@T3Ln}c_ThrfRwl>*}1m7{Zm?( zqg@j09`>A5MbC7hiug}8rYIyF8a*$GQ5RaS<1gVWEARsD-=7D>cQ-2GP8St;FzdpW z8WE9X{%{ip;Gv?sHL8FbA~9t@Qpc9KCQXfm7L`rd&|~7C)I)tgbjC&1sgaP(R7>bt z@=gkwFDsSMcknSBsEOypS+W1Lq|{=YF4I-nVviv&P8H+h?hqIlEWlhoG&x;c%5DF9}6A8%$+Zj<60H@jLDxNJ8Kc0i%HBo_CxKAYheR z=lJQUuhzLJ6}jkahQUd8+e1Ay}MTT+kypp@h0=D6jeIUiQ(OS`ZoNiXyto4x|DP!-$Y{Pt)S!Lj}fT- zs;B{5VqvZkq^RM2CucdBMtEu`xJSGzxpEuj#ou&4u;^~|*CIX(82lrp@g=tB!{E#t zQrrU-h`ZE~TOxn;{9J5Ci7X;V#r*2@oZM~;j1Q!~@+7r^qJd%yxh}FS%#H1Wn<5tq z^6w9O?1C1#zn0Ub^ENVlRtapU8&Vi^F0P-ZoHi^^cTqn?g0KD&4S8tef#>=9OiapJrXSkb`tl3sX(WFJop8QhX$OK509c()7k!nH5 z0I|KSe;qfDh89*60kg+;2oMnB|BM?QjV#Pum<*iFY+acC-v5&~GX8zqnIb3miy0&A zG5E8<)M0km6(hrylk~U75E07kD*F<@^v>3s50juFoSj~|-hsaJ}Me8bVFG0bLwM2SKBOMlQ`0Q+wBtI9wW}jdY@=gq&a}xk9r}J#t-sP9* z252%;H$r-QUhEiYPlPBh5`$1Mjf3a3Fge8881_c7aT)HWqX2#%*AJ~#x16-At-UJH zEK2(CoJX<2q}0;cN@EC3+P;%ECqGDSaf`GOi;4}~d16-QnK|XGQmTwFQ)c!vzqm2CyH;nmq1!rCiI2*O$3Ud3N8c|M4 zP&hx&_5C{DY;;(W2@_zEQKJ z@sES6ZD;{6SC2hiQa<;jlg6M!hx3Fh*w}7eYk0Ahu&zZXdi60bPj(t9Un&cnk@1EqMYIt=tq(4JO2SAQfU67sUB4>i*>!zdzBMZzWY#+Z{>L=JguNh`a5AhT zi|%SVqLxEFLWCgFp*z?VTdKJ|lsHi{=tRw7Tld-kI?CWFc<05>?#;6BK^;=g1|@4OP!L zi~dw&&~o8WOa|jnBiDn+A5BA)V-=&SyHkpDU4K`9yZR{IAWOrK4;lL9a1s=2F*HaQXmVopikk zz+SjZ&796k;353hA~?A)6yL6#wAuKF;bU?Zjt)j3>?J?)^-Aw`wNDvt)Go{zjCF(icArY+y z;^SqEXTPYO;k8!`ObO4m1MNo|T5T#C1gb|GxEt7If@-&(Lgv^kjNn7N=#V%6qz&Or zpe%n0Se-YU;D(xt>fA^Zvp6~|i~$J@qOtA#skF(s`z2FY|DuTfCoTF{>gwR{2Eg?R zuIqL)@jgv51^L(Ti_xDW!XK}%Js-E1n@3CXTafVl_NsK-yQGtc;Z9;=4%5S`kHuU^ zy4(WPClajNwT`{P$Qo8jPL3BDr}f;}4T&isd*17aT1cZ-)pxXOoPTgC-pO48Mwc;2x zp0j%%mMNn7#Et;1O+7~B+t#qdU7=hh0XPrk{PN2BMPAv%&09=64Q+8INP`B$ySd*M z7w$Pw`BNMzoLL@PzV8_&1!>!RK?Jw>H1K?odPkr{GfRlZ+MPC_jTsq&F~-o z_$8V;g{`Y`)3K(wRG&EePLo;Lsi%+n*3$YW6p7N8l@NYDJ^@jOuQWG~j@2vW;S6s5+H8%tps-X( zI)Epsq7UlE+FiwGr+1{V=tl$pj2__+1wPYOsL|B&dBN<}T5V)2RQ#(^i@#!-c;L?P zvP6CopAR1YpZ` zbq$82($pzFKSzDiBxx8k_hmb&|q?Zx$uVr^?}t+v@{7wruSq0eiO*uFO}L= zp@UkL%=PlUMLVOn8zD+h&HVw^6fFqlJw-xs1w&C7mKG-t~l5-;I&1PB#Rt z7(yNs7K*t%W{0HvZOhgZ@Q}28?TlqW5OXT?b;*Sjtqj;*`Josy)zDLh65yJ4byAa^ zvNYgTCsz0|&?n>uFy%GfmLtgL9k(bNFL9F2p%eFbgNQ1FYL;qNinp254fc3`B^7q* zi8?gAT`#_cWYK4h&gj`c29L6&ok<2B4eMs2ST%ro1m&{E?mBp2amGL7PxIa}cXj)0 zS~j+E$=tD>%}h~SGv{^xMDQRk4R2#y9{4VG}i z21ptoT#=@ki6_=rCl&QKbLqKZjLsJ+sqm{W+UbPYIB7IWC7s$dA>5HK)>;?rhysNF#KD<;^HC_*0|$EsqpmM!vNi}>0r99%)Io$ zo973bc5qhN#EG;Y4H%Zz+5W3 z$SH2K8E~;Q(apfcm>}2^#KC#;%?MM?dI2f6)p+a?JpMQ18eZz?`5PJcHW?k}$g5Kk zR-W~Zd>M~!IFDIt{G~&P&7z);-d|~3gx?wsn1oGNX6uR~Dl%+SQL&cwPS&i_HM0H1 z(}-oy>>O6XS6+5CqMyNayGOF^m@OIFHYxiO0$gVa){(bei6Nsvsi5huD28F|MmfKV zA?mGi{HT-h?_g3HA(f{OIB`h%{xgibBWjMl0_&+rI(s>Z8rl>kA@KI)`i@V=%ZYVW zaL!wEwO?|Df6inyi!lCvY)*{s%L~Pf91QA4kB4lag(U3sNs6$bOd-E5wX(_302>>j z_PS@%k;|}<;rk+;ICrO;=r3p<6;}U13L%XMbx_^d=24_E48C5V%g-Doc`~h5kpuT?^WKZD=iN0u%mIryvWOd(AiV6Me9Wf8d zZxfL~($wSsZ%Ff>3gk>@*?F}Sv-|SvW>Arj8sSg|FFF2LzeJQj;UOW7Cfl!@z)|YQlr&XMBahH0d}hQH z&u!m}pKSviy->#|g)6O76qPjgMnASVE1-J(o^JCtin_dW>Cs?c{(>fO1f};+E_@9W z&)7OIE3MbTO6GVAn{^F(yO3$eiE}#I5H;oQj8)F>s1FTHpY_!JOv%ZW@VQUDn z42YY`h%B(Wne9N_JkACW@Ee;g{EM4hsX*KmNyIeUwE99-+@y^^chXU_&sQop03C0l z?FZc=uX$}5xaIV<>T)ReREoq6pK!S8W%4%!8Sr}HW(9ma%k5$giX29?auK`!g`8K~ z+*|LK1Mo5zpJtppv0-r4n~#cEz2+{RU)0`v3a$qkzB{o2esg(|QJ z;M@2;8atz~h1o?Jv!c$yV~jPuL^&gJxyQ)g+pA(E58|9K6;anK2a0AS8jN+diM&Li zynm8+W3^$`9Tgswk+MWypg*C%}BN$+wXyioj zd&ZciKQ~?hN$aeV85K_$D#2jEy2CEMX30T(V9Q!*I8WwvuA4f=7IooN^L`GED;sJ9zX z&1Kg?;n0pYi)Uu}#Kpw!p zqP!y7R1clZLu!$nL%jP_3d}b4~6J?H+ z33sQ2kJpuL1F7y=7mBzKkt_S_bKXcD;PKl6-ypsLid|qhVsgvU|tWO|Cp9Vhhf1*$?*cU zG*?UFxyV+z@@Yb{5EIhcoLRx}y9ubxX)C|YIfN6M!@fuZ=~QOas{<+?8Eh3r2T5y3 zGBY8P=aCv@2P)c`(HZjB5G2HX;xV)l+aKgW@bm|QXK|@rMhGNr<&E0d89vgr4ALglDCUs&$2F%jSh1qM$k{6-0I)bnurA*6cJ*27rxvu zSe@HxGYDdxS>PsZzGynyvc)0Fr|Tgy@_)&!8p}nMYB;e0Y;*JKMl@vYNiZ_b?0+`u zb{4pS>6R2CD|W*{HkyCKP}FP;nRXQwYr%xRknEGEUS8xkXz3b>XP3(elbmc0**nx^{kf**CL3OkHn_S0!_bGLGT0$ z2&F^+KqV;VSul{}Yf79{i(*gMhT%z1+abkUsF$^~yAL z%P#UT{c&7r-HB@Vx$G7l%6`f-*M(Kbs^wxq8*`IVSwdGFw+2;Q$!xs9S`^YgJm@Sl zk&Lg@%sTPVGmU^l!qlTI4`CK!@DO;esepkZx{7>!);dmzegKm+lB^dBRHjXVNWObu z~nM18j3d+Ij&hRY5Ai7ZT21b_UK zE{44`lnU{)y#t?>={tjfFXjcZfFlal4?(dvH#^dgLn9PFt>#aJX`-SG^s(Q@~jas=ZXM2 zXw?7Iq#joGrVbu1f6EtJRXt$Fh2aORmwU7F08Yfhr1>XFj9Ea{QIRGunyI@(zR)Y# zlHBy^zv#=M^%&fC=)ZLMw6=FpQj?9Ynkkn^y5l`!RG6Z}_&~#(xn73D!?iq&JPL^Z z!Ea-s>_qt+;4ncVfxa`PgzRVL8^BBxB@>AMoz^u9X^7n=#?8x+W8Qv3j-q+(OKS>8 zS_c8s7eOa(JVk!iK8}6hIgKih^#&ubgNx$IikTXHa_BignVA8Dj z=UR)#atd82|EajL@ol z&8Q&Jsbe^BfA6`ZIx$+IuWr3OD8;BtdQf!~(g+qD9D@$&1-tfPLKqA_{4lmWMN z$SFG1(;F&91o$D;Ap%?8Elv^)^wrY=nb^K%ZmlfPX6IzH1PW@Gq$~3tZoRo)@UcrR zR=Extyq*969im4;txc^)BG-N|2O|&z? z;WsNhd?k?nQDZ#uBQxizQUj0@83QNENw9t7v~U~Q(N#KtHQ-X>$y$i7OQ5JeK-BBY z=B;BcFE%!Nao)O*OVhU-L#csVbX@muYZh9;q2twiL3w(0NX}^`Y}4Sft(C90%!Ysb z2$%}NIw~Af8I;EAE3>v)#Aa72?RS=aQ(a2&p|NA$;|P;!qF|h1*1l5f|2o#uEmau> z?oWStW?%#^E86?LqsQe_SFv)!r`@ zU*bweE*{q|jvj{e%T{s*kiu~JF-u@x_gOP!Kp#)io&TZ16U zS7czgu1!m=gzb#CV8MrUr(*%<1lmN`bge1O-kOPxv2q>|dKM)8qx z<`VMD)hKCNpcC-U9V^T&1hM=0fIZN&ps~tv&>t8w{a*NcbHT|~U#zm(VK5N~Q2j?4 z?_`Q^;-v5GqzhtI=0Yn#X0@RTDADti@b1*WnZVvljboB5gS9Au#g;;0m8Gr*JqH?j zC>!pUlX7%WkO`w_GRz52rg*BbJb~&UI<*NBq7k&FT|GQawLJ%X@>{XJLEwCUX)}S% zk374R)OsA2V7+^I$%f-n8CgENBsc>o0UgbJJ66dpg+T+Ox^Kb97{}G5u2g21JNz*< z>0Zh&<=-`-L<#4il8V2bKo`WAbksInjQ7`# z`E~V}3RVFsa(*FLIah-1Gs-Lxx4^MRTb1o}d9kq_3ST(_lT9+Qo*mM z?3P@)$mVU@)m{nG!8_NzrNeM^TDCeLWe_d;F{n7DZ6q0_c7Ev;Ka5ap3)C6PXvxAB z&}Gt4y7VV4r|n11k4aH1kJ1c^T~CWG5VRMoLs#Uh!Vc$37lxXyTW}jHMd~ZU3kz3C zY&mT8n)rn<2v#4#1{Y1ogH#cm8^GE+>E%h%Oee1O-EyC9*swmlcFfJLJMp?k9+B8! z;l0Q->b6@exlFnHgKwfzM7?;QAG9OH&h3GN&oun$9s33=8Zd0zYR5RrLofrl+EhIv zG!yQgR+f>EijO?y_}05_bXF=l;Dz*7g24CfYly!@Wiuv=s}Y^OmJ$Lo3!_@VhMzNy z#|w+Xf~Y&9O10A9hTqL|{735FBK|hsr&A zV(g?h%IK}C>E|QZ&Rmb(*$F@B5Ti2yX)my>gzFqHg}waYS&3Nd6*yavMMo2NKAO1< zmrp|)6;h73NS^N15{eT%#yWQWYRoNSviSx|cyGfyf>m`Q>t-CX%~N9+;vpReyRh3o zGH<8)2XlZ6W1d++v+4)*ONw&X33LCcT6@_!n0V;9_c`V_x)ir*nn8gkw7BxcBIP%{ zrZ~*E8ba5eEuJ@r%lef*bM1<1mqSMcXZkouufw?aNhKk&Z!f;VY z9vKbXmjp}qCl?2yCK2w1d~&>Tn+}0P)byEXvxec&l6`5jL0T{ZoH zg@^5bedY`RPRsoSghb;14if*Z*~bGK_mOJ>^=D{|4Wk`FwbE8c*#@^%YM%XJRM@0% zK_K9P4b2tr5o&@|sXe1|AEW{yA#A^t3gxwJsCGiwLA*#WQHStb(c#z?OtyJ*eJ5{6@x;jHC?DaV7^9bS^04~BWy1>{j!R3U zLp&UykIF%%s|0n${SkG+nSW~fJpGe<3`l{@Rw83-7ktSi5Cj7%c*F9ZmeTT|m7U_i z6C)xI6i9zVt~Q!{@A7*~chO;YHK<&W`73YajUNep;trT_)Q;{yES_ScT5i*qqIae6*MMBLKN)L(P z5->U96B$1n-3R+^ND*v_1_=4wHf*v)u;(eE&yUN1_oCbmSWhwV+*V%fjj3H*cQh_` z=Hv~7pV+^P6CK^MHE&IS8*G1v64Wml4F*5d?;u1x#DbOOail8n=z?FHi1d*ic=lqE zNpM6BI3PxJP{7%WmP#Q-%Es1b{_RVTHbMam_*NegQj5ImD?JdbpX%UV;1)n{%zgk8L#rr?i$lX_gnHg?G8y2y2f0XHMfvs+!}5^-oF!?S}IpfISnwgX@<8cOnQojU89VH@xi#zqp)Qj zaMLT)ZgA6OB>iK@Yn?J`>hyP=b@tsQ4!3t%38Gd-vo+bn<8scSospfS7nxH1cy3Gg7Y)tvM@XThIBv^5s*r5!zwp3 ztn>sk`&~eBwpGdCK@v9q!`>t*@6S1xVROBe-SEnhMV2=vy=07`=6i6WZM#+Gj6#-q z|6#!q4sDbC5X@S|8yy0c9CHq9)_mwi@tIzB_{@C+brneJ?TYY7(U9;gg4{cCij(c5 z#KJr0?Pe^ye0{gP7Pr4Gia82dzygy8*%^q2xEBV?{h`>9q8x4;iXxJp~&4lq|^#(ygdL>vHsss(J%Ruz#I+hMzY#)z(LP}+A$PzACo35%J$~I86|vW zUF8pa_1m|d;AmB|iX}&b6dNUIx(|QHvI~@2;^XU*Mxtq%nd?mV7oYvbra4z^|Mn(u z=&^TQ5mpQyJ<7;(o+V^@vM5*eWPHrHTeo>-a?N;AnQJw@Ry)MF*B_Mc2`0~|6|fIN zh-C&C<*NRE(>+p$@JcG=H_Pe_Ld<8v>GaD0lK}3$^#595wEO@T7;oig?t>CfVN*2@ z{aJ{mh_xKOSq%B>)9Guy(d5f5ftq3=9=wGd9e9I-$P*s%8r>jUet3FwfgXbmTV0q2 zE?XSPO1!QvX7g^o60N+TO%mc>C~mu%dzB;UC}K+LgOL7q2vnA5Swg)AxtToC6lAc|%kJUPX5p_DX9bh(L4M@Bt zZQ&YysQ2FNvi>0p^-%`PAs5*E;h*aQ8hqdA{njQnI=otLWnYN8lf-2EF9(xJ?Ux<^ zcM-7yWuuIM_ZVD%9vyGJ$lY{4pPhJ`t|6fl+7Qlwq4*XE3*FkIAQHI(hh9`OL(y?z zCyr4r(q(nqshQsov0t5E!l!P>c1aBwkkJZ;?Z`;`rJ^Cca#pt*6nrSUBL^6M3Qf*+ zdNx#uH`lcg(25Y-T%pV~%e@OR#z0=BAU$Zn+I!&ZZ)`%JN^V|K{4N6yE-H@rK*|0= z)eJSDpB&i7^utZ+QH(mTM3^PNsRhiyIc7S|c7XlQbhF+ZT-M1IXdhoIrZ2Aumer1) z76CcRwIlrX4x_?carQ1Und7mPC`2F{7=&(Mo4;aw>ec+ujdH^>({5%fUA16Z6ib>&A3mwzMo?o@9q?2zMBOQc!pC zy;p+M>JYWBPkk8Tc{Y$Qz<|U*4CO&Dz=34v(xFZKdkTutS6I{C6IK?H#Uv`Sp(RdzR*JaH2pAT48Su=Tw`yM_0G^!v(vDLGcp+{1s zm@t{Y^zMc#I-lFm*8_kl_5a)fTMg_f-ve2Z;J;%<&VSB#{wr2&`pb$X|FGh=A&627 zXERaa*kSPvm)EF4v4taw7y^ZMakD$ApmcA3S=r^qG3dtU4M*h9aAu}LdV-r-zQn_R z*ChEOSHV4p8t}fopM~Pb7=v24NYBG{TLI5kheBOaQv0M|MUf8522pWuq8oGx5upYl z0DpBN0H_nqynD67n@7K9?7bjO_mr6LA zTlUgty0Db4M$N=Q#9Yg_AEK3Am}zlKul(xYq@u1<6+iAxKr*6oJ*E^Y|8hEn`ZawY z28Y)^^naovr*`1@ zLJ>=nR$5w9fCF$a+I!|cC=eBKQkBP2@?nD|2Rbk zpi_K!{(c$wU!39vSS|tH>Vipgt?9^z>e*Nt>c;C*bqEJu^ zgJlKm$w@K{wk-wULu>4|Q*@s{VJ?lnxFi?+Z~ek226;-ohw;>s2;9R$W#6B(r4poZ z0*ASXXlRF{ebpOGpO5!q!0x7LyAb9e!4Jz^rY@XayJQc~nrrRb9W`MD>eAe~VtyGg zkPu1Gr(8rTDtmn?Y7)O?MwFY>3-xj*0w6>=NRi0`QL#Oi8(QLPq;7mR1Em)lMShwT zR#3j3ET=^t4^_05uFr=BE?N+V7Qp>HPsNyDvI>oYK4tM?*-CS(tX#J)0)JEgryh3? zwaYhw7`DkgfJ9%Wi<6sN;wvmExX!snS*wK}Fp$-ke5B7Vdl;0!o*lnfhm=jDU%Ebe zD~9Kzy=bJDTr<;X=$&G;gytEa1qQMuz(Ce(PxYibE~&29eoW5{R`!dA8yjz_w6@N? zJi9@)^H7S(XK=&jwF$o%i3n0q7TlmrO84Nt0+18T3~w8Um%_0Z=M-Zl!6l>`Acd+TpCm4LO6R|A$mO z$58(DZ&I;?$10Z{#tid6q~dIxbn}0eio5wqArCQe*g?6fEFwS=h|*Bqx~A5n*+CDURg`Jx*MCT{6!kwz@z3@DAQe|I z2bK{?T^D)y$i6wuGwe0V8vHIZefcD1j;I=N%vriTXxli7ih*OXJE<}LntJ?&Wcyj> zTj42;1;;W%CAeCy*&JMtX~NQ5HCMCNMV&-+$<}X>DhH)`UbL9nx%_!g!SCC&TDQbW z5Q95G3h|g44NEO=o2X0PEV72*cL009WLG(}2_RAzrqLWz8H1s%NUkM%=gre40*oih zqJ{Gd4Ez&kf28NKSn4&RS#$ls%ALy8#+w^jv6ha48!W|wX)uSZo3CTf4eJ*ZlTe-wTOdG?rAq-A%igkEH$fzP0g%L|UGM35773sF(FJl;Y0ou-yzs?vldXwZ$xNcolzURsOb*SK;|g*#QGK2r zlly|}65+lwNN+>{z%w9+L$zb`c{mMV8JnKq3#33VJZxhpY3Kn99Jy26V$b&cd ze@UOkq`V3}|Jp8X3l0TUZu|RI~59 z9z%}7L*38d{J4Ky6Bsn+Q%?q=)|&~&!7fqkz^jLY=%gAEM3UVU(=pc_37T67k5mDe zl>;!fn#Z{<@F=J)r_CO~R(C<94C8THmb*~jAhu{T-;I9v@jm|*a%ww(PtpcDx+K11 z!)I~IU0>#XK(j$w=Bdjw=?QUlBZ08K{*Zlns4h==pw>dpfsWHYl5wWW3zA*#aul`mls)b_Q&>Z=MMLj#(0SMk<45K z%+(C3i2goj+mBiOAZVvHirr-T$-ho92Wz24i~`1#gOIe{yy9~>tR5tHwr_*B?>uf` z{Popv{phs|@XRjN5{@xL6x?`SJY;y}gT}m6(rjH(gS_9kC4-x?062t8JID&IILefj&76L(vWzYEaqMti13i5;YKb&IV0OXV9i`$4;7@(@_ zpdIKGJ%CPeQGI!{ohE@-LLK9cX)?;cZ=Hx*EF!c4{G{HJ+D(?t7bg4thCOoj%6;!Z;#5ES=;plJ6O6hE5I2mUoE za{Gt*Jpw_IwxSUj} zd<9{NDs}9Kto_Gz(5`qc_;1Iw9h7&nTdLDXIu2 z7x<4tm7ZyaQJEx1-TPlEnV>4IKPLk`Ka~hk=a8iI?QW6HrjC*=lPn}S={DsXOcPLx z2>HdgbPaEk_=y?8ktFDs6*Wf_7DXnt*<5|uZUQNl@9?P-Bt$Uu@IE364PR)x=OyM4 zF_c~QHf=rv(KAVARD9=d>_l4W32@N-`e4DfWb1$Q0`g3#Ies~gRv0SCv2DT>Y6qV4JzBuj8Bi7FJ9?)Am4RPmEKm3;+Zn`d9 z5%GPkBK6j-6b2bo_HLf)Z{JBWX-b6N-K=`8$xspaxru zP$?Fg-PR?uLr6=-YosQzlKCUil*Y-Tg{L_wvKptdlLzT*1U}giBZZ^r#X24oX;=u0 z)FaWb#%x~Cn&_@n)fm5t$2rulF=iX2@Kh6u-aM8WDc2q7>aMHo`3H~mYP>EVpKD>i zQl+HN2*4j!_&Lpl-8J}l1SL_xyYur39rwpYz0yacdSs;1Up2z7h)g!PB6$lRYq$jv zKBu(T7Ln7}WjSkV1*-tm*JI*nk`^@F&?m5~vRU?*dh*Xa-f*Urq!YxpN=2Q}N*tVi zCd+Q@u#S#6I05&cJ^txf)qdK|cs;ePAr8tHtgl~iN73Py!oGTsyFt$1Y{GTDklK-9*f!ojjGbu7){tu*>|G!I$ zcsEf%QtbZ!N%8;5q&Vz5|MMSGJp6wXDe`tM=l@?%ijV&{k)p@L|CdP7f$Cq8BJ2Ml zQXItwGo*fhc3fMmL0-&xc3hmKG5}#d3;=)sR!gtNk#tOBsT%PVkthR!vA}@dHbQyM zPs-h9lR<2N%Y1lA_sapLzx(u(LEJ10{q7|8KBC%dZKtt9VHF=-V#Rg~?{V}Uub2uM{7;sqnCXz>LaYo@)8zI= zTnhX5hjv6C@c+swj$86P%_4z-+{yo2q-g43qU7x0=mH!p;AUrRZ)9c5Xl7@=r>kR& zvG|4XkEEZhj=ER*A8f+aR#^?wrb<)7S=kENOqi8Y(I~WC#)KcUv{tjlGEvGdz^S?e zNuhGYL1?mp+|4WqjNB+$S$#OW@DD3KE}ai69W9T%KAZP97^*ZJG=IrJsWc+S<2;bbs)e!1^Px6V;iJzM4^GWdu@=1FoYfbgZUG1cP zW%G3~#MOLh0DT+2)|yz?{*%yyYki4%F_T2TUv=vACMd`{WY11KC+Du=v?&q!=MeS) z0&}d2MY?x8>8o>8vjXs$o~qO4QTu?y{%teufh9K_zwF z-hi~ZCuki{q3uB8jO+u3#9kf>lY>4z>RvG%!#L%C;p{D7<7k#e;WaZeGdpJHm>FVb z_8Mcx7-ME;jv3>anK@>RDQ0Ho_+RIo@1FOhbET($rCH6)c30I@Ro8Y;L90il!4Clk z%qY{-u~e6lu@)3@;v*DppFb04bU4Fb$Xgg}c>cEKLiifaJ_0o*@P-LwLs$v+?m;BW zIp6S1JmmasmO=@33i!g7$Y87d^-Bc)_%|IDRrxyf3(jM#<_k ze3SOlaGyC6R`B(_w~Ptg6Yd=Ww;O<)Y}Sq3Z0bFaqMfh#aUxfy!mJQ|^iDfIxIaP9 z=P5shb;Kj6QO+MX6a@TO z{61eue>u%^=ON5M*8EXxrYx z?&{7;u(oTnSHN3Mld~r4P=EN~(uz$1J5B@~|9(6^YgCTUNDW89OZOkubK|3 zhZnp2nInI8Z+M|nG0T{k4v$W~v@%+Jyl*a^UfUX*8r3+8)pO5}_Bd=rF>-Ad5=Zs; ziumC!L4p1drWZudb@O?CZ79IFgX*|)(O9Rlv~c>rj|nmlDkPLkw{M0 z7s;&l=xZ)vz2tK|o=sNE0bV70+OGob$=XL?AELYme%R~@tb`^{byw$J4}2!KOtL60 zhEU(PsM8(~8Lgg+{X#!5R`96+-OYkMtto0y&`GEX(#FeEa;7*?f0~WYYZ=G5SD08J)uP5CZrG$)JH`R8I}dQ54G4tE4HWVGL}~ zpUgQM3*<(lVb2KZB_cRiZl(Sd>oF`Zm{%2ys2gSGtGNzhy&IV1$~a@xY;xqKWi;xC zemm{RcktT=PNMnD-A)WQ;&tC|Cf!|&cl&^;G)RwR5WUvG;#}B{@I=pzEtG3LvRw2+ zEA7S4sWe^EI4l?A=~`fOpO;%TF1U`dsV^nn8?0tDV~>z+#Jyb>Cs~N#X!Nh+PoxDPlLhiBjW5|& zB{4}R;kcV1nbr-@C7Y!5sisE$P$s#wzSs5sodO$EhJ~~zpdKYzLZ=_a5=K-|X@Wfk zk)hh?;@y}Af8>m}i-@zG?y~y541D8fblb-hKGV#v*XCp&j2D;v^_{(|adTAET?MT< z_~Xh^zjc#9eXmKAhD2cCkbTIyua}HhD zG(b)o5pe^bz*hqr;>*B6HWsxGJJ100d*x5awK)QVV6D{)Y8zKLo}`mkRAS=8_Ups& zw-T}K3|k-0+Je_jiOiDoHXKTiB#{uBb_aqg9(>J53z@vSmdJ^X?j$<#pyPEkZOJ)! zwxZmRzUQ)&!w~9;oMQN<)Sv~v*87h?;S zXhmQ#4DeM|vT}3It{=}PCSr_8a34IDUqAm^;$dy3+GvxdCu8CDbapvN``)*8?#=7) z>bii$Sw(UW@0`PRAG|P??G%j~kwrsK_ZDv}>S!E?%?3B^3HPOUrNmyFa0xVl#kzZ@P@fyK-#lx-Jn&~jNzyC#*lxzt@ynH z7pO5KE9)+#JHtkbF*lc+Krab-^P^9cDK(KT@snawEfm6>WRz<9=r*!yJxu8mJltzm z=%su==YGclx{t~|(7Z|AcvYs2^2Yo*PlFN9y>ug99GN1~b|#9`q81>d5q}-%pjI|c zZ(aUX-?;ATo6wyebv9<;uS<0}w6HNeP38qc?`{KLGwYAS`&PQve%=)0gZz}}IqXc8 zpCelXw3H_qXl}L@@#k$FX#>VlGutc%$j9+8-oH3>C-w{xs$nSLjxrVI5{#}x z{LbwAaCFpocE;UE^4Z4b%Wg7FoU6wlM&?4;D|T7A#ND0zg0(ff(B;-xqGtr^9fy>x z{3${2hxAFMrY6^w{O9NO^8wrJqft3G0p>1Zx~}5L5q`{Fg=nH=&}-eB;_){bph4l7 z81WbQ5&;Vi9(q`NQvZxNTz9Y6;m0qkyK@_G`=UJ7K+O|6Zafk`mRiyxXzg6=7VY(^ z%JU$Kd=J-9hto2Z8q)5V+yI~KMPU-;K8y#km-eljXZIZVc27Q>Y2V{yyH;E~fwPlG zrez`DyW$;Ol3~bD%#=End%Kkn4nW%y9JWzSCRKLsd*mm#l^ND&nPBn=$NQym!9&F+ z7?Y$5Ja-3Gj6dSJi4n;k4@^rmaR(k_Lil=TmhyIfxW~rosWv^+#O}z+#kVl1b}$!# zJg5m~ie8SQy%gch*?n89X`=3=)TiT<>BZ1Gc6Q8xx`=I}KcdKMj>pyyv7qImx3{;O zXX!H1u6YOirBq}h6MqTBh>KEuU_T53uBOP)VNeL+;GG|Y25awgPDb~oN!;DvzmcXF zs^kqa&>)&fi3NxNx=OmwRW-Z_j!sJyNDnM=s%B}`kkfTQv(gHL zfS5Y<*D{QAf~p45zN^NwhqxVo&b|+#{NX6^@+@x0ma{G*cT@ls(9c+9qn9%wIXM2) zd>H)L$<7yF&cv{DX^GDWk=-dPbJC2F{b=?k%|<88vH2)=MUfb&H1hqGXtb+52B-H* zNoP!ys!wh~W*oFXVJWsg`j-ZLHcJ?Y_JyuSqmT%gsmJ)MEsv?Zr`mr1we8EBnZS`85l>S7`U|_;5dS{Y+Rrm&s%V8~ifr1M+bB=TiDiU=A@@OX_Rj3c8 zMzz&OOxXFszO#GD>Y2#R1&z)>ez1R9R!<4orNior(S*9#GpuS@Gp=f=Z_?da4-?YL z6mHz+{#I(=q(Q{*NQCk!H8fxE(B#+U8Hq2XO@ofjZtlPWc=-T${{qYhC)PIv?ICz$ zW}MO5+X&+!=a+=WGt-l>HmLX%Ka}VKtZ*hj-O6FNnGg3!ZURjGF)+KoKDxyG#E`jj zzu1wwJeBK$fw}MOsUCLdPW|rMJf`i~BQ{*sJU37NB1iN58bri^dy=qL0+AT;TltMW z=$Z2j5YtR?f-f-9^L&4x)=b+aH$V)y{e{`lljla77YjKC{V%C{f4BWOAy@*X>fQb;RnPP+5^eWu z#c4l5d*Sf5);CH6)k4`%F+P#cXcEFD2kSRQe$(uI66`zDPK*NzpFumu0X_D{mL}7K z&;2~JX#Sn42Xn=5MJj$sOE7fk!qeOVCt*Vh%G4Wr&(!1bh=}O1o0#19|F8 zT69dAMi>(O)sNs9h2{bLk}|&0tWq}6QRn7}8auQ6%p<`tNr*7$j|7C?9)AAFHvWYt zeZe1L{W$fISUNSm9yk;h5laT70134yIB5ZBxF0}q*OC-QMZ!%MX%Qv!HJHk`!#$^& zo%HM%n7$2Cbp_jgh@iNd3md@)mKzc4_wx-<_{`aI_2d?f2v+-aAUD;}qCB)PSO%4& z*Lq-zi`XsxXWclN6hh}7JADL&B1uItiP&8$6_c9_O2%sso`*~m+46$c@&kqdM$l3q zGNmx{8``hVGN@0bRukueDCZ=jVkWcG;f4gyVoP;*o}gqg^30@j$)y)kiUscr)IiOE zs-L4^msl5+CcPh9vru4K*Xmj zxFVoH$7hk#mH$TIn+SG{^(~QBqQcTyG&qm7+IqD9dMbDuKTfww!P5j`MkHUY;ybOT>Mb91t;72%%^X>kt3)TL zRtYd8VV&sK2UB9eEdoQCcK(PVVpN%NRS2u-u-aJ7DlWq;^Bc!J(rQj}peP-okA#&@ zrjs^L`TRXCz2grMtaBCbO)x^v@^cktRW;PcBCud0%vMc_GJ#DyRkdN)JG%&Y0b(&- zL2LC(Ws_ffD)_12?IPHE8#D6vmiJVuM{^$t@j};RQc?(P z_IW|BBr%XH3664AjW!p18ZtVM?OqvueU~*xnFZ_HZ#DgbZ;Qb+L7!-1ag=F^`1cnf z;CF;U6;ZlCg;A_+aV|oj1#D#LH@6vOONLYwAlMJKi<~DATd|p9Yn`xTAJ_?}yQO|o z<~VO;F$@)L5|)ahBd@t0~M0Y#bvA8U6;u4XUsAPx%5z3__IktdY)JH?z`>f}paTE2g_dUqyysD2@$ zfJ;HpIvx;6`t8`Q?3tcdFFs2fE!&eR0g5`3AdKkB%3?9m*IrE3a!?sd9v%;G8>Ecg z<}KX~mm;;yj2~YD_Kc$wFZy1j2aA(RCLu6@1%>ZfSn%je8F}G6aPk8BSQfhaC;x3uKi{3_u|r0`Gq#j^haY zI!?Sc#lI_To~(t0OVu8M5N?C+iY}l|3sIb7e*S2I}xpw7;UVpe_EMY-b*H%bCpq+VN!<(SfjJQ4~ zi8tuMOV@9s@?9EPDCI0u2XQ0f&gR`;F2<(sg~?OMCwQEkxM{9M)j!J+F(G4!nWmDI}}80b`MHsBP2DAP}rK1*|X554Ktv#j#?T+P(;Wk zY?oQ0JH@BRbm?1H>CGhYMeICwd8o%Syr2wuf7#DG%18omS^Jn2N#dqsY}$Rvj_CRl z1+~Nma&f2=mi|K$oECx09)Yk&c=%GF%*9{2HpsYI0c;*!nbwi}alJ(9VL{Vop0p+nL$l_T!63_kJb?Z%c);WaD~%C>o5F zvGw%Pca@8=#s@X!fWCK0fh*7&IvKds+{>If$-cz(^R(%2)}nt0vN|Pj?zQ6I zS&LcUJ>IhxTZl4=87j?csXtGBI)k<4#G_!5cNAljST6r3Z_!Q{WwX4rd{jEWfouf* zo8~MY(sIly7fyhPn66>tE)LzA*CAeDBNh%vs|JF8;@|AWlz*}p!C^*g=4xE0uU?d0 zY}XMm4HG{|m8IhQ|NJ?FX(F?rms@sr-2MU&@z$x>RQu~plKHCR6|qI|w8SxetrC_Jq9Rwd8 z-|rbkzp9rMH{XSNh>}H6IQo^<+nA>GlJq5J8RddkT;7uw ztD0;+VVvwPXe1wQ5*yssTnqATWRS;CR-1TretygV+L28afXbKtw)Gxi%?JC@ol>;pH`dtqP)VvytXBKkvokf<6M!f zUhzLEi;JRy^C6K*c`m=klQD1n;!>RY#qH;> z`G78~%cY(f)A7s5BgSTBgDAoD>uvMJ&QT-XQN$)egmqd@#ry<#u#>ok%@e|wbY zqJ!(gQM$@AT_HL|BUmXO;rbhhE~x932?|7?yz3`X^=j}_Q-`+u6Gc)5H_>b`?X8av zp%h9XyYBx1Vo60p3580kQBRjM1BH0_kVI&bA?C`q<(Hfn0Ve?(nUD_UaK$S0IQ=PB zGe)THjBu~}`N*HKR)r#9R*MK}#U<)Ar|PS)ViZ)33=Dq-q`muzAt(^t2Dom&mcApj zWEErU=am&r!wKEjDAT?1{R4;YH8^dqgyBMdJ(rJC{cSh;hqbBX?jMAGh(|{?uR@{n zpN86e{GP=&vA;d)Cs8`G_8Agx&BO-5k_H0cnlA+LgppyC^Ea)(dscG=Wnd#`-a4x{ z-49jFd3Y2Lid7JOUvTyF6Ck{Axb9=;B-T0gxcW$ptK;|b9$W+uTh9EM_T6XHaRBdl zOQbFprmWQ@zd@d93yMVlSYiIvdw9s)M3c-n5Y;W)4@g#i%s8DF1Us38nm-R8?;SGw z{$u;r3qOKm7618YfAzMz>%RR((56v@a1DJLtR+7PQ?K;8}j;y+#X|^Cu}$K=lOSA?N}U z_)*~_0PrIg;l&sVbPeYqt?di|Aosl=U_CA-M9Hb+Y$fwYiT&b8 z`UCRPAvtl0{74J5#Zhy!R@6CPCp=xB*S<`4+^=%4571E3tlb){dEMW5-gkHbzaO^> zM*g{8e{-#~;clDsed7ig0mh|-ls=$=F;sW_N&Rf!d2)vw1J?cZv9`c-WWOAX+-N|m z^ZNMn`6U6s2zFdfNV5tR48h=KZC$CnHlPR6KLWcVW{)Pf4m->rip1|IIk7ecg%U95 z>aaTfvg5n}j#hfQ-}P4V^N$HCST}URd^+r0NI7CR&)>74a>P8eNOh^}k5eVd%wGN;+@**X8!)p60akUY6y;(8Iqbg-~%7endP4=Uj0DWq`Qgi``LxjJz*$+TyLg< z3}*g}A@9$r)Zj(>-k0MCxwmz|dhy*Rgd$~$pXHGt%i{}N|uRoZ&sP8e+nN}f+ zAgKebmD~&}`7+kMCsIklTUyGae!GaPOG3nyBZ{QEx!yfQ(}UQ*b9Ym5UaW4e#Q>qa z9|0+}Zt?+y%~|N)86#k|Mg!Vt>O}gMTBmp4_cM8%s;v4RG`@{FV5#09J6uGOE;8!g z=g=z41bnC7uT(Qz-BOMQyu~*23Az2St{F^{9Aen!?V`{UH!V;FyW*Qdpaf|uOm!z= zhlbm_rf--Tw6bX5I}IBdPsNqVWbt50ALsF~P#~OHWqTT3$m7IhpLsxn3#Kz%Dy(D6 z!Eizav#a(YTo?r`=j&&Wr%Ei(g!?xp-8q(y0*oWE@&Knt zl_Il7Xj4g_l6`LCNebv8N@YAx8QtISCCtp>fF1?2q zq>{+vM~pySKD4R0nbIKW3BgQnBW18WmeV8K&Xdn;orzTW;r`Gd;$~+=U8%v#K9#e5 z1@*!`Jz`V^^^#6r6+%|W^XL5lA}Ii~+DA`RJ>y>PqhSx?-jAs{9HXr$Zcr~Ry3=it1g4H`OMWbsWVHLS%K$J4Ktbt49=Vy35RC3VQuL8L zq-arntQcs-P)CAzA0+#kgquYfV5Ao^NK^KH1B8XVf=yr#CeIjp1q3{7ryOwvF;71O z#a``QzNRgAj&vx7{W^FeD{N{&I?$sSF>>5O0p=U(`ax1-2?0GBw#ry|5C;l z#2(YUGG>6SRdqI%8j#!}1q2bq`PqbgzDO$&MBu+zZq&+AQI`gSu#vbdG%-f;gDyX& z$4?1kJq6`$?bl*i(eCT+!=&}*idD3mE0-a3QxOJO?ovbMw0e57Bvq2~AsvzFj(n%L zuF#9SsX+mkj==`&&j+o2VrRaE)k{g|otNFu=e@~^RCo~1)Z*hHPPjR$Yme$IbrUe3 zz3iSn+4wm?h#O{KpJp{sy zpR4?Pv&9kz?Uy;c`qH5pmt=|=7ymMK-48b^cD{qhNgZ*FNHK-Q4$(q38U`ZB!OLOw(0qrk7-W&; z8Phv%OZ*@^6cv)j4$`(9BSAxpLfCzKBx>rC^sbG1ywT-YZ-+lb+{iTHbh|id><&d= z74FG~(E9p|H@}bzK1Q3M=y~SQ;J4G6yGNl%@26>C!TloVF)r@;lo^)=3D;Y$(Drx1 z$GWpe!_H*2p4M3fF=wSVzH3e)G_b95wx`|U@-ZSr2>Z%bIx2S2AGpVX+4e*G&XM~{ z3uX^C(aFtSxo=N(AD`vmdOMW<=$Il!xmvP0bGO8-!94Ne8}j|OkUBf_GsLR>X{4@= z(a|Id8V~-IO|b-gxQuB!Y;yfg+uI4+Rb3BgBV$zPs zO~1W3eIQL&m$snX@?do@f80=SVj8}ds2?aVsFV8BIUrKFda&olbKCb5Zlp5QeyF6u ztk{=vLDphtwdfS%)8HrJ&#IsSd1@)Q_>8hB#8gB-`>^38%67cDa%uG;U7?tb0;jsU z#NuM{9E7y+absQ&Zr(a_ z7Ds-13^eSmq9cauB}e-Wk#_|R+PbZ$nO!u?Lj#m`N`j6FQ}tPGJJkGItVo~PeA28@is|I<)i-eRA*?K|(~;yv1T<0uQ) zMl0`Hsne{4g;8j?ImUmuFFRuU`rOvp%ib^88kv!Iu~;kG#;04Ur`u}9L63*<4@O=2rXTohF`vH5b=R@(AEhIlX8>eiG8Ndd(zn!$j=167H zth|?jkl=l!?;nE67xIV5-4c~+BUMAT^^bM*D+Yi(zl{aNl|jV_P(3LSR(6EsrDCy1 zTrz~0w&wE61t3R?oBE*rIBB!h0uyE3g_%V@8^gGsY9d*SeFoJ7U!u4l>!B6Yvgo2{ z+*og7dhlo^rMs8aD}1q=dgJl2JftDVc|m{T_OX0DGswV7TS!|7of${D*k1ZHN?yYk zpGWSQUCnFDv&{-gFGNc}G9gV_%Uc*nn zyG%#$!5&2c?%*i&lNNEXJI-rYLHHv6TNLaBBT>{BcXyFGxl)j)<+gLCb^54C3WSt( zZSN`ugiB7uTl*q;pEoUNwf9}iDZ|E`3`s#+)|IPB!&%zGy&+{x=lj?JtBOnIjAo)< zfXL8hu|3^7_qHr2I5yZ<>Ta62u`}xr>Dr}ZmI{%?2_D$*5r|%w>o;x@GT~ zR>8T7u^5ge|0Go{d!FyY=YLcjo1VQ1C9|Q5)zXjiehF||egc}qoxdQ88}+FJ;cS3s z3W)73<^O6PH%6YQUBy~wYV}WfMe**{-ieBfhR{o zouG}f9)psAm!J*njxZvk80O@#szSWA{WBbJ51RfKfY_$H^?R;6vkLqlnS{)aMX;%v zCxt#dIFYkZw(!jglz#e`t*K8LQ%;{3gNoWys6`RJA1rmm2_UQHi}d!OU{%c~`)iN> zwo$M3^O!lXBt;QVX9nfhh(o%`Sb3WiM`HY?N6BUcFpQnFYf)~3El+)L?cC~5DMs$?aPDg$#$VTj5r4zn23hNkmq&$lYl8-TQbXOcUm2GY z1ulgc`O4PH)d(jU$i_LH_G!7SUie&%{OG#L0F6A}yB>0oj{aC~j71;=H(kZBI|LXJ z?uIf8Io$4Uh)aqaMeQ6#p+E!b>BQ9CT7C3j(QqScY0BCCzhpV7uK#++r&awye>8b~ z*#-!RqZWH^e!nRaCeu^|0T3QXq5{uPs9+b8 z1{me;=`6+kZKUR;%U78V#xb;(G`8=|sPx>7N{-rhs=Sk|Q1?z4E*5F<@=!2p0B)kK z91I|kQ3E6{lfwEU_N50%K!{aiEJb9pth%H)sfMhp#nJRKphorZ&XG)`u$ z4G0*t;-c5ykEr_#2eaDB!HkW4F$EdmrB+cJXgdE+dqh%k59Bn@nnG#XpH?3gDh*kpRN!8I4tjuvI z!CFdN;mZex93ghYf*AdGELZB*WQPvDlmJE@kVm;j!4FfGCju1hpKnsb{QbDRoq-AlDOdGjW z2XhS2^q1uw*_c5x8rm?JLLeCaw|0$`nRie-8_P3Am7oCtmXxobO!ZgpEqPWfA`omG z^qVcDIB3IAAYMnY|N7fHX*C5I4v923q=JncoVTdH$T=`7lpEZvV68N0kAD)3H(ccN z=QT#BQ$$cFHkHn=G7qbh3Xo26WfOY3d|B4ur8XTPgAfOzOv;|;8()F514sy?r6Mf9 z-no+$Hl5Ww(%sT37eQ&HbCo(RWLLw=)1O4++qXyHJV(Sw*IUHq;Jc^t_{ zQ45m*qpT$rjKA2dKuZF`R&@wK?_~?7O=smh(@M!eA^@l*wY)?4_eH&yD~I1>R`o|n z>va9L@FT=LDwrXnab2NQ8?*qOzk`k)Kx@-Ew){@pToUNX0Pyrve=l~HXN*q~yF0=E zVzdKc1myXP{_6sy3Q_D@Afz>bccqhj=QMV6aZhtCoRLz``@raiZ?M0H@Xwg}D|f7F zD;9NNCNKv~ME}}+`d)p!8_83{%4YEh%F z%5o5pm;h)1Ea)B?Kw!$@qyV&&wLk9v@(zjZJ@EKM%f?ns0#nG@y-7cAi@pL=C-1|D zMt{cw0r9Dc4uK?P^38lCqpyWRAEzzlIVDp{!%z!)EH6+vevv3kpneMy%?lqa4;NRF z4J-?1%_9rSV?{&L?y|p|I5R)Ab`*QrrZntgX9rGXIiIETuT+Se@fxj&QaLeS0O^y- z?XN>WT%;KkY3h~+W#N-wTM&s@0zMUAP zKkhV^k)JD_{(QpEzGLs`8ipkrJrUNs|2dr8%0mHjdgd_r+vFZ;)c99}qnaog{FKra zqX+~XAhvrax{S)i-!77+CMnRj&Sx(O_6#Q}-ntCDS(w;0g4e!(5DDNcBnk8(sE(}l zJ(8A09u&fVy5ohsha2sA5pM`8HkyR&-nVy-thORDx2A@2y6TIIM`CC=q83ofY&sHX zU}=8-Vu!dn+1u2$_+y>>u#H~VMXh4k-vkkSHPv(DcS+<-i#~FC^fotO5#mn38~PEU zI|ruvFw~dy^&tGE?K;l)j5r)iu8)9-lfPoI79_H(54hZ;sNC*eK>$hAC%aSEN? zb$yAI`;6E6`&6s5=haCwk>BeWtWPe6h+DwOV0inToVrH`wr3(M>>Y|Z8zBvWyMnfZ zC1M3%;J&hE6S13NS;x4-iJ(#Q)|5tH2?fDw{C6bRkvW?02fiw~C%=wT>;!cEkpINT zRtnpuz0+Zs6{{TMx7q&a;re@=`1;31pmppc&zr)ksnGBkOuFY^7Suh$0`KG&r6}!% zpwESNXU^~OiDDmd**D>1A4%Cs%mztvw{eSwo(Evs^e5aa6cdHn789+`kA2oc%KRLK z$a()@-DaR9MWwaETnkjj3Y2&nSWl!h?~o}mauM=BNAN0{Rrqas(v6;^R>y7`Tsu09 z3o;$&j$PMo-B70P7g;@s^a&COEu0K>c}rfm$CWAVdGhd_n~q;kUrU9{{k|EX?5hXv z`8?z77d(K!Jzbq0MNZKAfGPmbPdm^#jqne3W?mA|aw$r&yBkyOJ#^|E9bYP10x|%N z8$Kq_aImHUd{*0W>t1h2raI&EMN-!%+s>b9M2CiwPtwsrSt#C>`TlHO3RCA)3H_^`U3D8dOG?u;iV`pXe7?P_8 ziQe{4!mfqXj}}alJ@!rhEycph(EWfFNzqaOwzs={p!~DiR{`k{GVkT!USiHSZ zREyEc4FmKqE}ULdhpDHDb;`z5QwPg|7*$TCoRDmqT_I0O!H2hXxlxf>)ndkh1-xrP zh*GH0fR&Q*tWlS1#@fq!Q*fgSNUd2pum!lq<^34+4lMmHbMxg^D7Y*h#L%(`5ET>x`{WU>PToEsg0N{_GY;b zDD9LkAGuh3p0R&{UAztD_AHPLTD}IQA@(1CJ8v?REPeyaZs+~Mbv@7taNB!Wkl|WD zA3jwSoD~h<|y%fJa9&H98s=Ag-WdtbslLOP}ol@v@Q5GaSy*w}* zNgx%$bp1uIoLi3bRRu}2k6f+P+tAKGTLF%yzV~@#XGHnZ4a%_^!gq{xL*UH6>GXS0 zIlvkj{6&dS7Aof>e4$M&F+Fwua$7S|ri!GREXnz-t6`b6!>kQA|NahZy z3>_-$*DItBT}X}Vz$bM=uV3EMUy%*q)@W-mjffw!2>hwLxt@L2?@r%z-{#+P|IgI( z|G0)UOAgqJ5dnbr?bqx(M24;dT{$E@}M4_N+NTFb{yO-tw z03!dtT|-%K_Ui6nJ%IhTmM>t_^cOD}JlhZRy6iWX{zfAz;%6N~%;fjXBTfG&Llt zrbQR!=j*Y}?wR`YjvTQC=6UK8)orcABJ0x9@`t!nKB>+P%sm7FK||L;5}r>>NjlM|=C|SB))sNgD{d7(9haAq=i&_j>1DU&Yye7Gf6mE*P2ZrnEx! zJeT9Ny1+Z#dHwz~WA}Bo1IlzyaZ?SVYI$~nrfY5b8|B*dmQZ?2s~31UG)Lk&>vf4c zNh*dPMUHKa26aC`FVDZNUlh)!B1{C)d z45fl!=%{Bz{z&%^?rUdklTUTqcQ!U^_&zO=J#Ogv$rlEcB9Y16XT`yA&6O=pWCh7f zQ+}shWaOJ-0zQYDkiX(~auo*zzM!IW#*Rq`#G%atJ5PG1 zX?r@=#>~~Ht=4h z&6jR_$%cLBHKkY?xaE*!afZ3~H6Wg~jAy=tlFehyS>{BOe5uCEb_I>7{a6d97d`w@ zBkN=y&WwEN%~<~AwI=$fo1{}4Imi#Dii=tQtHbx9{qAh)b%Q2;F}KS{tFh6=s!z3% z8Y?)qP$KTtNnVGBgOka?3NJ{0RRJ?vOVJor4;No0fq3o3*sCom;A-?U>6gg|df$CM zUpDcNl+U}6Jgq#PuTEm081M|Oqw0rQ9>s4-6HmUXrhRCBz>X~>v6D$C^@;iou==_s zcx5Nm=41^Y{Z$&m4E+bI6~#0oG~52UKzRl)R}Kuh0tVSnXz29%)yqek9KwW=UA>`o zcolTGVKS=%MR#Y9nvoKlzTq)W0B>*;IOP@wEATjMBl%-~^zd|l&-AK~(wz9$iJyJT zseiV)1re?Wt>6J=mV3-i+%|ww^Hs&oagis{SZ@3hAvAJ4HS3hi@HpwGO+F!A+V}w* zv!0h=t0cR1v5AKaMp8@o;FEb&K1 zp%MZmfjD6~z&CgKh()HvU^!nhrNWw`N^$5AFLLeV8jtQFQ|&nJp0PzL2-FVgr6>6k z7K|~(j1(^5xk-D1VqWwf#`LcmZeDLYk!9x7`0VlP-Im(#!>ZqXWq+8>0?pJP8JFCj zNM<;vFlET?MgxM4wO3=caXT_B_NqV=t$qESY#MwLc$*K?`;ZZ?_QN`8)(^Y4!L3C9KQbB*rC@`))Cc212EqR-EKdZeD# zyOvjCx1YD!!Nh0evq@riRN>R`9_>}X#UCg)ZCq?xtQsi^+rzCVtfszckY^aBZq7mMG(2Sla7THd9!Sq3r(y z5M=L4~9k6urrI#wHv)IPp4F zIIJJ|Eu9fqhGeEgngN%dnEn`q;-9$5KC>4U@r5Q(M5vB!sGF==@iIX%q8Y4J~ zX;qwiOA~7@KoKqWpN|Q1wo^X4HJFR5Ma3Bi@r3to*OTr3i)b>wRwCLS_|bL=l<{R* zOJ7iMK#?`$hNrm>EGQZ?xmBD4N!U&-^q=K~-_8pF;@Ikb205$g1o28IY1H;a>BneG z*oVKurZ7YN)c2}<+o3|KjxDLx-BLz;4S6>=su}v03y`)6lkQ@POZQ(pu9Aer4>b>K z!W1bAs1l@d3`;-HK5LK*BE#}oQeFnSjC38PJFwJ=#3x2G&<_`nK0qt>${3bf$qA*P zO)KiHZ#dFfrKu|mC5*PxCB*|HZZD|0VYss(U8(x(7AWiPGkH8}3JsL{6$xWI&521c zRmAPkuS>siomG``X{&Hw-ONMu3pI6(KU!V~p+Kj6*)8$nl&!FO{si!k)!NLC8^5oy z$Qh$pAEAq-q@#%ySX@VyAwGPAfjCpu!>D7& z9UOaQ$i#X+Q~T;4Dd11Nd|zps(Z&^Ou*BjkZB~Ft6(B-^_LdgCwMu%?x3HWvOo~As zt#-#Rok+@#=l@OH#&oNRJV6s26Do#wVfo~617mhC3q0i^d!~?g8^eBYG)q)?xI~Mq zs6v>S6oW<{DlC#+*SMgi>#45nP`B3moF<87hCsxtA6PD|`)NM6RN9Og2I2ZG6 z3FDM*MPn`_sHCM{pipA^U;qYE8Es2UuJuDfouY?zdwZys-lw!qnGzP=JUdBhSH3rZ zRgviwEM;Pljv+WtqdgSPcAQAEehw9ulU%3s1%0XnVxC^0@DI234xJs zHX7R4S9K4|B)Y#wp+wPGxrVHN5LF0+?NXSrO4T zmc`zK{3i-&ag1iPM&6PPX=?1mJ!1eYN3L{4!8EU^<~C*s7|0-DhO#<;-iq1%;_8`> zLayE7{gS?R2m`L=V}(Uy;&+M}5?mztvWr+8Om`_1!PG#y!Ao%W4VXH2XdRX3+@_(g zXpAYsemcTTf3^yMZ1ernCgKBNo0k6rOxVES;!}byVUcv;312->f(po&~SL%6_BQ5~S0!M%UuLVZ;nNmBe+;v!q( zQn%T2XSAR+*rK^59zPRr%`Y&NKTP4ej_!>unik#El)L%ok6d%hBQ6uu@6hXOcOp&A z#m%$NXgRrEM8!)sa@tI(n}>%s%^k0pOw7VrcU%0=&e6P=ttn}N4Lz{5BA5x_6oLW* z#3@9JXZO#u_k^Ho0YELeMkr@(jGtBkyjmETHgv|Y-^?3yh{S(6eK0WSd_!|=sR?QL z(Y_3VL3^o;q;m80v`yNZQV~B)HlSTAdm*35n-<8K$EC%c_0^l0AOKU!m!{YMJnE45 z_|{8JT&q3`)p?5G^Kk1lW?|8(+ZQe0v1eKXoZqf0C`A z3h6$UTd31W3XPiS_#pj#xFVYOK*s895Tk)?5Zg#b|D|CsX@;C{tVd6pWXI)zpV6no z)!9e7{NwMWb|rD?NWR9vS>?<)EQ))Q#YWb&K(U%1MP``Y(Z@o9If-9yYnkqODT51f z$n7GG1Fnac95Bs>*dB8)f2f!t7Y|!0sn8#S6=*L$qnPpHL7cVLx2C zvjF92A}Le~F%p@T%ZZXRl34t$g!uzzptonsMSgdw0Di||l)%t@?6tds( zQx`yyVIVE+$6gc^L|ePt@W;yYC9a78m#@Feu(z?heiQ$EGeL|yxR@i7bn{C)7K_@< zw%-SYZW##F!Jk$if62qd%_i{IKvs^#AIx*(KE2-+jCQ}Yi7uq$V?2JsE&Z5X;svij zHt^k?|5PCwoXI|g-*n?gRT9PYw38Au&v$nlInuDP30(goL1!ZpTcNulXy@LR4x;cd zR56kJd_T4kNv&*$ejZLOMxoHP&+f~KtyIjEZ(LKszGXu#yj`5!Fo+^QQc51zgX#>4 zuH9}DF^^OJce`Q8T$`9m3jn+y|J81A{&%|pMh|)i68+b16jKOz{{OKXw2c1*%dW%{ z?tAV#zCpD70*nlRw+};|yI`$BPDubD;7Gfki6&dhzVACp64}?W8?tBLNlJv2rHBTR z$QFJ_z57(&(_irW-X0Hh?>WzV&g;C+>-9S4-g{1d?KsY@V7#@&hw`K>U7fpIZ6hwf zxHWe`WRsRUrgzZi%>(Nct=Kw&9RHczfoq?yNmZ|m!bkU_z3mn^X}twBE8(v0N-{8F zhpyc#blKA#u^%S~a$oM0H_8gVp|GW_3Ln#7SD$7RO-nhcRh4?_@D~$A43==+f7|?V zmjzmGM~y`z+dq(ohtsHKhiiSpytGRaE%&yilEYg2-itZiN>B2FAd={K3?(?LRtbtR z+KJ#a6n^L`(*FK_bTZ~9TJFIqgHiEY+q#_y2E(|sp8gXI@RC8Fh32oR&4H?jf1cQX zI%(UOF^(Y|6{_BRte=|EGx;*@+h~ZjE-`v^H}T6@hKA{wUTxLWt2&m0K35)>KYtws z_P9&(mT2$K^}5bZ4o>>1C3~aloBjP3k(4+m5iHJbA=DK5<#2t5C`U=atV_?!NJQ)~%=T{fY<`_u-PO z5q3@Y7Q>Sp1aVRCec~;d8-ZM4^bpe%P&uvE2oh*-xh_JM-T0t?x*um z46!>*&SH|vzzg?Jt6}1PLcJY@c=lq^X*5?;KZOIA#B`|lg_@-6*WP*y@v6%;%XzVG z>7?=wqHx{Lf$3d$t%lEKH=$Z5UPjkgM(8CCvPl%HklEG7Stfb4PJQm~Tp;S;kwH_@ z26My}t<>yZzf@V)na5H`%urB`kykVPM#?+8m790mNjfh2Ei^(;dXSBlU$rM(TUXKW z!XPO_fdoeWpQNb!s;M~+qo!gcvcbFz1@A0B(`tjEbSrYP%+Wv1j?8m zr%z{H7K(4*;)2~MwQuR2ebAvxY_dtk-NYy{W4_)z33jEiyhUw%cm*4~H`t`wphRZ) zw)yt)Bvbj_v&CkGEt#YZpSj_aUz#gcEN?NIL+M19)g9ieuMs)E9uz8>kmhIE(+|Xw z1v70Bjk!&ezjX8`k9OJVXl6V*-9IhW!E+QnNzBSYvhhJ<_pD5_MKw4}+|lEWo|H1- zAZchc^%!H3c)C6-^qc#;GhC-;FbT`vL0@?U)mpvy}j;x+;Ms3PN3@5iXqfbxGi+eYCzX!E(NM%~( zn^v>1XNU}*)qI^QQ|$e~M-XYN>n}sXny1a_Y_f{ejImBZ$|{C1@H*$oo0x^tPQqw6 zztlY)RyaiRG2&p~ho<$IxCE?zoZD_I8!hsX&48l72Gu=74E#N2@ zY_8EVbQ{rL+oKDEXLltZ&*plQ=@p zd$5U41^uL9ed@^CMvs^fatB7t%#gQLRt|IW4ACr$J3X8Niw+E%S}ROZEV~GK-JzDy zD^|M1=ltdRh{3Z@+A^g1f{qbb+(V|vp)rX~tDpVN`>j1|TRt5gv0~Y1?sz4LOosbc z3c~p$*J1Nx%4MD-&n{#wg+B%7b^OI9CB#(nE&h2`!Ns)H7u6VV6Kt0Dx*g@H0686Z zqOE7>NL^0UzR4cVXP%7o)5RWt?J~2x*X#6V+FNA7tgukmUtJJR%h%DvBWe{ElQAcR ze1(yxiJ*PK#lXuu*hI^r%&Ebu{kh@p5)`ck(GY|yonk0J=E)m@Bn%OHHwV)wRKhT) zJMy7u!B@|SoS8Uhx3|CuYF|39XXxhRPB@?5}((6azUV7Plmmq`kd7T^xgMW9!g(p z+_J5QF@)D<&kMM~LouG3+5#tNLY*uJEQq4)e#?X@oP6b<)ukWN2X*a?nL4hk@4@ZqZ(0(BPxR;w#|l<~<4>YKFP; zZ7a&C8=GP<6hS>VM_E_YSI9u>4LTmLd2#mb*0FP31mFLk? zhSyPKiYX>wfzqx-PLY<)I8^2Qx5Fikn;c{${Rzf%K*TbxEIMp115eC?_k7mOHnXU8 zs!DkSJz@u7m?yFl31AVy<_A>H`+TL~c6FS77zNrt^PdC#l>d8Zz3Ow^&z8=bN zohs*AemUrZCcxBr2q*713`KBQYEFl)f0FoE{=P(Cz@}&~t<`N+twV)CB65>z2F>ZbMthjr{J4>P6ilp`+kD^VtNasC&IIz+j?S6h$TW?8DY0 z-2`-O(6I1JSTk@oMIlZ(Y+_kc1A@MN3JJ8}g(8L_?<>Zan%-=`)+d5N;1kcpFn|90 zMbrI@dGZ|Yy`uuEyDd`9`$+=BV#*XDOkObgH4dD-dO@FfZ(U%l24Dm+V@Q1>m_8P3%iLRyk3X+Q5pFoVdON2O1?h&DzmxrxM`MKE~(Mg z!Y<~B`!s`Tyb(~z=op6}raPfnc1z6@mu@9UY$j%VVdRGycpWG>W{!)_5t}PNyPB1h zMd}G6FXxE+<%4P3mkV>EKGIXg*hJiaIhbbWf)zv#a;x;Xq9=(u!lYW&T!FW2M#VTr z+!r5gIt4;ea7r0s*oumQ0M(ATuR7SI3?fkOnw{euGmN74Aab<1n)NMR816 z#=$1X2&ibY+NLJN!v~VS5~zj$tG?fuIolmX1G_5Yp5%>s=;kItX>{f*?O8 z>@HJ41a`%s%;jE8*nOseDC`Oi2UJ`%gb)N3Dq(|cbP;i^4BSMbAxFfX_K1_#_{U@< zF}0D}k#3Tv?+U?1G$3YesG7hSc6EqZJF3PvCW9SKb*>}dB!V_h$A1L)U52MJ4|2Nc z6qN%9eHaRgL7ph4=Y$>k%n`Ih>7;i8uw~&f8MT8xDndvnLHIQVh?-hunRuK>rq1mM z+Jyb+990n%vmc#b6hzXPXJNQS)5s$9%p+()5N~y~BcEC&>~uOQg4obwlja*h+&y5D`a`eBK8DC#ktKSr{pgI$j z|9Y)&adoEV{73PL`Uku1CB9t#&N65H*3Jw8Cr~zu? zV(RW91e(LcWsqeJ`r?IPmS(Q>lE!jO%ge!a8Pq#m+DXwgp|8UOV8}Pf z{K7(5=Jd3UXm*OK_Eo(l-je=;5e?k@lA%T6Q4FD;To%9QmHHz_T<^^l#*wJpRj{tqhY6vDedhD>Bq5-9zJ8>KE*=IKO5 z!u>HM4BU4=3!Stp;9fI4-!!B)!%)D1rs6Zy{Lo`L#C-P9&$=w7)UbdNs-qkvgLdOo z$xmU;-O#F_N4TPM10z2JuCTH`l~!7gIfJp z4JL$+XS}mM`_VAnv!g*W z>}%7H$UjobT+#BDai68)4_)(q_C}3WRy23l^N~VS923k1d+&#cH;-2p^{P$zW$bx; zx?WowNFIh1uzVn1Zq+?jI>SY8d)d2qJB{=XTNbK&q_&5laammcgW#=R5 z46s{v0>(^7^sKOO;sKB7AJ7UCT5jv(cDLmVcXt=RBK5xLHL$0*U4&ppu5NPgTwe|N zE|-c!w0V1Lso`bk(4(VuvEvQv#!}Ansvp1Mv(f0q$89ThjK@>CYkKrK z15kN{abHA#G+QJTmUY$E(?INl{pi?)M!$eJujgV*Do=^YHx0U?{23F0;{5G%dXIbb z+txuoy)QyP^68PCg=_D8NVM*qD%+iWzgpDmokMhL$7!mhEDg%H@f9|n8=4OaEYo=r zVkJFccIvxc<=_^>;1)ygb${p?5AD^g zH0$7J;k^?&LQIFpO2gHUDZf#Ys4G3Cc5l9m;)%eCS>BtX=@F#rCLj z_>(1`*uoX)=Tk_u+=mQuy~!BAG8kXc9-IVITxPd7?HPZ=Jgy{!5;U>!d$)hPBLh2$ zMcrv@TN5N?>$%aDl{bmC zCf%=iOsMtEvq?o#w7;8-Q5z)&?xvIc7QKh{Q(^Kvx{hc1s{LbaN>-q*+fq(Fs-|VozQft;9e|Tv<_T7-IhkvkV=C%7-qXzvwjc(P2(j%ICD{(mD*gDiqY{T+E z_G&BCdSke;paBDPP6*`J9lO-XY?D(})m<*&W|^B26%|GTxW!C5`T?;%47rtNRfB){jz{qakSa1ev4co(2L(415);Fu>8}?j6U`H#_aHn{P{*0Ci7x9$e zl-i7zk&%EAiFMi4_(Rr8tPPZm1v1FZu%O5Y9o^U0?S&=F=x_ z7G6WXS^Y20LyMH1`Tan#_(7kX3t7r#dzQx#XPSkO4w{P9i{*VjP5unWEvv3Rv3FHH zu!Y1E^n^LNGciQaEOu&DvQ)EO3ymy?k?R#Tbpp&HPR%N=t_I4x6WK$n21`cz>Gtxe zphbauNz33=X5lV$=)QX2b!uhtj&1$cqoxcJ-`J{CQ<5#Ai#}K;V1~*0;At&wY8Ht~ zxSMu-*MjRG@>iD$Q`~t_m9RZJlc}~zRdC7qlYwWS8k(w{ii3nlD+2LeZE8sj0^PN} zTv*z}r8whI*s!{yA(iS`HrRNZ8QAM|6*5E`n9hvxQ&%7nMz(@}$G{uJL*tN@7OhtA zaw(|Z)q)>MrD!NEzZ{QUZX}G* zOs^6cp%1{eYnX-5Mkt}_=oz2)D;p?8(>{jsER2L|-xOBUGmDI4Y9l&4)+2srf1tol zViSPgK*_vBO<}uX)lJud(_rdGN&oow&Fmnd`~bDpKkA41o#N{P`$z! zKUR;&g$f7@!>p?Vu(%Vwov1in|G7gfyh)q#J5Tu>B;k7-rrY~f6#cZyx3~TFCXbq) zVIPAS|SI1pksVlUcCk8T9Q4s$rBsbh9Ow_Z;N zqla{!*~^9Z+G8V)2^@vssAJATZVz5GkiX&~~2*ID#*>>(W4=7{S9YVxe< zL@!Z0Ys_D8VusH-fthOAy&_e;dINe`Ul1;(V(~hJb`{DKA_}gM9FNp{8ng9j`x1|m z-s>>hRYsnFP9a?kt9hb5-a>VVd8SZ>q~u)a9lu97DfmeIk!_}(>|31Dpy%`vDcp{v^oZXSFedEhQF4Yl^-MsHuoEzQSRIN#0M zcg_#jPH@|wM2xiVxU-(kW7F$44@@QOl=G@~5V%m~=G`_QKL4?*|BgFPf)wZ-Oqok4 zO;+uf$$>p4IL_J-+T!$J?MwgM{pjF%J9m{R*{xH@TuIAnNiI^{R5cY)HekQEajTd!B)|p<&1ejXR0--xQ$RJvLTaS^vmu zZS@7oQEQi#zQE985$PujTyv9hz(CjjMYg>HkGJfusm z6MKaD?>rr{The0AFZvBu9qQXEJYW)`Ro-%uKS?Um@}`YFooT;(DNF;*NWdi;6|X7x{gVuw$fVdOe+xQ=TD zBg*7rExp?|%>4FY+8eDUI%^rHZW|?epIAS+R0Y`(S&JK<9eRY-+^DpDQ&#TGm0Y)$ zd1q^DB75nn*U1a#*6BZP&e&y#JEv$LR$r^~8TYD$(ByHg&fXO|IG0 z*lHf?d^s%OdD?S(W%gxs@t%!TYzZ=IH*W_hADL>`Zu z=Y)?+_Oq5B<8Cs3wh}pV+9OuC;%UjQQea-!JiTmevFrwFcdb>~Si1T2uwvjgk3n&v zbU_PZI(~Ndj8R>*O@>=@Za%-00mC>l+qfE`tsmpp+;a}85V(hXJ${0aklR44O2Crv zo(_+{HqxTNcjP2uyo#?l7+0UI>AF5zhIKqiem4SyKxI4zkcD@%%^%S#!})HX2V9I) z$gFKrw-#4|+-NEx07S*Yn0c%8M1hrS>3P_?O?Yp5OOVw<;pN9{(!wh5ubxM~@T-44 z<2iPB=}^A$6GYLxns3qDV_x;8IpYB~yzaW@?`tApCq}xAE2X{AT5lU67P7iS1A3U! zqGGG&j@uyaDUGSOy6jq7@M$c_<9wXkXLyYaJITlKvN+hz*i)Oe)7A!~w>(CC_&E@V zk2(Iq=Tj8$}*AqtBZ(dZXiWVlp~YR3}{bY+Ai8@(1JWwBGwT)-TiO z%{kExG;ap$N!Pa7AXM`!b-K504ZMtG;uQlsFF&5tjR9hKqcTH$n4Lt%dp`JO&3!%_ zulZoMo^9Kg%h@AF6wt?;MHAVNCgQ|n`M$mChej!pd5lMsjYal65L?ewpaK@<#s++$ zI2e5$qAD~;a^Aj&O0PLxRJp(tRlDKZ@Rcq~MZ%>hpI)E_%DwE`e+MH~amm0vXK!ar ze`u#t**NU&8tg<8Pqs@l7bjzuaMe<1e^CW>I>MwIc>& zd9@PmME5P5d@jnU$$1r6s%x>*KyX zV`)5xdwE~lH^psArFTlrcWE}WC7+Q3EQC90sK2uNnoWPxp*WZ<_{CN8s>tl{FFMW3 zx!f>;*Jq}to#|P0ZrMi`y``;{XyuZ=UFin3zn8s;0`EP~7*fRbsZC`tt?XKFyr_Zh zTd3D_ckTo|6C3%42rPKzge40>Z7z4`Tg3^?qA>~~gUgIG`wt?e!w}Ct=vm1a*IRlz zlQf|xt8I{)@nZYYL;P(aL?wHmXIbr)x2+cAz5EH;q%W2Q;RyuA^YN{@yv)ssoJhR_ z56NK#3tspJZQ!iZcq$}>R%WPo*jx)@_F`7PBbIFDVz*?{+9Vj@T+cn*!SX@!5aD@; zcj(S)mz?eak?;BA6^1zBBcuU#Ltbt-M7QfCj*~9mp2~7}DKtuIJ}1r(Pa_rjEQKWJ z;_=4D;-rv{h!at|j~{lR-vDXH!9+vvM|KK@O2vT5t;l}tMLO-M9TIK!9MsU|ncfmHlaeW~Wlbaw*FbXIm~E)b@#h7~rN>0P7F zf5-uzY##^!~w$8zzJ^_c5LNut7ZC~s5kI>8`JYibc6G&B%V>idI*sgX0 zM$FWXiVGJ-8iAQysSMIAA>@o%gdTmmS(XZj;>`KWwJdRYnwy4GTkrbwF55ehw)jx*ywO9xto?$S`~;G+v;}jmmBeqz8{@^P{mmvlk0j%r{?y z-2oq^3rEs6K<-z);F2zxMSgyQ8c@vUf~=WGr+KX$jzxx`|< zUo8Q=xj-=+aF2R9a1mAi{8nK{aznOyp*>-Mdi?yO>-uj^vnVixnn75eVZHC+vq-33 zJUNG>5_oGNLa!#(usXYCAZLFVUEC2C1H$}43PUd=l_vU1^RksTVVs_s;YC}p|6p|46*)dV_ug_G`DGtTc_%>#CO*!syy`WFE*=GjPL*%bvEPApD+En(KA0 zgpb*?TOoqX7kG4r+l z9FLS{Qo`OP*O$TMUi_ObweKAElX7g|ynN^ygW-T`mczuJy?Xl%)L4N>O&M{}BU`2T z@rG}%AVaT7qfiNpHa&R907K~5HHBJZ6UNl+l*WHT3o@ypMn_^~mQoD1Di8G&(P`hG8h|D9IsV+V&?6L49F8&-_bnqi@73V-@f;X|lxCiJRtc+|WV702 zc>UovkaHJx$Pn=IsMpg5Sq?^RxcXB`{&~QoaujxSvq77^bl*Qq@_}ru?2b*l?B%*`x^O7lQ%J&D3>baO6efLh0q(tQ0{Lqw&lX5hYX9U=lzn_%wMY^|cIIA7e- zpobzihTO@hDah$~XYfuDE@hM^{%x77TRd#P;uL5hWV#ZMv$yjEE}ct{`4yLuwHNzQ zZeY@;F?43oE8p)|ZdX}zH4bhpS)(btF?Zd*(Oi@*Sd*#%#t~P30xVDwrx{s;5ewxic&J_B%E>?f@q$gMA2i346z^1FHLkI z$-PCr#m^@TPI~+I={+$`R|UfV=KIe{6&@J%_eR>H+c&;l0)f~tX?V?ZbLgf0|H^V; zfh7-MD%f{ja$X8arF~&B15^dEji0_QB#5=sfqQ096-kdAVMiXeWE+w-nH%&ugJ|d^ z3w|@Xp|W|qT@DhW@Zn~mSrkxwojH$iy#?SM*}{AU02tUpowJ6~(0v0KV)hPQ$dIRl zmZN1JHfvYA0si372Y-M$_YBlYqy&dwgsQ%M1FuT{Lnf+rYcJ1&c+`}O(s3LID<$wl z86%D-cvaBSqHGzTK(3)oQl&dhPJp;I=o1pfh7{xP@*&R^hOgxjQb)E_`P!s-P|jYS zt#ZE(u8VkVH3wd>xTE1Qm3`?W`8iXg=4xKFoYG7wPe|-=_dk*TT}3ua!f?ob=HQ{` z`0IA@#mC;gr15h?--;Z|xROSyq*Sa!%+5ai&0Dzcd7lq~hwQ;u8Go(W@SYK~lR!v7 zKtl``;w1Qo@PC`dncF#7>~AT|mT`#iOd0`5^8fb{a8KUuJsVZv67QNU>dgs_!yMAy*RtY3?r<_z;Tu3avtV~uq zz-==ox>+%HUpy;B9d#9l1g+ zMQu4(dghbSoKlPM<3aLG&MRqO@~;d~+=HmJPjt6w+4DQ6+t=ayKV*IftUW4g#= zYUS{IT**g8c(=UTbfv%T92SNQ>-zc~WxGe-hm?39=5Cszo&Bs|b@Bcd&2e{ngi?!g z;6Effq>D7Wy}sVJd~G?*UX$9;V6GeY(OXoU9qo(abE%&UFYy*$c@tnhJs9*!4*HOo z70w(NyfwD|Hprui*~pdX8}878edpJ$bMMLuarcatP<@x%=Ovvaj;YGU>g#Y?8A(v2 zcjdLfB1#ttor^|;9lo6Flr)-g6&S8|1?$P~?GY3FxdzF=Wy5o~fU?>GeWv+CpB-=C zv9tL~mM(ogp|+&PO{74O=@;64{b`5vf*DnqSUTU0@JE-wzSVbR zDqnc)I={`;zvOza>cw)hSO*2Ux-kiK^GO$2`NAA`^Mw?UNjiTsLqE!%CM0g>0;%`%fr59DNb(?K9PKT z;icsYHLrY+?zHHvW`&+?5nKii|fY@#aJqIKHhobq`(~1<$8gs z#@g@^mLk_>>r6L2kokW#)mka{8w=3VXs~z=)$f{WYH$C4YWhn}laQCd7cxg1C`Y`h zp4@)-#DF#`T>91F(n^(kA4(swpTi=RS2!haY|X2V^%dw5-H|+WU(NHInogGg{BSlK z@ADwu(KXyqqN@zLF0RT*)V&d-ZHwe5yPVa56U-nN z^o_1{FbWC29xQAZxYj}tSRMpE028IN+a#ast7Mj$)ej2siuO;n=WUYin^m+ZP_V9_x*zrsMi}q@asqq+&oo_134SLCos$ zNz^%6XFp-Clnn7Fg$Rir5%NBl@B7V4O4GJFNEG@mKwwaqT!`9`h}$lovo3c>>p_IC zMdBEwW{Bs~TNmf$i}V+z5;STm8KJZOvKUK;Z~;?Iaa-+mZ5oI8zN8fPK7E%5-|pYa zuYRnR*#JA|=e^LLH*R*6wR2khE3J6Aw)0He7S-lvQ-*a=fASmEEc#BS2+671)LSu) zR=J%?Yhr%X45vz+ZE3u5Ph)d52pHv`AbFfxSRNt9G;{TqAgQEuix#bUEWFKcm)qrq zVb}AHGJZ|Y#mbc)TO&LFSa*+CU^=~plj!4(qE}i4&cun#oFk0MDkOt9B4T=0LVb>y zOSsat^jWsihn^Zi+u!HBT3r{Vl*v6{jZ79jzhE{V#S3{j%v%($Rpg+~Y_mSkN>4eV zz9XG`{XON)Q2{q*`^cGFbBmaEFROe?#Jh*jN8FtUB|s#`*f#nwkAv$Uk4EzG|e|yA)nJp7&~5 z|LE|d@#In?XN&j$YziR}AHlD9?mS;t!x^wfR~B^N{~bIG6zy#9SlHe%LAcsm+&0=b zGq6j40&-C;6{mm$H3p^$Y%l!VVG6#IGjXu6zAeDN|MOr*kw=0P7q|%s>K+ghfJNkg zJF38%U`{t~->?$^(WRpexIexdryq9;$^;+COo|c`F#eXCfPhozXMP*g+jlG+ZVUYT z8y{x$8Z<%_lwBR%6v*JWW7ps(#vZI^e_P=DPke}T7f(ijLJ%Z_2;;KET2$=qm z^mqt>-1O&^pga+LYV`9+dm4I#hlheWQ7Y<%!9u2&G*%OpSLGmDnkpC|nyxQ#U zur4rsnt;ID_Mm(!CH}&}tIlb!ugKQ`!%Dk)usrQ1f8pTO=bT{*$S80PVqhJoKjl*i zOcXvj3**)2ny)qa!+1HJ5r5&})n@{-#ki-S-7o&9-Csrjg@acQ<%krw6+ne%{?or+ z$Nq(bR}a^t2If1!4krERgYrQX|Am8B54Eo^GmZi8Q_6af18@2Z2d^G>Oukp11e_1R z2L0Jy7F~bg;MK#;yw%l1V33jVpYnJ<{|g7N9^QXkt>1#T-D^hv!oh2QdhS7oj{qy* z^dCJeAH&Z%hgT1I^D4)Mfqc6EQ?J#Dzi{yCVF8;uOEu8LG~hD+l(X^dUpRQ{wWM>h zehzRhP#olF&HsgiSD*i0FWaTRaPaDLz?Rm%bRg&3z$X4#uaU2R;o#M0HS+Tw_kjK= zgD~t*4t5(qM;NdDp);jV%kv{5xHC#|ATo15MD(xy`4ySrZK|p|rjTpEl?Iz1^z8b< zhwz#(yqL>IOTy3p)#N|pjFklZ7`zQGxJl?+0~-9%k%Oh#Ou~=B+uk{+3vmxXX-dE* zN`IE-V;X)8-sY~144P8~UCIEs^*=F{nfNhyTe~|TqmUKEmbE~0{){h0N`GPw#+ToP zj5oeKyI|=n2JAb%?2j+ye}z#o*q^jJRu(oE0^fh)Z7pXNR9`4y7)c*wY}eso;B6|C ze4PPPAmb2FD`4V(JE}W=GMsPNUbAz)jW4utH|YE4^L{IXy=M16`2TgNb^px%TQ%^u zPY^MW#0Frn{fA-m5)T7!#9L6aQf(yv4)7>sBPZ0zKCOo&gZ=1F#=$+z4wmEKs@1<3*IDo|zOP~ZgYl~z2bakF#kg=9599lSnFkpM z7o+*bpg)I)@qKBUgN%a Date: Tue, 17 Mar 2026 16:26:23 +0100 Subject: [PATCH 2/2] Update README.md with new sample --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a20d600..839330f 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ This repository contains comprehensive sample projects demonstrating how to deve | [Function App and Storage](./samples/function-app-storage-http/dotnet/README.md) | Azure Functions App using Blob, Queue, and Table Storage | | [Function App and Front Door](./samples/function-app-front-door/python/README.md) | Azure Functions App exposed via Front Door | | [Function App and Managed Identities](./samples/function-app-managed-identity/python/README.md) | Azure Function App using Managed Identities | +| [Function App and Service Bus](./samples/function-app-service-bus/dotnet/README.md) | Azure Function App using Service Bus | | [Web App and CosmosDB for MongoDB API ](./samples/web-app-cosmosdb-mongodb-api/python/README.md) | Azure Web App using CosmosDB for MongoDB API | | [Web App and CosmosDB for NoSQL API ](./samples/web-app-cosmosdb-nosql-api/python/README.md) | Azure Web App using CosmosDB for NoSQL API | | [Web App and Managed Identities](./samples/web-app-managed-identity/python/README.md) | Azure Web App using Managed Identities |