@HtmlLocalizer["Taste our coffee"]
- @foreach (var cafe in Model)
+ @foreach (var cafe in Model.Cafes)
{
}
diff --git a/examples/DancingGoat/Components/ViewComponents/NavigationMenu/NavigationMenuViewComponent.cs b/examples/DancingGoat/Components/ViewComponents/NavigationMenu/NavigationMenuViewComponent.cs
index b7e0fbe..0dbdf25 100644
--- a/examples/DancingGoat/Components/ViewComponents/NavigationMenu/NavigationMenuViewComponent.cs
+++ b/examples/DancingGoat/Components/ViewComponents/NavigationMenu/NavigationMenuViewComponent.cs
@@ -27,4 +27,4 @@ public async Task
InvokeAsync()
return View($"~/Components/ViewComponents/NavigationMenu/Default.cshtml", navigationViewModels);
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Components/ViewComponents/TrackingConsent/TrackingConsentViewComponent.cs b/examples/DancingGoat/Components/ViewComponents/TrackingConsent/TrackingConsentViewComponent.cs
index 5aba6e7..dc70e54 100644
--- a/examples/DancingGoat/Components/ViewComponents/TrackingConsent/TrackingConsentViewComponent.cs
+++ b/examples/DancingGoat/Components/ViewComponents/TrackingConsent/TrackingConsentViewComponent.cs
@@ -54,7 +54,7 @@ public async Task InvokeAsync()
{
ConsentShortText = (await consent.GetConsentTextAsync(currentLanguage)).ShortText,
ReturnPageUrl = webPageDataContextRetriever.TryRetrieve(out var currentWebPageContext)
- ? (await urlRetriever.Retrieve(currentWebPageContext.WebPage.WebPageItemID, currentLanguage)).RelativePath
+ ? (await urlRetriever.Retrieve(currentWebPageContext.WebPage.WebPageItemID, currentLanguage, cancellationToken: HttpContext.RequestAborted)).RelativePath
: (HttpContext.Request.PathBase + HttpContext.Request.Path).Value
};
@@ -62,7 +62,7 @@ public async Task InvokeAsync()
if ((contact != null) && consentAgreementService.IsAgreed(contact, consent))
{
consentModel.IsConsentAgreed = true;
- consentModel.PrivacyPageUrl = Url.Content((await urlRetriever.Retrieve(PrivacyPageConstants.PRIVACY_PAGE_TREE_PATH, websiteChannelContext.WebsiteChannelName, currentLanguage)).RelativePath);
+ consentModel.PrivacyPageUrl = Url.Content((await urlRetriever.Retrieve(PrivacyPageConstants.PRIVACY_PAGE_TREE_PATH, websiteChannelContext.WebsiteChannelName, currentLanguage, cancellationToken: HttpContext.RequestAborted)).RelativePath);
}
return View("~/Components/ViewComponents/TrackingConsent/Default.cshtml", consentModel);
diff --git a/examples/DancingGoat/Components/Widgets/CTAButton/CTAButtonWidgetViewModel.cs b/examples/DancingGoat/Components/Widgets/CTAButton/CTAButtonWidgetViewModel.cs
index e4666ff..7d2ea2e 100644
--- a/examples/DancingGoat/Components/Widgets/CTAButton/CTAButtonWidgetViewModel.cs
+++ b/examples/DancingGoat/Components/Widgets/CTAButton/CTAButtonWidgetViewModel.cs
@@ -22,4 +22,4 @@ public class CTAButtonWidgetViewModel
///
public bool OpenInNewTab { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Components/Widgets/CardWidget/CardWidgetProperties.cs b/examples/DancingGoat/Components/Widgets/CardWidget/CardWidgetProperties.cs
index cd47e46..c432008 100644
--- a/examples/DancingGoat/Components/Widgets/CardWidget/CardWidgetProperties.cs
+++ b/examples/DancingGoat/Components/Widgets/CardWidget/CardWidgetProperties.cs
@@ -23,4 +23,4 @@ public class CardWidgetProperties : IWidgetProperties
///
public string Text { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Components/Widgets/CardWidget/CardWidgetViewComponent.cs b/examples/DancingGoat/Components/Widgets/CardWidget/CardWidgetViewComponent.cs
index d532287..e008489 100644
--- a/examples/DancingGoat/Components/Widgets/CardWidget/CardWidgetViewComponent.cs
+++ b/examples/DancingGoat/Components/Widgets/CardWidget/CardWidgetViewComponent.cs
@@ -1,4 +1,4 @@
-using System.Linq;
+using System.Linq;
using System.Threading.Tasks;
using DancingGoat.Models;
@@ -66,4 +66,4 @@ private async Task GetImage(CardWidgetProperties properties, string langu
return await imageRepository.GetImage(image.Identifier, languageName);
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Components/Widgets/CardWidget/CardWidgetViewModel.cs b/examples/DancingGoat/Components/Widgets/CardWidget/CardWidgetViewModel.cs
index 4c36108..7e27780 100644
--- a/examples/DancingGoat/Components/Widgets/CardWidget/CardWidgetViewModel.cs
+++ b/examples/DancingGoat/Components/Widgets/CardWidget/CardWidgetViewModel.cs
@@ -16,4 +16,4 @@ public class CardWidgetViewModel
///
public string Text { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Components/Widgets/HeroImageWidget/HeroImageWidgetProperties.cs b/examples/DancingGoat/Components/Widgets/HeroImageWidget/HeroImageWidgetProperties.cs
index cf92a29..ad72474 100644
--- a/examples/DancingGoat/Components/Widgets/HeroImageWidget/HeroImageWidgetProperties.cs
+++ b/examples/DancingGoat/Components/Widgets/HeroImageWidget/HeroImageWidgetProperties.cs
@@ -46,4 +46,4 @@ public class HeroImageWidgetProperties : IWidgetProperties
[DropDownComponent(Label = "Color scheme", Order = 3, Options = "light;Light\ndark;Dark")]
public string Theme { get; set; } = "dark";
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Components/Widgets/HeroImageWidget/HeroImageWidgetViewComponent.cs b/examples/DancingGoat/Components/Widgets/HeroImageWidget/HeroImageWidgetViewComponent.cs
index 9fc24f3..4e74f23 100644
--- a/examples/DancingGoat/Components/Widgets/HeroImageWidget/HeroImageWidgetViewComponent.cs
+++ b/examples/DancingGoat/Components/Widgets/HeroImageWidget/HeroImageWidgetViewComponent.cs
@@ -1,4 +1,4 @@
-using System.Linq;
+using System.Linq;
using System.Threading.Tasks;
using DancingGoat.Models;
@@ -68,4 +68,4 @@ private async Task GetImage(HeroImageWidgetProperties properties, string
return await imageRepository.GetImage(image.Identifier, languageName);
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Components/Widgets/HeroImageWidget/HeroImageWidgetViewModel.cs b/examples/DancingGoat/Components/Widgets/HeroImageWidget/HeroImageWidgetViewModel.cs
index 84f095a..6c50c57 100644
--- a/examples/DancingGoat/Components/Widgets/HeroImageWidget/HeroImageWidgetViewModel.cs
+++ b/examples/DancingGoat/Components/Widgets/HeroImageWidget/HeroImageWidgetViewModel.cs
@@ -34,4 +34,4 @@ public class HeroImageWidgetViewModel
///
public string Theme { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardListViewModel.cs b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardListViewModel.cs
index 26c15fc..7c37d68 100644
--- a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardListViewModel.cs
+++ b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardListViewModel.cs
@@ -21,10 +21,10 @@ public class ProductCardListViewModel
///
/// Collection of products.
/// Hydrated ViewModel.
- public static ProductCardListViewModel GetViewModel(IEnumerable products)
+ public static ProductCardListViewModel GetViewModel(IEnumerable products)
{
var productModels = new List();
-
+
foreach (var product in products.Where(product => product != null))
{
var productModel = ProductCardViewModel.GetViewModel(product);
@@ -37,4 +37,4 @@ public static ProductCardListViewModel GetViewModel(IEnumerable products
};
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardProperties.cs b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardProperties.cs
index 478674a..cf4a8d3 100644
--- a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardProperties.cs
+++ b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardProperties.cs
@@ -2,8 +2,6 @@
using CMS.ContentEngine;
-using DancingGoat.Models;
-
using Kentico.PageBuilder.Web.Mvc;
using Kentico.Xperience.Admin.Base.FormAnnotations;
@@ -17,7 +15,7 @@ public class ProductCardProperties : IWidgetProperties
///
/// Selected products.
///
- [ContentItemSelectorComponent(Coffee.CONTENT_TYPE_NAME, Label = "Selected products", Order = 1)]
+ [ContentItemSelectorComponent(typeof(ProductCardSchemaFilter), Label = "Selected products", Order = 1)]
public IEnumerable SelectedProducts { get; set; } = new List();
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardSchemaFilter.cs b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardSchemaFilter.cs
new file mode 100644
index 0000000..9f36e5f
--- /dev/null
+++ b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardSchemaFilter.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+
+using DancingGoat.Models;
+
+using Kentico.Xperience.Admin.Base.FormAnnotations;
+
+namespace DancingGoat.Widgets
+{
+ ///
+ /// Product card widget filter for content item selector.
+ ///
+ public class ProductCardSchemaFilter : IReusableFieldSchemasFilter
+ {
+ ///
+ IEnumerable IReusableFieldSchemasFilter.AllowedSchemaNames => new List { IProductFields.REUSABLE_FIELD_SCHEMA_NAME };
+ }
+}
diff --git a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardViewModel.cs b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardViewModel.cs
index 6b5b86d..19936a5 100644
--- a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardViewModel.cs
+++ b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardViewModel.cs
@@ -32,7 +32,7 @@ public class ProductCardViewModel
///
/// Product.
/// Hydrated ViewModel.
- public static ProductCardViewModel GetViewModel(Coffee product)
+ public static ProductCardViewModel GetViewModel(IProductFields product)
{
if (product == null)
{
@@ -40,11 +40,11 @@ public static ProductCardViewModel GetViewModel(Coffee product)
}
return new ProductCardViewModel
- {
- Heading = product.CoffeeName,
- ImagePath = (product.CoffeeImage.FirstOrDefault())?.ImageFile.Url,
- Text = product.CoffeeShortDescription
- };
+ {
+ Heading = product.ProductFieldsName,
+ ImagePath = product.ProductFieldsImage.FirstOrDefault()?.ImageFile.Url,
+ Text = product.ProductFieldsShortDescription
+ };
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardWidgetViewComponent.cs b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardWidgetViewComponent.cs
index c127307..04a3e77 100644
--- a/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardWidgetViewComponent.cs
+++ b/examples/DancingGoat/Components/Widgets/ProductCardWidget/ProductCardWidgetViewComponent.cs
@@ -1,7 +1,8 @@
-using System.Collections.Generic;
-using System.Linq;
+using System.Linq;
using System.Threading.Tasks;
+using CMS.ContentEngine;
+
using DancingGoat.Models;
using DancingGoat.Widgets;
@@ -26,7 +27,7 @@ public class ProductCardWidgetViewComponent : ViewComponent
public const string IDENTIFIER = "DancingGoat.LandingPage.ProductCardWidget";
- private readonly CoffeeRepository repository;
+ private readonly ProductRepository repository;
private readonly IPreferredLanguageRetriever currentLanguageRetriever;
@@ -35,7 +36,7 @@ public class ProductCardWidgetViewComponent : ViewComponent
///
/// Repository for retrieving products.
/// Retrieves preferred language name for the current request. Takes language fallback into account.
- public ProductCardWidgetViewComponent(CoffeeRepository repository, IPreferredLanguageRetriever currentLanguageRetriever)
+ public ProductCardWidgetViewComponent(ProductRepository repository, IPreferredLanguageRetriever currentLanguageRetriever)
{
this.repository = repository;
this.currentLanguageRetriever = currentLanguageRetriever;
@@ -46,11 +47,11 @@ public async Task InvokeAsync(ProductCardProperties pro
{
var languageName = currentLanguageRetriever.Get();
var selectedProductGuids = properties.SelectedProducts.Select(i => i.Identifier).ToList();
- IEnumerable products = (await repository.GetCoffees(selectedProductGuids, languageName))
- .OrderBy(p => selectedProductGuids.IndexOf(p.SystemFields.ContentItemGUID));
+ var products = (await repository.GetProducts(selectedProductGuids, languageName))
+ .OrderBy(p => selectedProductGuids.IndexOf(((IContentItemFieldsSource)p).SystemFields.ContentItemGUID));
var model = ProductCardListViewModel.GetViewModel(products);
return View("~/Components/Widgets/ProductCardWidget/_ProductCardWidget.cshtml", model);
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Components/Widgets/TestimonialWidget/TestimonialWidgetProperties.cs b/examples/DancingGoat/Components/Widgets/TestimonialWidget/TestimonialWidgetProperties.cs
index 3decca3..57c31e9 100644
--- a/examples/DancingGoat/Components/Widgets/TestimonialWidget/TestimonialWidgetProperties.cs
+++ b/examples/DancingGoat/Components/Widgets/TestimonialWidget/TestimonialWidgetProperties.cs
@@ -12,7 +12,7 @@ public class TestimonialWidgetProperties : IWidgetProperties
///
public string QuotationText { get; set; }
-
+
///
/// Author text.
///
@@ -24,4 +24,4 @@ public class TestimonialWidgetProperties : IWidgetProperties
///
public string ColorCssClass { get; set; } = "first-color";
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Controllers/AccountController.cs b/examples/DancingGoat/Controllers/AccountController.cs
index 704a8f4..f43a9c6 100644
--- a/examples/DancingGoat/Controllers/AccountController.cs
+++ b/examples/DancingGoat/Controllers/AccountController.cs
@@ -180,10 +180,10 @@ private async Task GetHomeWebPageUrl(CancellationToken cancellationToken
}
var homePageUrl = await webPageUrlRetriever.Retrieve(
- websiteChannel.WebsiteChannelHomePage,
- websiteChannelContext.WebsiteChannelName,
- currentLanguageRetriever.Get(),
- websiteChannelContext.IsPreview,
+ websiteChannel.WebsiteChannelHomePage,
+ websiteChannelContext.WebsiteChannelName,
+ currentLanguageRetriever.Get(),
+ websiteChannelContext.IsPreview,
cancellationToken
);
@@ -196,4 +196,4 @@ private async Task GetHomeWebPageUrl(CancellationToken cancellationToken
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Controllers/ConsentController.cs b/examples/DancingGoat/Controllers/ConsentController.cs
index 79545e1..5e11048 100644
--- a/examples/DancingGoat/Controllers/ConsentController.cs
+++ b/examples/DancingGoat/Controllers/ConsentController.cs
@@ -5,6 +5,7 @@
using DancingGoat.Helpers.Generator;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace DancingGoat.Controllers
diff --git a/examples/DancingGoat/Controllers/DancingGoatArticleController.cs b/examples/DancingGoat/Controllers/DancingGoatArticleController.cs
index cf03528..260fd39 100644
--- a/examples/DancingGoat/Controllers/DancingGoatArticleController.cs
+++ b/examples/DancingGoat/Controllers/DancingGoatArticleController.cs
@@ -27,22 +27,22 @@ public class DancingGoatArticleController : Controller
private readonly IPreferredLanguageRetriever currentLanguageRetriever;
- public DancingGoatArticleController(
- ArticlePageRepository articlePageRepository,
- ArticlesSectionRepository articlesSectionRepository,
- IWebPageUrlRetriever urlRetriever,
- IWebPageDataContextRetriever webPageDataContextRetriever,
- IPreferredLanguageRetriever currentLanguageRetriever)
- {
- this.articlePageRepository = articlePageRepository;
- this.articlesSectionRepository = articlesSectionRepository;
- this.urlRetriever = urlRetriever;
- this.webPageDataContextRetriever = webPageDataContextRetriever;
- this.currentLanguageRetriever = currentLanguageRetriever;
- }
-
-
- public async Task Index()
+ public DancingGoatArticleController(
+ ArticlePageRepository articlePageRepository,
+ ArticlesSectionRepository articlesSectionRepository,
+ IWebPageUrlRetriever urlRetriever,
+ IWebPageDataContextRetriever webPageDataContextRetriever,
+ IPreferredLanguageRetriever currentLanguageRetriever)
+ {
+ this.articlePageRepository = articlePageRepository;
+ this.articlesSectionRepository = articlesSectionRepository;
+ this.urlRetriever = urlRetriever;
+ this.webPageDataContextRetriever = webPageDataContextRetriever;
+ this.currentLanguageRetriever = currentLanguageRetriever;
+ }
+
+
+ public async Task Index()
{
var languageName = currentLanguageRetriever.Get();
@@ -55,11 +55,15 @@ public async Task Index()
var models = new List();
foreach (var article in articles)
{
- var model = await ArticleViewModel.GetViewModel(article, urlRetriever, languageName);
- models.Add(model);
+ var articleModel = await ArticleViewModel.GetViewModel(article, urlRetriever, languageName);
+ models.Add(articleModel);
}
- return View(models);
+ var url = (await urlRetriever.Retrieve(articlesSection, languageName)).RelativePath;
+
+ var model = ArticlesSectionViewModel.GetViewModel(articlesSection, models, url);
+
+ return View(model);
}
diff --git a/examples/DancingGoat/Controllers/DancingGoatCoffeeController.cs b/examples/DancingGoat/Controllers/DancingGoatCoffeeController.cs
new file mode 100644
index 0000000..75421af
--- /dev/null
+++ b/examples/DancingGoat/Controllers/DancingGoatCoffeeController.cs
@@ -0,0 +1,48 @@
+using System.Threading.Tasks;
+
+using Microsoft.AspNetCore.Mvc;
+
+using CMS.ContentEngine;
+
+using Kentico.Content.Web.Mvc;
+using Kentico.Content.Web.Mvc.Routing;
+
+using DancingGoat;
+using DancingGoat.Controllers;
+using DancingGoat.Models;
+
+[assembly: RegisterWebPageRoute(CoffeePage.CONTENT_TYPE_NAME, typeof(DancingGoatCoffeeController), WebsiteChannelNames = new[] { DancingGoatConstants.WEBSITE_CHANNEL_NAME }, ActionName = nameof(DancingGoatCoffeeController.Detail))]
+
+namespace DancingGoat.Controllers
+{
+ public class DancingGoatCoffeeController : Controller
+ {
+ private readonly ProductPageRepository productPageRepository;
+ private readonly IWebPageDataContextRetriever webPageDataContextRetriever;
+ private readonly IPreferredLanguageRetriever currentLanguageRetriever;
+ private readonly ITaxonomyRetriever taxonomyRetriever;
+
+
+ public DancingGoatCoffeeController(ProductPageRepository productPageRepository,
+ IWebPageDataContextRetriever webPageDataContextRetriever,
+ IPreferredLanguageRetriever currentLanguageRetriever,
+ ITaxonomyRetriever taxonomyRetriever)
+ {
+ this.productPageRepository = productPageRepository;
+ this.webPageDataContextRetriever = webPageDataContextRetriever;
+ this.currentLanguageRetriever = currentLanguageRetriever;
+ this.taxonomyRetriever = taxonomyRetriever;
+ }
+
+
+ public async Task Detail()
+ {
+ var languageName = currentLanguageRetriever.Get();
+ var webPageItemId = webPageDataContextRetriever.Retrieve().WebPage.WebPageItemID;
+
+ var coffee = await productPageRepository.GetProduct(CoffeePage.CONTENT_TYPE_NAME, webPageItemId, languageName, cancellationToken: HttpContext.RequestAborted);
+
+ return View(await CoffeeDetailViewModel.GetViewModel(coffee, languageName, taxonomyRetriever));
+ }
+ }
+}
diff --git a/examples/DancingGoat/Controllers/DancingGoatConfirmationController.cs b/examples/DancingGoat/Controllers/DancingGoatConfirmationController.cs
index f213f4a..2a4d559 100644
--- a/examples/DancingGoat/Controllers/DancingGoatConfirmationController.cs
+++ b/examples/DancingGoat/Controllers/DancingGoatConfirmationController.cs
@@ -37,4 +37,4 @@ public async Task Index()
return View(ConfirmationPageViewModel.GetViewModel(confirmationPage));
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Controllers/DancingGoatContactsController.cs b/examples/DancingGoat/Controllers/DancingGoatContactsController.cs
index 1642f8b..ceadd78 100644
--- a/examples/DancingGoat/Controllers/DancingGoatContactsController.cs
+++ b/examples/DancingGoat/Controllers/DancingGoatContactsController.cs
@@ -6,6 +6,8 @@
using DancingGoat;
using DancingGoat.Controllers;
using DancingGoat.Models;
+
+using Kentico.Content.Web.Mvc;
using Kentico.Content.Web.Mvc.Routing;
using Microsoft.AspNetCore.Mvc;
@@ -16,45 +18,57 @@ namespace DancingGoat.Controllers
{
public class DancingGoatContactsController : Controller
{
+ private readonly ContactsPageRepository contactsPageRepository;
private readonly ContactRepository contactRepository;
private readonly CafeRepository cafeRepository;
private readonly IPreferredLanguageRetriever currentLanguageRetriever;
+ private readonly IWebPageDataContextRetriever webPageDataContextRetriever;
- public DancingGoatContactsController(ContactRepository contactRepository,
- CafeRepository cafeRepository, IPreferredLanguageRetriever currentLanguageRetriever)
+ public DancingGoatContactsController(ContactsPageRepository contactsPageRepository, ContactRepository contactRepository,
+ CafeRepository cafeRepository, IPreferredLanguageRetriever currentLanguageRetriever, IWebPageDataContextRetriever webPageDataContextRetriever)
{
+ this.contactsPageRepository = contactsPageRepository;
this.contactRepository = contactRepository;
this.cafeRepository = cafeRepository;
this.currentLanguageRetriever = currentLanguageRetriever;
+ this.webPageDataContextRetriever = webPageDataContextRetriever;
}
public async Task Index(CancellationToken cancellationToken)
{
- var model = await GetIndexViewModel(cancellationToken);
+ var webPage = webPageDataContextRetriever.Retrieve().WebPage;
+
+ var contactsPage = await contactsPageRepository.GetContactsPage(webPage.WebPageItemID, webPage.LanguageName, HttpContext.RequestAborted);
+
+ var model = await GetIndexViewModel(contactsPage, cancellationToken);
return View(model);
}
- private async Task GetIndexViewModel(CancellationToken cancellationToken)
+ private async Task GetIndexViewModel(ContactsPage contactsPage, CancellationToken cancellationToken)
{
var languageName = currentLanguageRetriever.Get();
- var cafes = await cafeRepository.GetCompanyCafes(4, languageName, cancellationToken);
+ var cafes = (await cafeRepository.GetCafes(0, languageName, cancellationToken)).ToList();
+ var companyCafes = cafes.Where(c => c.CafeIsCompanyCafe).OrderBy(c => c.CafeName);
+ var partnerCafes = cafes.Where(c => !c.CafeIsCompanyCafe).OrderBy(c => c.CafeCity);
var contact = await contactRepository.GetContact(languageName, HttpContext.RequestAborted);
return new ContactsIndexViewModel
{
CompanyContact = ContactViewModel.GetViewModel(contact),
- CompanyCafes = GetCompanyCafesModel(cafes)
+ CompanyCafes = GetCafesModel(companyCafes),
+ PartnerCafes = GetCafesModel(partnerCafes),
+ WebPage = contactsPage
};
}
- private List GetCompanyCafesModel(IEnumerable cafes)
+ private List GetCafesModel(IEnumerable cafes)
{
return cafes.Select(cafe => CafeViewModel.GetViewModel(cafe)).ToList();
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Controllers/DancingGoatGrinderController.cs b/examples/DancingGoat/Controllers/DancingGoatGrinderController.cs
new file mode 100644
index 0000000..be3f1a4
--- /dev/null
+++ b/examples/DancingGoat/Controllers/DancingGoatGrinderController.cs
@@ -0,0 +1,48 @@
+using System.Threading.Tasks;
+
+using Microsoft.AspNetCore.Mvc;
+
+using CMS.ContentEngine;
+
+using Kentico.Content.Web.Mvc;
+using Kentico.Content.Web.Mvc.Routing;
+
+using DancingGoat;
+using DancingGoat.Controllers;
+using DancingGoat.Models;
+
+[assembly: RegisterWebPageRoute(GrinderPage.CONTENT_TYPE_NAME, typeof(DancingGoatGrinderController), WebsiteChannelNames = new[] { DancingGoatConstants.WEBSITE_CHANNEL_NAME }, ActionName = nameof(DancingGoatGrinderController.Detail))]
+
+namespace DancingGoat.Controllers
+{
+ public class DancingGoatGrinderController : Controller
+ {
+ private readonly ProductPageRepository productPageRepository;
+ private readonly IWebPageDataContextRetriever webPageDataContextRetriever;
+ private readonly IPreferredLanguageRetriever currentLanguageRetriever;
+ private readonly ITaxonomyRetriever taxonomyRetriever;
+
+
+ public DancingGoatGrinderController(ProductPageRepository productPageRepository,
+ IWebPageDataContextRetriever webPageDataContextRetriever,
+ IPreferredLanguageRetriever currentLanguageRetriever,
+ ITaxonomyRetriever taxonomyRetriever)
+ {
+ this.productPageRepository = productPageRepository;
+ this.webPageDataContextRetriever = webPageDataContextRetriever;
+ this.currentLanguageRetriever = currentLanguageRetriever;
+ this.taxonomyRetriever = taxonomyRetriever;
+ }
+
+
+ public async Task Detail()
+ {
+ var languageName = currentLanguageRetriever.Get();
+ var webPageItemId = webPageDataContextRetriever.Retrieve().WebPage.WebPageItemID;
+
+ var grinder = await productPageRepository.GetProduct(GrinderPage.CONTENT_TYPE_NAME, webPageItemId, languageName, cancellationToken: HttpContext.RequestAborted);
+
+ return View(await GrinderDetailViewModel.GetViewModel(grinder, languageName, taxonomyRetriever));
+ }
+ }
+}
diff --git a/examples/DancingGoat/Controllers/DancingGoatHomeController.cs b/examples/DancingGoat/Controllers/DancingGoatHomeController.cs
index 38d5823..68ee611 100644
--- a/examples/DancingGoat/Controllers/DancingGoatHomeController.cs
+++ b/examples/DancingGoat/Controllers/DancingGoatHomeController.cs
@@ -34,4 +34,4 @@ public async Task Index()
return View(HomePageViewModel.GetViewModel(homePage));
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Controllers/DancingGoatLandingPageController.cs b/examples/DancingGoat/Controllers/DancingGoatLandingPageController.cs
new file mode 100644
index 0000000..5dd7951
--- /dev/null
+++ b/examples/DancingGoat/Controllers/DancingGoatLandingPageController.cs
@@ -0,0 +1,42 @@
+using System.Threading.Tasks;
+
+using DancingGoat;
+using DancingGoat.Controllers;
+using DancingGoat.Models;
+
+using Kentico.Content.Web.Mvc;
+using Kentico.Content.Web.Mvc.Routing;
+using Kentico.PageBuilder.Web.Mvc.PageTemplates;
+
+using Microsoft.AspNetCore.Mvc;
+
+[assembly: RegisterWebPageRoute(LandingPage.CONTENT_TYPE_NAME, typeof(DancingGoatLandingPageController), WebsiteChannelNames = new[] { DancingGoatConstants.WEBSITE_CHANNEL_NAME })]
+
+namespace DancingGoat.Controllers
+{
+ public class DancingGoatLandingPageController : Controller
+ {
+ private readonly LandingPageRepository landingPageRepository;
+ private readonly IWebPageDataContextRetriever webPageDataContextRetriever;
+ private readonly IPreferredLanguageRetriever currentLanguageRetriever;
+
+
+ public DancingGoatLandingPageController(LandingPageRepository landingPageRepository, IWebPageDataContextRetriever webPageDataContextRetriever, IPreferredLanguageRetriever currentLanguageRetriever)
+ {
+ this.landingPageRepository = landingPageRepository;
+ this.webPageDataContextRetriever = webPageDataContextRetriever;
+ this.currentLanguageRetriever = currentLanguageRetriever;
+ }
+
+
+ public async Task Index()
+ {
+ var webPageItemId = webPageDataContextRetriever.Retrieve().WebPage.WebPageItemID;
+ var languageName = currentLanguageRetriever.Get();
+
+ var landingPage = await landingPageRepository.GetLandingPage(webPageItemId, languageName, cancellationToken: HttpContext.RequestAborted);
+
+ return new TemplateResult(landingPage);
+ }
+ }
+}
diff --git a/examples/DancingGoat/Controllers/DancingGoatPrivacyController.cs b/examples/DancingGoat/Controllers/DancingGoatPrivacyController.cs
index 5a3d602..992fd9c 100644
--- a/examples/DancingGoat/Controllers/DancingGoatPrivacyController.cs
+++ b/examples/DancingGoat/Controllers/DancingGoatPrivacyController.cs
@@ -1,12 +1,19 @@
-using CMS.ContactManagement;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+using CMS.ContactManagement;
using CMS.DataEngine;
using CMS.DataProtection;
-using CMS.Helpers;
+
using DancingGoat;
using DancingGoat.Controllers;
using DancingGoat.Helpers.Generator;
using DancingGoat.Models;
+
+using Kentico.Content.Web.Mvc;
using Kentico.Content.Web.Mvc.Routing;
+
using Microsoft.AspNetCore.Mvc;
[assembly: RegisterWebPageRoute(PrivacyPage.CONTENT_TYPE_NAME, typeof(DancingGoatPrivacyController), WebsiteChannelNames = new[] { DancingGoatConstants.WEBSITE_CHANNEL_NAME })]
@@ -18,10 +25,11 @@ public class DancingGoatPrivacyController : Controller
private const string SUCCESS_RESULT = "success";
private const string ERROR_RESULT = "error";
- private readonly ICurrentCookieLevelProvider cookieLevelProvider;
private readonly IConsentAgreementService consentAgreementService;
private readonly IInfoProvider consentInfoProvider;
private readonly IPreferredLanguageRetriever currentLanguageRetriever;
+ private readonly IWebPageDataContextRetriever webPageDataContextRetriever;
+ private readonly PrivacyPageRepository privacyPageRepository;
private ContactInfo currentContact;
@@ -39,29 +47,33 @@ private ContactInfo CurrentContact
}
- public DancingGoatPrivacyController(
- ICurrentCookieLevelProvider cookieLevelProvider,
- IConsentAgreementService consentAgreementService,
- IInfoProvider consentInfoProvider,
- IPreferredLanguageRetriever currentLanguageRetriever)
+ public DancingGoatPrivacyController(PrivacyPageRepository privacyPageRepository, IConsentAgreementService consentAgreementService, IInfoProvider consentInfoProvider, IPreferredLanguageRetriever currentLanguageRetriever, IWebPageDataContextRetriever webPageDataContextRetriever)
{
- this.cookieLevelProvider = cookieLevelProvider;
+ this.privacyPageRepository = privacyPageRepository;
this.consentAgreementService = consentAgreementService;
this.consentInfoProvider = consentInfoProvider;
this.currentLanguageRetriever = currentLanguageRetriever;
+ this.webPageDataContextRetriever = webPageDataContextRetriever;
}
- public async Task Index()
+ public async Task Index()
{
- var model = new PrivacyViewModel();
+ var webPage = webPageDataContextRetriever.Retrieve().WebPage;
+
+ var privacyPage = await privacyPageRepository.GetPrivacyPage(webPage.WebPageItemID, webPage.LanguageName, HttpContext.RequestAborted);
+
+ var model = new PrivacyViewModel { WebPage = privacyPage };
if (!IsDemoEnabled())
{
model.DemoDisabled = true;
}
+ else if (CurrentContact != null)
+ {
+ model.Consents = GetAgreedConsentsForCurrentContact();
+ }
- model.Consents = await GetAgreedConsentsForCurrentContact();
model.ShowSavedMessage = TempData[SUCCESS_RESULT] != null;
model.ShowErrorMessage = TempData[ERROR_RESULT] != null;
model.PrivacyPageUrl = HttpContext.Request.Path;
@@ -69,28 +81,6 @@ public async Task Index()
return View(model);
}
- [HttpPost]
- [ValidateAntiForgeryToken]
- [Route("/Agree")]
- public ActionResult Agree(string returnUrl, string consentName)
- {
- var consentToAgree = consentInfoProvider.Get(consentName);
-
- cookieLevelProvider.SetCurrentCookieLevel(Kentico.Web.Mvc.CookieLevel.All.Level);
-
- if (consentToAgree != null && CurrentContact != null)
- {
- consentAgreementService.Agree(CurrentContact, consentToAgree);
-
- TempData[SUCCESS_RESULT] = true;
- }
- else
- {
- TempData[ERROR_RESULT] = true;
- }
-
- return Redirect(returnUrl);
- }
[HttpPost]
[ValidateAntiForgeryToken]
@@ -114,17 +104,15 @@ public ActionResult Revoke(string returnUrl, string consentName)
}
- private async Task> GetAgreedConsentsForCurrentContact()
+ private IEnumerable GetAgreedConsentsForCurrentContact()
{
- return await consentInfoProvider.Get()
- .ToAsyncEnumerable()
- .SelectAwait(async consent => new PrivacyConsentViewModel
+ return consentAgreementService.GetAgreedConsents(CurrentContact)
+ .Select(consent => new PrivacyConsentViewModel
{
- Name = consent.ConsentName,
- Title = consent.ConsentDisplayName,
- Text = (await consent.GetConsentTextAsync(currentLanguageRetriever.Get())).ShortText,
- Agreed = CurrentContact is not null && consentAgreementService.IsAgreed(CurrentContact, consent)
- }).ToListAsync();
+ Name = consent.Name,
+ Title = consent.DisplayName,
+ Text = consent.GetConsentText(currentLanguageRetriever.Get()).ShortText
+ });
}
diff --git a/examples/DancingGoat/Controllers/DancingGoatProductController.cs b/examples/DancingGoat/Controllers/DancingGoatProductController.cs
new file mode 100644
index 0000000..511c03d
--- /dev/null
+++ b/examples/DancingGoat/Controllers/DancingGoatProductController.cs
@@ -0,0 +1,97 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+using CMS.ContentEngine;
+using CMS.Websites;
+
+using DancingGoat;
+using DancingGoat.Controllers;
+using DancingGoat.Models;
+
+using Kentico.Content.Web.Mvc;
+using Kentico.Content.Web.Mvc.Routing;
+
+using Microsoft.AspNetCore.Mvc;
+
+[assembly: RegisterWebPageRoute(ProductsSection.CONTENT_TYPE_NAME, typeof(DancingGoatProductController), WebsiteChannelNames = new[] { DancingGoatConstants.WEBSITE_CHANNEL_NAME })]
+
+namespace DancingGoat.Controllers
+{
+ public class DancingGoatProductController : Controller
+ {
+ private readonly ProductSectionRepository productSectionRepository;
+ private readonly ProductPageRepository productPageRepository;
+ private readonly ProductRepository productRepository;
+ private readonly ITaxonomyRetriever taxonomyRetriever;
+ private readonly IWebPageUrlRetriever urlRetriever;
+ private readonly IWebPageDataContextRetriever webPageDataContextRetriever;
+ private readonly IPreferredLanguageRetriever currentLanguageRetriever;
+
+
+ public DancingGoatProductController(
+ ProductSectionRepository productSectionRepository,
+ ProductPageRepository productPageRepository,
+ ProductRepository productRepository,
+ IWebPageUrlRetriever urlRetriever,
+ IPreferredLanguageRetriever currentLanguageRetriever,
+ IWebPageDataContextRetriever webPageDataContextRetriever,
+ ITaxonomyRetriever taxonomyRetriever)
+ {
+ this.productSectionRepository = productSectionRepository;
+ this.productPageRepository = productPageRepository;
+ this.productRepository = productRepository;
+ this.urlRetriever = urlRetriever;
+ this.webPageDataContextRetriever = webPageDataContextRetriever;
+ this.currentLanguageRetriever = currentLanguageRetriever;
+ this.taxonomyRetriever = taxonomyRetriever;
+ }
+
+
+ public async Task Index()
+ {
+ var languageName = currentLanguageRetriever.Get();
+ var webPage = webPageDataContextRetriever.Retrieve().WebPage;
+ var productsSection = await productSectionRepository.GetProductsSection(webPage.WebPageItemID, languageName, HttpContext.RequestAborted);
+
+ var products = await GetProducts(languageName, productsSection);
+
+ var taxonomies = new Dictionary();
+ var taxonomyNames = new List { "CoffeeProcessing", "CoffeeTastes", "GrinderManufacturer", "GrinderType" };
+ foreach (var taxonomyName in taxonomyNames)
+ {
+ var taxonomy = await taxonomyRetriever.RetrieveTaxonomy(taxonomyName, languageName);
+ if (taxonomy.Tags.Any())
+ {
+ taxonomies.Add(taxonomyName, TaxonomyViewModel.GetViewModel(taxonomy));
+ }
+ }
+
+ var listModel = new ProductListViewModel(products, taxonomies);
+
+ return View(listModel);
+ }
+
+
+ [HttpPost($"{{{WebPageRoutingOptions.LANGUAGE_ROUTE_VALUE_KEY}}}/{{controller}}/{{action}}")]
+ [ValidateAntiForgeryToken]
+ public async Task Filter(IDictionary filter)
+ {
+ var languageName = currentLanguageRetriever.Get();
+ var webPage = webPageDataContextRetriever.Retrieve().WebPage;
+ var productsSection = await productSectionRepository.GetProductsSection(webPage.WebPageItemID, languageName, HttpContext.RequestAborted);
+
+ var products = await GetProducts(languageName, productsSection, filter);
+ return PartialView("ProductsList", products);
+ }
+
+
+ private async Task> GetProducts(string languageName, ProductsSection productsSection, IDictionary filter = null)
+ {
+ var products = await productRepository.GetProducts(languageName, filter ?? new Dictionary(), cancellationToken: HttpContext.RequestAborted);
+ var productPages = await productPageRepository.GetProducts(productsSection.SystemFields.WebPageItemTreePath, languageName, products, cancellationToken: HttpContext.RequestAborted);
+
+ return productPages.Select(productPage => ProductListItemViewModel.GetViewModel(productPage, urlRetriever, languageName).Result);
+ }
+ }
+}
diff --git a/examples/DancingGoat/Controllers/HttpErrorsController.cs b/examples/DancingGoat/Controllers/HttpErrorsController.cs
index 06b2b2c..7057f60 100644
--- a/examples/DancingGoat/Controllers/HttpErrorsController.cs
+++ b/examples/DancingGoat/Controllers/HttpErrorsController.cs
@@ -14,4 +14,4 @@ public IActionResult Error(int code)
return StatusCode(code);
}
}
-}
\ No newline at end of file
+}
diff --git a/examples/DancingGoat/Controllers/SiteMapController.cs b/examples/DancingGoat/Controllers/SiteMapController.cs
new file mode 100644
index 0000000..28d5fdc
--- /dev/null
+++ b/examples/DancingGoat/Controllers/SiteMapController.cs
@@ -0,0 +1,117 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Xml;
+
+using CMS.ContentEngine;
+using CMS.DataEngine;
+using CMS.Websites;
+
+using DancingGoat.Models;
+
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Extensions;
+using Microsoft.AspNetCore.Mvc;
+
+namespace DancingGoat.Controllers
+{
+ ///
+ /// Controller for generating a sitemap.
+ ///
+ public class SiteMapController : Controller
+ {
+ private const string XML_TYPE = "application/xml";
+
+ private readonly IContentQueryExecutor contentQueryExecutor;
+ private readonly IWebPageUrlRetriever urlRetriever;
+ private readonly IInfoProvider contentLanguageProvider;
+
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SiteMapController(IContentQueryExecutor contentQueryExecutor, IWebPageUrlRetriever urlRetriever, IInfoProvider contentLanguageProvider)
+ {
+ this.contentQueryExecutor = contentQueryExecutor;
+ this.urlRetriever = urlRetriever;
+ this.contentLanguageProvider = contentLanguageProvider;
+ }
+
+
+ [HttpGet]
+ [Route("/sitemap.xml")]
+ public async Task Index()
+ {
+ var options = new ContentQueryExecutionOptions
+ {
+ ForPreview = false,
+ IncludeSecuredItems = false
+ };
+
+ var relativeUrls = new List();
+
+ foreach (var language in contentLanguageProvider.Get().OrderByDescending(i => i.ContentLanguageIsDefault))
+ {
+ var builder = new ContentItemQueryBuilder().ForContentTypes(p => p.OfReusableSchema("SEOFields").ForWebsite())
+ .InLanguage(language.ContentLanguageName, false)
+ .Parameters(p => p.Columns(nameof(IWebPageContentQueryDataContainer.WebPageItemID))
+ .Where(w => w.WhereTrue(nameof(ISEOFields.SEOFieldsAllowSearchIndexing))));
+
+ var pageIdentifiers = await contentQueryExecutor.GetWebPageResult(builder, i => i.WebPageItemID, options, HttpContext.RequestAborted);
+ var languageUrls = await GetWebPageRelativeUrls(pageIdentifiers, language.ContentLanguageName);
+
+ relativeUrls.AddRange(languageUrls);
+ }
+
+ var absoluteUrls = GetAbsoluteUrls(relativeUrls);
+ var document = GetSitemap(absoluteUrls);
+
+ return Content(document.OuterXml, XML_TYPE);
+ }
+
+
+ private async Task> GetWebPageRelativeUrls(IEnumerable pageIdentifiers, string languageName)
+ {
+ var relativeUrls = new List();
+
+ foreach (var pageIdentifier in pageIdentifiers)
+ {
+ var webPageUrl = await urlRetriever.Retrieve(pageIdentifier, languageName, false, HttpContext.RequestAborted);
+ relativeUrls.Add(webPageUrl.RelativePath.TrimStart('~'));
+ }
+
+ return relativeUrls;
+ }
+
+
+ private IEnumerable GetAbsoluteUrls(IEnumerable relativeUrls)
+ {
+ var request = HttpContext.Request;
+
+ return relativeUrls.Select(i => UriHelper.BuildAbsolute(request.Scheme, request.Host, path: i)).OrderBy(i => i);
+ }
+
+
+ private static XmlDocument GetSitemap(IEnumerable urls)
+ {
+ var document = new XmlDocument();
+
+ var urlSet = document.CreateElement("urlset");
+ urlSet.SetAttribute("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9");
+
+ foreach (var url in urls)
+ {
+ var element = document.CreateElement("url");
+ var location = document.CreateElement("loc");
+ location.InnerText = url;
+
+ element.AppendChild(location);
+ urlSet.AppendChild(element);
+ }
+
+ document.AppendChild(urlSet);
+
+ return document;
+ }
+ }
+}
diff --git a/examples/DancingGoat/DancingGoatConstants.cs b/examples/DancingGoat/DancingGoatConstants.cs
index ad53549..774b6b1 100644
--- a/examples/DancingGoat/DancingGoatConstants.cs
+++ b/examples/DancingGoat/DancingGoatConstants.cs
@@ -8,7 +8,7 @@ internal static class DancingGoatConstants
/// The constraint ensures that broken URLs lead to a "404 page not found" page and are not handled by a controller dedicated to the component or
/// to a page handled by the content tree-based router (which would lead to an exception).
///
- public const string CONSTRAINT_FOR_NON_ROUTER_PAGE_CONTROLLERS = "Account|Consent";
+ public const string CONSTRAINT_FOR_NON_ROUTER_PAGE_CONTROLLERS = "Account|Consent|SiteMap";
public const string DEFAULT_ROUTE_NAME = "default";
diff --git a/examples/DancingGoat/Data/Template.zip b/examples/DancingGoat/Data/Template.zip
index 25c6560d553248b371691d40d6001b4b619102e4..2c7f8f33b7512d3eebb7331a26679e1d1ae1685c 100644
GIT binary patch
delta 239059
zcmZ^KbzD^4+BV(Y-Q6A1-Q6uI-60_ZNH+}K-67pbBi${M(%p#YH>l4!=kfi0{=;(3
z?AbHdb=SJ?dtXM^K-_h-K%l59Ktf@Gz5L@cme)%_VTStkSA_TXUmqTnW6!}PD&f$Y_@+1N!W)c^65B032RcN_
z>LV0u>V}AcUymWaV={}5JdGeTSA#p$K`R%n0A?;Up&j5F_~_TM9=et*Q9SpkGL`!=
z?Wg}c4@?I(b1}woQk)zY8zvw+jK%ZQ8?Y!+E6&yt_HB3>$Tj3Rp4Vep{*_Sk-&CTR
z%7`j`@m~`J=3o?aMh7Z(uyl(oP>MkPz{n}Ll5jwy_M
zBnHJ#3(;*rbF;1Z+bAgV0lH}idSra^gYyUh$EvyYPiOScNyEuU=+!+INFlg*YMfkc
zwZxlBSRDu$lf_~WiHRRDy6!-zLw#gVsvs-1USXI9gh0K|;OzaVsVAofD-G7@Pp8`f
z*K%?4Bzi?rqTnnSw6JIby;PL#I&B7*OQ-Ys+tJZ%7_=82cC-GqvRG05_$l9*COMQ{
zJ_2OwteJi)!l~hF7R~hhMr8YavoU$dlB5}F#*vSkXd9oF2-^zbvYA^5S@RA^^QBW{
z(<=ki0C9Z`Ow5a<*l-s5i(lu$uqbFuV^q^>3|Wr(IFE+qEsFj$FJU@YI(;6
z%K<1Mr8F^cHuZ@Xd`wXCctv|bJJzwqt>^5+VognQ7iYzW8&u0(NU}>>GGx1Jk<0Nt
z?mAe9KbE}z_heBF)#(o;92h2DQ@l>6JTPK85mY9>Z>$`B+emACV(^t6?ph1|GMXD7m
zYJk@xXPT1ovb^^Zm9g}~cMYJMtl7RVk^O#t#u0PAt6N$vU}(Ub#%cS$D1(hH4gHYZ
zSm!aqJ~z<=ynNGt2UsElBh9Cb+Aa*3z;h<7V2=bSHFw;+a^?&6%CT=gr*7OghLhG+
zQF!;QKCDgoSW3Z1+dZV^3}$R=^zqR7tCo)6dL4X4{@9m>yr*Y|);HH(aStb+!hB3;35m^
zO?-H?8(DwXcmCCo;5
z*lkFxz7Y>}RG#({_;$qcZOieI^uJ-A0~F?gdN8k`el1dA_|UE%s&fS
zAX*pBUl{^e0;}}j*Gb^We*Gu)V~s2!@FzS~>ZU9N?BAE9z$yRrF5}Pgus{}ggx}jv
zhMwkaDORfUFStND(Spw$o+wvl4{Q3}J
zEQ030?hluOtbm+)AuWpoWJ3J?9e}S8MScO%@D8yH{P#*2x$V#D38nqdstv6j9R3A4
zVq!UYGGM;2Wh#=WJY54kCIdL~%f5&^PZt3=7}zN=LD4j|^X0V>EUG_OUt(|kzPiio
zb2TY&THdlj7*7ox<>f*m(wb#4(1nZ;z(9=G4bS*);BYVdk6hZ(z-UFQhA)Jwzi+W8
zO595bdgsNY(^Nvc>*bV-`csg5Ek*D0eAPb6q3?Aj3I
z5;57Zznp366+jWNyb)9^q(V}4qfGiT+25611c$qDiw)RWX9?j2S7X-MFpKy35#K7wS7C
zhj`v1=$jk)!V)y|eRwDm^2ux(qsP#L*ri85j0W1!V5&RHlNBc=%~55~_AT7c7M_}3
zhkh0Y-02cKvb72`b%VVdd(Z?9{xmtl{l}unPSQYeT;M{;W+IPfT#{P?M*VH9Oiw(lRW56aZQ~Hw)Hbr#)h@
zUNfzlZj3&QS%l>brpLf|DDsU`#Ym$FMLBt%`2Yg8?Yg`n&-gwI$oxPm`4bndyktcPwk2szb6M^
z+(q#aD1Jy0u*uWw3eZ$v{u~rUe3un_qSoPEFRZ7#4@OUkoe7UY>mhr^0h_qwK~)ex
zs7Ax*aiHdD(p|t7M@oznMtH-6TKYyQH8GZ*|M{o7$iGQyP^9_?byk{xT=s(YpH&@w
z#~)6d8UJx!7Urhk?&n#<%_%k_^P!?Jt5+*wue;C%nc8
zBmIZWhDi>!-=DHqYTZTp@+l25Tz|Gs-{J=l1G~{I8x(m|{@g#8xAV`+g#VxKL?ZCd
z-WS34-#3}dg<5&>>a$;7&1YrBZ^6dR&CJ7Y&dJQh#m&de$7agQ%wxgH$HmQV%Ee*D
z`P-}4<@?#Nx^ex&W}mpK9a^yJW9xd+E@9O!@0f(r6L{zyj;0#Cw?S7*c*>fngV~Fr{NLEoxwW*|s1pP_l?>
z%vD+!NrR(YJ>@IB1un-k=Bulx2g*GiVS2xPcPO8&uJTLQuW#=4GZ2JYAecYHRwFN4
z7dMZJclm)=*J*UaARCC7(-T&t71Mw~8Min^s^ZW+!FN4Vv?)gK+Ytes9f<*iuO4cPBe-lCI
zGnn~bFaIg^kC!XU{9{|Fa;<+pXiWZ}6cMi2{ySbPa}YX!;U#O?2fhpXH)}K
z3?+_ER{j2u9d?mg5G!d><5YO
z@Q94Z=)L)Qn0&Ii_F=qAY0s6-%rG_Jl+U=#%&kQ;gr|9xCcStkXFd8oFfw9stM9!Y
zPuxZ|T>_4y8}-QHJJjj7>`;Oklg9)nbdBZ3-rv0T)%}?7UO5F``HU>RAv4X%)>t&0
z5%dF4Zt`zCp||xb?gj;aY4B8M3JBuVN&|V!RFPa+7{CjR4)J0rL2Ou(_cUMf54)|w
z^Qm-k&B6(J55P0-3YGHk#3+p?LS(KGC}@h*QaRJpQ^&7=gySyNi{kPvv~##AX46Z*
zwkU2~nYwHnf$v8YCK;@+BKAfb5}lC?-u@~>)h>)vupW-_mLmGZhpt-ky>{`m6tT*W
z-4p+I0|VNu3A|gwBcQ6cs9!v~DT6C~aA0O-0K>?^hk4!;_{?W%Kms5>y&HUrz%+@k
zoP4pv(|(O4@ZLb8q@|sc=8o_`rPJ?32gxYJ-TUjO0zbf#q*fWo69Pa#5TWno2L^e;
zt;-lh7mF+5;ta&VG1LGOO^_RH*tO;>+b(2{d-d}r-TC{+1=IGQ(P>jDXx|9x8)cN^
zBKgJTB^1wEiQFoCNK>+IJsUG23dF;*!CXsYU`z>9EHsa9wFg6ZBS`ZIaj@poFfJFy
zgaOPP-*p=m8P+H0=PHRyg%E@#vE!(r2jz)VAigHD6vOgVaOlr=o^iV3eF$q^IC~YojK)w+fA@wV05&pB9Y)EkoKl-sR^^P
zgumE4C0KD?lfHUac}M!e?+dyMazJ@Ok~-DeSR`==)rz-so1xo{s;p>0@0RS7-BY~E
zD62gx3Pv7WL}XIa;vHgC+F{P&*`b}!x456*g`duB({*#nShtykviM-{27)xL7?g3t
zfEDvp8Gc?j_a7&A>-pm0SrNW}s9K2tJo+ZmzXhk??UX!mqf;2L1w-3SO6`1(GhzKQ
zsiIO}q+cRKtEVrnKdGRbV=-o#LLkd2l6jZ6m{vPDMK%_7j7^l?`ATFtLg?3~6XIL7
z!6TE-R;D)D%>#ZFgfu0m=zI1(fvtVYX^|`HlOWRA7L4>7DUQr9)IHLDr2v;Y`G+RG
zYRpV*%Keloy%x=hC*F89Jv
zYFk;HKc3n7u&zc=y3bd;#sgdmNAKdzBv#yvizsp>nzl%6uk*(>6C`e1P3TG!)tRix!@poLTbZ8;(rBe}F8PDpi
z)yjImYUVUSRNpe%fW2#plx^CwgTPgrc!jCLz*qlfuGb3{&~6^M(g?s=%}v-+$YEjV
z4hS1#hifIZEtZqj67>rd31XLO#J&0iFNqbrTtu9qY{v}MmK@ts$xB;Gnd}6B|J}z%dMgpP^b{#?ww^BZ?9fE+Dq{x3kBlz@m*rK
zJCi^M!8wa{WFW9S5AW@HXW@R$l&5lWfj=r$SRRz-vw$olOS%MLNH04J(q4T=gWKtr
zq(wEI0Kdd);bx;DMu?jjQuuLT2&EXbzY5jaBjts?D!G|}wsTWX+%{X>LM%7nGNnH5Vmq2EwN>+N^SMSjM8U(3xb?`krD1nT$l77hdqsfpVBj}
zcPT>aW(tAKooHM>Fjkz~8ecKRk|i2lB?b)%ypg1S!1IcK_6;^|74KKE^X2WxOma(i
zk2p9RS(7rl7G^j^DfDvhXO^*oW&G~i^ldq7Vptb{P_*bfz?!r;OUY~JOFn}1)Gt
z=e*>#ph9#B>GNxC;7V_uzFE6rQVgb0t7z}UoR-#P$-9FevAl~UBTjeIopUj}BsxDu
zeb8DDgz@4i+=C!g+x0Q9D&u?F0;T~N-TC*3MMlsjqR4q2U|A6i}1w=ka>s0|SfxCQ-@??LqIc
zpurtGQ%(g+_d$4=J9_Ddz1}|CL7$NKsHCBWpW*mSJU+Z?gL;hmR6~MM36ov`Gd!1n
znm~7R={od1UJ`>5MKde`EpnAa!>HteW=fNKOlBNsjbW)muXO?f^-hV%z~_g|$WDN-
zMu_j{2WCKHwb3CVvfH#NeSGj5R_#?nze701*H_yO!{^G|(xk#N7hhxyeyXU;5)Fi-
zSNeo>ir-t?cJ)_pRD(~Vy>`Ce@Z6J_ehfWDPwX(m*-ppfiR^BQNv~E56|dOO`RbkW
zF{nV4S9lt$3aW60_bJ~6b+dUfH`e}x(pDOi)!Z5&*ykL{^7XZE$yrSCeqARQjU|^a
zla%RrvxM`w5V}*e8X8*7%pGK8>aeW2xXLN5`DHG@9iSi-5L#*<{WCpsjOnM<^V;Hu
zz%lCpe3prow|A{Vr^>ww1edl+6AT%}z_(&jslNGZ>IBD4P64Wopx7Rr3+dcG65m(Y+o!w=gEDwGbWLvv_y8`}*-l=jWp+(E2G-x^J1>1vd7NqE
z>*(pe#O1(SLi;rwmdmxVr_hQ;I9EN;f$gmUZS#)&1$0wL9E%s^N3r3_{FXzETOaTv
zO|ImGrYBP9R`lGDMCwXi#-l65t$6Uuu+zv~sE(<}5
z90IdJzCnpzTHPY9p&*7h#ZPp%!PZ6oey6Q97{nVb)IItuKzG7#q-v-~&A9I%|6S+I
zXuJa`f(`|n5MW?pAOO@Yot@ll+?`y3qHhQQrjAxN4sIUKmagWeHV&qaPRvd`?sj%g
zygo0G#Hg<+zZXS&$9qW%cW$7o>j+=W?y!0z1#I^3`GEUAWE}>l@J9x!f8s~78f&`5
z<(6!Ix4kURmAICB_e;a%MaSw=tnXhqw+t*KyURq1;oq*bDQN6S;O;XO@s1M`4U$^e->ro0IyYP#aJ&~cq
zNh`pU*p_xAOXO1~=3JdSyOL49-TFGv5XfrUsPQI%AazoNht|w5fmXaqboPvm5Zb4?
z9MNW%h7TGa8aKoWAeUr-txQgmAe%XIrO
zeAhGxV>TJ7A;46GV$*}deDUo<^U7s&VCU{izT*@;dP$Q}RI0tN3
zLP6QxX~dEO9YZ`qxhiQKgOAYKEUAdc5a0&$-@Hsx6V9kYfr!}yUKj}g$1~7>Ri6KX
z9Fa-YQ;sgC&Za+#rb(FB7axu}6$VG+;{>e8hzXjGy>)e+6Q|qWcot^|snhw)i7L(z
zBA0`)js~Vdtc@tOZMx3N{E22{8Gn?M6NOrHN*N<`@+fxFyAig6r*rXH+)!sVT#O8h
z8kcqQt-xdeTJ4d()EztV=2y23g3;I8!Q(RHw`^DCGH6P5qF4>nJ
zaf0rlecb>;Wyo7nXO86U&;z+GC-
zxb~sKL{Dg=vA5ut?T3w*3d>HbnBg_x_^i4!IdlFW+){)Oj0#=VL_6>yf_cw+SI;;#
z+n7r_j669U-UfdX{#l;;Z`d6MEs50sK|M9kP#zl)qduk#Qr9{uFHyD5l(YCyW#l!;
zE414JG)LQ9Pdt(s;u87FF6@XNsQd$8izla0_^hq3tYqsw?VJi_oQ|1YAt_}pEzEyV
zvRBO8Zu(SdZ|g2kVLQHkTp6BPJ#s8BR_qFGX_BE>u=Wq;5Wg|sj7-ya&YKo*KLDo{_qnZWizJVp->U?zb>xDyCSk
zIA;Ys3wgtnp3+_iQk};g*^P2Z&L=~mOLr#8l3@tQaH9T$`7Fe?$DGa1{)df5*i9oy
z3gZt2LdDOoOPStHXG(wV4DjTH3b)VdYFoDqxBU9!cBC@41UU{(uTE^`&N2ZgaqBegYz4Ey}7%8OuQxC``YSD<~k^<
zSa-7`?m(}y)K;b+>MnETVR)qItfj9oMx^n_)z(s|dH!SK5+D-?!Oej+JosV9`z8eHYaqE4bhLtHK_HNKb$R&f`&LStzSa1j#Xla!k{I#@yQ)l
zyxN2?oVLB_3-Jo3W@Y2g1n;3C+{fq$=-L72G_8r`EHE)uU42>sCl;E3LkEOZIBOIqB`A
zN9)xGxP*7#G(^DvZQ~BW8-ly^8bXE|Jb?Onexe^91*=zNSXdu2zC1X(K=qO
z3c-qjz$=FrI|tthWnh-NY3^uf5NNpDf0E%^PYt<+c(L;V8kA<{GD+rZTh2OxWO6H&
zowZEaq-x5eUv^&1qNnW+prdM^4!drTpQhq`pNRsG+6f4LtGC498fSybn&V+d_YO5I
zi$a(HQ*wn*l!+38y-$MZH7g>1l;Pa!9LXFrT$9h5nBa7B`g($ZXpHc^(m;sXcV4{*fL8?{frlYtT||60=jZ%iqDje2-GCto^>a|7RsY{a>&+?(3@{{1eKwM(
z0mLLKy#$+(d)d$VqhBJjO@0TP6;QAt;J@Q58dXW=bKoaLj2*yc%hx2wn#mS&%GrOn
z*!i(rszE|e(Q~@d+eiu7%*-4DyH?8BQln4MNn%*pM3LRX`!K5Vcyq{W9euH%zf0uan2GfsLws@0VJ_0Er3J?+I4i{<2
zy6bO?sIod4$E(s7szQB=(4JBZJ#bud+&g9S(E+um14gp*wUj{fJ3DiopZUBoqu$`B
zbDcG55RFp{oJabSY=dj>+g7Zs0iXB|J$(d*th(wJ-&%_NCGqV2;6ii+F@g*U2B!O)
z5uleLed;@7d8U`B@Ay*g@g9ok-cceUu>r}3thpRl2Ugup6*-Y`2QS#z9u8_fW>k(?
zlhjwqR_E70`<|uyPNqM;_4WD|#&>i=HrCH|NZ(pXPb@2W6gE;(ip3$SdDzjy8ykLI
zBZ~T%g~u|v6V9n*qofze0Aic*AFapO?pfzXIDmB
zLXL*xwwHutLL1DoX|{riR+p)kwp)GQ0#3d^%-o7>B-XU1Mrd8E{w%WxO=z-cJPIF34VsD5L
zdm$|VaAN4_G*US>sh39s=E0nEY>cF(Rd-q-hNULE;68h6XJHU5^Pi$iCIp_xdMCBm
zi0Ec6Al*2!6Cv-t9|W~H!^r^N#$jeLok(|IHS)-k_+OPk_Yo{Khn-nm|oZ+08?_W~FCNS5IA@!TFJQ>I}CP39DR>(a~H>9aZPa`A}d~pO%
zwLRBNJI}Qnxx?!+wud<#x0jy9b~ti1w<0l}b4OJN9hb9whDJxxUcn-SNC_jEu$3R4*i+3t|9K}2ldd%PGayVY>6EbDRCU7lCw+j06F5#TPY<2Er6zzA
zk{>fF|IQ05k{Q^_Ak4Rctnm!M4NLO>Eq&C^9J5-Oi_0Y|e^oxPe0K!U)I9Q82;DJ|
zxdW`5q3R*3l1^W;iO`fwbut*?3Ha&{+8vCVRITp7)~
z9&KkSnm#IOZV(G({zwqwK$L4|glHYL5P*sa;iw1ssBH)I29#dGIgy;uVar9+N1-8#
zlS)x3q9+K;47|ZA6^Bj!BEm7X%ojhErprF)
zz(zPRZeLyu_0X@*Fb4;#OEylIN0$JRoalzNlQ@lLjWyUyof2Km%E5&p*vx4!`+>}V
z93!b{Mhpp^=glggGzDEh#%x+h;Ln{YV9lkDR7*&=xh3*r%_;1!OzgY)4w1s7p*?f9
zyN=!t?nZiPq1)_O-bH)fV}VVJJg1}`+;%QAc8&73MCTj)zwu_mBNci%daVQ5-pGQ?
zTkIwBOZ|@gF_;2%l)unk2Mclq8zw2#mW#%K9bM6Nrm7KT%a>O`UthW2kNZjZ2r4tP
z&qmE|kUSdL7X}cAmI=kEV^%feFl(C#T%0nDjEm~+hh{Z#7&_`yJ&R}Pvftrq8|90z
zDCXxGPh_9H!ZM7)s22d3+aI0Rc6It4=wo8b@S$Tx#6yL<_Mt5WN(!RETk*}p@0XwJ
z`>rWCC^+T42{p=zei{-oW5k7m7w4{s~8Xh|zZ_Y}k=_yLB%9jg`YCMi4c
ziY#0$mRlwt3yF)8iRy%iY;Aq24}XBTuNAj!HwijIoLvQM1`pD5TOEe3K#odo{3@OX
zmh&ED+}abwjWM4PKP`G3_o#s4{yo_mfo3zBl$-t2OstV(zD`M9Nd|s3xFaGtxT$yx
ztL+<V;f*i9W(TK|DWjn~^~!of@0
z0g+K{tg}6Hty+z$8Tat36ve0&&C%#*M5nFBLh!H+5XP4dL+a&Ue
zwa0)}s!0{Tp0%}_q%pQUB0TUZFZihE@PScmD$l^VaG1zpm+hNk$Ww+68B>%g)U;Ul
za(~b5=xO8P>$q`D9^nyM#j1Rab+cyfw3P~NgiBO~gh;&GGAb-S3>*eI4r(ZPYaBOH
ze)B-DSn9dKH~0kbBx{GXdE=kcG;&)>VEY_`&oNngP6vX;DG8UzwqnET}Sx*)7|aQ6V=ynt*aqda-U$y(0>AF{A-%+7kaAQGOMf#p?REpdu4CHnyuKC=t)BRM7ud
zOnEI{Hmm*;Q_|PdlR+^BIO3+qXHe!*Q&D$}`r%k~F!@vE#Ii%Q}SbQ;izAN^pp_0S;5K+TZDQCUa_gh#s~l~Qpu3)8DiIf*EBfMZf{5=hG?
z!ck&anFpp7NnlBzFp^Ap-5buq+K&7vHGEv}r+2F$AVD)nobNm?=eN%Lg4+7b)NOpMw7xK}mPr27@S
zs{5RUnJ6gtjY0P1NdV>b9ZDdwZ`|LfC7K*d4!?~oPDO-4bCWD-x1d7;MAB52@2G}4lg2SDy!NUZ4Z+R%Qt&Gkj>r$xr!A-Gx(1L_dyV#!4kD{%4RAL1C)0l{Du1a->Ab5dORd)EBq#Lzd@&;mnuA#g=`yPV3+(WvxkR`UYuJfWU!|&2M;V{fQhlz2*lt<`
zC|Qt>i5Uxd6z1Ou(ON*&MMRe=cs}rm|AH43^XC=!Re#Y5WV_En}
zyh7QeV)GO88e*vB5n>=HxxiptzF|lnA*GL0QhqxgiWr?Qm{OcghUo&jkL++jNATiZ
zYiQZwQRQ1{?_sVmw#c_xbb(2XhLX+!*671M=+q>=c;T#quCDv+OAi%A#u5gcITGJ>
zn}mLW4lZdB7@f*gJM{v3rO81SeHridzTyW>CmI1egOW0z^)rd|92k;2(v|((zo#*t
zH%T8~^qK#no{Dbh8o`03k4}nVUa+Go~bFn=E1eRBRERAJwvsz
zC?!(RP5#~yYYcr8MG$<%NyJ*6ZbNmJgho2#==$-fko<-`gg`L=03dA`1z=P7Z*<(b*
z{3O|sriYS@Ui_g?Bs{6nZ;xA2R!c*hrP(i0-nw^d*)$KFs^|mEHA6|#O)MAdl6RPjIy=u$Pp3d(@e<@?n_YigBAmrzO
zB~bVmZxBy3c=<=LVdGR$v%&$fi(h&{;C%3lUa8#fi1VkGrT9Us$rD+X^G<-s)947kKLnh*OgnfVUp;P=iiOF)IWNeuk(iPtLs2y
z-1cpIiuWK_l5bc$Z~)F#Q7(?UNtL9Cwvs}^6MAIGkufBTr_gWpA~A_Zl4i#n3L#IM
z-$FSyJ59yMxy$(qTuYZ}9X?ZDN5=@g=rkIgs8+@4>Er3aB1q^F=3>r)L1gki5@>}G
z3XyPc;6G8x%ElX-eY&}o@|1QRwmJ!sl@?4UiYFt_i$@HlGoUGAy%fIxaKX;M>OIYE
z+~mkR-BeXZw!xFl?T_-L)B*X0o9v3Za#dp$)pN8yaFSGh(vyHaKSz_Op7IRMdoSC6
z>@SVLQPaKmr2^jpUIa0u9+}Bg{8gq*Zluh*Csb(hkR`i<0fx|$2B=-ognr2ZaO9dc
z^aTP_o!*@16Az%GP_I+F7^KM<9QZhPaM~NFA~HvPGj;TmCO2c9J+740JXJhc6?H&>
z)XJ@|qIy!^eP`xZ<4&JHk_suTDcfp_T|`)|v<)EYLpR>IFV>VMFJTfLzc#``6Ooo|
zgFsJJBid0_6UTT%M{Lvb9X@#F%qw2mz1-AuTX9>y4OVe;HYhSe
zUxXFw4uao(kW5n(6)U3JmWRVKQ!Yd0f)hW-P$-E5mEh=tO`MAH1K7)ml#+DLSOIIK
zcFD4+kAYM~qTp&XYE$oPY$`j~MVB~?#oHa)dms2ucu!FzmjV=Zs_a#4M3(98bgfGi
zj4p#LtLQy4b+RIcA<~_fw)eXL^EQH_+gbi|e`U<9%!@2}5a9nQQc{h~<$qNvFR8Or
z=SW1dEpuR#Di*5`9ASG_KFL3T^f-kf!e*Q7p_$~H+;d0$7zEDxr!ieL-AT+SYuchoz&7BX;@~rL~
zzQGv%TGdM!8tj`Q(LTEhp!!m7zcmOf9^ydyo`yaUN*N7DEEUcGI`}i)QHrRt7e_3q
z8mvG9piLLUn2U%_Dps=J5;wZM6e;4-g%9H4_>93q-+d~jBxFh8!ma{ul*$3>Wg#T9NH9?lAeF2-jbiCqeJjRwm^WG21c
zkWOo|t~O>1?J@Wk=CHl0x^isUX@xSp9V&fNPy5zVMAu}2Xnt{!{T@-VNgd3Z5yc6%
zZ9Ny+#wqvhGwL_!f1i0O$I25VUI0%eKLIBJ_1Tb8Rj?Hhf#rQjfBG9U%J12*ez%l}
znTxBG@O+(D>IbYj_Fx2qK@2l;#04TN%c5+eH1+3X_)_5|E?Kl<|8NLo1ZwbHij;@$
zDd>fX*)3ISIY!JJp4@8O&iq^EXiXcTBv_Puk`6Hd9W+#-TkqhPoFBNEpX~^7
zTc*iAp^64mzwYFOMTVeAkvo+3n#f1klvXINJ+xZ;mLMbJ4Rp~ONb)u5^Pl4(%RsPb
z-;{c%{M0+Cw=RAjiOhOum|>e>*UM|Tkx39=Q(&({Gz!#yhQ_%6p6d_sZ)@LbBH#4^
zK~MgoFut6DQiZHQPcTG!vHWlHEcW7MrFAJn)71ZU4x-g0A2u#!mNOhwhW<_fD;#0c
zgA5(g3sq>Asn9R>WBJ51xbXG!?1(c{CEq`P2x_Fq3mKMA?4L6fCni5NU
zOHR>e8qUX6FR_M;PF}YVeP+#jh>(^eR7-Aih%s@tY?~h=e~g+gV{bnqqljcPqR3`0
z=i#J2jpXk_)rz?_%?CkP3TI9$#f60D8i2`*W`hTHK`OI4|MO~YcFl9n{vtdMlEDz`
z5#UEyd+zw2hx!dql;qL&{Ljn%mYO>qOzsf<8Llu3?S+_2^JVf=99<)D6=^P=r$$!$
z+y#`I6Mwdosc-i>gpd_s3KbqGRS<6_6%oJ#803<9aHCUdGK(Qu39<1OiuLz3nMwRQ
zTJ+yoqhqr&ZVOH9hmoHx4le#k0KCY+c)y-r{5{T?p{cm$1!4*J-z>>`gIEG-j(vYL
zM^BN)xt}z}!2$6s^H9CWT(J06>!`w|oLc+ZnU4mEARTX+;v)@>UsDgFgiS54!oYkgE%R#KgrBYYVOq`ibzq|>64a=t!0dHZI_-`6{4DmSvTp?8$Y!+X(EX!Z0peUpAl
zRD+`fCq?`I$fX(+;vBHOQFpa?u&?P=_S=hp-vn_P63Z{+CsKuNZ6YuRTe42rvq8RpYhM){2m``k3lMtThbcly?a
zvriIx;Dn^RkTjvH^0?!=?@yHwbT?UJIR+_6UdhOM%k#aV4`hoE&c`SfO9>SV_~~L{
z^vo*4+~vSK0fPfx^66b49W(%!68PQ&4N;F@hXVIZHQRVaDY-|op^fyYygdDcAaBPF
zH$7|?`O}7BbMLf|q4jQbQfehV0Y5oAPE(fGey*MWPnbgkJ^4cJ3kL2Cq6hnb>EZs1
znGP2s83eI#h*4-NI$BMw*e-af2%`lQ2B)1K-~$8=7M47Em$#Rv=NoAdF-j_nN@7c@bI+bkcDlNoN)lJoK8C&z%Ys)_d%t@g57FB0sb&9d!zkZ
zrK>MwHMSJ;iu;1+keBI4n-;P)?6MQ_dC$zd5Qm0ufh6m>O3J0B_xma&jn|A@B*D@Z
z4z{MM!l;9f_x{qye|MWAD|{}X?#t-x}HRz~BIc7N3p*;ctOb(FTy
z9L9`~Kx^lPcNKx45*L+EG5MrIQ^v+K3(~c?_ep6&!088_1F5h8bU+k2UTOJV%!VC3
z>e;on3fk}up7gk*KHOYMR9Pcm0nWAJl6#R%xf51(@hOcVzN-(Jn1K-z!FAXadl<1yX!A52?(l(b;qLyR
z@Rryjuc7EnG=)W^0gz-;L`(5bQ(eXaPbMpuX*I_sdaCI!4Yfr|H#3Fmwa7drWLT{`
zMS0r{jeet7gaQ&Q@+;e?D{Weq(%nmzIt(?h(dQIW$Pxz870|tPzX-3M>DyzCVl+jh
z=}!_j)O}%!egXoJM2p
z$aH#x4X(VL0`zF?`A~X3NR;i53{(}^#3DpL^tFPX{(6kH_YzMOB
zd&%5^Eijw{EOP2D<%G@6#1u+U8Y;>f6NAn+QDuTU$Wf9got-1uJT)XCbIEb}(jO?0
z{YY6{sI>eOas$8Q6L$4xh6ZsI3^)@}AaMai$%lp2XART9Zs#JeE)66rxK-t;{wqPpn=taFM~h5FXL^X
zK@?Qvd*+T0J&CG5A8h6ZtY;Td(~MxEpci{)4_dr0fZw6f>++k1zIg6UWO|=lf~4xg
zLxqI6JKcqJ7Frxa4ZGmtSvhTC<*K0~N!_`JZw%^ELfY+Ix*6lIXPTu85B56h>ND0T<#4soU^}x8%gc|3KoS_&d*P`{z14y>O$iWlZ2fSu<
zVx#gIS7s*P*KAc-cJ-COq?>n^XJ{{YpYS@wRFtzt?8h&aHj6epLcOaur7g<=aKy}a=wX*VVwo}U6QcqH1Z}3T`G@FqAF22bb`9C;Tm!CnfK=xj4qKDr&t!Gjt8llz=R3w=1WB3rv~I;dk?E$!L|!
z2sFf1=dQHmqR~lP{T|W?*R4UZBFsQSHY_L-39ddOZ?f<>Hyl%>eJb^KVaBPRbGDdt
zQR@Rt(5T`*yBPSQZL`_let1~gV*(=7^~G?mj7fiOy(98F89nI3l2fG%4bX9$_@Wy+
zfyHJa#&Tm>*Al1Q_VBE3cfFsx5u?t`*2xPRVE{43z82MNd`adgy7uO;8PADWp&3mO
z+%Kbq41hn6L!12H*-l3fE>jmSP7an|vz`B$2GTln+#dQh4W!>R3SHEkm0(_5nK!`V
zP4>Wp;)n4ufc>Q%`8#)eK40GDj2le
zL`-?Y2U>c*6ymGo=Cr-Qp10rpb)MZagWcjZHxn!Q`r>baZw>6+7VR)Gd4m2FR={#4
zq~=IGol@vCot|c4>{JRt~O3?c9yR0PL9^5juwANW43d*Q{d&EolgsP_bI+kMGjMv=;T}EyD1~iw*0)VLD1qraR?%2<35uD<_$&)Yr
z`3IU@cJ?=knS)H&bHFMq1JHO1xw9fbd=A2Y7Jw(RDXoHoCm=Rdt=22gL=o;NnB1hK;Zmufqlo|iNr9s7RM
zo{0}bhb&FCm>Of<`z3QY4ZY}x+f6kztgkcFE8B1t>v+MbJ&Y@c+m==#T$~a>#MA>E
zOVk+=M^kW)Sh&-vcts){QV((&jlRBaRtW2eByyBOK2)~Ld>H-^wuEYAlQo4G3oS)K
z1zwOP8IJqX%4d&dV>Fw@+(^D_>^K3NJ=@43Cq7{Kd@?|q_x~9C>ZmBY?_X((UFg
z=$4Rfkd&^WOG-f*x}>|MLAtv{8l=0WQ@TO!gRk#5-rw)8d;ejbH8X2i>pW-n+4~cF
zE9E^#4q+0nY+z!`X8}}xEuLEwPu|;gDPdfy4P*A$V7w$sIS4^!SO9?}^FvWSE&29KC@)F|fy}K76&EjyC_w8@ZvR_g7#Jy;}#isdnqx|q6
zu*&bGDZmD)`sw;!{1=KCo9qveK>t?i0zU|>-uJRrjPXTzPlSYbX=@pDNH`Y4*ZSWV
z$v8$)jYKv8+YS#84H%Mt-aRN~F3~F4(<}aRsHnFf-d)=_w)6*HS*KBL9JwvRM3
zkjc^bwaQLM)8lMHyFUC^<77aGb?eTtz4$6=T#{W459Et8v*){u*$6r+ltowqs69{r
zZZ8RwT_-HhsD^0bKAMQv1;mF|SIsXrz<0lV=Qn%JlS>d2
zDwqQy56wC!no1PY0~4zs6DbD^$x%5fxI2U`$scw}o+`PnjefM_7^GD2j4RuRTm_5b
zC!#5(X$%csn&SY$Me>n!OvZuGEm7H<8Dd-OS==PM;(S-`h=)933I|45Lh^bRB-&=Kb#r+kUO1^+~F-9Qz|c0@&xL72uI3oqyCOs|E|N2a$HFs`v0
zn_b=1E3TPw@dE=vAqzy|NrH;3Y$iHf)H?C-a2`ceTiRcqQ~z
z5z4*RDYUiEaw+{vk?h5rP*(YISP{?#4GXlG(l_AI<}#T=Y}bwkSXvs~)yuLmoW-IE
z;9ynpx`M5!FsXgl34&5M6Rt^JnVS1EMCUK|IRV8)Q)>FPaEe1STma1Dv!IL6d~4C?>IwxSRz};XqQCqa4-#UhL`l{pExUwn{d2GCU48;fMAq!S(WILBogggzwMirOe=R_nTbHB23%O-JgU(0{D{7^mkv;G?v86
zPf-=Zr=QiM;|Is!m%QEKX&Z6w-6c2pXBwJerVJ4B05bk}aF2Big-<-Nk|P635lbAWf#N>NxVJ`$hD4IIg1
zg`3>Xp1DJV;w|yrP_ltw3*N0$l#?}SGWvdzClnhxW2cHH&z3O(F4schrq{AL^lrD)
zU)@rLp?LR~@M2V1=T=As0UCez@2a@VmtmO&U^go#LN|{QqH&U9DyX3o&4Mw~DDmJ)
zj4`6|`AZg6
z*Bt2(Q3i!u#N$7yw<6wd@28t}2grTof9r!BL+OFTK4uU2y|m^TG6=5Zf)Rr95a&_ACB7VoqA^t#KH-kAa_#e3~i)-
zH3kT&V1X$*n}MPYO=m}VQe+ZuPhWwlZ($dS>JU|8gHITJczRiFfw09<$Hks0OuuO2
z!Ow{FCsN{9^!x6fj1S#iVH%6D)hY^+<1w4ZLDUS68`wZfBl4;(lCw*u4-;OjRRv6g
z@&iwLKF#5jb5zg;V4chqu#Q#nFsP-#R&~1|M^p>X_5;)s<
zUo7(9(dASp2Kwp5um771dOGv5cc1+0POXBK(uJB@R*sstIjJ6DB-lFC)J@8RX~hfJ
zA)8)Mle1L)LRHD5=;Ic-@T@&%&uH=(I^^TM;y+c*r_nrCQ_pP_8kX%Vi%+fcfz6~ALP<5skB;toKFNBmZg~tzbC**JP
z^-n>RP3?#toB5epS%*%z
zkod=vmC0YhixwI03JlNw(a9y`HV$7B*#4>i0DTe(6QPLy`$3rTxx4ULTm9~=1Y|k@
zMT)biwMUBKi6Dq!OCydKj#Vkcl(!2N_CSJp64G(*T*vB>YmgNo&m{Mnn|Sc(J8^q*
z^b?@~L`E
zMk0P^^5RDZ5kRKH@b63~EF2pUxzLvTBZ2jug=OX2f<#CdWV5}Aq`m!6;Gp_33bI6D
zX;K3jbBqxa`5@!@ZG9u6N2B3O7$$Nd%1Ecm(jZ(cC*P2MZS$7^g)LvQDL!nQY)NjONMnDGtmWg
z<51J);>OO)8B|13VyO-wUQnuR^rl+qFBME*;H9K|B8kzTs_6*=Fi_nnML4UfjrU6h
zA5A}M67RrYUNw1$2XQRQr_XiV5??a5{?hp;6Ky4q`|(Ku{e-wNCYIX#Ru=sW;Q@k7
z+Uyg;gU-UzsPZKa-SL1Mc2kvB3GQ$B;EOo@Q?(T44z7K&Qyc(x3gO>Y(uH)R1z)*I
zj&iaBH{fVrGXLXf4~A|BNmZdb9=aP4OIdItIfKD(+fHcwaWDPlPp3U`c8B()Oe
zRq!WzYD$v<+~7u`PRdJ-F71Q!$sF5sVZYIZ8B!V;!=lfmf-p7iPq3Q;pu|naKsG?C
z27GoG8(@cb5Sq6dtIxkuySe5c!bs*Wr%AKh(Yq57&4Q
zpV6-#O4S@`UK(Z=wsXjW%GFWzAB*J=W?v!s!r3;i{NHzN0)}nP)0RI;73Kd&La9b!
z%sgg}%xk^X!jmUV%Pfjd|LNA+;E71?b9_oDYqv!ncOTQwpLC(EaouJJuCc||)Hg-aWj-@0E8eu^oSi(yz#2q7B$Z$=rjbMGP^<)mUBPa%d8ivZ^7pWGJX<)Rr)tO-
z@>+@2TaufXTfvf9q69RAL7~z>1jk6e^uipWIEu>mG$uh*N`jVPs4?cV4#BX<5Emmr
z+G7lDJO@y+x2V#27t~zb>-;o>MY|nOemdnRkqd{#`;XRlV@mo<;^d4h#KwDxsiB9}
ziv|vwGPZ8nC|3(P{13OL+vk!0j4WtOGS+`%`HYFc#v{e*#}WejzVamG>iN5Xf~GY-
zFd4+NpWJETd2mir$VA4;8Tm~t2IJ!MSS;#$ww*uodkiH;J8f42RiGY#1GZH!$n2;K<&
zQBqIZ>g_DPe{b+QNK^vL+NWV#7N>g>6-HK^?#wUwPH$aR#}gSasw3?-?VYaBN|F67%=yA`&*CqdZ
z-xDEra=^y_8w3OF>T6x^wVzPoV!da-)A*1#v`(^ro3@M;{unI&R&`Y;Hl-Y79r9Eq
zzj>-$x%5I6Un`Xw;L_KDcP}(L_lLKtR7VTLecu!Sbjp@s^lsO&UZ0$3>UUIo#^0!L
zd>n+)3GD{}3%fGl0_R-{v&Zrcep&bcuEe=A*
zXlOv@_=NI>TRyxk6`zo$p%HrvxD$`rUo9F1@Fh^0jCCOnuUFU{TA|OO#p$;nQWEZP
zEdAso$xI(O{+E4vP^~dYM{^wBijo(oTyrWZhWLGhePTK+F$(k1Qq<1ycpX5
zOBVe%1o_yNu&7>`r@;&GS{#TIc&`1#p#9E-S7e47R+f3QXjCd(b>}=^-S&-w%W!YdhdUi
zhuZ~!Uhv;QZ$`)o?MrNv9yxowCzQbcD)360O1Xz@J1mnX6lkf5h+`;H?a=
ztBqcIuh-yDpL*_Km*LYbb%6RPY6`H=Sk0ei;@41vR#+(FD3+co#4v&;6L1>Ea)`M+BpsD6jAYgrov!~fr6W>ia{V@?
zzZ~(T2CQ=3pSA(3T$X)Y*%nW-F_0-*ekodLTuLEP^^8vY+?{O;7T1Dj%t49M@2^_>
zRNk4-gwh+&N;8>iUVcT2RrU_)cSbHKG9zZN;!>&*2nAl0Uc5j&{en-Kg6%{914Wvz
zk1(%tq8@G5)eXHfm(5c~s_oRv?I3J&8Bn2rr)GcogPJm-1#rqur=-p)A$Nb0*ATwP
zWD5S!c^{TZ0+MPQgc~sHz!(-!!=$nrzG0|Ta2H{i>^tXE6M>5LZcu;?23Pe-dc~=B
zi7Qhao2`nIaRfI}zP7%d%%2lqI4<#~DP4GFl>5-*MlnxhR<$O{+1*ylFvZ68QLRTb
zJZ>dQux^FC;@g0!#V!9o9q8zwG+7s5K0+1hvu7ay21XlOk%9vGzxLb_1zG@uc+7as
zc+A=OK|ChL+=YO3l|vp!_URe%L06Wi<1j%#>L0SZD?*U3Nqt0H8e>OXFal!A^-6?f^1X(U5d@+hmMvAh~Ht3#H|7OZKN(nMMIy^XYqtP
zF2qLp*h<||AqI{u>B`jJAM%TgiFJm%^VEIKOZz1+e$qfpjnl?V*1%l!$A(z%FgJhF
z5Fo&zn;^Ti-+Ntb-@~MxQIRzVSv%wEqHWrv5L&CDN&x)F+_nWRUUc+}C78Iub)Ct~ic~LQ&
z!e0c}GecCl8GgXaaU9WJL}fyam0bCAi`EqGVMV2?E6DgkV5*FG-}xHhnY4A-j*hS}
z1vEe6(it{GRStp=&k)o1ELoJqQGyb|ToNLKMjHJ{+byY+=qqY>I
z3+ps_V%(KWYvmL~r%_yrP-{&)gZCja1<~rnD9RRD?0X(P#()B9Fug!24>(V4W>!G3
zVdtC!!tQ1vNXNw=7+gbym=PRqy@YVLyk{lwoxtaTVOs?;#LkwMVuA4$8m%!O>C`R`
zL?@OtF%daVo3io})CwNU)G2dGv^h_pJk>3-d8Xt$nx{2H;NrrX`yCowY+qrNyX(y3
zaJz~V-Z|enV+u8txzKu1r%;e5Got-XEW1qu^88j^Nm{1*e0^A%ny~_R@U5;SkBYVc
zkM9o(mnF!rYiEw6237{n(`mzuFa*{Ny^$5Wm}*Urz^U^Zx|xk+MuqM2vbfH{@c?th
zhm>7U-Jd)nA2F}Y+rbS7o%v9LtR4=r&_pmfwevgll@~m6p=plnM?bS%D|ZQ{cz9d|
zAjOpU0e$S2a(jM3s>FgDb~w>R9#`~w7DaXNT3G^sJz(dX$*W56*@N*;6z5y%Y-9go
zCcXDQ!h)0z-z;}xTlV@4IKmF*Il^9iBbXs(@mcwD858~!O#q*lhAnwINNGh8Wz(CI
zk-;7_12Z$-r3rByIS?Nc^lJyozMw@93Bt37r_-Qw=&Ug=s3;f(c&kS*g&{O;WW;rO7RXac77((S
zxd^hhkK_ot?qBQD&BGn=8x9L+r4tlA5te`0*SkZ1xGwTSpN)3h@c$Jev6iD+s>9B_
z>)EAT`C@7*?Q5u0*Mq-mdmp=E2VeL{dU|xq&or`nG#SkoW=EqZEewO0c&pWj1z8~*9Kdn`IH0zA)>`*KSkLY@l}vZ0s6zosUytBh?2C#zvjz?l#Z5x1Be
zt+mD78CsjIiU;8eVH&m<$)7)a5%=*JefD$WwXs7TOO0yT@Mxo>DM#!=>&?%x*nd|~
z=82Gj`0{%C7X7~y$!f2Z$LeLuRd=Li{q@S`6)58AmBdj;x!2Y3pOyYJ
zbJos0`m>VHe)zLe$c2OcJzSuIiK|#LHoAr{@td=pLG^LI@?SFoE`Kt9m4SWs>^X9*
zPaS8hccBqPbIE>B3Zt!j(tY-=vpvYjv?BshHDxD_O44p}lN+!e`$x!1z2)$oc%&g@WxVDZms5%+4mig*)
zoGbi`)^i#Z2*1%I?R7=YXDw>y^$rcUjk^m-Z40E}sdq15HzrxJB(Wk5)y4%Y_%ggX5RBQD%a%s=Q>lQ95>d=2({ya5uV=>|
zP>Y3p8JAyDAS@W=Ayh5NirUm(ueO#QwuV(*SAX?Yj;e>XL-Z!o`UB~d2X)**3yx(-
zlmSI)K3&dZZD3hG=TV=oTHS~3z0V3n`V~w@Gsk&4#2kIzzvRA$!HcjaPW_D2!;xnwPsD#e6Kod5mMz{dW0*D_0pTwf{NJh|c-l
zsDIRQg<;Zxlc`!+AFX2^Ln^d6k;p*n*3l9GIZwsU^SuHCME-w#{!r7f%+21?WuRK-<*^Q(I4JnPgF$*28+rjX1+AT%{%@E6D
zcbkvQ?|9siH+B7_WXh^qRq+fF4Vm^JVeXUBQEWz5k2e$OS=2H%kR4A#`=7<+s^eUv
z$K?s=NbYE2XN46BT@xg_gGzsF3{5SFk`Qll_wRf@NG=sml(cI{nE
zD9+Ie-(DF16gx+~;IPriTZWXxU~gDgS5Ce^UD;knT?P=W*Z$0Y(fIKndP8m<;Vm~naz2dtC#_A)bdy7=1{E*B{GM6j
zZn3_a0K}smB6ln8zcN0&V@5uG)+1LM
zA@E>7OPQIprS?5SARb$6{08)JnTo_@muR&q%DOTjO#j*aOCcIg+f
ze0wmkIZjl*d_)5qN+V2sxa1&L7$Dc
z3D|FpK5CILkNN6Z<@XoJIVt8+ea_2HNb|`Wzg;PQDMay!1O-D5mc_i1M#nr4+NNJz
zpo@B%uoS$3>|In}3!y4HF}3IV#zI0!BW+m%FA0`nyN90;f96quDq!Kr4HJ+rthX(kc;crbKmPhbeHCb>nGXWwh#L0EMtw9mVw7TYlGTglfO&D86u?
z)%ks{FO?lA4FdW5pplxbeQi$=Iiqy3&N4;(e3sq)J$kW*&CW@oPX{io4pgwet=HGS
zOy?I#_KY^yBM?`1{XK-keJNdv<35!Eg!)V{d=g0!1}xJ+?5IC+$bBp8Z3Jo9wU;XE
zSncyOJF&SYMr%T$F0K?>Ot_DtDT=7Wc_yw_6(sUag~mcu+xPh#
zn3R^->VD_BopxsYq)*T(9KptZC0mSSZ4E2m-(>Qy
zWO;#IxFO|iFBsuXf3Dz08_8n8Y>Hv|AYNn4(ko&QIX7@`>w+#*PqC!9ZQ+gEQ#^As_$>VoYWD27@SnxSi0&)
z0*H-pcnx+Q|6!@E?ydX^{d>$3`d0$pSg|wy*vtm_>XDk|AfA~WjF>nlE2EN2hF
zzFZ!D`Di;JzqDP&p`E;F)NigcAP4#e=|cnwze!T+cQI4!HS;(>JD#IlgC
ziZV~Drp|x5DLs+XoV?uPX0``|yp!
zl8lnV3Sjo<16m`?qf-a(h%AVS^8KWFicO9c2t7A5DjDsxLv?9PYhU5rGApcQLAH&C
zgnQBb_a&%#o!-TD4W;_CqWf+4F$x^u%PnNK=x0bq_L{D|;&GxA!{KWip?;AT)({&O
zLm`?-yI5bkfZHzk@a3f`d~LFRQQ-B_)m-{kn3eN#mt+|y4mn2&IAi}NLS7m6=LRSk
zO?v&a`v!!lg?Oj8JEIXa#O1Md2dL
z-ulfe*5&iJAC*c}&cV*8DAxHXeXwRZ6vjmoo56aj#m0@FGc`FhN`$-x{k6xW0zKzc
z3d^FmOT5{%nH?}YkEarO0!&e5hqJ5)2sFrFQkW@tC(zba|M0>cNNuvmwuWd{cpF$`T$E;;`3o3`L=rpU6W@5-2r@gvD2HYO?LS1}0xl7Nkx_maAiJST7`>AVb68D8`X
zRtPmAZT6vQs-_Dbep4(*=j-R9tywBm8L3jU)9?t`GjLUeOb_e5_8W&wR{M9yHMuAC
zjWFe2N9lE)Rt}kaq?eGzF~_b4zPD>Xk^(;;H)4BcIMS)^M8N!rOqTJ0d{~Tl^sb0#
zal^A`jtIvoHZ>LgCP^1R$0@`5B@Eq$Cce7}AtZOYW-0cfsP+>hc}W7)C*=EWHDQ5%
z_><8^AVx*z&?{tTHS?s`Z_J`kc{J?6@uiG59>8JmeGF6T>kRShj9l_I21Nu3s{F!V
z^$q0jmF`{idpz|$ZgF-;wLV(f{_*Q_qsWLFfo-EvV}|xMLz&^@^wF!O@v-)jh)??h
zu6wB*uhtDj8kvOS7}og(PiQyaiDA|Sr=VSy{WyF-fAL6jJXU-A4{cd>a(fr_UnB60
zJD2~eJTaHn&(?uV(C>My(-u&9c9}pl7oHHvk8Gn5qlYTCES7z&5TA9)r~_6#*riM-
z-ApkRm5n|VifC3@J0AL5^Se=?!KO>@Y-M_%Jv2d;1lmY4VFuypio>JAGNhF06t3j8
z)MvDwZ$_e`$kg!$X=p@-qqfIhw-4^vs?AxTdB4knS1bzp#4L^5e6oET_Yf!Rz}MSL
zlW?AWv(e$P(46G_-r
z%)aC|{84Pq9bsd!p=v7fAPCM|%yGVGD05X6m9L>`K~{Ld%+HS^~BOFe7o5AC~`lf{}z2%dAm;R5q;qxsBvT1ko$d}
z9@1$&);SkSXA=CiDUFOWmK#>}%GGMSUd!j5ncnQi%SB#$qMu@mwR@1!vXbcVV{%;e
zaeZ%WO%~z#68FoX)U!|3H*??3WaETL>D>bid`J|w^WI7%Wk2g^Cn8}e`GWKUu3Y0n
z^t6Wobr>_RKPa?h@RK7;zn@j`YKrzMZVHuz}5S(
zmyj@ONs%w=ZoF_z3a5Oae(po`$w-;9`1p&7GF06q-ofbSw>X~
zNv3kzdeY7c5$@Jy2ltTAx;|_C&m(CgV@D#$nt8OpAL;z+PXW(eC>lt7K_M(KrsN=k
zN#sJ#%H)7@8q(IRaH^Q_^#Gy0uEjGZs-~BP3m<2%Iu28Xhd7B(un+dCab(C<25mx+
z$`noEY%fm3A0~eMD*9#~w6_Y?-k8_Ihu$2Y!+SeNJd;*WYP20w?YUE)yZ%et#{FHr
z-YC1NYwPvdW`I#_#7x|g?)XU{%{eSLA?c)}h*I$*K5{*4#y^4x{oCxJg)F7@#Qt%|^a@sojQu@=O?o2fFVw4SL~mU@
zmgR!4nqs=-&x|y4yMC!y{Y<`p`KkWzW;am|PEIa%U~C?j37eUTF_;|$j9CQpnzOTT
z@v(EV7;}TTSh#ulIkhl_+NoL0m
zj?Sj=twFAZEO3ap({v}#nyJlO>}N+#YFP$TQT5Cp3UB}Vka%`>ksdBGH0>Ew#40Cv
z`VHz*xS~ouU@7dr$Exez$qSMw`x@QMid0*R4^+jKUlS_09Ga1+csbq@PnXVRmlwPC
zVg5#-z*pLy;