From fce8015a97807a2c2303aea3a9c12207cf7a9e5f Mon Sep 17 00:00:00 2001 From: Michael Cavallaro Date: Mon, 18 Dec 2023 14:53:42 -0700 Subject: [PATCH] Feature: Nudges v1 --- CommandBarIOS.podspec | 14 +- .../CommandBarIOS.xcodeproj/project.pbxproj | 103 +-- Example/CommandBarIOS/App.swift | 29 + Example/CommandBarIOS/AppDelegate.swift | 9 +- .../CommandBarIOS/Base.lproj/LaunchScreen.xib | 48 -- .../CommandBarIOS/Base.lproj/Main.storyboard | 30 - .../Background.imageset/Contents.json | 23 + .../Background.imageset/shop-backdrop 1.png | Bin 0 -> 71094 bytes .../Background.imageset/shop-backdrop 2.png | Bin 0 -> 71094 bytes .../Background.imageset/shop-backdrop.png | Bin 0 -> 71094 bytes .../Images.xcassets/Contents.json | 6 + .../Logo.imageset/Contents.json | 23 + .../Images.xcassets/Logo.imageset/Logo 1.png | Bin 0 -> 2581 bytes .../Images.xcassets/Logo.imageset/Logo 2.png | Bin 0 -> 2581 bytes .../Images.xcassets/Logo.imageset/Logo.png | Bin 0 -> 2581 bytes Example/CommandBarIOS/Info.plist | 28 +- Example/CommandBarIOS/LaunchScreen.storyboard | 47 ++ Example/CommandBarIOS/SceneDelegate.swift | 27 + Example/CommandBarIOS/ViewController.swift | 99 --- Example/CommandBarIOS/Views/Button.swift | 51 ++ Example/CommandBarIOS/Views/Color.swift | 100 +++ .../CommandBarIOS/Views/GradientView.swift | 78 +++ Example/CommandBarIOS/Views/HomeView.swift | 52 ++ Example/CommandBarIOS/Views/LogoView.swift | 25 + Example/CommandBarIOS/Views/Toast.swift | 25 + Example/Podfile | 2 +- Example/Podfile.lock | 6 +- .../Local Podspecs/CommandBarIOS.podspec.json | 7 +- Example/Pods/Manifest.lock | 6 +- Example/Pods/Pods.xcodeproj/project.pbxproj | 629 +++++++++++------- .../CommandBarIOS/CommandBarIOS-Info.plist | 2 +- ...dle-CommandBarIOS-CommandBarIOS-Info.plist | 24 + Package.swift | 2 +- README.md | 80 ++- .../CommandBarIOS/Analytics/Analytics.swift | 139 ++++ Sources/CommandBarIOS/Analytics/Events.swift | 179 +++++ .../{ => CommandBar}/CommandBar.swift | 14 +- .../CommandBar/InternalSDK.swift | 106 +++ .../CommandBarIOS/CommandBar/Options.swift | 96 +++ Sources/CommandBarIOS/CommandBar/SDK.swift | 68 ++ Sources/CommandBarIOS/CommandBarOptions.swift | 14 - .../Components/BottomSheet.swift | 148 +++++ .../Components/Buttons/Button.swift | 35 + .../Components/Buttons/ButtonGroup.swift | 35 + .../Components/Buttons/CloseButton.swift | 37 ++ Sources/CommandBarIOS/Components/Image.swift | 42 ++ .../CommandBarIOS/Components/Spinner.swift | 15 + Sources/CommandBarIOS/Components/Video.swift | 110 +++ .../{ => HelpHub}/HelpHubViewController.swift | 4 +- .../{ => HelpHub}/HelpHubWebView.swift | 54 +- Sources/CommandBarIOS/Helpers/Color.swift | 99 +++ .../Nudges/Content/ContentBlock.swift | 112 ++++ .../Nudges/Content/SurveyRatingBlock.swift | 225 +++++++ Sources/CommandBarIOS/Nudges/NudgeView.swift | 244 +++++++ .../Nudges/NudgeWindowManager.swift | 192 ++++++ Sources/CommandBarIOS/Types/Actions.swift | 432 ++++++++++++ Sources/CommandBarIOS/Types/Config.swift | 6 + Sources/CommandBarIOS/Types/Nudges.swift | 394 +++++++++++ Sources/CommandBarIOS/Types/Rules.swift | 119 ++++ Sources/CommandBarIOS/Types/Util.swift | 32 + 60 files changed, 3965 insertions(+), 561 deletions(-) create mode 100644 Example/CommandBarIOS/App.swift delete mode 100644 Example/CommandBarIOS/Base.lproj/LaunchScreen.xib delete mode 100644 Example/CommandBarIOS/Base.lproj/Main.storyboard create mode 100644 Example/CommandBarIOS/Images.xcassets/Background.imageset/Contents.json create mode 100644 Example/CommandBarIOS/Images.xcassets/Background.imageset/shop-backdrop 1.png create mode 100644 Example/CommandBarIOS/Images.xcassets/Background.imageset/shop-backdrop 2.png create mode 100644 Example/CommandBarIOS/Images.xcassets/Background.imageset/shop-backdrop.png create mode 100644 Example/CommandBarIOS/Images.xcassets/Contents.json create mode 100644 Example/CommandBarIOS/Images.xcassets/Logo.imageset/Contents.json create mode 100644 Example/CommandBarIOS/Images.xcassets/Logo.imageset/Logo 1.png create mode 100644 Example/CommandBarIOS/Images.xcassets/Logo.imageset/Logo 2.png create mode 100644 Example/CommandBarIOS/Images.xcassets/Logo.imageset/Logo.png create mode 100644 Example/CommandBarIOS/LaunchScreen.storyboard create mode 100644 Example/CommandBarIOS/SceneDelegate.swift delete mode 100644 Example/CommandBarIOS/ViewController.swift create mode 100644 Example/CommandBarIOS/Views/Button.swift create mode 100644 Example/CommandBarIOS/Views/Color.swift create mode 100644 Example/CommandBarIOS/Views/GradientView.swift create mode 100644 Example/CommandBarIOS/Views/HomeView.swift create mode 100644 Example/CommandBarIOS/Views/LogoView.swift create mode 100644 Example/CommandBarIOS/Views/Toast.swift create mode 100644 Example/Pods/Target Support Files/CommandBarIOS/ResourceBundle-CommandBarIOS-CommandBarIOS-Info.plist create mode 100644 Sources/CommandBarIOS/Analytics/Analytics.swift create mode 100644 Sources/CommandBarIOS/Analytics/Events.swift rename Sources/CommandBarIOS/{ => CommandBar}/CommandBar.swift (76%) create mode 100644 Sources/CommandBarIOS/CommandBar/InternalSDK.swift create mode 100644 Sources/CommandBarIOS/CommandBar/Options.swift create mode 100644 Sources/CommandBarIOS/CommandBar/SDK.swift delete mode 100644 Sources/CommandBarIOS/CommandBarOptions.swift create mode 100644 Sources/CommandBarIOS/Components/BottomSheet.swift create mode 100644 Sources/CommandBarIOS/Components/Buttons/Button.swift create mode 100644 Sources/CommandBarIOS/Components/Buttons/ButtonGroup.swift create mode 100644 Sources/CommandBarIOS/Components/Buttons/CloseButton.swift create mode 100644 Sources/CommandBarIOS/Components/Image.swift create mode 100644 Sources/CommandBarIOS/Components/Spinner.swift create mode 100644 Sources/CommandBarIOS/Components/Video.swift rename Sources/CommandBarIOS/{ => HelpHub}/HelpHubViewController.swift (92%) rename Sources/CommandBarIOS/{ => HelpHub}/HelpHubWebView.swift (73%) create mode 100644 Sources/CommandBarIOS/Helpers/Color.swift create mode 100644 Sources/CommandBarIOS/Nudges/Content/ContentBlock.swift create mode 100644 Sources/CommandBarIOS/Nudges/Content/SurveyRatingBlock.swift create mode 100644 Sources/CommandBarIOS/Nudges/NudgeView.swift create mode 100644 Sources/CommandBarIOS/Nudges/NudgeWindowManager.swift create mode 100644 Sources/CommandBarIOS/Types/Actions.swift create mode 100644 Sources/CommandBarIOS/Types/Config.swift create mode 100644 Sources/CommandBarIOS/Types/Nudges.swift create mode 100644 Sources/CommandBarIOS/Types/Rules.swift create mode 100644 Sources/CommandBarIOS/Types/Util.swift diff --git a/CommandBarIOS.podspec b/CommandBarIOS.podspec index ab4c003..6a2ba95 100644 --- a/CommandBarIOS.podspec +++ b/CommandBarIOS.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'CommandBarIOS' - s.version = '1.0.10' + s.version = '1.1.0' s.summary = 'HelpHub and Copilot Command Bar for iOS. ' # This description is used to generate tags and improve search results. @@ -22,17 +22,9 @@ Pod::Spec.new do |s| s.author = { 'CommandBar Engineering' => 'eng@commandbar.com' } s.source = { :git => 'https://github.com/tryfoobar/CommandBarIOS.git', :tag => s.version.to_s } - s.ios.deployment_target = '12.4' + s.ios.deployment_target = '13.0' s.source_files = 'Sources/CommandBarIOS/**/*.swift' - + s.resources = "Sources/CommandBarIOS/**/*.{png,jpeg,jpg,storyboard,xib,xcassets}" s.swift_versions = '5.0' - - # s.resource_bundles = { - # 'CommandBarIOS' => ['CommandBarIOS/Assets/*.png'] - # } - - # s.public_header_files = 'Pod/Classes/**/*.h' - # s.frameworks = 'UIKit', 'MapKit' - # s.dependency 'AFNetworking', '~> 2.3' end diff --git a/Example/CommandBarIOS.xcodeproj/project.pbxproj b/Example/CommandBarIOS.xcodeproj/project.pbxproj index e890dc0..7a27a23 100644 --- a/Example/CommandBarIOS.xcodeproj/project.pbxproj +++ b/Example/CommandBarIOS.xcodeproj/project.pbxproj @@ -8,13 +8,20 @@ /* Begin PBXBuildFile section */ 4843AA191A2DED0CA2F52040 /* Pods_CommandBarIOS_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 07272DC8996BCC77417C4BC6 /* Pods_CommandBarIOS_Tests.framework */; }; - 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; - 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD71AFB9204008FA782 /* ViewController.swift */; }; - 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; }; 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; - 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; }; DA41BFB8BED6A51CE50A6D1A /* Pods_CommandBarIOS_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E6A6D4D4FA9BF47C33B8F1B /* Pods_CommandBarIOS_Example.framework */; }; + FF409B3D2B2F694500D2A3CD /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF409B3C2B2F694500D2A3CD /* HomeView.swift */; }; + FF409B3F2B2F69C900D2A3CD /* LogoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF409B3E2B2F69C900D2A3CD /* LogoView.swift */; }; + FF409B412B2F6A7200D2A3CD /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF409B402B2F6A7200D2A3CD /* SceneDelegate.swift */; }; + FF409B462B2F6BB400D2A3CD /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; + FF409B482B2F717200D2A3CD /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF409B472B2F717200D2A3CD /* Button.swift */; }; + FF409B4A2B2F76C900D2A3CD /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF409B492B2F76C900D2A3CD /* GradientView.swift */; }; + FF409B4C2B2F7B0800D2A3CD /* Toast.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF409B4B2B2F7B0800D2A3CD /* Toast.swift */; }; + FF409B502B2FB49C00D2A3CD /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FF409B4F2B2FB49C00D2A3CD /* LaunchScreen.storyboard */; }; + FF409B522B30995800D2A3CD /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF409B512B30995800D2A3CD /* Color.swift */; }; + FFB6A38B2B1BC93D0036D16F /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB6A38A2B1BC93D0036D16F /* App.swift */; }; + FFB6A38D2B1E27850036D16F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FFB6A38C2B1E27850036D16F /* AppDelegate.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -35,11 +42,7 @@ 4E6A6D4D4FA9BF47C33B8F1B /* Pods_CommandBarIOS_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CommandBarIOS_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACD01AFB9204008FA782 /* CommandBarIOS_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CommandBarIOS_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 607FACD71AFB9204008FA782 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 607FACDA1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; - 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 607FACE51AFB9204008FA782 /* CommandBarIOS_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CommandBarIOS_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; @@ -47,6 +50,16 @@ 92163EE95FB1EE50D8179ED0 /* Pods-CommandBarIOS_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CommandBarIOS_Tests.debug.xcconfig"; path = "Target Support Files/Pods-CommandBarIOS_Tests/Pods-CommandBarIOS_Tests.debug.xcconfig"; sourceTree = ""; }; B070E6A9FC190A106848CE72 /* Pods-CommandBarIOS_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CommandBarIOS_Example.release.xcconfig"; path = "Target Support Files/Pods-CommandBarIOS_Example/Pods-CommandBarIOS_Example.release.xcconfig"; sourceTree = ""; }; F13A7F09F23D0ED81552C380 /* Pods-CommandBarIOS_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CommandBarIOS_Tests.release.xcconfig"; path = "Target Support Files/Pods-CommandBarIOS_Tests/Pods-CommandBarIOS_Tests.release.xcconfig"; sourceTree = ""; }; + FF409B3C2B2F694500D2A3CD /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = ""; }; + FF409B3E2B2F69C900D2A3CD /* LogoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogoView.swift; sourceTree = ""; }; + FF409B402B2F6A7200D2A3CD /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + FF409B472B2F717200D2A3CD /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; + FF409B492B2F76C900D2A3CD /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = ""; }; + FF409B4B2B2F7B0800D2A3CD /* Toast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Toast.swift; sourceTree = ""; }; + FF409B4F2B2FB49C00D2A3CD /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; + FF409B512B30995800D2A3CD /* Color.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; + FFB6A38A2B1BC93D0036D16F /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; + FFB6A38C2B1E27850036D16F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -113,12 +126,13 @@ 607FACD21AFB9204008FA782 /* Example for CommandBarIOS */ = { isa = PBXGroup; children = ( - 607FACD51AFB9204008FA782 /* AppDelegate.swift */, - 607FACD71AFB9204008FA782 /* ViewController.swift */, - 607FACD91AFB9204008FA782 /* Main.storyboard */, + FF409B452B2F6B0C00D2A3CD /* Views */, + FFB6A38A2B1BC93D0036D16F /* App.swift */, + FFB6A38C2B1E27850036D16F /* AppDelegate.swift */, + FF409B402B2F6A7200D2A3CD /* SceneDelegate.swift */, 607FACDC1AFB9204008FA782 /* Images.xcassets */, - 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */, 607FACD31AFB9204008FA782 /* Supporting Files */, + FF409B4F2B2FB49C00D2A3CD /* LaunchScreen.storyboard */, ); name = "Example for CommandBarIOS"; path = CommandBarIOS; @@ -159,6 +173,19 @@ name = "Podspec Metadata"; sourceTree = ""; }; + FF409B452B2F6B0C00D2A3CD /* Views */ = { + isa = PBXGroup; + children = ( + FF409B3C2B2F694500D2A3CD /* HomeView.swift */, + FF409B3E2B2F69C900D2A3CD /* LogoView.swift */, + FF409B472B2F717200D2A3CD /* Button.swift */, + FF409B492B2F76C900D2A3CD /* GradientView.swift */, + FF409B4B2B2F7B0800D2A3CD /* Toast.swift */, + FF409B512B30995800D2A3CD /* Color.swift */, + ); + path = Views; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -177,6 +204,8 @@ dependencies = ( ); name = CommandBarIOS_Example; + packageProductDependencies = ( + ); productName = CommandBarIOS; productReference = 607FACD01AFB9204008FA782 /* CommandBarIOS_Example.app */; productType = "com.apple.product-type.application"; @@ -212,10 +241,12 @@ TargetAttributes = { 607FACCF1AFB9204008FA782 = { CreatedOnToolsVersion = 6.3.1; + DevelopmentTeam = 7AFRVF8235; LastSwiftMigration = 0900; }; 607FACE41AFB9204008FA782 = { CreatedOnToolsVersion = 6.3.1; + DevelopmentTeam = 7AFRVF8235; LastSwiftMigration = 0900; TestTargetID = 607FACCF1AFB9204008FA782; }; @@ -231,6 +262,8 @@ Base, ); mainGroup = 607FACC71AFB9204008FA782; + packageReferences = ( + ); productRefGroup = 607FACD11AFB9204008FA782 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -246,9 +279,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */, - 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */, 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */, + FF409B502B2FB49C00D2A3CD /* LaunchScreen.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -256,6 +288,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + FF409B462B2F6BB400D2A3CD /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -331,8 +364,15 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 607FACD81AFB9204008FA782 /* ViewController.swift in Sources */, - 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, + FF409B482B2F717200D2A3CD /* Button.swift in Sources */, + FF409B3F2B2F69C900D2A3CD /* LogoView.swift in Sources */, + FFB6A38D2B1E27850036D16F /* AppDelegate.swift in Sources */, + FF409B3D2B2F694500D2A3CD /* HomeView.swift in Sources */, + FF409B4A2B2F76C900D2A3CD /* GradientView.swift in Sources */, + FF409B4C2B2F7B0800D2A3CD /* Toast.swift in Sources */, + FFB6A38B2B1BC93D0036D16F /* App.swift in Sources */, + FF409B412B2F6A7200D2A3CD /* SceneDelegate.swift in Sources */, + FF409B522B30995800D2A3CD /* Color.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -354,25 +394,6 @@ }; /* End PBXTargetDependency section */ -/* Begin PBXVariantGroup section */ - 607FACD91AFB9204008FA782 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 607FACDA1AFB9204008FA782 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = { - isa = PBXVariantGroup; - children = ( - 607FACDF1AFB9204008FA782 /* Base */, - ); - name = LaunchScreen.xib; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - /* Begin XCBuildConfiguration section */ 607FACED1AFB9204008FA782 /* Debug */ = { isa = XCBuildConfiguration; @@ -478,8 +499,9 @@ baseConfigurationReference = 1716B1D54620EDFE703901A8 /* Pods-CommandBarIOS_Example.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = 7AFRVF8235; INFOPLIST_FILE = CommandBarIOS/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.4; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; @@ -494,8 +516,9 @@ baseConfigurationReference = B070E6A9FC190A106848CE72 /* Pods-CommandBarIOS_Example.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = 7AFRVF8235; INFOPLIST_FILE = CommandBarIOS/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.4; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; @@ -509,6 +532,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = 92163EE95FB1EE50D8179ED0 /* Pods-CommandBarIOS_Tests.debug.xcconfig */; buildSettings = { + DEVELOPMENT_TEAM = 7AFRVF8235; FRAMEWORK_SEARCH_PATHS = ( "$(PLATFORM_DIR)/Developer/Library/Frameworks", "$(inherited)", @@ -518,7 +542,7 @@ "$(inherited)", ); INFOPLIST_FILE = Tests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.4; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -532,12 +556,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = F13A7F09F23D0ED81552C380 /* Pods-CommandBarIOS_Tests.release.xcconfig */; buildSettings = { + DEVELOPMENT_TEAM = 7AFRVF8235; FRAMEWORK_SEARCH_PATHS = ( "$(PLATFORM_DIR)/Developer/Library/Frameworks", "$(inherited)", ); INFOPLIST_FILE = Tests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.4; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Example/CommandBarIOS/App.swift b/Example/CommandBarIOS/App.swift new file mode 100644 index 0000000..838422b --- /dev/null +++ b/Example/CommandBarIOS/App.swift @@ -0,0 +1,29 @@ +import Foundation + +import CommandBarIOS +import SwiftUI + +@available(iOS 14.0, *) +struct CommandBarIOSExampleApp: App { + @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate + + var body: some Scene { + WindowGroup { + HomeView() + } + + } + +} + +@main +struct CommandBarIOSExampleAppWrapper { + static func main() { + if #available(iOS 14.0, *) { + CommandBarIOSExampleApp.main() + } else { + let argv = UnsafeMutableRawPointer(CommandLine.unsafeArgv).bindMemory(to: UnsafeMutablePointer.self, capacity: Int(CommandLine.argc)) + UIApplicationMain(CommandLine.argc, argv, nil, NSStringFromClass(SceneDelegate.self)) + } + } +} diff --git a/Example/CommandBarIOS/AppDelegate.swift b/Example/CommandBarIOS/AppDelegate.swift index d386cb2..d59c512 100644 --- a/Example/CommandBarIOS/AppDelegate.swift +++ b/Example/CommandBarIOS/AppDelegate.swift @@ -1,13 +1,11 @@ + import UIKit -@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { - // Override point for customization after application launch. return true } @@ -33,6 +31,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } - + + func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { + return true + } } diff --git a/Example/CommandBarIOS/Base.lproj/LaunchScreen.xib b/Example/CommandBarIOS/Base.lproj/LaunchScreen.xib deleted file mode 100644 index 9e2b99d..0000000 --- a/Example/CommandBarIOS/Base.lproj/LaunchScreen.xib +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example/CommandBarIOS/Base.lproj/Main.storyboard b/Example/CommandBarIOS/Base.lproj/Main.storyboard deleted file mode 100644 index 35fb398..0000000 --- a/Example/CommandBarIOS/Base.lproj/Main.storyboard +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Example/CommandBarIOS/Images.xcassets/Background.imageset/Contents.json b/Example/CommandBarIOS/Images.xcassets/Background.imageset/Contents.json new file mode 100644 index 0000000..744faaf --- /dev/null +++ b/Example/CommandBarIOS/Images.xcassets/Background.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "shop-backdrop 2.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "shop-backdrop 1.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "shop-backdrop.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Example/CommandBarIOS/Images.xcassets/Background.imageset/shop-backdrop 1.png b/Example/CommandBarIOS/Images.xcassets/Background.imageset/shop-backdrop 1.png new file mode 100644 index 0000000000000000000000000000000000000000..d9334a268b4918e275946e8e08c850a13fcfee94 GIT binary patch literal 71094 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

-vBob%4$!A)qzAQ|&QoVv*~|I@L6(zS8okjr=QBf0N9%?gDd#+gqA;41Oue`+#( z@U1sn#{yr>lv=*8S$uYHl!eVj6g17|xF2Mi7+Y-K>Dx|e*^+Bq`sSzHRhE!C>=|_P<$>@ zj%=57zw9~#Sk&$ zvgXkk_mxYUn8}d|`@UB1;z4P(bXgx^)B4j41SVF0Cf)dHVRifQx`y40gBVX@o#K1t zzM!Qxl9S>a(hsK}=S5X4xW?O$h&^j4AI^9^eMPyX1o1(sMK|VwEZa^JHOyD$Pt@}1} zfy)7h2)wwHbpH|R{Gb_wyDWdB?I@V{TEJO%Yi;%-jF;T4M48=%s8Lp<4)O@wd4v4Wxdah zmhb)?)ak!9_Hg=8#a5@Z?h%faTK5fE%Z|I6ef<~YGtG%c@95*oP$HEQQsP_q4J_Wx zhFJm=6Y{YTk%6C_Nrp3=eV;-el}mzYCcWW`IEQh z94wjgV*x9z=M^KmCN&+OC8OStL-c;FJC*cma7Zhf7a3|i_+lKA8nGZeqw*m&?G<9a zNZO*ZnEX=$P1>f`q^pH)TT9#z?x+ybeUaXG!|RdB8G{3=SHiN8B2 znSKyjE@kv>w$G?~XFhDq_d7AP_eGw>UMp%MSzjUJ%}6m{=|Tn@(~09_y(#6v!1_U) z$DC6=!jt@tzz)q9<5kDiif;ETeQn9c7N|nI0mErS^Y76}qHo_Ct#Y3|No19Ud3bv8 z*RJN6p(xG$>e51X$;z5f4!b_B*ETJc3aBCv^UUSZ+++W4k1ISi&n=B(o-Y{nBzxV_ zP#e3XQ?BynV`^_j-t{YhUtMEf<Vn&Rk$y{gB;fP|~;JTe9#8 zq59YK*DRqW@4;f@H~IR5)caKrt~eCvtqxYAuq7YIX8*3;lUKN$J~HzoBWKm!0{891 zl_ig_Om5u& zYe5x!-P7&1=flC9k4ldXIFWqDwWd@hvZuotdJV!#+eM`s4hWqW-p9!*o6Y(yW|)Uz zNAy*`E8Si+`mshSYp~0vajJvceiCYZL}J~)7oX?KkMsA{R$q{##+Ln?VfKRcPoo*H>~^J z@7ryYw>#Oz@5Ftij9oN-I5<8vF#e>ij1ssZYQ}_x5Dnx0Cvnfd-wX3!*qxRnw9j=i zixq^bQGPP{Y0J5~tela&C?j@_gzhuj^x7tOX6HQ|Xa~#)G34@eo-BTcKhlWy9an#U|MC{X{adCUzym+zdO?vv%7Db0%_nD;9_30dXPD&=8Pd34Mm z&!gOLT0+uXckK#$>b9s|XbeJ-!nR(HcMKdy?!d4Orim$aZ@#UIq$}FiV-8BaL~M{` z&90I%Y7Km=m05l7zQL;QDaMXDGoJ5+>3TvRJuoZUN_@T~5F)B+lIqd1CR`L=bPxjk8^I9G^hGJfZ{D`5?j&8m%%j zMB=$sQS@`hE737x%C#(D@R#ROr_=@+v{U!=_|mt@p#&hg=MT zbyX;PG`MOT?{HNt&+HA5j-4VOrr7!f!S7bUFQxr|yV~kred+Jx+pZqFq*JAUgg&L<^@gJdu zLqTV8lU0aQhRm|BKg2G0z2Rue+FHf=0TG3rzcIhUHuV~qRil9s526zdUGJ9;J3kj9 zsc4xrw$z)>qmOF6E$Kqj`gyQ(ZLemwvjyIF0}}IHeR>f4K~tJ{Lpk$k#YQ^p+tJMf zm3M}$G~Dl=DW~~PY;=r_95;+OtJuzr-M@RkxcE@0ayH|k0%72Dbm;^B)k)f3!r&$J z?@vczTN;j$Oy!}&4>A>AlteN_hxf}(6xG)mmtud7OcG}alv8e($Os+W|51JG)|SQk z?e7Mj~>XMQHnZLbX3%E zlk{rWJnegn{IWx#s)P*cE4G`q&DZ1{{U*1bAE#a(Pa0;)Ob9n1>?k6*!b`EP%}a)w zJa~c|3o9Y>urX%5Sz~_91yYrAgpbQO`x9YH_Lw=}lcUPz%X8y;-+Jq6>X;B2+53eD z69ak$YS(y+jz^c37G90|$~DjuZa(K%ugr)!G}z9|jTl+KCj}YjH2p-@vnKpN4BERR zY?fL*F+csJGRZ89i|x+?qxCLNLko3-ooZ=1o#=y3$=kR7nPFW& z@8gxj#3vJ%AgZCBY@+3M@AJs!_*Zg`{8mWK^^26OgsOiX>p8i`+q=%lC>#6+*%w+W zYqrnK!^TdUW|kmQ{ka7o8ou2n95T`>y?yhdN_jUzTM3R(aZvSRDT_C{)miUfOBZxf((Uz zkw}osMNm9i@tvIR(EZ;dc7fIU(%?$utiit;o;PMQ90vr(r}Dc_(Yd)>>LU#TfE>0-TP9Tcr?_I2TwevgkbAn5D=+)~Y9aXip6Cgw1 zmf`s#-Dk`e0$PGPOS?osT$GEKv6wh%*`IX~`e={BVhCGwQ!|`AN886VyE79Q$ zo=GF2m%K|DWp?o#ob*xgste&GX==RC!q{t9uYR+)sGJC`xh^cDihP_v(hIn7kP;F; zyH8AEQtMI;l&?b8wS*--FaE2enn*dHF(}wgGSyCtiFpOOs0E0NDu}!k8t%}9vcay| zKY#xHQO@I}rrr!$i|Z8ND_@>x|NbqH+-_9)zA3Znr@2+P>h71i|3rIm)vpsd25|KS54JUX5of*Ng&QKob_7H! z5x2>L2{}LIUyEJCr4%jAy7!1I8}GFq`fe8X*+!Z9ZB{R#%Bq(N@m@HKFXi`9{Au3v zxgLXR9C!9gJGRMslF;l{vpva$l=oHR(XZxr=GwU5fQcKU0;RL^$W?NhZ+(|WG7sy} z_GpUHfxcn!M^6AqimnKK^7yQMp9s#7zAOdJ;_=vC6nBe!4S0>;-qqsK#bEGwDqipo z71wWrbwl(b*Y<<`Vmwb=K&?zEOyJo+BL@{Bfli>B1oBSvf9GUpYhz0=OkuwJ1Dz3= zFj7XXJ{hbN0VL3R2s9km7+_=3-ot*r0U5TL8Uu&!4&uSpGsEClkR zID%4KTlzq6x8syG_DoUId&kl(fH2|)pSR7fADlkd;k5(G1T-+P?e6;KjZb^pZ|QL;aV_wF}Xg;Chw5U7H_oxoAEC1=50ZWjiz4+ z25^ccNM`?^jhFwe!S#Rn$u-f}#dD?4j~7;ZA8u=qO7H7T*1B5k9wqRa==)!&n&r9o zNsDccmxEFdk9(?L1lK@tK~rqTLwDCNiHMr{TYCtVc@kg43Yrii05lpqlk$Czr@)M{Ixl*J6$Up(Sbk|uit)gvmQhvfO_%H@2?-RqOP;4S`Rm?JkC#+^8nV6Go&pm z4cN~7V=(Vj260E2jIH|R^pA^Kt3%ghkH7BM)Hd^)z5IFaI^D86u6NiD(neeeDS#`Q&W5zsoxrw8f@(KJKS&zpnL6*43VAF%9(d1OgGbWJ1R$ zqp*1N=v)MMDW?Nd19B04I2Uw-PZh8n2q=$2a2ye{13M&8Qr_wtIMRnd%R*?XqofYU zTNXd>E_!tHVl)AhSjOw*w-2)Cu@qPuaIK50^xMbv?N;Hrs&GG@2r{?Dj|MfP3OC8$ z%mcc}AW{I@ldeD*zk)<8CEJ2u|KP*M&gsB{QfQB%pBe&WPhpkck$S`wu5Thy=I{IU zA#?=J?`(IrFaJgRYg4ZoPwrY)q9|IHN4wL8Duf@%%KSv~ArL~5+vIwr&;hD>`t7!}{A)Mt-)??a=TnMxWG?)I zjfwETy@=F;gE>z|7=Atch0fKtWC$ko&&L|aPmWMyO}-MQsd4A~+Ok!*rCJWFT@S8= z*Wp!UeZ3dAshU@!zI!S${~b`tFg(FF?U{d=oObUcjYLGD;&@F&`L`EhtWI(dzE?Ek z#H(In-dw(Bu!U*xbce>H+FLqbmZy39^H6El&flFJj;)o7sc7>p<{l+q&lkHK=`4Nx zTakOp;bCr#vwp@@)p?;|%j=%PWv0WYed)~|o4Im^vK(&beUj_HGRq98plpv^z1wJ& z55tipBZ7}~k3sfY$D_)Hd_AIf(&pMmML0P`j*N|+&4HqDb}!wFl=qi%KXOS6%A`Oc zoW(?QiFMi^Yqom2E<01(;@hKq{Ee#R@qQ&IZh#S2^v0&;bi|c1t#t~;-n^<=w!Mxe z>q(Z`&y2mv>$@6Jk@*qQB?itSl5nm3YVz_qvRu zlCDeEf%| zS6EE~zo93~;p)G)9=XW!Ob`1LX6Fmapg-PWZ^h%b%ci#;H|lh4BI%iPz*glb`tQA{ z$gbg)8_a*CCsy?Mb2-ozirj;L=50-j#dgb4giKWUXb}cFyt8w_Gj{8>evAz|X~ZB# zx-g5#CpJSl=I$ANq$QV(j32Ff`7etZ9E!EnmmPA26L=#Y9@wBiS=*))#>* zE@kxx1G3eb{;w!Qtj?>&kFDe58$1p^kD6tKiaKe#4Z!tggnQG6igXq}eDV8B*XGOM z96odgY-Nz*zMiAx;pS8#1QNvLMi<^Yc))G|C$n&jD?DxYGca{K`SJj67rWRs8F)Oy zEhpys&;eG6HQv@8G+D|xl;%hX5AvR{&7S4RG=DfmK{kIb*1YP;-BW0l5!RD7K*^#o z{2?9{BUJO`mU=xJqfp?;s~C)YIh@;nPeV`fk!LU`$E3e$do$AH{k6`;B>D2-^$aLmfu%=G(8Hd*~??${joI2Q|)SHu5YR)jA7#$ zHDu62&1tJCIF{^dwxr}p9W#2m_VE}Kyw}jIRa!&jvqlypDde+E!TY2@yM)JgFlYQ= znfEq2ou{fTqX^D=cQ(=I|8#MeldzL48@y@lXzAP96NLE`>yG3&qQWlf%9KB$!F+{p zI2>T-$FcZjt-eT{)BPP4iw{rHdmj5!hRzNL3m=!v;7qZ5&^ZS~*{G+WW~t?|B3Y%5 z*Q%5BMcI}eTG@)=)z$_-VNLYBkRyC0^3{nmE2+{`NoA)9Xaw4NSG=&t%Xey8>RCWd zt`F+q*YrRhn{tc;F>~{re}Exjq&WUy?rmd!Xl!ZqjRoYp$Hv`J6Ob?EO403v!zs1< zk`l4$Ig$xQluTKy?qkr5hBeQtE$9_@vZ=^#jvfT1Ua%NBXz0N;yT^Ea|6!fHJ&G%* zFY)tIUTKY)voIc&;BbJk1{kFt-G$y)c#a?}BttwvKWAA!h+VR%oq1*AhE4a|qL!?m zHkR7?a+$lP-jQ$Qz~qqgW`^%t zkpXevZj)V^MM?PGk@7kYq>;vOnHeGse;Dm|D3KZ@zgqjkVWCN_Lc-etNxUrVE93$ap)Q zYcNo?n(FS`Nx?i1SU>8M)ag%dVD&Gajv;%h?+E$CrmCSz@wn*98YhMF)REm~3rgkg zZ#KVXbTX<>fO&8-d3t(d0xCIAyZ+c!no+au^?p`>QPi*p?f~y+{du)|$bxrYCG*ud zrvmg5invkmz3~$|cZ3NvwXmmPt!w9sSEG8wdP!}}1~;^=xdkwQeE!O}a5U=;z(aF$icAFmXTP9PKIqJpM%gEE6qrXdPtxD;a-RK6Jb(^^=bO7s~bT3KRim3$mmDS7$%PJE#{%Ye7u{caSCxrzg_CNFMhDG3j^d6fjK2?*{jrT~mKf@5V09GK~E=SnH5xip{LnfM$R`e=RI!@;xA2%YIn;y_C`lKWo{j zsLi!DdcAJCNlO;e?bZ^_KPI%bSG0cD%i`rBGir-YY8-1(@3q7R+{K>eCVGP5II_Tf*8Spj5*NDh8K0eLpy3^ zScwp6*Y#{r0`lnwI0zRsbv%Rhv^O8krffCs^`f;^&tO8iAUZ^q$?Cv>rc?}bfG`1d zjLy23Bt(015J=p!V}t+C!HfSA{}OnC52Sz-*r7cF!VnP|N<&p;fLM1SfLLx4hF>|L z3fQHx-=1wwONE=gOVph#xl*+9H*S=K`@;<}&3;~^?r5@B zVBiXK!SCWP(ChglajSsYzX`S37i_X_*%ia?mfn}Lmmut`p|mY}XDxp|h-Lfqt5{uX zJ}B9{VF0zV!tM&WAUVg#tM5aR=y$TW;>O2b%39Mip8dWCf)F!Aw{Nf$S338E1Gf8~zaZ5JpL^l*^)2AA?0*D2COUu8p)b=av%JfFFayUchjCkS)e z@+XihwaxHlk;d+yFJiER?$-|USo@@F&-R?G`UkJm4uxu_Bm~rClh>rjYf0JoO?v;W zY2Ubh`vz03fGpP{QpqfSPY+g!&i%P;B`whj?OvkjckhE2V+Ymwc@?zlTcO@v5`r&l zxK$wnx1baxGG~^O`#;_)D29p~^wA?T@`i-444T&%8(byyoXkncr-nu=U){O%c0wSw zJ@sRn-C{t3C=EFX57lIHUwix$?L#m`;JF8)(L^3FvjIrlU zgVqLR^<^`U&0vP9=EVdPsTdYiKdJ}egC^O)- zxS&~3JDsO}DS60@eRTeCPPn#*OK}yVGTpQjn)je0`T~b`ByYfY?tom}QyB4adG~{^2DU};_$wo%w90w-KX2w8~uz4K=#Adk|DWIk2aZMo#zRQ!sQG>6%# z66~uu@sFWn<)(E`_4<&#$FCP;?-zS;rFuE*Q@nAc+m*sGLXvWcpaX(QCrEevu(VgM zuK8(P_|MyHOH7gyUR*F0-8B1fnzwvcR#Km99vo;}CG+*5(Aw>F*okU=0?2o$reiSj zBy!Gkq1yXv=}h=fDBE)$0+@#?!@U+R#@ZLtO2fjium$_o+wscu7Qsk95sn4nR)RqL z$lex|5O0h(uN7M!uWjnbq?__q-3c0T<26+q z(JJOF&DA_#5s=X9w~$lN{pwXZLQB$ftlqw4USy)FsZ6kd-f@|yS7+aIWf1cerHOi; z2_9G$io(-K8~B%xgTs=#(W&x{-Tp9(_@c5F$xC0@+NGdS_827$ZohNrC_zzv#3#{o zl7{UNzreb>w~Y^=Xf@bUkIgQ_m*LfYH{LX_RvX|>`!`{#C-q0?m?5@!cW=9SVQOV( z)ca#mDF;?%YTNxxrNIO7tR0y`cFWWyIEaw{ZAiLX=J+XmalQ#Grc)~#kYXc3WK#EU zLyD)L7+93UQOF0drumB6JavCu>!ZAMgv;(xn#GyZ>8@EV=}d3YtlJYwdkGDVh~#z- zFuvaN(HCdwNNuesMxxb+O8OV4@Y77tsov!B275m!djlae#Eu-}%~*7PxPW);^29p_ zn4HDXM2?+zmF4YWyzPA#T8~TKbQYnnvcfbw^Ov+2#E(C>aK|yJ{`!LU_?%wD8R%u- zaHsRG2&4_Rm(53C(*0Z$3}`=&(K5DCRt<;%SZF2_**DY6FnVVi4)tzFbLS?l)qjt2 zsZxhmeZn$kEzV@@mmNwJj9B4_CJIdyTA2kU+=LR*H{&%?=6)k1t=9%E?s8V6x=o4S6e}^6TUD@;qWZkq*kHR9i#qoiAiej&mTwDLX@OrVtS#+^U~S$ zAFsG^bT1u=yHJrt@;RNLcgo@`YD%kTc@=89`#IyD1KK(EzK8aEe#IYY!nq<8ToPSZ z$K2y`Iqg)U)e~ug?Qeo=_!c7D0sCgU5w1i2!)nKC8;^yPQA@9BA#^6`4?oLl8V~bG zJvqsh`3AEqN=~Y}TTwk}dcSsWZ)mU2#($%P+@?1c%qd z`Mu>)HTJ*SRzw_b^5 zk1ZYgZjjaS*gczTvo~IXvUkPwF{3!6hfaKkMyV*~m>lRBngd*YmsW8~-r{&W&hP{L zW@j090`J=n9y*_``u0hp+q(Upd?5#u*<7I&o5qn3ipZcZYjj1!*ZxW>MZ<<0ghyUL z0+VLUF)mlUCKVUs zitkLe`G`9y|Zv$(@SfX3{u)JINl9b z39+geR@E>RwqF}OmmzLh-=y6lf=Z<2u)>=5(zZ1gen^OwZ`3I+D|4>hjsi8)HRZ8a z0v9^L&TIQu(@VFfoh^lM#;47qOxT`yMBzMJFD#xnMYsboz}!f~G=C17dTv~gou??f zJOQf!8tE;rR{Ni=8&0Lka zPT1avHCaC>KSK6MEVYQlNKG zx&kw`Wm8GRn(I*nC&rF4rS(gw-YmM02$t{my?Pef!EgDN?Rn`l8(s3&34I`R7_ITs zpn|Arik^VUrBLK^mAF)~`D@)%zPS&k_7Sx>XKUv3a_mv*^!e^gZ5}_JGx5P>k$8u$O`_pyxREdvWCvH~+v95UY!9VT z>;*E`2gOe~Vjan^oIfC>liAt-Vbe_$yOv5Z0z#cS?bZ)prRo0qgd0cr4Y8$tKFDsL zw3~!waf++_{&^i5mmi*w`qKchq|{3KdUnk$RVs^FuhVS^zZ`JiLCQ)i;_h{a_&Be_ zn8lsoWrX-{{APGHob_v9{uLzIK=sKJY8H0s_H~dM8Mm)bD$8=T2xB*kahE0;y76Vh z*|hY1l1JG3OM<%6o<1I6|WKc{Xxva0sm!WCdh_y=^rcTO|*bH_N{1pl64~mL$JYwVH0hih-NEE9bb~62-dT63AZu9`HL$73P8- z8$Q%bF)UYQW`SYC_~;8*Z$>@rQ~cFG(~*rp=AJ?Q;bA#7M7;>zSpO54>Pa=b_NqQ;X)K1}!sb9C#bEKvw z4qQ+dcAk9QAOOFkiRzjtnnHn(r$JWjc@H#TB`^tJJt^DA)ell$rN0+-n*4BaS)9r# z5$rHC6?W7UB+>^~bF*yIcOhY~y<=OQ&qon;P2_fGc`5Gl5-+$80gNY0D-oTWlcRLY_!g*;ZUI)M zFEHm;>n~%6Dz&BGCuJnLof+PMM#|Ybj)vqvP4di?sj(e5fQ+vF*)xYzJWGyE;-8OC zJbz~Om+<;%v|Xr3(K#`c1?_qjQv75;ar`hMGU|`;wSiPF1z6KnjdZ534Yzwf=9&pX z*E75@P)LmQz^~P8_j5JDmt;eCzB2dLE@=$iOE2GoG0URplx%lP=|49jJ(VqPx+_Bj zcm>1ce-*y|{S`Ynr^2YEVLq(jB)#WUO(yh7ImnYsSvTUT9fx42;zYqI2%te(AW04R z?~$nRP5e*CSgn}cP^%K(w$1dkS52n}O1!~jg0#I4*7c3vk})%ddPD5{lqdxU=a6fuayUtIrFnN9&U<;} zKR^7%`c?4WQYzA@bio#wZ3yxcB|~vw(d#cIlQBR74}MAA7LbRMu&~)(u|$vg46VDbpi$%jD$upV9)EXHmlk8WSvbWnRZhYOGY4ZuOXTQ0~; zzwhrlQE{)Q8yo;VO-#@HH_AJ~vHls>SgFTnvkjh(s0+wobIOaNb-Qu<9FQR%M?YBc zI%l)x)_(sSbDq*tOA$>otlIWH+wHud5GLP}${2c(A}jW}@=`x6*|^ACEqsq&jS}kR zbiw#z>AC5Z0XFa){(QD_d3OF)d`^~zG`~B2wf%B$n$orRs(K*#!vRQ&&BKj}%Ez=& zo7Dx7r}%6?l)L{Su_;^p(h(*gz|9K$hCG}cii^}1f2t^XG(DqatMRd0v`fYu0(d4Ui%rK* ziPy);9^1`+5g2BI4*R^cgkJH5eXH4UpFAK#l$6U!-l_eonzARUD?t)KPinRqxDRMo zSp0jcOw%SZd6srHNskpB$(Mgr-#0P%AJ2W11CO9Hi-<%}atMTs1_uWpPd53SYoZ?A zAZJq$c8?&WY;F77k^^MT{@Oiw_zq+PPQYz;7TUFV%!j7{q9{%8S0iPsqOf%Y3h5(e zTWFlm1do^u2MRi6gv5ZiVNiO397v`t563IKl0=fD_kn)d3Yo zZhuCZ*W%KEMFZ4H%oAEM7Y%;zuQwtx(jIDS0tGDfNQZwnfuR3JHpspMG+O*W?32&l zQkCOad=P|HXhZDAW07H0R<23R34A5ca_l}V+oFwa}TXw|gMXm+gMI5Qn6^Pat!3l^~Kf)#RT574a(e6`!*7oTSR z0?n!3H)Q%2c5|0zKG^O;?5<5IS>ozFVjCl0a{vfgeWwMmOaOA@Vt`VTp|9?Sh|6y?b zm#@kHr(oUx;F?9*1Fw67)pjV&Yc`p|cO|n5q&Mfc0Tx$$)&#mSYF~twC(Er>K$(fG zJb_^xP@V%s(U4}x_EVN;!9?U#=H5>MQ4|Ttj9B5Vx^Pv7MStJ&U9ay-2?;M{DbN$5U=A4l1oh)T~`e&t+#h+CH#ONPz z4?tsgWWn4~ZNQ&nhrmi&S@BvJar*n3Y|`vuO>K@kUp*W6?MNoUOJD$xy?nE#Lo?>H zoVIB)aphp#IyUbD-r=M2J-QPBq~Q|tF0h4F?^g@aVwB8iic2ggF2KfhbZoLWzS_Lc z5HKIkkx-U6H6+%u8~w2pt3k6`s3CyQl)QUM&$4a<1p^hI&}V<6_$j^$*>!IbxdXfxC5onL{Kf3;C#>+5d75d zx;vKy9OAweM#z6*$oQ?fAAX^G| z&w=j4&}xE7i;2;eK?F%-F+X(Q|IjvooxblPk$_f43*U#q;&S=|&i6VtyZKw2s#kT3 zSy9S}4Qod3Q?+3V2i%J0RQRDq5z8-X{75>5tgjax$uqsWQMoDlvs>V zddfqE$HV6v6MJo1Q?b^u&ZF4scA5CXsnXe2_vM;Q`h_AabpC+m&{*$?!)d0$XHlfI zw5Z$nQJi>&=l=>(^zWsI{3J!JuyO~e_~HDvCQ^Vo-;L;g@)kxx=~_1@OA*q;UgpzN zl-R0L-L=S@Zo2@KXjJq#Vh8o^>07S?#?X*Tbq}qCIr}h*Q z_a@jJSipYJ_}9xLp5dOdeS{^M2#K3tJP{34zsop$Joo)Ch-Ep*F5D-^T3{!|Oc?R= zRIO5E57y9f^|pPp=xF?B)SFg3wlU#GrG?#V9^!GqGy5UQh7Co!Hejm>_rI@~DR!8u z$$G(nphhV_idZPRimutjxOE<>q`$333XpdWQsye07~i~MlOtZ{{FEtX`S;h$t6kgy z<=f|KsePg&*Ovj^*rdfOtmJ)Mf;lajf0gJ@QLf=J%jYO)Md`#Ue(8%9IUA)OH4A!& zHm%C9*6&IMr?CEwopKF|o86NU`DQ=^qA`ZA(Y4<4^y8>&xng}O2=lg7^Q8>O&u`~T zVvZa3!C+LL4o5}2WVAAa3zYhkGgRLlQE+v_ij>uVHtdV_-`9bw z!)49^N+Q#ISY5VugTRese(I>uuoL9SE6@_!PGztCadb_98skm~54;c~D@$#wlQr1r zRFV0+3)067-M}P_aMwxiewtZKfhF(mT)04&=36Qz3|E1ek+~b6*S3u9V$11C)ZWhI zSc`9tk7;n+-(BySwPp9D3uPhh+QwnN_?Hi@R8+a%!hWG{L3l*vt==eol}4e5mFB7> z*;YZbTh~L+`51*i8TbP#j zVo&ZqD#w7^i%@X;l>;fWl5P z%x8m?bJz<9NrPsAavJ6N6rA{|+WqBBA{)kF5Dp2_@wwSdHp*a(>YaKx>*izeF26N* zz|{Vr{HxKZH3rT9OFS!7sWs&Bm~ki(bTMBuQ#~m^G=7Z;4*6nrn~icf*|z1yp9k>q zVk&VzOaaeM7cjMY_v|shmezuZ80p$t+U6&--=cQodTww$;?lgUlH;gnxaDUH7mW**%HoZ%_ zI_D4YKmtu?K#!Z(HTb&}QL2S9>J5Jl;QVd{T40A^^u0WFL2>{iMhsxBVH;l&c+wMf5dU5}LsgU`NagB~hfsNm#8+nrEK%|Co&1$zsIS zZExS5^|{Ld{(S1_Wt-H_zX!-Ypp5fU**W4j zoCH5v{pu+l^zkFdWIFuqcUOValF|FB-0Er2hX=-L z4Z;PYbM@dl(Ub2h63`U#tcT?rJM=v-*O<{8WOUUxb~k+}qCk66eAxHRQLLU6&SRfk z&7BGdn;ga_In7F)xK1yeDaj(e>8(gUn3LC@FB!N!lnhXD&nrzU$?_R?u024Zz%C`N z$dPCg36y0m7Z173cOwY@nW^-JUcxPa!C9K5U?b=#$OBWnOvyELqcP%(E~S-qMmIbT zJ@lgb1ud(L(z})W-yS~+PO4y(GwUrLuJ3y4qYi)Jx?Tp2ebUjQq0S#)lHNxoC}?jX z^7^}DzlbU<^Bfpmrfv@%ZlSLaW;@#ffS9u_A z#lA&!1I|<;R({`6mE})-7c^Jl;4VwBa0t=?k{`K!5Z?-R-C;VID`%@lpGe4O@Kf-2$#9v6brXZT_Ug$;GnJvMOxc2EmADehWVV6MDJ+_S11qXJrK9ew$k7S?8BK%ub< zb78|0KqxbEHPN`T0*p+r{Q< zG3U4ztyaPAmlr;o5!c3dckBGYyOOWgM@u^X*p3*LOu<^C@}XQeI^7toyhmP+Py1p5 zS4>UIuH?sN@BahgKIMqXl+2tGD4$*9nH;E>a!~CuPDm1Wc`>^F^J;iLb@+ik2UFA- zlS43zK>OyYAB)%D=KOmg{l4NsUwu2{d_Qjp5Xlq9dt^s|EM9THyWVhqI`Zj`2$agq z1AcKwVE%Rdc{UP0ihgIv%c-oJz*#)nnv;>8M8;3tH$t6~MK;4mTn~(mAz<2Esx{sz zA*H89f1*`vtGN;({{3#w3M=D@w~b2(B3eY)IS#8-R}hv^HzS;Bl0w8W(8>CIU<(tw zeT#?o(qdtezo2H@M}u=Kj10^>U(D@(M?Jl*R=CA+h=nQ$otQzR&}A^fz^6~G;vc~D z9K}joPS*$_#iS_F5=8)bVv@w}T+Iq(xH9F&!PvcfSZiS(H90)`jPsCLL3=~HS(NFp zbv5N=c10_(ws*~Jg!b?LOo#6zSO+~jWJI|X<*NBrRz%#_WH?m#hnuh~Ka6_fek#pL z2lZ8%CxYMaI#Nz_pJG#XZP*`FH#m2L9B!i0Pw(lxEywLeQhA`&vdMvNJGYSFl*e&8cm>?q|r9rI(vpSgY+ zJsn%UrDzyDmfb)aC!SkK>)IrE;VB`GE=nP~-)wwj1&F}`;{1@98@ns zlpFs$T8hcUBZe<5xI_{Z2St*M=4JT%4*cQrM~^Z)FjhIda8q>hByQnLXlDstc6-_+^_~FQYs0b)B$W#=8(9sfJw`A#( zVET3W5~TB5+l7SWe@402|G+E#Pbeh&_m`bD-mUI-GV=Qu_5$~j5b|YL@tvU#Afy7` z13P%i=L8fFW&^o@QO&jsHVTCCwR0}YDUJacKd3}yrbie7NdL4|K+~l8)FE*VApBx{ zROT@kLPd!sf_ynnINZhru=RZH5evvVMoieaYVJ24&H4=iBfB!4JmgT??=V{}{M+$A zWif9^Ut2!=+SFqLD5-tg)?M0F;2vuY9sbnze_#g6`_c|Y4p#v~^MU|k*!LeZ1_(CF zeiMu&=Ea?mzmfbc;<&GjXJ5xb=0{VRVsgQog-%nkSZowu>ecM1i6w@}G00neh4Fr= zBAzj80x%XY@nYO`7!d_jV}6{SYm{m|`rtA|z~oew=N)I03hx)G_SzFDQ|=Sa*aQ4U z@3dVkzy>UgBUkdEZ&U(7$dOUx_KiQJ_#M*aQ7Mj7s$XbJ26?U+cRDv07PN`BT(=bXI9k?3|yXo#|{wlrog$E{o2qKE=vS)LbyYaEo%rKrn+YE## zi07VP)FS2v9EYhywkFHSTlKzlAY?CbbT8!m6aXas*M@I$C7iT#$iN9>;azImqxWm5 zMeeaDU$&eCL?m$${Ki+S2)W&U#aN2gWIlPTmB1#L9E+xcD70^qSdI9Mrpb!X< zLDp7tlwWVYra`)W_|x;0SPBLZ{EG%U7qLJwwCi? zv$*T)8=+IycA{H+!|F#a!XReDS7m~IJ91}&!QAL)1Ma@O;C=(2!D79?uEJuyzv$Sc z6+P&$zk7|$KXmUn)dlr5L&P9QXWJ=j2{|wY_h{P3yf$K~ zrq2(sZpqwEFV&2h%ZgD;u4dxtpmS5}1|fzHf@X&j(QN%io@3R8Yl?-)8xB=N4dxr|vj7D0vf;+h zw80k8qJ=>OQ_z>sV4>fAxHWp`TM#vq(zwO;B-om6{9JvL1>$-_M*4lq=dFyw3vwt* z?xeHR*+VH!l1J|zpH7-ReXmO=S7$15^l_l*5|rn$hi0>LcVD(pcGL0ubsVgS(z$3J zt+|ZAYcmp70B0Jc;{|Mj#_vnu0D)&Ck0y-hSa`%3eZGxV3QlHDfsy~vl(ePtSWA2g~Oav2OGf0tk*8t4glz$tCS^BfWwk}2et#72 z^2!@255C){nI-(t;#87~wcSI)Tp9Wx#O_l;lDcEi-_n++k>dA z;)kfoWY~QBf`|eZRN2K(gb%rNt(Bfh+JT~ZBCLUp7W zhP)8!ANAF(DOSG;CEcZ%;Xdjwr|p#l3t7Z3^CDt|%^udJtvXE7_J{+$KoT$kMfSZY zPO!7DefK>Q^_6N2c7CiYlY)L$zmY1AX)`@d0f$f2-ZpArHPF+_B>8tl_MiFc)gSLY zs8eg8JQ|W8cjUq~o9uY6;CnR+<&+&lDjFBM)VUYak&;)^_DFgWo?O=v1$!y=?_jK~ z#UcAnQR=|Z@wK-H9^F})mL#=|UbwU~=gnmb$S^ET=HZ<{ask){NNAD(flWQft?i6X zRjXJ#YB#t!YbQF$_0(@i8LxpY;P4uWa_|V0>QEQWTC(Qpyf;7awFFbNxsgyfJkoL# z_asy|TBmX?_*1RgakEZvdV%Ljj>Y#%h=RuyWHSzZuoHK}3o$>?TBnMae`fDr-CZSLayR-?d9XktFW|Qb%E_3X; z?C7+zstV*NW~!Rit?e;F%@7OWG5@pSI#Ip>Z@?uyo|w5JH!Y* zpu68s^^(=)1C4FHC5s?YTCLCiz;{o|>=riH+O@{W*ElHl(QgkUazb8Igxe^n;Gb#n z)U1rGHpl2=+SkA&{q4SByXUmml?Tord4FEc`T5ra`PJ2ugN{5{ddKb2J=@wqV9SA! z{4=-Rt#d%;96hu!xT`A?s+x9YPEIK4`^HS_>&t3!59FN>)RdevnJcm_ITLJk(OHJ_ z{P^$dWbARu=|VGOt=K~N=^hp9W9R<|q-kdCb)_a3VpY`{{`9ekgm$|>^~f!v!A#yx zAuB4_&_xQ2?ZtdbX^VTy&5OwZSRzZ>pgsKH|_T-YV#wNwXyK!h!O9JGoK$v zJ&hOH6}Oi??SI_N+)d2P%GY_Uuty7ZHK(y+3B-E4&tKA+OhhK|Za;2kRM-Rp$Fequ zu9W|}JY3(wne#h#$?6*QGi_S?p1E@aO#6iW)1q10SKVvo595E_VRmP%LJiu*d!6z59=gzm8e_jfgse`Uepu z)&Wk_`Jq#n&2MGy8MbbHe$#8#SxD+brbaG_WUF}T?djBg+BF9Dl{MJoj=6s{B?w)M zeQ0M^?c`@%CEvmVU1bJeooF_6uFH03qR7d#{Y5XE2F^aO^r`yby+4fxe&gP<+e2lh z4=R-zxP>@-^;sZ60F;#8kZN1*N9NY6?UV!MnAblkmisu&Z3)YlPmShSY)}{6~29@jb=aplT$s?Fa zgFq`BJTG14d^`wPo;d52(ywFn-29+?S+Jj2t4)BkvI%(mBbfQ0mBIGgEl8FrFEnIX(k9OP>iW9@aCWXS$iNwcy=dbh#ZL%VaFiq3-3 z)R2e{90i{3wLO-{<7FOc2Agz=Sb^k-K<#F*x$Yo-pdrP(f5;13nmr~fBxN^r1q^LX zOt{`0nFtkCUzOrlq}Lz(s=!O;ecqjj_*H%+M=II(#DOEX!Knpm&IhL3qy!~*i}SFC z7->i#jQW>7y>3)QNa}_TB64kHW>C`B_>~JV!OnBI2ajBRdA1*fbyCYNIZ7N>dYFD* z$gcOA(%p_pi&hUF&}SG4L2TbMN$@l4%FgH=f2n5PM~OFXO@u`%|?S zVz7cbv;OVxiWADT%kwdB4{gMKkb0Ze{cAMmjCI!Gj>I?hu&|1P^x3#0=0f+?ie!ObDX$W+ax)VKF0^^>{dC}pfPkU7TKKvC$ZhI zRModP(?)=?s#zQU=P@l!-y=F+IbxlJ!Q;NiCRAhd`9tNV8KxVbZNp*$K&!kdxwL5~ zIlS#%q~oqcP&}b%s_@C&;*WcSZ;7UEn>F2^e^H)@fSF9*wUCFYDMO%rIpAg*AX4dMe93P25* ziSQd`1#uuQNz(S4%cc~F8#qj~w>5Fx9Dn0=^>0uTIIs%4&Ig;xe*+aP6(U}*<3gDf z9j#!|{j_G*@fbQd1q1|>%r3mN6cnxFJiFKac@A_NV4m9GO=qu9rh=G-Ta6(1ydK0Y zc+G)+?H{DnmZZ%e_www%;rVMuPKM7xz(QYfZ~HwWD1PuSpoF0>36zvc+N<=kVgY;4 z7OcCB&VxhZO7%c-mTs^o;Q>apbH}tIE(dO3AOM1iF7O&pidB@j(uMcm$A&Cm+mha_ z8ux)&g=6p5DFZf$Z*0n|g35ghl-?~6OyZlRv2Z$Wxs(TjN)k`68t3Xh`&R{Q6-1Mi zgM9zjU}3*hSYh2R5|sH!oVIBTFKm-L)eo{T@3$wOPbh{2>f8g7LB|zALU1LxUuE@r zn`~|g&MTRJNlXh~UpzB69>qC8Fx#0(vN6)g5BxaypLw*at@*o5!bx%ziBj`T6OkQiRFo;{T*!v{k$*EiG+~SlP_g z$&gaH^b|zN?pBY9n?ha%MTCA1+zC4jmVH*XZqsofdag@SzckIpurfPbBPP!K;{jcX zm4JSSrfcVm4>U=FT0`zz8c_F*6Tj~(Iiqn~5_tA2WS{DZnBvLMr->p5mL&VY$q?UN z4)$eDsFqpAFE1L;BpmW8iqh&%aQm4CT3~ne2cJ8?ffH9`AMgBM6+Zee`}O~rq|$$` z{J*V6^`E8t&(i%rQRn`@a)SQHBmF13`rpy?`|n=VOkLvx@p|!Cq%j1``=#;q3~S|7 zAIFtc1qDj5f>gyi6yqlFG*tFzirgGulYYQ5W!z5S4qdneO6U-n%}izrod^M4l1!&=F4hD18SU5;_%_>>5rA zrePrdgdR903qj*}(7fq)WrEuKm?*)99r_+As+1opw>BKJ~F(}1nSfD@8WGtuQ1l1gUzI$rf{-aJ>U1e!w zf?@|mx3D?itO}DcK_7pH=en>XaQai%VZ}9N1LK}o#dz8+csoRK5Y(D?4d#r*GEB*- zgtjHj#T#C2O>d^9L@nyV1@APnss%N5B`Bmd55o=Tq29Bp&5>;}n!ILG2u=s}9Rr)` zLtmyvBryr|x>YO~NgFG$pES(DOmV~cTX$RsG(mw*(;Yb&qhAJ49jI^`MmxE3?%6zK zcv?Rgfn|tlKX}ZLwnvPV9#IXhbg|`$4%2K%aZc<9RYch^4?RM{7yhLkJa?2kQZW{H zImcATsd+@u;Yb+H#lQgZqWLFfF+ZGGXm#BnqbJh9chq6_3|SFjRBp{1!rbI(uhOZj z9gg%k3?SEfD6HR7zNf-3U^v336^&nDAg!tQX@0tl;oNaiHqzU$-;TOaFTTi#`RAi| z@WAg2MMVL~x2*zNfjuPC{f}n8%Pu0TDzeX&rpF{Q{|0*Jr?djUCD7(oi(-PRiHcY= zF~#go1#}$&ADty$Sl5$D^NtE&FJX8WYnyxU$&o9e5z48qWrA3L!#c)fC|uDPJDSqg zI_@#!Ipk;Tn-A}COl{~{YQjN2n&_9*VKrwwhyA{Rn-w08{rJ&@QpX};CJ*5eYL1FQ zd=A8YA&W_8v%nRnDps4i&u|ruQ%Z=g5ya34bQm%@*Bx!wv&Sf9n%WqxuB+&|Gl3g- zm9(oh`kJnWGmfBejzK$taHghRZx+YtK}~0a77(;<1|6>04u#Bq#2yEMuRs|?HY`0) zyrXHed!(_q0+<~ox-r@g=ced$kf&4f#542wbIbTDQ>Osb&>O#z{)(9t*X|0WVkkWM zWcev=hQZb{B4v+JfyK}ka9fm6LXB?%a2B@Ai-xg>VIolrx;Ie)w51`c8_K`*;_YGC z%GO7%cEWkV4IvTjg2#)fo$)#T_(faf9JW+>ubwOBA zFOJLOwf-Viz-zt6u*_`pN1nBm$N(r1K?~-KYtC?qu#apyQhw{x&@dMwP>v=KN{1Bo z(lXJA^3PvRlVuV*#P&FS(8+Hki?LxkX~qNA9Uh~I2~8%nM>bMM+H3`z*N=Twh7n&3 z>>sJ=4{n|*edOo+ZDs}$6$ErpI9|gs*2^-CWkudmtYD^-4dHHV(8BmLL40C&Lli$% zp!64WC2p*l>%yDqtM{wauxiQx^c`60&Nnr$X|!bJ*t`dawDO|r6H9%{+rByT-{Qx( zlO=oHFnDwc#i&2GvUz;k?ywUomGco{npGKS#GYy7D>T(&rm9lIkz>_8;zpM6=G>TO zglba&f!l_M!BfRZA;}>oL=Sect*4)%bcuVLM~{x!tKrSfA3W_}#(Nfmn^*J_y0@HD z8Q(X`{}2_$i`n{`*gVVp5)5snO<=DIt*ch){GH!PC5@|BMH*XA0ps&St&j$*ji^aq z@3Vug_pt+Ii`T{~%kB(?0cUeAd>*`R-~B>4xreiGGV70<;Yb|xfqJ=APAi~&7cD$iRKIX713`N7Q?%#O%i29eng=A1$ zm|MoTHoJJ;+i-@Byj1CC*??h|&$Z-YNUM>E;eDuPeKEN(c#{ToiVLekno*`)Pgwl$ z8k)JBwL)1ds91OlnhFe3z%|{vzdB%YgNuj}%XM!qLsn?fLlh?GaI{KC8k-)1qi~9% z;iHrrbOIyNxxcTz%o?0>9bSf-eu~AN=W6|#5k-v_WX9s2 zoRA-`?%BKG2E>J5@%f1|v_>$vlW^u-P%qTPv{8?x|2v9Y=*Wz=Q??J%%Zf;5Zz}gXd5Rguz`1;?MY(_aHqMar&EX=c$Cht(^6RO>ZZ#XIceqH-VC# zQZ^I#^zu+_6HV}ZlyIGOh-5zH4(uq=6N}pM)4j2%d2?_;I&@uMrDRAemO<~-T&QCz z;^zlu?hb|JXinEL{o3NoD`}_$om!N<(9j6b_gYcKoAOrZ?T`-ywWd8N<9Vvru&_T6 zs%`i%)fJW1UA~l)S{)6)38YPO(Jb2~L=Zoy0U=;v61Y5nsiLOP{0Tv5H=3jJ?qFV1^Lpgvi*y`|_{ zP_q!IXt?yxqanN(xdOja$((UUWEHEUJs5w9MHp;c^BHAXQc?UsDo_t^5#;`3Y&3rM z5WWc&c*?k42l?_E0gX=ytZi>rkvy6sNo>T|X0t6u+1sC5Y>IEXoB`J@k_x>1>E(5R z3anxUHyl<(w5*H%np^Uq_T3u6ZC)Tunu>|;huU1i8J5jObncD59$Wj?SPj?B%e~>q zX|AlQ!3#PVr2W({c2P5Ah@JJ5zV0X_Ax97pxxnzdPF~Y^SHZF4U#JTx-!K_ygpmoBkb8^S zyI6jB&1%5TcA3knMbFVv?N~DyP5?U$dlLxGgh{o_pY*v!8U->Lb@ zC9YPMPfQ<|uDYVL$yKC;1XQvQIXyOK_qhwkRv)#r`jd8B&wZLD7Bo0OzUOFta~Me- zmo4HJLC3Rv&pi!6KUf`98vfQ*J2_CglI5&|zYg#qxe)-<+ zkud8N0cdaSa4HIm`@VIE6;5&$aRqg$Q@^Oi?tpbqQ$~YxmR8nP$r0)R6}a`)UlZWO zC6u)L0e*`H)xfq@#bB%!IoK7M z&mh*~6|7lwMpV(aECzdU)4htYa23hXCkXn;&)JCMyEsjAH(wXA5(GVHZ0lP*zJu?> zyJdBfRyj^@!?pI8t+=3wLmc!s_fWu@Qwku52@7O)I_-+jdeamaZMyKUJ=i_XhMAhr|(}KZ!cpO2w`Fy`E z-|q57e1aQ8hRE?aSRcivx4JS-g5rx%Pl=S{S>%W@mz3%IdLJ%)zxV z-*5WSHTQH6axl~bmt5BtXD@rV#jlt;TJ{8+)G zatlfAp*-TWt?#UyorruF#hvb#o;YDg~E1{3YvU7Y> zNx?TWV;oorLktGV(4YYZr#5k49rDLQVuV@2e0@dM_XaSh(|oxVnvlJ20(>5(01XHb zvvIg_@>FbPfZwN5lX`#TMj5j)5}tb9w0R>`3se85Z~1L)>nO-8+OVb&9$~~EwPL(l zO(D*t->4s6uibO)&UlL}6Kx3xzUKyK@{E$;y2x8~p(bgOf*QJPC>+2hzfJMzKAkZC z{H<-tf-HV76=>Y@7Nji)r4RQs0YA$51{wd>xYWS4O7|2Pqotvgq9y4BkxnF3pD$*L zUPnF&+x^F6%-5QNU(r~4qEPoyu5b2ciFh*rEXacS@?Fv<{FOl% zFPn6edGjab@Ic{y>RO_$>ES)7AKhXieoZ+k(vwOa$i5<0cHhAStvf)+tv9>9}n{DY_86{CC#7;(LA?d zO@Grwn7K&MWQR7IxQ{iLQA_Z)*1YS`d$d+YkB)p4KP=R!bFE>H<xUMwdpjtds7Vy%J^u(JXi6XJ{9dA9fM9 zq1v3kS=Dk`OaE#oiCaG-c5>fy=X|VG+Hn8Ts=79HLM9U0#rdk>8wOXEilP#c$5! zdhNV-OhJ04PE_NX-pw+fOket*~uEwWX_!>bxGc#qV z>M`wN`=MwAn-DHcmwtl2e5GVOu9JQS>R#BvqYnMT9=y)*ce#PZs+6|p$5tssq3p{h=qXH}NR$qu+<2iB?4&i}-%JiE z{4^~moGT>YxQ1L#$(-49xhFtEEgX9}r(2KetHAoeeo*i+)L5PguDWUu8v?BZJ_qs9 z)+W!jrd}sMXN$YRdEd>k+e(pGd_Sdn&Ud}q9->V?g1+c;rS!?}8USA=lPE}0w2W0@ zdFqJjzl)IB zy5yr_yvKO%rky-Gb(Q?PW7e3-5t;y&D0=T9Ou9nPrF{>O9ucL zMo|kKDA|2svyNa|O?5@RtE(dbNsoVY9_Qp3)+_{v7FH4Ejh*LdK8C4$l$KbuUOF?C ziDG|SBg9p+&{NHpCyWZ&sF8+Ne{A143-dXJLFF;L|EL3%V}e1iS>3ahoRZ;+C#e7f zU;4$Anrq}pXOe?WTC5P*Qao>0?m(^klc_hjm5pfM6V+K9ePl{H4_Z*|`wHuP5$0;} zaoY0)l?)q)ffGc{3=t*f#0i`3dVmiKFe-?hr5O?_FcnOr0)6V zyZ}R@zJTKGBn-j2dpIQK%Zzg&3FtVxKA{g*Mq6_hSWp+DeqQwe&1bZkyO!fl#qedq zz?(0Wk)-Sa86aOmHQ{_MUS(%2s(_4 z@@)qmvqsk)tUJq?5__|v1col$QfU9jNghvcy$x%|9BMY2}yumNh>(X(nui#tEh8qmN_DSD%i3zprpBO9MrF^3m`$QNrhDTmbp3xv1 z29jaj0{uHcpaU$oL!4Op5vfMCN7nMPDpBXuOC2_*Z!h8+Tk(t~1!UV=ZJXd5BjS*; z;LA&OGOUEWa?Qk<9XtwbG8*>aE19&41?PxgeEKejW>R!aRrd{?9v7Xl9PRId)y(a` zimelHf`Bjv+JY45j0PCOc6{Amz+w6Ju$+E-04#E#JNrMse6-?fQm`yjUFWxWi1e=E z@2bws)}u8KHs(wPBHIMQL<`aqS<#Oqwb#iH#VAzf^Ug%Nk(sps&hSC|{0|IZf<00i zEA#Trrd+eW!oQ?1EV5n14s_Blv6IRLKODz87;%=QZH_EIijj7oYBBKIfzza5=w$na z5uBsB$_5FTu=6|gylvt;qb(nsvQ3#@vCa3u3k^bYyCHWYiQgXc^=!)O<)Q`R{) z%#E|B8Pp(3P_M`k-YX0SHOJbifI z(FE~bStpy__@}NUcay?QE%T{AXa=X3TY5N75qy1lPj*8YG9VH$#CZz`m`u5E%|q+> z3QbxFimm;x@=7>g@hTO#KEEmd#{(SAo!~K=Dci2+1S4?uz-k81S<~njl1`{2FYKr$ z`YC+YP)Ou-?p6ia1OeZ&GX>@PCc0dZjw5tJ4@7}Hw2~D!jlK?|Ej|@p+Lm{br5gqIEVCr9M=spILR0`z9o-okG*BXD^DX~_&xyUJF9$orkE&R`$S$!~EpKE_ zq-%1C*A1t7(-$_G>4F7%dC2#r^a7OLHX*sUO2+LAjC6N?PtUg7&N;0}@z<+kOndHf z;Zc=4bE$&QFO?HsCA!AkUn_+;bt!eroOoPt(I^UyvfOyn}Isu8zYBw#d zrA4wfd?Gg=jidHMHZMMYRv#G5LMqbh7d~xfvcIRP@gHo^NS(IjtG%S%DF#bGXB*@+ zPA1+1&vRBoa)F#|AyC*kxDzUP`3@v`5V0rH+tXYoJm^VdegW9 ztNMlZ#SAs5fY)jl#4I2i`K&!y`tA6X9)A+ zVueu6`}|JSFMixgtDjRAFb!K5f67*^sz9$RlD>Ut#wsGi(NOi?!OVFz{x4M9O>gW8 z>#qDBkBPSck_Bu(E7b)^ETJscDREI#`8VRP0a^kmi!+W`6{OyRufEKFSuvi1-v{B- zs_8Zs+X3d(zQ9>9^$$E^(br`Q*dShsNR?}-&T63!mkI;!gxylGp>soK<~q8Gu8+G} zw)X7zQ!ipZp1eL9*q9F=O1!yoPf&6TQ%u=-e-ac?kG`?mCq9Gfk>O8IB$ciYs`;W7 zTaJ|?P(u&pYET1O#d{CFF{rQmq~Hb%5TV$-$bK^`zVtX>4L3!Y1H!5_ z9(C*6N}L+s=om*Gp5cdFDc6ciuvL#sQlyvGswd4$pFE=U*zCZBvUxAKOJJF(nDTI5 zp8l$!^E$Gx#^12g`OuS% zQJQAU;@|r%>1Q4lJudj6KO?DhMMC9@-N_%hs&~D7e3~|VNBl!ICS+-E>JK*U$6MXT zRi_NDzCPTruzSCxl=Z9Pk}=uL9i43_@~a5EEL=|fwRD6!# zx4Z^nIKJvesSq~HW8=LV{41mFx$AO%%2z-ndTj3cE`NHuQIy#j=B<<8Yicp~H;17s z#%rD9#*$F;ikOLQC0W}@M=n`?swjd|Pf!l(N>1%-kWdkf1l6x6WXUK=-IDkqeTBU7 zSmlT*uY?Y*6QO8FIy3?M-nsgW>TDah%Wh)X%oPHFlbQMIllaHL(F^8|I-%SNf;&7) zwqqhoK*!mPajk`Vsm1-h2bzMi0FD~JN0yg+WP8oC;u#rpRD3pWwU$7Ids8p}VQBs< zU(F==)V5Q?!iq4QyfVu=@t4f`J{-8~@qimJj&)`R$e z8FT9{txXRUc&%G?Jr!1dj(a6!CBJ>hp0XR`6CvM3CAHlqgNa9l?*7`CaY8_X!ml)= z^faEX2UX{J9(!+Y70rDHxgz9O>_f^fwl(i{ca4qDD}t()nwtCXF<4JQjmhf%o^nsS z6EiLQRV&tFJSxPzDZ65z{?j|x-TOU9Tf7V|ZC+u84egCy9^FWelcVb(-<~$U^?Zi# zGs866k^Io7{XuRodE~09_R?3^=;qVy zziic6)L6;=>g^Q<@%@FY4RFb*ba$Hikll`@+#Y7c7~<$(7NLjk=iTiGj7 zi4h;@x}3Z-Nz->P&*{FC+=jY)I_=Rmp}uH@Sg+NP+~#yS*UX%hcTz&-qHb{F zUAuwwN*Sdu39{7FX~sfdlVx__V#Jc=(w_+q)gPX|sK!$etA6F}E5#lo{1P*+7qJ%G z_Wi-(OG5Ssb%iB1m!{@sb&69!e7(v9>ZFg~GKm-LvzD)F(}SGoG`C-; z6oK^nCx^8~Eh7o;OT^{QcMFB?IOOuH-IV+agG2YGIc4C?uwsU?@iw8AA|KM8ZyTtZ z*m!4H#$dCcn6^@^H}M`eH(SOhbbc#BGiR?dKg8ZPk!`eFrYLsJc z2h~tvX@dpmkdrqpx(DHwen$d$Jv*5nU&q~c+_CMxf0CAMbKhT6A24tCOCG({dr5~C zAG806;meqn&YowrnR?@a+7^VwAg6I7pw+p08`EO-*|jL4cc(0_Cc`ezy{}%~0Y&dj z_#*+~;FO43?jCmq+ScrflP&;bJhd%;`rzA~xD zbD${sao>Z*`5Z3*%6gyhecz+v!Qjc5BI?UlIaR`eq9d6J`y>e4KoloTkTz9_%Dp?CM^#n11kw{L^5YA=-#f%6 zs4AQWSvmKk*B4-YdgiA<9${XF?!NkQ6T!JFS_YB4^xwQ!T*u;`*dEP(h2)esBAr?H z2K-S=jCrK^(d=rG{WS=c*E>`uu9eoiBi`uyu|0McUb}TWcCX0@5313qmFU|N@h!9? z&w?&O(LaCNiU?^N-5n`$QLbWdt`sly=SCMWGLCEe|4Ey-!u<)HTSXS<$+Mxuv7W?i(G=L|JAJE?*j!vz-6rqTFCc z#e94+!T8$J>QmJ@ok@I}eFeuMp`XWL(_L%$9OA{Jvy(r|YvKMW=#xsOn*ld>I1J!6 z5BQSTj7{A|d+ybzC&~ujf8|S+X zDb+G~6{+dmwE&f!T+2-;*C+F&j^Jd(<)iQgwQnV(I8AG7(vwbg!Po3_@Fw3zQRT^( zz7nspl5IVrcmVo`sBdT1Z~PiX9OuS)69@C5P>&*A6WqqesmN&WXsDf=+dG@0i^5C~ z=ikD9>zlqfX}UXs=b+sX^SX(TU_(#Z*&=O`BcoV|Ygzy=_ST zZ2Q~={rH8;BTEIp`5!;%X}q{2Kaue3p&d|eb5qYuoJ7LOG97I#_9OmKQfJnOGn1<& zV-70;%$^FV7p-=;QvwjXjh6BjTUC55b*Vdp?WymDbCa^O2hrVeap-QDlZU~)Wwuza z`vLo_&Uw4@P*R2O>J#!lP=qtYk(BS7ew*k@JE&_IzU1%u;n(O+p>xh|W#3I+KuIuo9)3P@WOHh^}wekAHpfG=RVTHo|aLMxv90m4k7h)faag*Sg&r z@_cGjYy9MIR6)7v_T8y*`*E|VY4fouRIWyFW&Y~S&LPJ5rqk&r7(VFX|FcL)MV~ue zUjJe}-5>+Qv#XE(vphD8-!lWea*T(Ic+Ms=9J?peRJOMlyc^t}*ZkPieu{AYW%4InoTM1pil<^~-pLOR*?+a_E ze%UMgZl=UXMqP7PTaGs2Z8Uj#C>f|W^po+w(JdRlyYMMumCKzv+B^E<#fP}H=SXbe z34Gm2N&RzQyYuXR0LWm3oohBq*0EFGQa0IM?fRyW0DnivD1UsM`A2&Wfz|MSn^JN* z`Rh#BT&s1}4{}s7L?3C&eeKl3!=LjTqo!96e!Nl-1xQuRoSprADEn*QJm^dZ>Otu2 zl?Gnf_!o7xHA(S)_IdoOm}}~xGBBw%5ZAi$_s65y+gh)wDrNz4zobz?(TV=1*rG&tSrTV*l&1;&tws zed=L)d%H0AESsMITSDn40m%W%C~xC5>Vce~@GQz)?q$bD=98VPKu?HGgMv%qyktkg zZHJJuffxOTs%iGSl|E*~F7g1JmG9U>?V#a2{^RMM?~kd|J+F8se{mG4FO)U1T2V#* zb7@Tcbk?9Qmo32vaJBLrtD@g$wP%1_SOroY0^YfQw<3wN(O)2uQTev61Z#dTWyrEJ zDPDS})$cskSw1#iLZ4UJ5ZF-SHbvqk#tl2e4J9pBTAxQwZ)|&Kt%#{$>CXqP(LDb> z4_=kpeWMeQPj8Yj+GZ!5F|FU4Ke4ON=6x}x`%f?=!1*dkV;23Mbs8j*cZrY2Z+B^lY*((isocv1?ewK(M$55F?TebEv_1duQxVpttX$++y;Z(mVbPzyGUGC zj}OQ!zh$rt`lEr6?RmVb!?ij@z($o#WuO1AUvZZEUv$pA4kYFEp1kyDKt=1nWC*@2 z(>KUDyVG_0>o^~y{niq!r`jvBp=RjOXGj$BV!vA%c#%2=rT_8L3_eVPh>9R#2#iX8YPTvtSsu?A&~*<4H2V0jS<~oAN=Y88N$w3YsCJh z$WoATwyo^NuE|Y~%d>ljwd>b-s3A%myi)yyblJenHgDb5%&CuDr@Y5eA-P(^H zOyRQihvJ_oyU-7L^wCvq{V92x9x)Mdg@@? zRaN=b2nj7(Pl4+|6kGp=Y3|vDH!|rRxM$~8@LqT$Ex*;@Cs%#*;x*=eZ^xJuH<@`E zIcf%93hEz!{ZF}j4vrq>Pw2}nnS7%zbpt&EDdR8C zyG%lwkjjbge&~p#vcN8>-FaMf?teQDq>jwZ zahNOydjY=X8?nPU66eJ;(8jz+3TANNSjSFHgvSUx{Q0ozEgdg}emNvEY#>2dS@-@I zS)HE4X2=Z5g^Zr!jugM}CtpM%)yvZh^$aw;KTPt<%0SodVqRSFjAzyB{_$QyoEyE6fb=BnM~tN#}@v0y{~S?Hu;Se z;f0=RlhE#j5)a7ghL`LB^BE`izQys|N_Tw%=Sx&|lm*`=7%K?#ZV(F}71TFYNCXY= zfh)ftvg~S1Jjk#QUMMi=A-4i4CgXi%{|?97!E4F_X6Il6^BGEZ3&%~$@t3F8YKb%cmszTZ|- z2D}NSQtY_6q8GFN*bBx$^er&LB{Qb>7WUSvvj(;7^YdA8%rt)jGkXFhKgw{ z3dG<2fDk zD|dynbL$oDTAd0Gspo~|?9smD84oqFX))-_K6Eg^*@r|I6-4vk!17$h7kVCk?s?>z zK-{1p0=^7y&xWSNy}mfK#oLM>&@(djYm4Kn8O$(c)YP=Euj@CY2!g>&lK(ASg!IN* zH6qo-qWH@^F{Ph$E_7gRdbxz8$dL_G?uxmHtXcL9(0PDFlST)mEp(&U4ej7@_2@44 zU`-6|tG)X^Pb*6M=h?V`#E0s^py~bnFe>TlJIKj#1axq=6F))pxk`+N(565@I<0P# z$AwPDX@h7xk;Lh+Z~d!bv_X7bM5=w@*oUJj542oTxZgbM?OBPx#?UJ&az7Oga|biZ zYvjX9F4WH&)VH79UfBIm!O^OqsN%n3+54-r^5g&Nx%YMbrCofv_FVZ=iM_C z757ZMl{Aj31XRP&pQ}s%6`R;;2tr-FMJFMdrUiA02z&ZgXj{Za)Ja{QMxbi-T;S~Y zqOe$8>_pOP8mJT z?QwC-w@*{lq#>vXXh9giX%QKryJ;w;&Ufbk?B1I&GoLA}V;U`Srf_945T^xQYuR}_ z)3z3|hKOO|5@PuMcOG!I>$?|M18k!v2BsDFYWUrV`^gxHeu~_09k&fZ9MW-=z>jjdHa1ewRRZ_l0S~1-|SoPh{m{EgCDk+ClNP z|L#up;YQgnaaw;$3=Di27VwuAQBo>6HD0 zgHFl$44{t^gYb;vVTU5&o%U8yA8!9xEoxJZ79)OGc!mM4Af!TNzNl#W=I^JN=WNSe zJ|?AopKFg9z!OuwaS3~kh1>;sbr0J%Of;un{){|u5l3WY5&u=6bZl_o`47vr3hLmm z@EU;&eC6!zw7tR)YZu_45s4LvN5+Gh;A@`k4fm{TIXh4IB6)j1VI4#L&lLCX$44~!%iK$OA^Jr(yPszL$!qAiEG77i54<3E8oc3}Obe1nIlCXl_dd$PPv!*LzU0;wVWNLr2qy#xvI@LTz5 z>&q>&xX3=6k7Vh3Wd<5rjERmc{!+)2wh8qIs}g)v?JS4n13%*2XyXSM(l+pbmd$uT z#jS?_4A|VHcUblg<%JHM)?|o8k3e=8i6;y9i;jTHe|aBd8hbt7kvhulO~-1wHQ(ZU znr&-seNqRXCOO2RDr*Yan-mdJ(#rYfw6S zIf_KWAA^P_WYf)xH%_Xd#tNATe8z^9_^UPqVlZV3P2Oe{g?486Xbw+!9qePPu`ONs zBKdV552Eq!R`v?{N?aLri*$ywQS`zDA73w&78zqZkpV-O)bu>)E{DvdK%hANRDjV# z=icgPk*xKy%!!$)??9#Bg4|@DhdIhuSGTBR)5``S$TILp^Y+5~wRWN3wnO9MQ(yhL zN*@Yo9joRxzBV20rso-R$dV=?6Q83=Kk!>G;F@ zP7beaMDEjYe~^T!UZ#Xnm+OnbGHUAaUk70!q572SrkieH4c5!bae4$3PcU@)fqS%7 zV$n?sq?g1cwu;C+r(3MU$_s%&blJO+Cdp>RAAdeWe3dkjs4kxsUxYk_SW6z+wQIi~ zv$>v@B}ifS{$#A+`)-F;XQt)f+{|xSF%@?3j%Excf0|eTNOtHF1l2UhI$Av@C8z_R z3S<%L>8a1$?Bm^sgLGe@u5^sd&uqg(Aj>{tImyC|2$8tt1-54@R;Y~9Ym8-l{9DtN z=$LO{p$EFa82gk zlG57h-VzZmKrKc8<3=jl7=aSCR2-1AD;2lSfxY?( zPUeQl!$+mD67r-5=p_xt8r+8*FzH8ppud z03WX`lqgcVI4-C5S|GVRqtyG#ZMb8zCXkbXK@}bla*{N$@jKyf96r8}*VKqbM$s#7 z_=umsR92qDQcM_9m)CLt4)HC|%lT4AZ-=3y4qhjl4iT12ImnI$dB~H97nAvy3lOt= zpHPc|&_c}Ag;T@7YQ0J*<=3o-4AW&*&W#6n)D{2(q{tKb?E2As2~hIK21%9anF;&zHj{xv&G=iSCrwgGLKBvr=FGZKPo{2k3Ti$``h z8>XDV2pQ*&jLDjYTkdn+nbU4#xJVfh&%Cw2^?TrH(-a&@mQF*e{Xtk|bLst9HXxvS zZ`)$sL8;r@Te0lK1=1o67BS?|3d%_~F(v)6yE19|kXxM@OM->>tAdF2Q%`8R)vTlD za9HOPgfcqBs9^itj-XD|&;zp|;#LYo^<}+F5qsK8#wr1ah{hG?-ZTC+h)cB{*Wbq# zbgCxBQ3S8nN&6(}ljfcT4)#EFAnS!a-@Yg3MB?Le8m%16e4z@Xh#dGUaNLc=ri(;PrT}s{u1EXrTna>ot zIpw(RGs9qro+h%!pvLv;h!?+_fSdT~5uYwUHsU8Ya=09M1k$An!FJU{U{+u9(Z|zb zWHkavjUS;Jxu0a;aLlYZ4b^wc?Hrx31>9yX9^L;v==3~aNDc9ouM={0?A+sGuZfR- zqeIhQbtYxhi!+f|I$$nE9m+o9LE>7DsE%@e$Xa>i-|~*03QyR!4Qg~*yU7=&B;mEv zsB*^#Hc@)E!U2~Vn=t9!^PR6z2nI9H|@(e@K`7FI2;C<2&)Np6b+A9 z-4gNAwm|(rO@6%_Ij$GW_Rn3or|_&!Zyg>YyO(=os&zTA<`W~1{00_xe2TC8@Jx6+gF zjVmiluS&^g2YY8<54zXgLU-MALVrcI=fykTmZ~;n^I1dh8NUk-LX(6sbON;$F)JC| zh*#}Lh5#ZbBKsjT9+2=00Nk;}{jF^xAxk-9roQubU|@#)5D@Avv#TFD^u)sv*$xBB zkCB{l+EJ53_vr751h@V{oGtto&!le$I8v3BDb7#o@6a1va$87EGE0=K#s%5W)Y_F^ zyez;rBev*?jg9)HtR%JWCZyld3y|U7->!-2M<#sN=Gb`nRvwo#!`>}4$yt^R*G<0g z{&c<2GVLq-W0Aa0WN|dor;o)Q6D-pn6f7?~%irTvD9l(KQsziAd zuNzm7}^&z<~EF-a&TvJgB(VL(YRafi={;fC3pW;b(VQ2$g1b&nM6$#ddw}rmVe& zN0*UDwYrv9Tt#o8Tk*L2TSb!Hbr4K5#1@Uc!OACHRhSu$rgpUm!&u}HS<;cajrWY#*4NK2- z)2<&VXK=Ig>i$ml77*UN$0B4 zd669lPo3cAI~n>tb_LrFJC@}4nt1=UQthi@CtD8Q)ydPihA8a58Z!Te0fUpiG%>vk zsaD%0B6H|8J2CQ6>Fjjj!o1=i>Wkw-H;-}}%HELT38|y!xB9g=>X~nOxO>Pc2aJ?C z-t+Epya$3=)q1pTgwR0+CvT6sti@_s#3Dw;?n3)C5Q4&4vZQGVZr9r{g*ndt3|vwm z&!=j6SuB|n4~JjoXoZjxO7yLAMYseKazvWI5n6ff?SYw1JA?&<5s<5L@pT{jX3x{l zl_@cv#Udkil+!HR^ru1T{2ZI0y=Bs`K&RS{*XZ(S3BYhAcRUc$F?jDe%+2sXOzq$^ zTb?&&1=X#UDf}l7N`2>$nNYc0eVgsE#;U(Pk{ABz0@UQ{3ejhx9wSOyC4vRXfmb5xBr&Tv};JvXIPp!Vdzmq83c8N2e6w)?c z0x){ArM+DkkqA;6^N`knAfsLslIDZ#w`_Vu86gh~TBKVZKuQ21W!^FUXBb+&`9gZv zIR6B*Z{RcjiTxg$KWRs-)$UN+dcri`ReMmNATJ22uE@yhatk2AmdRK2VDENmyjr$wgy2*%mc3PF6?{%aVYG41Y%>*A5Svy~H7HowBl zqshrn&D$M70CT>w@v~1`x>=uVM)tSV`1h#7ncP~&g}&A7!0=}?#;4c3d#r#L8BJ_y@BF(z)sbijF$iA@uL-IS{m(^y)iB z^5JClpoxi%Klle*CXU?b(nAA!yoH!?a{w@4RDQ$(?YoI0M)X}xov?2!(IJ97IO{}h z!9of7N8zwQr|%o~d9!*U;o+LJtzXrA(N0fU0cvHaqm>G$klU)HdUA?Z=xF{c*PMv$ zO-3X7%|qweQUwUecJd@Z_QzZyTS!|{IIOhvO~uF47N=oF{kdi7EY1f>67SJ~|`ne`R!J=}BAvmf-O5 z@}3P$m_hPTm*H4%$f}Z;D7Xe~yHniEtMAndJsbrD?+j0>%C^u=R2@}hhX!r^-TR)z z-OUjfuPYyNKr?EhZDxk@+(kt*Xf(vDkPsUY46{6ss60gV)qaxJ$v`0e`@9(ulOKt1 z-Jtp(^u=$|e{?-1|A+I5%wtDus;atgDv#;9<)K_|OoI!;|2?GkJGS+fUC&%iJ?Y4# zR)wRox^xNCvZ)s?+U|d0_9m@32CJGy#afT@>BW@-q(@V(`h5!0dasGFgDoclQFkAo zk%hBcTav7zzuL>pty-`7U-D-HPuc=SW4wDnD45ja6eAb{w_QA8zGfxvIJut49<)DT z6^_eUs1BQy%F)2=qJ&jSIStm?XT}Ff-Ho zfLZS~&EWuWCdBQXqFKNztUPfN#<_Xf2u4PGRi%5b0zo zn>lnCix`rG7}Zn?p-Y zWrj1tYUg7q*Gu~cbuHAZ0F3w91g%Xo+Z5=>y>e&`*UHH@%ME51#e1GBZ#ya7?-HPk zu2>p*Mw~f*lp3UN0)iv@p+RWEy7Ch3xL=WE;j#%`DuU57FjHPfnoyuoNWoyLJ=z#p zo~H%vcwpA-iMVP(&)3INyS0FFj@hUbbkblY&|+BfBM1k)nTdIEQyi&x?jWz%iY{aE z@@ZBdJiWQ$H+?*=WMK5@U>Fdvm_WL$S1<4p>!B z+uinw=1B)E40i#EA#VNqY_AUOQ_$M~mUq$}qxy0NQ#~J-hIa9uhR@V>It0!eRbxxW zRbn*?eCrZ3d%&jc*LJmekPnhLmmtuNnUf9eu3-JX-5J+P3{tMK;KX8H_*ypBP%frf37KZ`EDiug%H0z2T02H>Mr{D@nhwLxVqo>zk?{B>$VnMOb_jYB=vhH2kV&`Y-HvE zmzy)k@pti*jS9Win%gs@fes({&PY z%q5Md1bU@GYi3j^HydXIs?9UA&mt2azZKU^f4`q4Q%zd3H9q4rUk;iro9d{C@ z^N#EleLbF2@LI9mH}iHY$iDH;!4Iv9Nc_0&JrS)a5dm6~zFx^5TpWqAE829}6%H8tDwT z46$nalYQg%@%+)8hPoHjV#p_K?2CPN*l_E{)+YThOPT&B@FAqOYOIy^aM}yf-g4u? zTUgZ{Usy{^h8Lvn6Fy5FIU~o)T-u*med{iW9|`yqrWpfa#t96}iIbN@#i+M%mRCL{dFI@34ex|j2`5UN|*^Sa-6d0g)L&Hkr%sB=- zS_aezAhPrOY{y(4Kkl#M%ikRl4o6xrXg@ZUc=h30U5yU?tEgu9kZG>A$Jm%MbamtX z(VC);XV#EIPF_~s$Jr~g3-uY4RZg~(VmJ3P`82L4^X=OGJ~Qt4F}G5>1T+YGN{vsD z-1mkg?1F-0<*z~V^3ZODI;=b|DOy24o&@U3zC|feP2C?iC{09v@K=1{yd$6&H}t_9d62`aRAG75Pi!O&s6MA8CTpj%%%f3+RvbMt`6F`!S{FrFMZ2^%#5HaPVNf z>U}jza?4w#X`%ON)e{tV(R}%tS$~RQwSd}Bb)n|NxV6f-`t2``GRY0Aks6zA_^J2B z$`y@W=QDG-UzD;xKKuQ7|JpteKUqrAQVwltH^SsS+e$QU3`}c{nhL+IN)Bm@SZVcu zlv&o6l$#M7jr5@_qmPE4aDP75ebBJ;(Sw?CHJp}hXQXcRBFvi0|Na^;KxMYQoHWI~8ecuY_E58a|DpW*_YFc;^<>ng=sq0&d+VOI8%%dyhZ`yJ zibCX}_pOD+*f*@L7V^F52As0}=zQJ&#c1;ny+AZp-|NbxVjQQ%_u)XkMftH$h*4^i z8%d+%R?(`d{Zxc%#G)aHCXTG=__E!)`st`Mq-|7tox+qOrr7q$8^)VHWFolM^u+w9 zCE!YiYFj8V5pI%L$yb5eAMJ@3{z3k!{Mu*#r!=3>W5AQS6#Yr){I$GI?bS#x_pAh- z2~=mW;N!3nNyqW(=b(o|%x!f-1%b>us5*8Sg7ss5|M2QkT*)j<*^%JZj~)`2yhrC|5-)XqN_ z=oubnwooin01w%WHE|AdEVw%A(e*u^=w&qK}TtPpYZE3iHuf_Pm)|A#waY|7qTwbcJf|o_ zx=NKL#n^SyX)27jUA8nDMk3m&RpA2W+!G#$zqRRcZ$zM)%andJ)5^~jWS8iMdMr>pcQ$bA>)S{cuWSbsTG;Y% z(LaI6PsAMj3%WEz14$0Lt>nw`V^l$BHN|#KuBDaQTIL$Q7CLaee{4o7h*)J;y{F;B z2*eP=XO6V!LuylQWQ;G$SDSun(`5_j&V*R4V$|l91Co9!kq0M^8S@yjJ^22b(+o#q zf9Qz(h$yeVb;n`)_|LcWw?nq;1OBr1+P+;z<&fhp56IyUW#~p$IrUeTGIZq`_x0$E zBwPEk>;0#^vZ%0_SbcfErn_VKzo!R3CXUNFxwOp%Cq8U<7<5PFDag6qHUdb>ICf?h z*k3}+!1y@vDyP@%1eJ4ChSxab19&i1BgB`RtX(2x{azlU0e7&rQwKcuFOQan+dTjI zjSuiC_i2q3+#CZls-}-QSeIqdoOMjgiUrkzM5v!eg8!>yrXO=4_UO7j}A1`I)%N~ zVu7+d6rw&@`eaD3~7CPvcdx-IHP|j&`(E?6Ff71C*)U@!Lx3K>*Ve zW#jXeXQfuRSHjdBI`}AIgEG*$Avom@>}%}=G}!%l`**%i8c>-q?_l=I9%Q=z8?Vxc zwR!&XF(scrDmni0QfzFbnq^v8>KL+lJW)3LC`!|Rs(y47l+-E)0TyWKFu>_EWpqdT z_mwaxoWjcxgiQ#UvTjrS#ddjTtrE~si56;bNHn#x1d4YsZFt|%$)5en%%GBnPBHd- z(00!Tz|ZnLGjS!FoySTH@qshp-_Z<|=zzr1sO*{45s!RiZ~WtfB1~JC!@a29>*em$ zZbmG1te~yOG*`Nz1Yjpyrg| zY=EG|!GR%LQ%#<8sUz_>g$oo3K}Fn$U+RW3sv&FOx<-6;G7C&li$=o}@y?BCRoS5- z@^Duol-7PkFPmuT6N{vO;S35PA7|zvcnY+*&t*~5W8nRR?9-v|OXV*mwtFj?H&TEk z;R5MwZ_)E=!^-f&fQW{%>KE0L(zMq!)HBL<#jZ)y+vsRZR7V9r-_x*Mc6+aUT(Bkp zrqTtx=sY;romNK$(}}U<${!Yo4qQlsJZx$$eSW@{waNv?}7kw!_}U!R*UY zWE8wh;>m>6(axG;fZ$Xlik}su9jmbV=j}8W@TS%lfA`F5_aX@;<>%GBLsHgqAb+&+ zU8e@buDtGe*ze$S8l}9=(?ijrcBE(%`gh=E_=3ptwhLVVQCqFadd_bq72M(LH{1-pvaYg^M9Bxw5 zQ1%GiEcMd~Abwi-6;OC)T9@^F{d?%BM)bd7BGGwI!r0TUYoX{$`0|PXSd#1>NNg5u zI4;FsLYfW`nXt$9FnWha2usmT$CcvrLHA6KdOFbY(91>EM8(0!oa#+Mz6DhVU$Zpu zilm3}!iu8@9bKzN{;uy^*8bpBaae5(mK(jGF|j%B!hmQJ9!CJvc&x8o7qw~S-)c-0 z_LPNJ86&Y{0jWUtev_5T9e1gMi3Wv-Prcl25=xdv+TzC#v7;{YfVxRKs6|Zeh!Sw6 z*w)mW;r^yyUQT6h#LiG32I&r7qofiuQ%_K$I#Jz#+ktfIIuCw28xu0Q9fm#rEq3rj zU=_7wmS5kylI6#Z0tlq!X}hGQDLcP6pLJl<)AL6=T`eiG`Xa(!9s&`ce8Iv+Ls*NG zye53tP*)lApkLcMp+SqVJDKOP1`E*!Bf`iB;1$ohJVq_Fe5i4FcsVL$C-%weFh5*{<;#27N)6jdA)z+R751VDJn&g(1Fwbw`V^Hih&O!fq)=|LV8fOIaHUZG1 zyM}vGz82h;I*OJ&`+f0u_gMlT6LfDsDR?`ZbMo-Z)X|R{)F5t2=r)w3Z+6cMF*XJT z`r%Jy8e@@bxRX%@JFyEmdI&U_MDc0uMbqi0iqhOc9L`pWm0L>`g7(0cy&NQg&3AF0 z=(0xJ{@`sJGTt6d`+f#H`}0hA7m9_pJwe5+HT$=<%r}YB>6u^zMr_)B#y|9wbpEGJ z#zy1>2SI_LhaT$oRH|LO0%tM-k$Js(c+~v}$V?k4FTlWbA2q_GzW<6{A4cHFnI8FQ z`;eB)Z{LDdFI^v~L_cas)O@yj@M&k}fp=dzY>F6YvRTm~u_Eq!R5xL(qvg|rqm~s- zluVQ(a{GhZ{1e|*NL%!O_m24}``(++ZguZhUWu6QKyYcLI|^~eP=I-}05K8+e}3<8 z1blmMe0|&loiFe2HNKCj&t7%juWlR`*|}TkK?rP9+sb`>w(=lXaf0-F`DkQ~U+du~ zE0w9JtB2ZWUqA4s)z*qBq!%*IzqRoK`qJNo#xSsj#3J>Xo*~DF8>`-P@$Q zF0rE*wtHf3SyY~T>qia7=cHHkNr`CI`4!yKK6kPr=J_hopv+R{PP-hkKXCqP(7N?Y zJZ~bLF#WBntMW_0l;k96j1n*vIohhgc{Vxap`YOgGhF#naM$Dmos_|WmNqV(L%-ck z@9CMaK*~*nMm=mkt^}8@5Jp?AxB7duCbL4H3jO+kNuPo6NP82g3|-uNv9R=_ju$Pq zT!k_r^uo;u6Zw0UoLrp5=_xEsYT`wzHr>WAe1t?IQ=hBNc$&5N$+2G2&+r`tww6le zqP*P0t~aNmOZ6ftczFPCM|V#d*qWPldZRKExW4C0kmaHx^C4tdX-R**E=ccY0cH+~ z&$x^!?7g~sk`%EJhoGZ)GO3TOyH}}-#B#+Y+CRKl_}q`1;Q?h@avOnrR z`vZGx<${5rWO=Y${X)U^bIay6jZX+nRN=T#MFlf(q8@Mf@M`1P$QJv-9wf1W*qsdt z_KX)cd$u;7IdP!eia&u1ZLje&z^_lm*vc~L7Ekg&t>n0c7d$AT?U1Ip4q+yyDJ;%~ zUB|sUZDYrq;!%@qfNQ3P2a~zUNy+48f&rnpXoLvx)z$d}2+);~Cj7o%KqI#(hZ-w^ zOMjyN(7Hh>g!N4UNc}MAD3F#RoQ)AE(D7PQNM(K_;epF-an;0}((jGuE$%h!G>)C} z5FTa%?qI+0_WT?QBHnmftmzgc?vwZj0i|=#HmN>mc2z_=d`Z`jZ3R(k-;!_Xp1prG4)|Up zsLypOQJYJc{iJ8GYu{MtLo2A?qY7f_!_Jz4v$+vH6kp66`l|AN3|-A&diAMRwoju;lXi+n#_%WE zH6+vN^upbO(;)?Uj?}k?hg3VITvfCbtAs_|OUmi=OA1_DHkc0d2p{g#=8KJ!X#NvJ zHfkTk4dOu4B#CRT5Qnkulw=$C$nF5$Z_-Q$pUE1YV`I8i{aG;lr$IYnX)jFaqNsk| zzlc57bZm4m7ohXb!sYV}AhRoaviGfXyuRTZPRC*YmWJP&&q$WuIdYWF-I;tfa;nat zjShc+%rtdP`}HTQs;Ic(tfu+=uXnEZS( zkQaz^Ll@7c`=+f%3shn;h6YUx6*65FXTA_zlFgYPuFZNWTkuJ{!PIAxrY6K)l~tfU zxYVibN&9@0M;Ht>j8E#l-3C+V#ypj-JpV?B34jKkvjd679#v`gha{ zeD|Omfn#Di`POn0-ZnPW96H3-e)ELFC02K^ zcH(a1$CaFvBm5T#An2*?&TOkS4_sIyL+o`EN&gB~ztEoiu=bx)X3T3P@ktL!&ve#~?mt1ha!c3Qb$7k$=9XRm1rM|7`k8-` zW^ONn!KO|Df@jk=I1hagDH4x7<>S$M3JtBESrUHD>m+@=e=iu?N5OygxA-20xZ~Dh zl`yO~3D{NQaOQmQfkE|ru=A68AN>}7iE|82cY$x2L{qyR4;mBAPlM&On_j@0_2Sv#lCz%2K z;gb>G-mR|6Jq4)NRxSEZ3tZf~p>uInmFz36rl>2PT|ZgmZ@}bVQdT|dj5@D6fAh57 z`BoU`2AXJ?+L{&sZ@t2Dim%niBaT#+@#uyPlyE2wM{;F%_PXMqew+PDbvx^&@7F)N zeryeszt75W|B^=4v=H3KzVcjxOWI8RY190LMra&sT_QVr+%PM^v`+g7=X|Lxx#3tV zoFc*j*Az5Gknm$J6LwL_C=8kucS?B%xnIw1Ss}XM-nm>?xdnXldxKEBO%Gz85ddq1 z+G*EZvZ-=g>Qv&}w+(z~a!#IWe%?Y?;tQ8Y_~>y^aLC)K(na^hYWd8%A>-a5<}+?# z(CZ?^BK~+=hy~(~7aJ)9Ul?3GuAvE(Cm5&)T83zc+M!+LyFRsqE+*Nx-UACn(*`pa zX~CG)y7sx(e2Sv=dmnX$?`Fb~j~Z;VJCr2YujsWGmzIch2%V0HgD?5VREnYuYCVM* zoLXpMkMSuw0BPI>-TA0 ze-Qq6ps`j;LYQ}zv882pH{PgIAG#K?!$g)bJE(*|aUtH!$<9ZwtlX6y7zEz*^#6&j zU{y?KdB|dRPxM?|UEzYWx~JBcg1pl=Mf1Nu)ndocFvve0+c#BSYvg1hS~DaVQ0^UG z?lCu5frh_gFRn&$tMER#J?lNW=NAXjdIPvuulsDp*B1rxqVK@eKm1q`q?K{1BJ=yMH`k=d5!XBhU!U6GtPp!q#glPVZ?NyE z&3Stj%`wgC^$TUUnHW@J@%pD@jzzbbsL2y{9*S)%@AJafn@vni$iM!4;q=O$==GOn zf}P<}=0Qi);@EUwOD~dO%F-Kmcr2WKG(1bcoChds#QeVHGS4$MYgw6{@*H-4Q}?~! zVhqJSn&FnRmN3*~RAOcBRpYjvi%16_N>j75;NipToo5{onr_j&!-BDIB@)l+us90r zyWY(3{0((?o^8NO9P&nMCMTK3Dr>K#5ArQmBYwSb(Um3%B5jP%!GxylTcC#nFUh2F z$h!+vWJUbV963=0no*I&iSenMBNW<)!YAIEqDX)I%5H1VeK#3YavXhY`{Bar1e0|E zvEtKF&B-knMB2iqAonE~`tI@)_(hPM`iNuwGk0l9{1&0ggc%e#ZFNHJ6j()Cv_w_!skkF_Lq}AQUC)%j?Sw`*307T3 zRgrUF?H*zwD>MuYW{;nmb_2#xSTI|JuA+;YQT{)g#z$`tpC%M8((n7+GS^wa8?Q3+ zLREa%j#pA@jciIr{x|pZRQJ^wW{C}#&L3nb+cjmY|2tx>Q54;JL&p;fZJWFu zp-C0a#1R>BW~Xy`Ju!v1+=zCnB6d^w5%;*p=;Tzh4C^#}g5UIO*G+fLXPBF6dEV+* zpBcgHk7EHmD*DfW;W;Q~=h8bfLTCeHrgnpRVuqhNTCdx)wija01d?~}97k`${wnar zvS~f{)1k#gzw5RGuh8l$h_)0~z|B(-*C+GAgX*iHDJzYQeiJI>u^+p!TA|0$oafpX zsLP(ieb4HTR~5+0!_HU?_`JZ>*zsaazumA*;QFCq_}-wJEkfcye{OL)IV!VWU-*3P zqv8-5p2?9l118{dicwUg1A6bZ`85;faM&KXtgSB^Y>p4c7UA zGe-Yq->)viDPBDl22J7Evs1jL6GC<>S`_L4(!|V^#o6f|^#Wf?8Y|o3sTe3JImPyR z=w#!IZZroHNG5df)@^qEyBi=c?+i*1()=ZKoBQ5rO~Dq9h9E|IRDGk?hBT`Yi2ujl ze?~R+J@LaR7K#BxktRhzK@ z5=!VqK%|5akP;vyxrguXf8X4cnToSd^~?>)QB%x6Ax8+rayE_4852*>cZi%&K4E&ok(Ga%zoHQMZ=C2 z)#Mew8CwP3}9`7ToKC#fQ>s50#Xa9uI5XT0QMgU%vi@feV2X%M%Ybzmke>V z6Py2sk9o?e7T+F+xOL^Rv)*yM)nld1cHUVe7k{2-TafkaX&^r}si~Avc{iWEThA;) z-~7yyZ>^%JZ-BBd?n)+T?w8rHf`VI$J_O=;o8x5q2kFN(vf~4tP1?6EU(C45ns9&P zU6I@t^YEjlOT`OrGVx#~-IVF8b@y4iJZ_Hv-5*M-{Au+ntVU{lpl}lxNL|p18KQgF ze94-1nNqs`fc%uwR)a(iOXU|Dymzj-W(LG)fRTL zcc1PzRil1oeSo!@D?K&QIY%)hqgywsQ^^SdUf}ik>(P^y6#TO%^l@rZV7sn)%|O48 z&&0!xaqU}W+C)>YIaTKPe`3DudF8#`;jil$miVtru~gPE3hFUJRv{n+Z1&KlYQlSdi&}p`+>x@8;j+)m-{-Zesn#G$m7Jv9eLN!Flq(CA9t97z z#^N*VFn>qG_cp{K_x?9WnQ9msryF}Wnejb8tL=JN7&C%(OZkq5TWM{7;O|ZRZ;lQy zuVUx#!$I@GSPKwXbh5{miFa*FE5;lGSY;3a4sZjQvz5mbr&>Od8Ou~qYdS3Wt)_l# z%XZz!M%s+68oT5O?#?=kvcEFO6MJ3ZW;TkxTeHK`^%&xbm&=;Gc5Y3-?kaojr^2}# z#8bz0%_2MpEpgmyJ-%p7IfGx`v=p(x(38|su|nu@jE{+HwN3q~UUjuB+kFyZH#Zz@PirJHVQ-e>cMJ)|nQ0 zHbGBdVWn*P2GV>7xz9d-(S#42Vd;BOa%{LLh^^(J@|wm7pRXB$AH>#leab4T4a^R5 zdo>v2i!!)B@U~5|l6`n_zg^_h?Vl`_;`uTYzyA25&&(W7H>Lu1tessV=kCsPSuPlR zlAz!Ss4!ur5%Di)9KZrTl=HoPRYlipuGMy`<#7sakkUEj-?rlc@%Z0#lm@izd#E)A z5>8}G5yin3!J~o{9faELJ<=D5V>0Li%<-&C>1$@;*^$Y|@x2+a|y9xBD zn~ZwcbfH|%f`k|3`NvK)fAquss$#A7%-fM4XZu&*4kRpG|C=HyB>T6f7{PP$9UpOp zL(U;{SnJy<@Yz;XFhXV=nTBr)e1K*NPPD@Ld@8>$H*I=@?aC^>1ZrV^%F#(tS;DK( zeDCQ>q0X*58J^F1dfTz#=Uby2Kj}asHIvEwmTNnf{x3j-pO28!iE2Q|etZ*l`O3J` z74X6(kJuO>bp#~1NPXN>Yq&Vax#;ceOeqaaApSns|J~^WeJ7KJy@uYAob1j@nh<;U z3#{xVId~HJUW}vN+w(i@f$N~<+4xw-#*?pk!mksxhBuEM3UZRD1gOiJzW17cUFM$}er#3ZGCr?1K4e@WkElroiBZvY9$laHaM z?546___P9?&Zql-C$j%obd1&3I2RuAsQ{%ljQ$&^a0oi?V>nnfnB#0Xf~qX&8tx5l zzLe_zjX41pt|8RFYhCwH;O3{&`{SPqDqW2onB(4g+B5;7f#Bod{M9cPA9J3Up_PQLb)Th^?ZU>lzrCa3Doxv#Myy|Pc=RlN z^W?q%qv2lPNv%t3+@;qGQ#|s9q{q9I)zsA1CbNa>voYJMQ42(uVe4v}a;^U(R$77N zd}i~Epv#{>D++*j!&j%LNBPdphuMHb*vChDZ8wzO-CIX}1s1v-OZ+NznXl}TY_q8s zM_fGOoYv1Tzq+p(&%H&=1uk0(Xa~3aGXv`vRZPVh2k57unpie3j^ERF{IIjT{aoDR zrq?N)HL9aSy~&fB7Wk_-&2P$&2sncp;g}=uN-ay{|H!^%A;5Ssz2g3Fr@rg+-=bow zJbT2J!c+nn_eT!}|NrVC80PEy>qu@fPVoP_ku|Uwd_=y+GRZ6Sqe(GmMEDY-PABT!BqhN3}~abs_{HE`~{ znSXX{)n?bL{f$2b_^XZ1R+o@Xwr|gCu%c!u5?Fcv52G4H9JPf^TS|}0lgJ-k4xgvX z>ZKbamQtqz;2%&IB9s_ZSO5GXJO)pxCK}LQ}cT#(DRhOU%%cECQ`M59q!t`dkJ#Yv{+-m zErQI!h$&R%-CGT|zQWVpkWjtfv#z=Or*c>r&SZRTAG&q8`J9C<5zw`YLD9=5S0m@< z7dMuAx+Vfg%7WMhPpT^`U*KVE$(%l0gl9wfI8q5s-s{k;Vz{E|KF^nUaoM~!)* z=DlqB>=gT4PVxiWg2#*e9+qzuJO>ip?q-+3$BWs+Il0o~2_c8aboVg1_h7(HlmY1EVn8UkBA>XIE5CV zy5k2Cmv2YZczAmDAie1oROm-u?deT2N&MR}^cx2Cd94Y+0<&2zW#qXj|BHF!End-Q41Q8-F>d2b?@R1;>^~zpdL}%<`y)gXc3kEOKn?YcT zC|@HPr^OAJK40cjkIHOhy4SAw?Bxwpm!!WczHSbP&O+_3&KOpV#_p zUy{$UFlpatQ})TdQQ~+$X4Gq2_x#f-rq07f`9wYP<^n)U^XSWI;ad*?;`aQ zE_O6`?jYuZGF|sGUF*4`f1hA^5K`=D0xel-SVI!JVjxW3`wP{ALE1&$aq-7{0%-Vv z3G!h-d3<9daE&&*@mysbeqhGmS?y>{JA!J;Ba)QyT}T*sl&K@EnKBqlSas|Gh@Z-h<~Q^{{F`b-@6gDkc(`F zZ_`Dclzr8AzgX=$VrbNG;965U)v`qHMiLkl!g&|`5I>pL_G62d0;d;iy?WAd3{tuh z8?PN7tJTP>J@bC#;P-lQttlM}qc+3Ue0%o-7$nSjA1h*NS_U|ZM;b=Fb2x~I%+)MZ49vCRdtqGlN7t$8`#-*3H!8-sN5C1u69d?_ zon3hct!>sf06z6W#!YMP_W=Fy++2tVXY7}9&8?OySx_tOk|@o7aVdM|NiOXh6?T11 zuyoxd@?+jlzpV#>9eM2bh~-mBCNrp&Y}iV6R;Z_Cp<{J|Ry=U(U8ga88g}Q z{TTWfW0L+ifL`{mp;ZfdFr3o2BxrV4MC#09t5LGY^A~DSNU9fRN0_eBLEk}gIa>MP z7N)nWLAtGI5_HAb6@(eR+^c#gt zkAC_y9Xf0>2T7aaf)}8{)l4G;k^Jqc(i>xzp-qHYLH()UyNd#JV-L_coY*-1&Q*r(TR09NUZ%7XOgNk4XD z@yw)*by1htrL7Y&wOc2?572*MYFcy2r@^Y7n|-X^L09KKuTw?YdcGK;pUtg5!HOUk zD>4`Dfi+GN2FnhB*^&MVFqvN^2G^7t$C~bgONA+!`o94 z%!n5O7KN1;CwLJDRru5TtOrZ5^`(c+<@1hiUn=>$8liqx%uf-t12Th#!SYQqw&3)E z9~uz2;&KakOpbRHB$d-WkT+xc== zXGQoA8=XnUiV|q|KVK4L{H8GZyOMGSR|3)QWz@40F{8=h-VYxWM^or-5d`c^#HD6% zg}`CM@3mH;MiJDs*yG%}v5EaosJ?Uo+fco#M8cppxsN|o8O3?jrg_Q4l_28rN9@S1)g~tYK}(Bx!|(0 zUH3;BPESqM(;1z6JXQ3c-S%fi(p?#uuJ;e8BRL~yGg)d-8w;A7!!{J9QwbxH(O-RV zWX=Ru{)>2OyzcPJwSNOn)m|>^zA)>?g6%lN(5TTD^JuJ5<2T!9HL)1mq`-j?Dydoi zc8aLJ9*qKLP_U+9)fZ>roG_w^5^iimM{`>z3tybBA$U64b^VFAYp5oFu&{`Vrqdp| zUcME|f3iAATzkHoC1zVNOquBO2Q1F>V~DOrFj$bVK2sG#(b3($-}J(Ww_vnFz*cMJ z#c-Wu52VX{vrJAeNc?e!u(Q|Iv%Ft%<|TL@{b2;Y$U8h2Yq!xF+J5N%cX;yv!8oA) z^w+`CG+D^WuEJFEhbECumDzV(o7m9hj`XcCa#J&O=|eVjy-v?-Za=I;JE_~UVXxEX z*QXsQ*zCY@f!QW%;|FtzqP5XTe>LxxqEX%g+`RMDOGtf^rSUV2GxOPeu*@N; zy1=Gc1a-%&t+kKyctqjCcd7iEiCiOU3ANfrTMyGJyHXFMNUA5Yv$dKarQ`w;%I_+H z%};q!ULBKG?2<@)@%MNtyEZKQW`yrFbpE&vs-TEilpnVYq$Q^@KX{tz!n@;>xxH4< zW>V;WDa_9@f`_*;O{iq8|0|qEXI;C*AYi+xSJ|$Z?|Hrt>wq|zpIu2eOFC_eN5{G{ z%oZCaBTxJ3>!H<%2!#cR68oDE{iDfzUxP=89w;X}ISlF|$-!Sl2lKg>gM%wAKdsz< z7+Mu(Ty>{BVtPiolR=$rc@)_4;i(b%8GbNOmJ6h{Uhi|>(%4EVo$6fBZkw_kQoYzE zI!>?ry`K}rk*txu8q4c<$}!D_;7lC(G;ivnI8V{HI(f=2Pz~3uUI~z4*&a6x(Kc?vrN<|@lyLQDVVl={P9=wDSZ*ROj^&m{q!33}O-pH`3-kjdLp9tv(aYY_ zzJl*eXdB@okifzQ|J^prMapJ$qF0{mjD{Io7K(DJ9L$O!eU9}r7hQ4Y=j6r(eu;@J z(8#%}JL2w~eD8E^mSThQzUNt?`ZTOhg<0EIfr>WM#){~jYJYZqy%2z+G*zEQ72&Ob zbuF?;Ro@+peJTi<`zne4xo^I)_oTn!BK^~voU+gf=7arz=eenR7&$=*KLZk<_BY8R`;Hj+)bGpt?VIcVsYV!`QcGD#AqmOeB z-tv-}wxZsvq;Pi!?^j8D6}YLxARg()YUX6G>;f;!c??Qh{F0pTveL3Lzsm?`mF=rR zI_-P@;rCA|Jsp$|GN(>*#a*Pb>BR%VA=52Ek-geF9!ehYV=-MUmWz87%zH>Yv}F;2 zG?PJ`xUs*4Y&=^5Y+AJ7p4l-+a+stb?`0?B_>%pF&evdx(7!ao7Y^z0!=i(3(7`+T zW*VyCx4EB5GMuOJ-QLU_Tb*7Qs@4#7C8>pvgJkCPx{5doKGO{4r3ASP31gn5H{~n~ zpldxq&Nx5l40}?(Pi!srZ&R7uiT`-Y!TeP|hZpax`*y9Exud4Ao) zsp6URB6qbSDv{ti6-2RtBoV4g##Wno5G9$+pED0N?}i3calw7R1Y;E^9|kG4v(8<+ zuT@{#FdQ`U<2Smig??W%b^fdOwUuVkkLT?$^uR&VekRhPUXXsx1_f4c9FS2@5pBA8 zlKd>z;G;_9T)`x5di)eA5nLLr5?Q!VpHS=Fw~;4RI#zPN#V5>l*iSI2bJqEj;B7Y@ zt40G|>}m8>W1@+(+hMI1ZruduZ-RS>0-vd{{YEWXP@ZpHxHiT;cST@2daEy!R)g>O zPAJd3rn8}>I5?>DvL(6tvq=W5{?kXu;x&;)sBeUdv(ZG(lE z7*1i7m0QODpr{O;_%>>xpv5m*{ps~@$8-5z{4iPaVNYdN;M4z(JSRC#yjJGG3K zN}T-@0U3(oSHD*qW&ikNZ+Dd3hLQGr&ceMrl8l${PD zx9t8jai6N7MBi4`SpEBlrBp4_k0^3c7t=7B`^iG;Sxylo17v{NFuUpOW8Fwh>7TSa zN6IJj&)_Cr(*yV}*=hnR?EKb$LM10U*ar&WY(fha7(cXD9*TX@~DN)h9@4Fzk+{M!a zbki~+EAs%DOz*<$^;@v&@4>VsTIEBf%r&EHW5MRc@B{@-UF#^q>=S*``{#$0Z{*oO zWeqk=6#xZOR>gAEh1^|=D{T!EuovZ$;u0r%x#xUEXY~ztHNlyp3B_T|>KaByct`1b z6~1$s$z2v^YZChR(pZO~CzjUTGk$F}(sk59{$agUs10YO z(e9MpUew8!0s)mLlTbb&+<((RnqWMABOIpmZ96Al$+~wdu6MtmQW?nURrT`40Wj^lbi?r?%?wJ>)Or{Np2DgI5=euv7$gp|h1djhcaX zCKvCehgr2gcjvkY@wlbxLBAO49s63-{I>9L-E|Rv)KU^L>rZ-|`SoP>vp-Q)NnqLO zs4cWg@!Jtl=DPYAF?k)s&bzMekV0vn#rx3SG#+N~e+Yj}T;?!bwaO12M3vc^gnVrU zQ!Zm1t(+k7pm7NqB_u23Ns9tyM^OK_s3_{fNU?FY(6XG|l~&5NRwRsR2=by|o4Ej% z(-AZJw$2qz{i!71YSv&lHS^$7BHAaR+)?Cq+E-yOK8e2PJa&5rR$u*7w$&*qgAxe= zN&wZpP=QLHdil<-sX)<(a8`F%Bpb@Ir-Yh zIkAy&)HimsBHPpauST3@Y9C|!qDzrJeidKg@*mu8w5EQht&eXzf3SXZK$JuC7LGy< zJn0J+VmtgfR`q1FEpX}!Fb47pEOiK^b7!KQvoG4!$$Zv5@ybkZ@5n?*pdxPwfv%uz zn@x45aLTmNR=YN~+;h1zM%Z#&N?AT_BA*jmzC2DGw;@{c&bW?Ul)wf4Ua$7M7x&A^ zR-M({vElSTleSu211RuIfE&lPL={s9qS0|&|wW9Aw$RGBhrQLOU^_2>E&^Zu`^l#eT z!fuCNuh5xTa7y_;aOiQf&oI{)Xqc%_E=ZAD4Y^ zwYnti==1e|uCBxP60j1DqS8gq$A}(WRrkafJ>B`fhgiX-@1ost{RS@&Dmb>da872`8 zo^j}H5qedv?c}+m2c_5y+B#O>wYHZM;V+=>%but2pejDwXpvs{l9nJYTRD;n65b4+ zq(g6O;1HSa+>>QBRqvmKzjC{<& zkmv>YF_g!fP=FK?tfD;>$`9F|_>viH6}nmz-nbD?WUd&j8SO9xJofZ$qy}%Ebo4^& z4=?6F-@kvCOy?S_Pdcw@p1Ql^dJ=I$P%PT4F4sp~+jB2$7us?Rwf-(1S!onANZjw_ zeaer*=45d<8#SqU9Kc%UF?f2LU(K$7pEAw{ zF&6bw*W=;CqLs-88-eQIBNOWq*5mYbGTndG;YFi{c4$3nxZF%?6;{$cNzSuMX=Sz% zikQ>HyjW{gut{#^)ni|m%6sx~!uGw8Ke~|n8_&xsW~P~1+f0e!&DDLL;|qM#Aw}3b z>n%Iy(ewjicDw}Y5O9`OXfmI2-e&dk_wT*Li(`N2^q)p9Js!3s zipeFua!4!RDGPCA5xBRxbyRm?UCrO42yj<0p3Y|$LV-(xPijPxLT-?`V|5@u@UK4o)szFFzVX___VWf?J&|$vu{!k z?bR6(_by!?@cO}*>@!{9*eo4v4Z^; zJXZG;l2_uNPO8R8o$X+-c^q|7@>W> z=|eX`rIy(muVA3~I7L^f_JQBmh9MBgB(j?J@~Hxbm1#AOFL`u}DqVg%uV&$yN4e4k z#c#9umETj7wcM8_;t8eR9q>focSrFAP0Vs;>Zeb^4UXU6w$@xr^C;(IgGY{|9Z-X} zi0b1xM-K6KGEZhiMZprQmm;(3_%N;tZpZuXD+GzC!HRCiI63FAolRY0%ogY!XNsw2 znt2IZ^75R7n;Z5=OE*la5sU%K}c7yvMZ-J|T zkJ8pf>-4rxI&&mKFf3{CZ7Bk=s2%PbI{oU`i1j{KR8$ldplW{;>h~{&DNQp5{1y8H zBQ!ZR)s0*)VRi?CyF}@OM15ySYnxgRIq`WS=XbPTD?n!6jf7n{7(#t_#m4>D5VZ`0 zY@TcA1j5=6&TUbb+J0trJ=s;riR`$*Y>B?B|+CV%Q;c%jPCjk;$67wxa?KZ2ojck5<0p`USItK z1ejtO)O*e!1kYdmUmSy>Z{VtA`jF7+Ja@N~UF+Pz<~b?OQQ!lc8*2r}$J0a{W#VdR ze9srr{wC|=#QG@8ItM2B@YpRJL4{5hbbATJ$lMO!KL^5szEe%Ib2|ffwxah~IgE2} z1^sZbzomwTQnTumx5^J=;h#9hcT(|1c~f;DdINW#-svktlwN?Jy6I%XjFP zF1Z8I9NZuNws1c#R=c(=GmIXV3-2_d}N*RwCy%|5JW+7Y{eWVno$v{u&RL%Uw zTWr`p!8g%}hqM>rLc!FtlxRA%(S*_=GdUARhkfzG(l*24BQx*VpkzXT5)d|YlZ#yA zz0wGUrfSqqZXJ-#5L9eO0FFqbOf11K94^>H+UQaI5t!xh>8LZD7ATE~^>D`R;_7re zwQwADrDbN5B1&{YYM#huoKNe_Ll5Yqriunu2<4MBn)|}nsXc5z!FF3c$$tQ@4jV*- z)zsqQ3>-9&lCA+qkgTWjF!^-Pnf&i2uDoK?kU&g;z$IWbjp(8#nCesl>AUkGm3pXI z8>DB0(k#Hy0(;Y=+Nlf9#7*2oV}6ySJK(jJsd>;fhHAv+L0S-HfWvl*ky*uexrnT_ zjlRe3!Vu77|FldQeQ_f~G~(9`Y`>X0wx8gzjT(_=DP}H#|ElJtjds77@^9R8k{hv> z@h#4O=7YW7%D|2BQYN$6&)}dbo$_?z3)tTxs?dxns_vXRj9WHsVORD5T~WPAfGY)2 z&(LP!Gj#Xq1*02UgU+JrL36Hlq$f(pf$b1LmOY!}Z=8oCYzq#0AD}d6aoxYUDd0q;}woNWog55}(&4eGX|DeC{Cj3;F1An%oMp((#NkGYm z?q?!$rx?qdHBEjLRS5KX?O!;9?(T!)7(KYJPavY*1)(PE)r83v(J|CsZUgs`meru| zio;$nF|HXh4BD`EGTg?clg`2OpnHsi66V3+0b)MxCH;mgQFD3pc!DnbWl9GF?bEE6 z@&U|j-&hfvzL{S~t)7L#iHH(n42m9O2ytHQi z84m>DL_5|E1a+CXlj%X*NTls6YZ;Ge3XWtQ6+PWlHDl|C$!are{9I*wXe;v>f9a0( zIZhsb*Eho1i)k3fJ219>a-o_x(!05NhyrV&VnyO4(v7M6p#vFzG=dl|K7Pfv$3FfE z8;zVcYPNugDj#4N%kDI)byO!9TY(R;X1|5QD$i3)ERRM^+WSQ-8Y@r1-i~ZiJxILu zJv?L9vjwXc5b#`cb#yikz0m4(-RR&B&TmwDeLgJ&)qwJk!Y$P_<^SZ34N6a$Dp#Zg z4e$ec3f)Fui(r%#c{V_xX%K+^Z(X#xZ<#g&tND75LCN0^lCh9|sTlI#Dfqy~hga5{ z&L(vg<}-uApYL7{xh!jdFS56n3G$rFj=Jx(d7g6NHmd)olJ1xum;Fj4A2G=w6tzWHGeK+3%89Gb^W(*1S+54cMSb{u?!h7vmc|EsvJ zr;vxm#l_+K|IGKo!o%@@mzDs&Y$h~#aqB5@ZH+@dF75<=Y6{XP4IDidpDu^Ybu+6y z{r48YbO->yt8+l1P!qEq0B3iTAKo`d+ThBqJG5;D<=eN<(`$5_0tgyH0?W-n3gpI7 z88s)w$O+Hr=sS1nVRPMjKoOVINV@{`+;d_NvaiTHHvTkzb3v**uKaVsiP57_ITO=o zk1&9DLoIUKOW?}C{f{CV(c=J=2XP+occY{CKdEp1YM7${M>yx{!NNMFqc+CZLW`W; z=6m_go@w(oJ%O4qa>adX@npqP;2ePsriC}s34wSmff(j8Awww0iYR*`b@NjRUZjuU`_Ls31Fj&E4G{ ze}$8S+iGrXeck`)Q?EWgXZ;2c>MI%b#KxCJ^RhS`{dWZ|R#^E!sC16_ANp|o$$y1l z{-4UDz|j0(JP7|-e6IrqQ+7wJ%qAupJOSv7#9<2%s|bDyMCg53xh^!)=`di*K2M4n zJm|Rb=irg_b2Ije`>o))QLqLM9 zC-o@z_h_H*B1Kd~KPy*7t+z;VoJ~6(-+FZ>l8Bh2jIPbJskB2wLltlF0V($w`pyqO zpHcI1^g@~%2hfjdomUkN$mm5_8+9Gy7|f!++BD_jPuLVex@O$nd_NGa!6tv{XsME# zMQOOy^AbRKsn|BL8ABtvvFmcT=7UB3(Q_=+6wF@Ab^E05WNkLtb4TCp*+zzKC&))n z&{vW4CXb|7tQVeqfiWly&r;NJV}OHb=d(r9-Yl6m`$fFF9DDeii~a!3seepwK@NDm zF8E}!s>LldbzNS*#Z>k<5=yFGt8JS-)1pIz$ zNo?Eu^(35PR@bZmJ|U*wsyvzuz7(x_P^>A;aw@;O$Mvwcd~F$bE;C;#?ct?#_loAk z3z1%i#(lx!+Rj-TjQxQ`0%pY|;DsM*P5O3Dlz@*E2Rm>4YC)W_LDyeP0c}58<4=ASig6)trlCI}sr$Sm(?& z*_j6ipw83uT4yz1$~q|->;E>+{3%0%v`}sFD$s?tY9~LHYj~nc$vEQ<<8W*4F7ei6 z77L{9*!b$aE^yOlvOgcID{|k=Om^Ra87_=yufc<`opmTx<_0!l2V4z#Bm7x&e;eLal8=U8A1K?GX=$!2|+K7vkfHGrym z8NNG}x0IQ6?+ppU7+qY|hi@m=KH&t3!Vj@r*l?x)6pintuM98Aa+-(``S&N+ zDKK(GB0_+$;|!ONuI;75o=%)EDk>7!o~dhuIv?_#PRP_`Y?--k?wP?4wlc{mc|e5& z*eE9166wgrmGb=B==_qfE{j_R3IdMey>7ce^~spbLcJnW>m&x9%m^wquzQA7pthn5 zf_gZ|@J_Ex({G1()YsX(u9dr=)&!WQX+M0;7H^y$kXWBDfo|%2nVQ|b97TfgJ1Y9O zk;*o1^Tg=NveO>~hI#)JMMAe6b+>^an&oF4#P*$mj=PdDycNIb^)X&z1tbYG#(pzs zg#riG-Sb*Sri%Vro{Kbx_rkn~tK5ISN_<<2v-(>i_}gwamaLebJ0Ed&a6A z85xa)Zs^3rp)C-reI>7t&)K;}L=b#XXA6)fh#&UT&{DAZw}hXYc~W45vf-QSbBR3o zfB$doX}Ml_(W!TjU0xWe%BR&_DLLmCK#i(LoWg01OHazXUO=&mMvvPTO-}~FzV9w* ze*=_NMoU|kJMC-i6)`kZVHRsgr(*#0=`F_$b}pGyXZ=NUOSHNX_9C=SKFzwCP*-3o zmDOUu2%7VYs(8%*dLJ^U*VUCTX{guWVOoVBHEf0w9n;5wYGvK)x;Z&YB>SX_WqZzq znC0V>j(Pq-)_=a8w+`CjyojNXBfOut~0fF z&HZjPBVjv2#xUEnwRjHK$@i~5E`#~iBG%bFy}?&IPBRNT3wM+qX}itW1TWW7?bnKR z6%~v%PfZ~h()L7{R#imGGq7so@ur?1NA=ESdQ`c?3bI(rr=3@X>M1tWaiRc6^eFww zNtCXxj_&@Z3_CXtB{#y&jpbyKPam*f>nz!1Z*@_)Z4;F`NuMInFFUT#t02SAPAm=< zp4t2z$0bL7*QoU$o+cW3rmO0|R&-KyMZ6x=6LL1};5++uOz>VAf3Rgm)%CIMx=ysi z2gRN@O>+_KLjyQ$dEpZHW9o|TEidpeN)9?3V*J%>`38a70YFa~_~r}FH}5(sDCs#0 z9XjMmOmctvs77udJ}M9NoS?Zqs52K@i(+vmhL3gEO^+abQqkm2s4l$YH z1|!d2c=vhy$uEs)xY)v%=%XNCDY>vQ*Q@R1oHuRwWQNiVBf`f4XZ?@B=y>qWBK9Ap zrRD`FiD|{UNer+8z5w;}O6PKTLC0`%cCf)Kny{c(sIPaITXWT#6E&-&vKdc0G%&mp zr%>D#HrjEuqtcrzW^h%un*^b$e+5LsRvzVAo3kHLo<1)xtts<+Citi9f1(vata78r zB09XkOAn-h;LcSEY>3-)5q^;~L>J!Yr}SrHj}A*^--JMjvaaKqp@Txv1FCVJ)j(lj zAxU2+9(?hT>XT19U#2^Ek6K}@sJpy__~J-7z#AFA{AzTCY0s*uY*9O2^V|q^mZEWV zjrnm_V%5M+yEg*Sup#}6mqqcFYU}dHioII=jA6nKu!WWV*shi-J^VC2KAepP4h;KgeosPpCf& zs9E*f_wU|aaX2v@K^W^nM$GKoYZKJ7d&9@OX_x|GY_5ivU~7Bly#>z|`rFAo&0B`t z-#U1MUdoGFn~fqn2hWh23I1cQaN4Jo(Mn!z_iKs|rULo~1voTIfRFoHM-XU0U2sw} zW>WB(*t4>-E}XxSJ>m5wecypR^(G*PJ@8|^oKKiJdpy1%a2Tr!(g&RZT?AgWi@V2q zip8^*SS-G!c!7~EFOn*$2vJs7t!hTP#yVKV9UW`4UBh< zNbE^vfH(al@h;G`;^|=w@NuU9Yip@r`p?Gr|DsLV053txbV$00T6oRBEj7ZvDUnPD zoTy9%6K5oHzUgZoSWtU_YtN5?h}ox7{~6OJ$p8W!__O@~X#A^z;_JD&IY~{(@13qV zR?gH#u9%1%5_E!%y6js5WoBa9WaH*6I-j%NL2-#%E==q;M$NCL21L8>?Eu9LPqE8# zcEYe~vp8$LY?ee(P1v1H8W#XnC&L+3gu~Te(D`%ub%~-d^vx7o#oxD6BV8Lc4}L`h zbpr1L%D}E z5%)&SW=BTD8sWgMtcm%n*Q(ufRD&_z)y@cOMXf?IG5t1*AUM}n`eSILc(#|X?WLrv ztV7|;I-+2kq%*lQHd+;=$~`}xv4@{{|r((t$}a5PHA>U4wSo;yO6<97Szn>1+)K* zqGYA{7oT^e*KIhe*uO>EBbOYEcQk}V^`Ai`J%?tNJP{O&{DDyx>5k4FP?n5(9-vip zz{Yvdp%Y)MFa~jcRB8MR++0_q6vpg0;O`&}8`dCzQ{5`=3Hc9M~wcHRI?23 zd?Hm?v*02GQFd_@GP&$*ye&AwdyP}2x4L2(uRIigRsCL<*ov;Ufz0j`8w5V@qoHo_Q~WTY4c>vJ%QYOpnRpb5N@pdEw7Q@2YFtO>g<6( zHA+(tNfWljA1Fsx?Q6v5Zh$ zd&vM76U3x&Zu!soHu#=lRM5d4@uFiMFB-yO;o}zso_@{yaLaqRYrsAVFx`wNgA0z^ z=vfUNH>;*ymi;vS1G`g1a^`GU^pf0^upYcjq9Cc4{b+{&CJY31M=jrkitd~@KA6C1 zT&8hIb-3m*Z-iELx0@y5->JK;PILgwrx@3iy3fsB(HhBE|je3hr%|3#VG8->tJWbbM`lPU20cMpyvYKQQ!-Hmp?E-B6q0 zbNn__&D+)=_xZ{=gi>PjXWMjg+cl7;l-BJpZjDC+nmq${GKLB~K!u{VUNcb7OJWP}b2K zuVkpIV?VSb$5e1Z@rj*Pn~UrP*uf38DDTak_Vp|~$B3oOl-3oX>Y1flvw!mkB-CLo zgpMm`*eyN{!%$!p&AMF2CagcXB}1RIe@?%LO!xH7RNO&6t60HH8U1`@rB#9hFp!(hxr7i29 zL+sSQ26r<#iMV`J6@8wZ>K`544cjReZ9-~n??{dj{tXeT1ts#}n-#Q4{S4&movg8G z8zqB7c>aN_R?=REK8ID^o#5+Xk3+4)*d> z6CVrXf42w4$l!dLW?REIUB4USkJ$(K*EgiDGot6@Nr~|Fe5bP)eQrm1?;x&&PRi+4 z?97!D7+O)}DY)37L)TvneS&NUofd_znsqOYxlhxG&oZ&ZM80HItNIFsI&W5h>}12b zpi1DlakXIup_F5o~DHB;j96%J<_x(qyOB`jE8Kj+F!O zopnj^`M;0=5Z%#;=h`9Pse~jz3PyVABE}Sc=gVm_HMz1^tnhbnt$C50iCWVL=C>V? z3;FQKuXoqe$>!E&5ye*F+{&GS%MdDv*YMzD`O`EBYMTZAr9DK|#Sr9a82M`&*crf_ zJRoaxDL=#zZMf-;$k9y*>iimse-n>A`r~N) zDT_k-Y%}9T6eS`$Vo-ZCpXBDKVeqjdwDupZUu>`@5w$w>=l@0BTSi6MhW*|nq9Q6V zf*_p|($YvXl;jA~C5SYLfRqD>#Ly~83?)Oibb|_rf^_EyNVhb@Fz?BI?+?#@*V=2x z`@GLu`{Qt3GhA`T5x?Vq=#J&S|J}UV?M1C0BY4{p#(Uk-bICj;msmHtMCT~aSLaev zwmNwUbX5U1X`LWU*MR89>PH^#j+(fdxpB+U_?Dp3R#yhHo)%3zH2zuLb@3~;A%Toe z{V;Xsk@DIaykZh9*1E)pU9dQ97Jy|7%2XepdO1xzvF1};%g@gWXS&(Fpp!?eo zaj(s*_$AfLC?R8;Jr`?o+m?0_byA7oO?&$c3YUZFqBN;5(&oIZYS%n3%Qb6KtXVh} z<|o#bYSM`5#LD-^d{Z=7?&@vAV&@td?Ah~{&3UwcPSO(wvSLX`QokKkizVhI+_H@# zHnysgrSY5lE|*{Q(dDR7xM1-aZ-em3FiUy2p{|t(c&8d2vAy|gQ7;Aw1bMwijg;0O zU7cfJUEXfcb$)KI7#uYAXjD@5;dgd>GLH|hG9C>P{BHO@(r6MFQ_aW61ATs}xOP

-vBob%4$!A)qzAQ|&QoVv*~|I@L6(zS8okjr=QBf0N9%?gDd#+gqA;41Oue`+#( z@U1sn#{yr>lv=*8S$uYHl!eVj6g17|xF2Mi7+Y-K>Dx|e*^+Bq`sSzHRhE!C>=|_P<$>@ zj%=57zw9~#Sk&$ zvgXkk_mxYUn8}d|`@UB1;z4P(bXgx^)B4j41SVF0Cf)dHVRifQx`y40gBVX@o#K1t zzM!Qxl9S>a(hsK}=S5X4xW?O$h&^j4AI^9^eMPyX1o1(sMK|VwEZa^JHOyD$Pt@}1} zfy)7h2)wwHbpH|R{Gb_wyDWdB?I@V{TEJO%Yi;%-jF;T4M48=%s8Lp<4)O@wd4v4Wxdah zmhb)?)ak!9_Hg=8#a5@Z?h%faTK5fE%Z|I6ef<~YGtG%c@95*oP$HEQQsP_q4J_Wx zhFJm=6Y{YTk%6C_Nrp3=eV;-el}mzYCcWW`IEQh z94wjgV*x9z=M^KmCN&+OC8OStL-c;FJC*cma7Zhf7a3|i_+lKA8nGZeqw*m&?G<9a zNZO*ZnEX=$P1>f`q^pH)TT9#z?x+ybeUaXG!|RdB8G{3=SHiN8B2 znSKyjE@kv>w$G?~XFhDq_d7AP_eGw>UMp%MSzjUJ%}6m{=|Tn@(~09_y(#6v!1_U) z$DC6=!jt@tzz)q9<5kDiif;ETeQn9c7N|nI0mErS^Y76}qHo_Ct#Y3|No19Ud3bv8 z*RJN6p(xG$>e51X$;z5f4!b_B*ETJc3aBCv^UUSZ+++W4k1ISi&n=B(o-Y{nBzxV_ zP#e3XQ?BynV`^_j-t{YhUtMEf<Vn&Rk$y{gB;fP|~;JTe9#8 zq59YK*DRqW@4;f@H~IR5)caKrt~eCvtqxYAuq7YIX8*3;lUKN$J~HzoBWKm!0{891 zl_ig_Om5u& zYe5x!-P7&1=flC9k4ldXIFWqDwWd@hvZuotdJV!#+eM`s4hWqW-p9!*o6Y(yW|)Uz zNAy*`E8Si+`mshSYp~0vajJvceiCYZL}J~)7oX?KkMsA{R$q{##+Ln?VfKRcPoo*H>~^J z@7ryYw>#Oz@5Ftij9oN-I5<8vF#e>ij1ssZYQ}_x5Dnx0Cvnfd-wX3!*qxRnw9j=i zixq^bQGPP{Y0J5~tela&C?j@_gzhuj^x7tOX6HQ|Xa~#)G34@eo-BTcKhlWy9an#U|MC{X{adCUzym+zdO?vv%7Db0%_nD;9_30dXPD&=8Pd34Mm z&!gOLT0+uXckK#$>b9s|XbeJ-!nR(HcMKdy?!d4Orim$aZ@#UIq$}FiV-8BaL~M{` z&90I%Y7Km=m05l7zQL;QDaMXDGoJ5+>3TvRJuoZUN_@T~5F)B+lIqd1CR`L=bPxjk8^I9G^hGJfZ{D`5?j&8m%%j zMB=$sQS@`hE737x%C#(D@R#ROr_=@+v{U!=_|mt@p#&hg=MT zbyX;PG`MOT?{HNt&+HA5j-4VOrr7!f!S7bUFQxr|yV~kred+Jx+pZqFq*JAUgg&L<^@gJdu zLqTV8lU0aQhRm|BKg2G0z2Rue+FHf=0TG3rzcIhUHuV~qRil9s526zdUGJ9;J3kj9 zsc4xrw$z)>qmOF6E$Kqj`gyQ(ZLemwvjyIF0}}IHeR>f4K~tJ{Lpk$k#YQ^p+tJMf zm3M}$G~Dl=DW~~PY;=r_95;+OtJuzr-M@RkxcE@0ayH|k0%72Dbm;^B)k)f3!r&$J z?@vczTN;j$Oy!}&4>A>AlteN_hxf}(6xG)mmtud7OcG}alv8e($Os+W|51JG)|SQk z?e7Mj~>XMQHnZLbX3%E zlk{rWJnegn{IWx#s)P*cE4G`q&DZ1{{U*1bAE#a(Pa0;)Ob9n1>?k6*!b`EP%}a)w zJa~c|3o9Y>urX%5Sz~_91yYrAgpbQO`x9YH_Lw=}lcUPz%X8y;-+Jq6>X;B2+53eD z69ak$YS(y+jz^c37G90|$~DjuZa(K%ugr)!G}z9|jTl+KCj}YjH2p-@vnKpN4BERR zY?fL*F+csJGRZ89i|x+?qxCLNLko3-ooZ=1o#=y3$=kR7nPFW& z@8gxj#3vJ%AgZCBY@+3M@AJs!_*Zg`{8mWK^^26OgsOiX>p8i`+q=%lC>#6+*%w+W zYqrnK!^TdUW|kmQ{ka7o8ou2n95T`>y?yhdN_jUzTM3R(aZvSRDT_C{)miUfOBZxf((Uz zkw}osMNm9i@tvIR(EZ;dc7fIU(%?$utiit;o;PMQ90vr(r}Dc_(Yd)>>LU#TfE>0-TP9Tcr?_I2TwevgkbAn5D=+)~Y9aXip6Cgw1 zmf`s#-Dk`e0$PGPOS?osT$GEKv6wh%*`IX~`e={BVhCGwQ!|`AN886VyE79Q$ zo=GF2m%K|DWp?o#ob*xgste&GX==RC!q{t9uYR+)sGJC`xh^cDihP_v(hIn7kP;F; zyH8AEQtMI;l&?b8wS*--FaE2enn*dHF(}wgGSyCtiFpOOs0E0NDu}!k8t%}9vcay| zKY#xHQO@I}rrr!$i|Z8ND_@>x|NbqH+-_9)zA3Znr@2+P>h71i|3rIm)vpsd25|KS54JUX5of*Ng&QKob_7H! z5x2>L2{}LIUyEJCr4%jAy7!1I8}GFq`fe8X*+!Z9ZB{R#%Bq(N@m@HKFXi`9{Au3v zxgLXR9C!9gJGRMslF;l{vpva$l=oHR(XZxr=GwU5fQcKU0;RL^$W?NhZ+(|WG7sy} z_GpUHfxcn!M^6AqimnKK^7yQMp9s#7zAOdJ;_=vC6nBe!4S0>;-qqsK#bEGwDqipo z71wWrbwl(b*Y<<`Vmwb=K&?zEOyJo+BL@{Bfli>B1oBSvf9GUpYhz0=OkuwJ1Dz3= zFj7XXJ{hbN0VL3R2s9km7+_=3-ot*r0U5TL8Uu&!4&uSpGsEClkR zID%4KTlzq6x8syG_DoUId&kl(fH2|)pSR7fADlkd;k5(G1T-+P?e6;KjZb^pZ|QL;aV_wF}Xg;Chw5U7H_oxoAEC1=50ZWjiz4+ z25^ccNM`?^jhFwe!S#Rn$u-f}#dD?4j~7;ZA8u=qO7H7T*1B5k9wqRa==)!&n&r9o zNsDccmxEFdk9(?L1lK@tK~rqTLwDCNiHMr{TYCtVc@kg43Yrii05lpqlk$Czr@)M{Ixl*J6$Up(Sbk|uit)gvmQhvfO_%H@2?-RqOP;4S`Rm?JkC#+^8nV6Go&pm z4cN~7V=(Vj260E2jIH|R^pA^Kt3%ghkH7BM)Hd^)z5IFaI^D86u6NiD(neeeDS#`Q&W5zsoxrw8f@(KJKS&zpnL6*43VAF%9(d1OgGbWJ1R$ zqp*1N=v)MMDW?Nd19B04I2Uw-PZh8n2q=$2a2ye{13M&8Qr_wtIMRnd%R*?XqofYU zTNXd>E_!tHVl)AhSjOw*w-2)Cu@qPuaIK50^xMbv?N;Hrs&GG@2r{?Dj|MfP3OC8$ z%mcc}AW{I@ldeD*zk)<8CEJ2u|KP*M&gsB{QfQB%pBe&WPhpkck$S`wu5Thy=I{IU zA#?=J?`(IrFaJgRYg4ZoPwrY)q9|IHN4wL8Duf@%%KSv~ArL~5+vIwr&;hD>`t7!}{A)Mt-)??a=TnMxWG?)I zjfwETy@=F;gE>z|7=Atch0fKtWC$ko&&L|aPmWMyO}-MQsd4A~+Ok!*rCJWFT@S8= z*Wp!UeZ3dAshU@!zI!S${~b`tFg(FF?U{d=oObUcjYLGD;&@F&`L`EhtWI(dzE?Ek z#H(In-dw(Bu!U*xbce>H+FLqbmZy39^H6El&flFJj;)o7sc7>p<{l+q&lkHK=`4Nx zTakOp;bCr#vwp@@)p?;|%j=%PWv0WYed)~|o4Im^vK(&beUj_HGRq98plpv^z1wJ& z55tipBZ7}~k3sfY$D_)Hd_AIf(&pMmML0P`j*N|+&4HqDb}!wFl=qi%KXOS6%A`Oc zoW(?QiFMi^Yqom2E<01(;@hKq{Ee#R@qQ&IZh#S2^v0&;bi|c1t#t~;-n^<=w!Mxe z>q(Z`&y2mv>$@6Jk@*qQB?itSl5nm3YVz_qvRu zlCDeEf%| zS6EE~zo93~;p)G)9=XW!Ob`1LX6Fmapg-PWZ^h%b%ci#;H|lh4BI%iPz*glb`tQA{ z$gbg)8_a*CCsy?Mb2-ozirj;L=50-j#dgb4giKWUXb}cFyt8w_Gj{8>evAz|X~ZB# zx-g5#CpJSl=I$ANq$QV(j32Ff`7etZ9E!EnmmPA26L=#Y9@wBiS=*))#>* zE@kxx1G3eb{;w!Qtj?>&kFDe58$1p^kD6tKiaKe#4Z!tggnQG6igXq}eDV8B*XGOM z96odgY-Nz*zMiAx;pS8#1QNvLMi<^Yc))G|C$n&jD?DxYGca{K`SJj67rWRs8F)Oy zEhpys&;eG6HQv@8G+D|xl;%hX5AvR{&7S4RG=DfmK{kIb*1YP;-BW0l5!RD7K*^#o z{2?9{BUJO`mU=xJqfp?;s~C)YIh@;nPeV`fk!LU`$E3e$do$AH{k6`;B>D2-^$aLmfu%=G(8Hd*~??${joI2Q|)SHu5YR)jA7#$ zHDu62&1tJCIF{^dwxr}p9W#2m_VE}Kyw}jIRa!&jvqlypDde+E!TY2@yM)JgFlYQ= znfEq2ou{fTqX^D=cQ(=I|8#MeldzL48@y@lXzAP96NLE`>yG3&qQWlf%9KB$!F+{p zI2>T-$FcZjt-eT{)BPP4iw{rHdmj5!hRzNL3m=!v;7qZ5&^ZS~*{G+WW~t?|B3Y%5 z*Q%5BMcI}eTG@)=)z$_-VNLYBkRyC0^3{nmE2+{`NoA)9Xaw4NSG=&t%Xey8>RCWd zt`F+q*YrRhn{tc;F>~{re}Exjq&WUy?rmd!Xl!ZqjRoYp$Hv`J6Ob?EO403v!zs1< zk`l4$Ig$xQluTKy?qkr5hBeQtE$9_@vZ=^#jvfT1Ua%NBXz0N;yT^Ea|6!fHJ&G%* zFY)tIUTKY)voIc&;BbJk1{kFt-G$y)c#a?}BttwvKWAA!h+VR%oq1*AhE4a|qL!?m zHkR7?a+$lP-jQ$Qz~qqgW`^%t zkpXevZj)V^MM?PGk@7kYq>;vOnHeGse;Dm|D3KZ@zgqjkVWCN_Lc-etNxUrVE93$ap)Q zYcNo?n(FS`Nx?i1SU>8M)ag%dVD&Gajv;%h?+E$CrmCSz@wn*98YhMF)REm~3rgkg zZ#KVXbTX<>fO&8-d3t(d0xCIAyZ+c!no+au^?p`>QPi*p?f~y+{du)|$bxrYCG*ud zrvmg5invkmz3~$|cZ3NvwXmmPt!w9sSEG8wdP!}}1~;^=xdkwQeE!O}a5U=;z(aF$icAFmXTP9PKIqJpM%gEE6qrXdPtxD;a-RK6Jb(^^=bO7s~bT3KRim3$mmDS7$%PJE#{%Ye7u{caSCxrzg_CNFMhDG3j^d6fjK2?*{jrT~mKf@5V09GK~E=SnH5xip{LnfM$R`e=RI!@;xA2%YIn;y_C`lKWo{j zsLi!DdcAJCNlO;e?bZ^_KPI%bSG0cD%i`rBGir-YY8-1(@3q7R+{K>eCVGP5II_Tf*8Spj5*NDh8K0eLpy3^ zScwp6*Y#{r0`lnwI0zRsbv%Rhv^O8krffCs^`f;^&tO8iAUZ^q$?Cv>rc?}bfG`1d zjLy23Bt(015J=p!V}t+C!HfSA{}OnC52Sz-*r7cF!VnP|N<&p;fLM1SfLLx4hF>|L z3fQHx-=1wwONE=gOVph#xl*+9H*S=K`@;<}&3;~^?r5@B zVBiXK!SCWP(ChglajSsYzX`S37i_X_*%ia?mfn}Lmmut`p|mY}XDxp|h-Lfqt5{uX zJ}B9{VF0zV!tM&WAUVg#tM5aR=y$TW;>O2b%39Mip8dWCf)F!Aw{Nf$S338E1Gf8~zaZ5JpL^l*^)2AA?0*D2COUu8p)b=av%JfFFayUchjCkS)e z@+XihwaxHlk;d+yFJiER?$-|USo@@F&-R?G`UkJm4uxu_Bm~rClh>rjYf0JoO?v;W zY2Ubh`vz03fGpP{QpqfSPY+g!&i%P;B`whj?OvkjckhE2V+Ymwc@?zlTcO@v5`r&l zxK$wnx1baxGG~^O`#;_)D29p~^wA?T@`i-444T&%8(byyoXkncr-nu=U){O%c0wSw zJ@sRn-C{t3C=EFX57lIHUwix$?L#m`;JF8)(L^3FvjIrlU zgVqLR^<^`U&0vP9=EVdPsTdYiKdJ}egC^O)- zxS&~3JDsO}DS60@eRTeCPPn#*OK}yVGTpQjn)je0`T~b`ByYfY?tom}QyB4adG~{^2DU};_$wo%w90w-KX2w8~uz4K=#Adk|DWIk2aZMo#zRQ!sQG>6%# z66~uu@sFWn<)(E`_4<&#$FCP;?-zS;rFuE*Q@nAc+m*sGLXvWcpaX(QCrEevu(VgM zuK8(P_|MyHOH7gyUR*F0-8B1fnzwvcR#Km99vo;}CG+*5(Aw>F*okU=0?2o$reiSj zBy!Gkq1yXv=}h=fDBE)$0+@#?!@U+R#@ZLtO2fjium$_o+wscu7Qsk95sn4nR)RqL z$lex|5O0h(uN7M!uWjnbq?__q-3c0T<26+q z(JJOF&DA_#5s=X9w~$lN{pwXZLQB$ftlqw4USy)FsZ6kd-f@|yS7+aIWf1cerHOi; z2_9G$io(-K8~B%xgTs=#(W&x{-Tp9(_@c5F$xC0@+NGdS_827$ZohNrC_zzv#3#{o zl7{UNzreb>w~Y^=Xf@bUkIgQ_m*LfYH{LX_RvX|>`!`{#C-q0?m?5@!cW=9SVQOV( z)ca#mDF;?%YTNxxrNIO7tR0y`cFWWyIEaw{ZAiLX=J+XmalQ#Grc)~#kYXc3WK#EU zLyD)L7+93UQOF0drumB6JavCu>!ZAMgv;(xn#GyZ>8@EV=}d3YtlJYwdkGDVh~#z- zFuvaN(HCdwNNuesMxxb+O8OV4@Y77tsov!B275m!djlae#Eu-}%~*7PxPW);^29p_ zn4HDXM2?+zmF4YWyzPA#T8~TKbQYnnvcfbw^Ov+2#E(C>aK|yJ{`!LU_?%wD8R%u- zaHsRG2&4_Rm(53C(*0Z$3}`=&(K5DCRt<;%SZF2_**DY6FnVVi4)tzFbLS?l)qjt2 zsZxhmeZn$kEzV@@mmNwJj9B4_CJIdyTA2kU+=LR*H{&%?=6)k1t=9%E?s8V6x=o4S6e}^6TUD@;qWZkq*kHR9i#qoiAiej&mTwDLX@OrVtS#+^U~S$ zAFsG^bT1u=yHJrt@;RNLcgo@`YD%kTc@=89`#IyD1KK(EzK8aEe#IYY!nq<8ToPSZ z$K2y`Iqg)U)e~ug?Qeo=_!c7D0sCgU5w1i2!)nKC8;^yPQA@9BA#^6`4?oLl8V~bG zJvqsh`3AEqN=~Y}TTwk}dcSsWZ)mU2#($%P+@?1c%qd z`Mu>)HTJ*SRzw_b^5 zk1ZYgZjjaS*gczTvo~IXvUkPwF{3!6hfaKkMyV*~m>lRBngd*YmsW8~-r{&W&hP{L zW@j090`J=n9y*_``u0hp+q(Upd?5#u*<7I&o5qn3ipZcZYjj1!*ZxW>MZ<<0ghyUL z0+VLUF)mlUCKVUs zitkLe`G`9y|Zv$(@SfX3{u)JINl9b z39+geR@E>RwqF}OmmzLh-=y6lf=Z<2u)>=5(zZ1gen^OwZ`3I+D|4>hjsi8)HRZ8a z0v9^L&TIQu(@VFfoh^lM#;47qOxT`yMBzMJFD#xnMYsboz}!f~G=C17dTv~gou??f zJOQf!8tE;rR{Ni=8&0Lka zPT1avHCaC>KSK6MEVYQlNKG zx&kw`Wm8GRn(I*nC&rF4rS(gw-YmM02$t{my?Pef!EgDN?Rn`l8(s3&34I`R7_ITs zpn|Arik^VUrBLK^mAF)~`D@)%zPS&k_7Sx>XKUv3a_mv*^!e^gZ5}_JGx5P>k$8u$O`_pyxREdvWCvH~+v95UY!9VT z>;*E`2gOe~Vjan^oIfC>liAt-Vbe_$yOv5Z0z#cS?bZ)prRo0qgd0cr4Y8$tKFDsL zw3~!waf++_{&^i5mmi*w`qKchq|{3KdUnk$RVs^FuhVS^zZ`JiLCQ)i;_h{a_&Be_ zn8lsoWrX-{{APGHob_v9{uLzIK=sKJY8H0s_H~dM8Mm)bD$8=T2xB*kahE0;y76Vh z*|hY1l1JG3OM<%6o<1I6|WKc{Xxva0sm!WCdh_y=^rcTO|*bH_N{1pl64~mL$JYwVH0hih-NEE9bb~62-dT63AZu9`HL$73P8- z8$Q%bF)UYQW`SYC_~;8*Z$>@rQ~cFG(~*rp=AJ?Q;bA#7M7;>zSpO54>Pa=b_NqQ;X)K1}!sb9C#bEKvw z4qQ+dcAk9QAOOFkiRzjtnnHn(r$JWjc@H#TB`^tJJt^DA)ell$rN0+-n*4BaS)9r# z5$rHC6?W7UB+>^~bF*yIcOhY~y<=OQ&qon;P2_fGc`5Gl5-+$80gNY0D-oTWlcRLY_!g*;ZUI)M zFEHm;>n~%6Dz&BGCuJnLof+PMM#|Ybj)vqvP4di?sj(e5fQ+vF*)xYzJWGyE;-8OC zJbz~Om+<;%v|Xr3(K#`c1?_qjQv75;ar`hMGU|`;wSiPF1z6KnjdZ534Yzwf=9&pX z*E75@P)LmQz^~P8_j5JDmt;eCzB2dLE@=$iOE2GoG0URplx%lP=|49jJ(VqPx+_Bj zcm>1ce-*y|{S`Ynr^2YEVLq(jB)#WUO(yh7ImnYsSvTUT9fx42;zYqI2%te(AW04R z?~$nRP5e*CSgn}cP^%K(w$1dkS52n}O1!~jg0#I4*7c3vk})%ddPD5{lqdxU=a6fuayUtIrFnN9&U<;} zKR^7%`c?4WQYzA@bio#wZ3yxcB|~vw(d#cIlQBR74}MAA7LbRMu&~)(u|$vg46VDbpi$%jD$upV9)EXHmlk8WSvbWnRZhYOGY4ZuOXTQ0~; zzwhrlQE{)Q8yo;VO-#@HH_AJ~vHls>SgFTnvkjh(s0+wobIOaNb-Qu<9FQR%M?YBc zI%l)x)_(sSbDq*tOA$>otlIWH+wHud5GLP}${2c(A}jW}@=`x6*|^ACEqsq&jS}kR zbiw#z>AC5Z0XFa){(QD_d3OF)d`^~zG`~B2wf%B$n$orRs(K*#!vRQ&&BKj}%Ez=& zo7Dx7r}%6?l)L{Su_;^p(h(*gz|9K$hCG}cii^}1f2t^XG(DqatMRd0v`fYu0(d4Ui%rK* ziPy);9^1`+5g2BI4*R^cgkJH5eXH4UpFAK#l$6U!-l_eonzARUD?t)KPinRqxDRMo zSp0jcOw%SZd6srHNskpB$(Mgr-#0P%AJ2W11CO9Hi-<%}atMTs1_uWpPd53SYoZ?A zAZJq$c8?&WY;F77k^^MT{@Oiw_zq+PPQYz;7TUFV%!j7{q9{%8S0iPsqOf%Y3h5(e zTWFlm1do^u2MRi6gv5ZiVNiO397v`t563IKl0=fD_kn)d3Yo zZhuCZ*W%KEMFZ4H%oAEM7Y%;zuQwtx(jIDS0tGDfNQZwnfuR3JHpspMG+O*W?32&l zQkCOad=P|HXhZDAW07H0R<23R34A5ca_l}V+oFwa}TXw|gMXm+gMI5Qn6^Pat!3l^~Kf)#RT574a(e6`!*7oTSR z0?n!3H)Q%2c5|0zKG^O;?5<5IS>ozFVjCl0a{vfgeWwMmOaOA@Vt`VTp|9?Sh|6y?b zm#@kHr(oUx;F?9*1Fw67)pjV&Yc`p|cO|n5q&Mfc0Tx$$)&#mSYF~twC(Er>K$(fG zJb_^xP@V%s(U4}x_EVN;!9?U#=H5>MQ4|Ttj9B5Vx^Pv7MStJ&U9ay-2?;M{DbN$5U=A4l1oh)T~`e&t+#h+CH#ONPz z4?tsgWWn4~ZNQ&nhrmi&S@BvJar*n3Y|`vuO>K@kUp*W6?MNoUOJD$xy?nE#Lo?>H zoVIB)aphp#IyUbD-r=M2J-QPBq~Q|tF0h4F?^g@aVwB8iic2ggF2KfhbZoLWzS_Lc z5HKIkkx-U6H6+%u8~w2pt3k6`s3CyQl)QUM&$4a<1p^hI&}V<6_$j^$*>!IbxdXfxC5onL{Kf3;C#>+5d75d zx;vKy9OAweM#z6*$oQ?fAAX^G| z&w=j4&}xE7i;2;eK?F%-F+X(Q|IjvooxblPk$_f43*U#q;&S=|&i6VtyZKw2s#kT3 zSy9S}4Qod3Q?+3V2i%J0RQRDq5z8-X{75>5tgjax$uqsWQMoDlvs>V zddfqE$HV6v6MJo1Q?b^u&ZF4scA5CXsnXe2_vM;Q`h_AabpC+m&{*$?!)d0$XHlfI zw5Z$nQJi>&=l=>(^zWsI{3J!JuyO~e_~HDvCQ^Vo-;L;g@)kxx=~_1@OA*q;UgpzN zl-R0L-L=S@Zo2@KXjJq#Vh8o^>07S?#?X*Tbq}qCIr}h*Q z_a@jJSipYJ_}9xLp5dOdeS{^M2#K3tJP{34zsop$Joo)Ch-Ep*F5D-^T3{!|Oc?R= zRIO5E57y9f^|pPp=xF?B)SFg3wlU#GrG?#V9^!GqGy5UQh7Co!Hejm>_rI@~DR!8u z$$G(nphhV_idZPRimutjxOE<>q`$333XpdWQsye07~i~MlOtZ{{FEtX`S;h$t6kgy z<=f|KsePg&*Ovj^*rdfOtmJ)Mf;lajf0gJ@QLf=J%jYO)Md`#Ue(8%9IUA)OH4A!& zHm%C9*6&IMr?CEwopKF|o86NU`DQ=^qA`ZA(Y4<4^y8>&xng}O2=lg7^Q8>O&u`~T zVvZa3!C+LL4o5}2WVAAa3zYhkGgRLlQE+v_ij>uVHtdV_-`9bw z!)49^N+Q#ISY5VugTRese(I>uuoL9SE6@_!PGztCadb_98skm~54;c~D@$#wlQr1r zRFV0+3)067-M}P_aMwxiewtZKfhF(mT)04&=36Qz3|E1ek+~b6*S3u9V$11C)ZWhI zSc`9tk7;n+-(BySwPp9D3uPhh+QwnN_?Hi@R8+a%!hWG{L3l*vt==eol}4e5mFB7> z*;YZbTh~L+`51*i8TbP#j zVo&ZqD#w7^i%@X;l>;fWl5P z%x8m?bJz<9NrPsAavJ6N6rA{|+WqBBA{)kF5Dp2_@wwSdHp*a(>YaKx>*izeF26N* zz|{Vr{HxKZH3rT9OFS!7sWs&Bm~ki(bTMBuQ#~m^G=7Z;4*6nrn~icf*|z1yp9k>q zVk&VzOaaeM7cjMY_v|shmezuZ80p$t+U6&--=cQodTww$;?lgUlH;gnxaDUH7mW**%HoZ%_ zI_D4YKmtu?K#!Z(HTb&}QL2S9>J5Jl;QVd{T40A^^u0WFL2>{iMhsxBVH;l&c+wMf5dU5}LsgU`NagB~hfsNm#8+nrEK%|Co&1$zsIS zZExS5^|{Ld{(S1_Wt-H_zX!-Ypp5fU**W4j zoCH5v{pu+l^zkFdWIFuqcUOValF|FB-0Er2hX=-L z4Z;PYbM@dl(Ub2h63`U#tcT?rJM=v-*O<{8WOUUxb~k+}qCk66eAxHRQLLU6&SRfk z&7BGdn;ga_In7F)xK1yeDaj(e>8(gUn3LC@FB!N!lnhXD&nrzU$?_R?u024Zz%C`N z$dPCg36y0m7Z173cOwY@nW^-JUcxPa!C9K5U?b=#$OBWnOvyELqcP%(E~S-qMmIbT zJ@lgb1ud(L(z})W-yS~+PO4y(GwUrLuJ3y4qYi)Jx?Tp2ebUjQq0S#)lHNxoC}?jX z^7^}DzlbU<^Bfpmrfv@%ZlSLaW;@#ffS9u_A z#lA&!1I|<;R({`6mE})-7c^Jl;4VwBa0t=?k{`K!5Z?-R-C;VID`%@lpGe4O@Kf-2$#9v6brXZT_Ug$;GnJvMOxc2EmADehWVV6MDJ+_S11qXJrK9ew$k7S?8BK%ub< zb78|0KqxbEHPN`T0*p+r{Q< zG3U4ztyaPAmlr;o5!c3dckBGYyOOWgM@u^X*p3*LOu<^C@}XQeI^7toyhmP+Py1p5 zS4>UIuH?sN@BahgKIMqXl+2tGD4$*9nH;E>a!~CuPDm1Wc`>^F^J;iLb@+ik2UFA- zlS43zK>OyYAB)%D=KOmg{l4NsUwu2{d_Qjp5Xlq9dt^s|EM9THyWVhqI`Zj`2$agq z1AcKwVE%Rdc{UP0ihgIv%c-oJz*#)nnv;>8M8;3tH$t6~MK;4mTn~(mAz<2Esx{sz zA*H89f1*`vtGN;({{3#w3M=D@w~b2(B3eY)IS#8-R}hv^HzS;Bl0w8W(8>CIU<(tw zeT#?o(qdtezo2H@M}u=Kj10^>U(D@(M?Jl*R=CA+h=nQ$otQzR&}A^fz^6~G;vc~D z9K}joPS*$_#iS_F5=8)bVv@w}T+Iq(xH9F&!PvcfSZiS(H90)`jPsCLL3=~HS(NFp zbv5N=c10_(ws*~Jg!b?LOo#6zSO+~jWJI|X<*NBrRz%#_WH?m#hnuh~Ka6_fek#pL z2lZ8%CxYMaI#Nz_pJG#XZP*`FH#m2L9B!i0Pw(lxEywLeQhA`&vdMvNJGYSFl*e&8cm>?q|r9rI(vpSgY+ zJsn%UrDzyDmfb)aC!SkK>)IrE;VB`GE=nP~-)wwj1&F}`;{1@98@ns zlpFs$T8hcUBZe<5xI_{Z2St*M=4JT%4*cQrM~^Z)FjhIda8q>hByQnLXlDstc6-_+^_~FQYs0b)B$W#=8(9sfJw`A#( zVET3W5~TB5+l7SWe@402|G+E#Pbeh&_m`bD-mUI-GV=Qu_5$~j5b|YL@tvU#Afy7` z13P%i=L8fFW&^o@QO&jsHVTCCwR0}YDUJacKd3}yrbie7NdL4|K+~l8)FE*VApBx{ zROT@kLPd!sf_ynnINZhru=RZH5evvVMoieaYVJ24&H4=iBfB!4JmgT??=V{}{M+$A zWif9^Ut2!=+SFqLD5-tg)?M0F;2vuY9sbnze_#g6`_c|Y4p#v~^MU|k*!LeZ1_(CF zeiMu&=Ea?mzmfbc;<&GjXJ5xb=0{VRVsgQog-%nkSZowu>ecM1i6w@}G00neh4Fr= zBAzj80x%XY@nYO`7!d_jV}6{SYm{m|`rtA|z~oew=N)I03hx)G_SzFDQ|=Sa*aQ4U z@3dVkzy>UgBUkdEZ&U(7$dOUx_KiQJ_#M*aQ7Mj7s$XbJ26?U+cRDv07PN`BT(=bXI9k?3|yXo#|{wlrog$E{o2qKE=vS)LbyYaEo%rKrn+YE## zi07VP)FS2v9EYhywkFHSTlKzlAY?CbbT8!m6aXas*M@I$C7iT#$iN9>;azImqxWm5 zMeeaDU$&eCL?m$${Ki+S2)W&U#aN2gWIlPTmB1#L9E+xcD70^qSdI9Mrpb!X< zLDp7tlwWVYra`)W_|x;0SPBLZ{EG%U7qLJwwCi? zv$*T)8=+IycA{H+!|F#a!XReDS7m~IJ91}&!QAL)1Ma@O;C=(2!D79?uEJuyzv$Sc z6+P&$zk7|$KXmUn)dlr5L&P9QXWJ=j2{|wY_h{P3yf$K~ zrq2(sZpqwEFV&2h%ZgD;u4dxtpmS5}1|fzHf@X&j(QN%io@3R8Yl?-)8xB=N4dxr|vj7D0vf;+h zw80k8qJ=>OQ_z>sV4>fAxHWp`TM#vq(zwO;B-om6{9JvL1>$-_M*4lq=dFyw3vwt* z?xeHR*+VH!l1J|zpH7-ReXmO=S7$15^l_l*5|rn$hi0>LcVD(pcGL0ubsVgS(z$3J zt+|ZAYcmp70B0Jc;{|Mj#_vnu0D)&Ck0y-hSa`%3eZGxV3QlHDfsy~vl(ePtSWA2g~Oav2OGf0tk*8t4glz$tCS^BfWwk}2et#72 z^2!@255C){nI-(t;#87~wcSI)Tp9Wx#O_l;lDcEi-_n++k>dA z;)kfoWY~QBf`|eZRN2K(gb%rNt(Bfh+JT~ZBCLUp7W zhP)8!ANAF(DOSG;CEcZ%;Xdjwr|p#l3t7Z3^CDt|%^udJtvXE7_J{+$KoT$kMfSZY zPO!7DefK>Q^_6N2c7CiYlY)L$zmY1AX)`@d0f$f2-ZpArHPF+_B>8tl_MiFc)gSLY zs8eg8JQ|W8cjUq~o9uY6;CnR+<&+&lDjFBM)VUYak&;)^_DFgWo?O=v1$!y=?_jK~ z#UcAnQR=|Z@wK-H9^F})mL#=|UbwU~=gnmb$S^ET=HZ<{ask){NNAD(flWQft?i6X zRjXJ#YB#t!YbQF$_0(@i8LxpY;P4uWa_|V0>QEQWTC(Qpyf;7awFFbNxsgyfJkoL# z_asy|TBmX?_*1RgakEZvdV%Ljj>Y#%h=RuyWHSzZuoHK}3o$>?TBnMae`fDr-CZSLayR-?d9XktFW|Qb%E_3X; z?C7+zstV*NW~!Rit?e;F%@7OWG5@pSI#Ip>Z@?uyo|w5JH!Y* zpu68s^^(=)1C4FHC5s?YTCLCiz;{o|>=riH+O@{W*ElHl(QgkUazb8Igxe^n;Gb#n z)U1rGHpl2=+SkA&{q4SByXUmml?Tord4FEc`T5ra`PJ2ugN{5{ddKb2J=@wqV9SA! z{4=-Rt#d%;96hu!xT`A?s+x9YPEIK4`^HS_>&t3!59FN>)RdevnJcm_ITLJk(OHJ_ z{P^$dWbARu=|VGOt=K~N=^hp9W9R<|q-kdCb)_a3VpY`{{`9ekgm$|>^~f!v!A#yx zAuB4_&_xQ2?ZtdbX^VTy&5OwZSRzZ>pgsKH|_T-YV#wNwXyK!h!O9JGoK$v zJ&hOH6}Oi??SI_N+)d2P%GY_Uuty7ZHK(y+3B-E4&tKA+OhhK|Za;2kRM-Rp$Fequ zu9W|}JY3(wne#h#$?6*QGi_S?p1E@aO#6iW)1q10SKVvo595E_VRmP%LJiu*d!6z59=gzm8e_jfgse`Uepu z)&Wk_`Jq#n&2MGy8MbbHe$#8#SxD+brbaG_WUF}T?djBg+BF9Dl{MJoj=6s{B?w)M zeQ0M^?c`@%CEvmVU1bJeooF_6uFH03qR7d#{Y5XE2F^aO^r`yby+4fxe&gP<+e2lh z4=R-zxP>@-^;sZ60F;#8kZN1*N9NY6?UV!MnAblkmisu&Z3)YlPmShSY)}{6~29@jb=aplT$s?Fa zgFq`BJTG14d^`wPo;d52(ywFn-29+?S+Jj2t4)BkvI%(mBbfQ0mBIGgEl8FrFEnIX(k9OP>iW9@aCWXS$iNwcy=dbh#ZL%VaFiq3-3 z)R2e{90i{3wLO-{<7FOc2Agz=Sb^k-K<#F*x$Yo-pdrP(f5;13nmr~fBxN^r1q^LX zOt{`0nFtkCUzOrlq}Lz(s=!O;ecqjj_*H%+M=II(#DOEX!Knpm&IhL3qy!~*i}SFC z7->i#jQW>7y>3)QNa}_TB64kHW>C`B_>~JV!OnBI2ajBRdA1*fbyCYNIZ7N>dYFD* z$gcOA(%p_pi&hUF&}SG4L2TbMN$@l4%FgH=f2n5PM~OFXO@u`%|?S zVz7cbv;OVxiWADT%kwdB4{gMKkb0Ze{cAMmjCI!Gj>I?hu&|1P^x3#0=0f+?ie!ObDX$W+ax)VKF0^^>{dC}pfPkU7TKKvC$ZhI zRModP(?)=?s#zQU=P@l!-y=F+IbxlJ!Q;NiCRAhd`9tNV8KxVbZNp*$K&!kdxwL5~ zIlS#%q~oqcP&}b%s_@C&;*WcSZ;7UEn>F2^e^H)@fSF9*wUCFYDMO%rIpAg*AX4dMe93P25* ziSQd`1#uuQNz(S4%cc~F8#qj~w>5Fx9Dn0=^>0uTIIs%4&Ig;xe*+aP6(U}*<3gDf z9j#!|{j_G*@fbQd1q1|>%r3mN6cnxFJiFKac@A_NV4m9GO=qu9rh=G-Ta6(1ydK0Y zc+G)+?H{DnmZZ%e_www%;rVMuPKM7xz(QYfZ~HwWD1PuSpoF0>36zvc+N<=kVgY;4 z7OcCB&VxhZO7%c-mTs^o;Q>apbH}tIE(dO3AOM1iF7O&pidB@j(uMcm$A&Cm+mha_ z8ux)&g=6p5DFZf$Z*0n|g35ghl-?~6OyZlRv2Z$Wxs(TjN)k`68t3Xh`&R{Q6-1Mi zgM9zjU}3*hSYh2R5|sH!oVIBTFKm-L)eo{T@3$wOPbh{2>f8g7LB|zALU1LxUuE@r zn`~|g&MTRJNlXh~UpzB69>qC8Fx#0(vN6)g5BxaypLw*at@*o5!bx%ziBj`T6OkQiRFo;{T*!v{k$*EiG+~SlP_g z$&gaH^b|zN?pBY9n?ha%MTCA1+zC4jmVH*XZqsofdag@SzckIpurfPbBPP!K;{jcX zm4JSSrfcVm4>U=FT0`zz8c_F*6Tj~(Iiqn~5_tA2WS{DZnBvLMr->p5mL&VY$q?UN z4)$eDsFqpAFE1L;BpmW8iqh&%aQm4CT3~ne2cJ8?ffH9`AMgBM6+Zee`}O~rq|$$` z{J*V6^`E8t&(i%rQRn`@a)SQHBmF13`rpy?`|n=VOkLvx@p|!Cq%j1``=#;q3~S|7 zAIFtc1qDj5f>gyi6yqlFG*tFzirgGulYYQ5W!z5S4qdneO6U-n%}izrod^M4l1!&=F4hD18SU5;_%_>>5rA zrePrdgdR903qj*}(7fq)WrEuKm?*)99r_+As+1opw>BKJ~F(}1nSfD@8WGtuQ1l1gUzI$rf{-aJ>U1e!w zf?@|mx3D?itO}DcK_7pH=en>XaQai%VZ}9N1LK}o#dz8+csoRK5Y(D?4d#r*GEB*- zgtjHj#T#C2O>d^9L@nyV1@APnss%N5B`Bmd55o=Tq29Bp&5>;}n!ILG2u=s}9Rr)` zLtmyvBryr|x>YO~NgFG$pES(DOmV~cTX$RsG(mw*(;Yb&qhAJ49jI^`MmxE3?%6zK zcv?Rgfn|tlKX}ZLwnvPV9#IXhbg|`$4%2K%aZc<9RYch^4?RM{7yhLkJa?2kQZW{H zImcATsd+@u;Yb+H#lQgZqWLFfF+ZGGXm#BnqbJh9chq6_3|SFjRBp{1!rbI(uhOZj z9gg%k3?SEfD6HR7zNf-3U^v336^&nDAg!tQX@0tl;oNaiHqzU$-;TOaFTTi#`RAi| z@WAg2MMVL~x2*zNfjuPC{f}n8%Pu0TDzeX&rpF{Q{|0*Jr?djUCD7(oi(-PRiHcY= zF~#go1#}$&ADty$Sl5$D^NtE&FJX8WYnyxU$&o9e5z48qWrA3L!#c)fC|uDPJDSqg zI_@#!Ipk;Tn-A}COl{~{YQjN2n&_9*VKrwwhyA{Rn-w08{rJ&@QpX};CJ*5eYL1FQ zd=A8YA&W_8v%nRnDps4i&u|ruQ%Z=g5ya34bQm%@*Bx!wv&Sf9n%WqxuB+&|Gl3g- zm9(oh`kJnWGmfBejzK$taHghRZx+YtK}~0a77(;<1|6>04u#Bq#2yEMuRs|?HY`0) zyrXHed!(_q0+<~ox-r@g=ced$kf&4f#542wbIbTDQ>Osb&>O#z{)(9t*X|0WVkkWM zWcev=hQZb{B4v+JfyK}ka9fm6LXB?%a2B@Ai-xg>VIolrx;Ie)w51`c8_K`*;_YGC z%GO7%cEWkV4IvTjg2#)fo$)#T_(faf9JW+>ubwOBA zFOJLOwf-Viz-zt6u*_`pN1nBm$N(r1K?~-KYtC?qu#apyQhw{x&@dMwP>v=KN{1Bo z(lXJA^3PvRlVuV*#P&FS(8+Hki?LxkX~qNA9Uh~I2~8%nM>bMM+H3`z*N=Twh7n&3 z>>sJ=4{n|*edOo+ZDs}$6$ErpI9|gs*2^-CWkudmtYD^-4dHHV(8BmLL40C&Lli$% zp!64WC2p*l>%yDqtM{wauxiQx^c`60&Nnr$X|!bJ*t`dawDO|r6H9%{+rByT-{Qx( zlO=oHFnDwc#i&2GvUz;k?ywUomGco{npGKS#GYy7D>T(&rm9lIkz>_8;zpM6=G>TO zglba&f!l_M!BfRZA;}>oL=Sect*4)%bcuVLM~{x!tKrSfA3W_}#(Nfmn^*J_y0@HD z8Q(X`{}2_$i`n{`*gVVp5)5snO<=DIt*ch){GH!PC5@|BMH*XA0ps&St&j$*ji^aq z@3Vug_pt+Ii`T{~%kB(?0cUeAd>*`R-~B>4xreiGGV70<;Yb|xfqJ=APAi~&7cD$iRKIX713`N7Q?%#O%i29eng=A1$ zm|MoTHoJJ;+i-@Byj1CC*??h|&$Z-YNUM>E;eDuPeKEN(c#{ToiVLekno*`)Pgwl$ z8k)JBwL)1ds91OlnhFe3z%|{vzdB%YgNuj}%XM!qLsn?fLlh?GaI{KC8k-)1qi~9% z;iHrrbOIyNxxcTz%o?0>9bSf-eu~AN=W6|#5k-v_WX9s2 zoRA-`?%BKG2E>J5@%f1|v_>$vlW^u-P%qTPv{8?x|2v9Y=*Wz=Q??J%%Zf;5Zz}gXd5Rguz`1;?MY(_aHqMar&EX=c$Cht(^6RO>ZZ#XIceqH-VC# zQZ^I#^zu+_6HV}ZlyIGOh-5zH4(uq=6N}pM)4j2%d2?_;I&@uMrDRAemO<~-T&QCz z;^zlu?hb|JXinEL{o3NoD`}_$om!N<(9j6b_gYcKoAOrZ?T`-ywWd8N<9Vvru&_T6 zs%`i%)fJW1UA~l)S{)6)38YPO(Jb2~L=Zoy0U=;v61Y5nsiLOP{0Tv5H=3jJ?qFV1^Lpgvi*y`|_{ zP_q!IXt?yxqanN(xdOja$((UUWEHEUJs5w9MHp;c^BHAXQc?UsDo_t^5#;`3Y&3rM z5WWc&c*?k42l?_E0gX=ytZi>rkvy6sNo>T|X0t6u+1sC5Y>IEXoB`J@k_x>1>E(5R z3anxUHyl<(w5*H%np^Uq_T3u6ZC)Tunu>|;huU1i8J5jObncD59$Wj?SPj?B%e~>q zX|AlQ!3#PVr2W({c2P5Ah@JJ5zV0X_Ax97pxxnzdPF~Y^SHZF4U#JTx-!K_ygpmoBkb8^S zyI6jB&1%5TcA3knMbFVv?N~DyP5?U$dlLxGgh{o_pY*v!8U->Lb@ zC9YPMPfQ<|uDYVL$yKC;1XQvQIXyOK_qhwkRv)#r`jd8B&wZLD7Bo0OzUOFta~Me- zmo4HJLC3Rv&pi!6KUf`98vfQ*J2_CglI5&|zYg#qxe)-<+ zkud8N0cdaSa4HIm`@VIE6;5&$aRqg$Q@^Oi?tpbqQ$~YxmR8nP$r0)R6}a`)UlZWO zC6u)L0e*`H)xfq@#bB%!IoK7M z&mh*~6|7lwMpV(aECzdU)4htYa23hXCkXn;&)JCMyEsjAH(wXA5(GVHZ0lP*zJu?> zyJdBfRyj^@!?pI8t+=3wLmc!s_fWu@Qwku52@7O)I_-+jdeamaZMyKUJ=i_XhMAhr|(}KZ!cpO2w`Fy`E z-|q57e1aQ8hRE?aSRcivx4JS-g5rx%Pl=S{S>%W@mz3%IdLJ%)zxV z-*5WSHTQH6axl~bmt5BtXD@rV#jlt;TJ{8+)G zatlfAp*-TWt?#UyorruF#hvb#o;YDg~E1{3YvU7Y> zNx?TWV;oorLktGV(4YYZr#5k49rDLQVuV@2e0@dM_XaSh(|oxVnvlJ20(>5(01XHb zvvIg_@>FbPfZwN5lX`#TMj5j)5}tb9w0R>`3se85Z~1L)>nO-8+OVb&9$~~EwPL(l zO(D*t->4s6uibO)&UlL}6Kx3xzUKyK@{E$;y2x8~p(bgOf*QJPC>+2hzfJMzKAkZC z{H<-tf-HV76=>Y@7Nji)r4RQs0YA$51{wd>xYWS4O7|2Pqotvgq9y4BkxnF3pD$*L zUPnF&+x^F6%-5QNU(r~4qEPoyu5b2ciFh*rEXacS@?Fv<{FOl% zFPn6edGjab@Ic{y>RO_$>ES)7AKhXieoZ+k(vwOa$i5<0cHhAStvf)+tv9>9}n{DY_86{CC#7;(LA?d zO@Grwn7K&MWQR7IxQ{iLQA_Z)*1YS`d$d+YkB)p4KP=R!bFE>H<xUMwdpjtds7Vy%J^u(JXi6XJ{9dA9fM9 zq1v3kS=Dk`OaE#oiCaG-c5>fy=X|VG+Hn8Ts=79HLM9U0#rdk>8wOXEilP#c$5! zdhNV-OhJ04PE_NX-pw+fOket*~uEwWX_!>bxGc#qV z>M`wN`=MwAn-DHcmwtl2e5GVOu9JQS>R#BvqYnMT9=y)*ce#PZs+6|p$5tssq3p{h=qXH}NR$qu+<2iB?4&i}-%JiE z{4^~moGT>YxQ1L#$(-49xhFtEEgX9}r(2KetHAoeeo*i+)L5PguDWUu8v?BZJ_qs9 z)+W!jrd}sMXN$YRdEd>k+e(pGd_Sdn&Ud}q9->V?g1+c;rS!?}8USA=lPE}0w2W0@ zdFqJjzl)IB zy5yr_yvKO%rky-Gb(Q?PW7e3-5t;y&D0=T9Ou9nPrF{>O9ucL zMo|kKDA|2svyNa|O?5@RtE(dbNsoVY9_Qp3)+_{v7FH4Ejh*LdK8C4$l$KbuUOF?C ziDG|SBg9p+&{NHpCyWZ&sF8+Ne{A143-dXJLFF;L|EL3%V}e1iS>3ahoRZ;+C#e7f zU;4$Anrq}pXOe?WTC5P*Qao>0?m(^klc_hjm5pfM6V+K9ePl{H4_Z*|`wHuP5$0;} zaoY0)l?)q)ffGc{3=t*f#0i`3dVmiKFe-?hr5O?_FcnOr0)6V zyZ}R@zJTKGBn-j2dpIQK%Zzg&3FtVxKA{g*Mq6_hSWp+DeqQwe&1bZkyO!fl#qedq zz?(0Wk)-Sa86aOmHQ{_MUS(%2s(_4 z@@)qmvqsk)tUJq?5__|v1col$QfU9jNghvcy$x%|9BMY2}yumNh>(X(nui#tEh8qmN_DSD%i3zprpBO9MrF^3m`$QNrhDTmbp3xv1 z29jaj0{uHcpaU$oL!4Op5vfMCN7nMPDpBXuOC2_*Z!h8+Tk(t~1!UV=ZJXd5BjS*; z;LA&OGOUEWa?Qk<9XtwbG8*>aE19&41?PxgeEKejW>R!aRrd{?9v7Xl9PRId)y(a` zimelHf`Bjv+JY45j0PCOc6{Amz+w6Ju$+E-04#E#JNrMse6-?fQm`yjUFWxWi1e=E z@2bws)}u8KHs(wPBHIMQL<`aqS<#Oqwb#iH#VAzf^Ug%Nk(sps&hSC|{0|IZf<00i zEA#Trrd+eW!oQ?1EV5n14s_Blv6IRLKODz87;%=QZH_EIijj7oYBBKIfzza5=w$na z5uBsB$_5FTu=6|gylvt;qb(nsvQ3#@vCa3u3k^bYyCHWYiQgXc^=!)O<)Q`R{) z%#E|B8Pp(3P_M`k-YX0SHOJbifI z(FE~bStpy__@}NUcay?QE%T{AXa=X3TY5N75qy1lPj*8YG9VH$#CZz`m`u5E%|q+> z3QbxFimm;x@=7>g@hTO#KEEmd#{(SAo!~K=Dci2+1S4?uz-k81S<~njl1`{2FYKr$ z`YC+YP)Ou-?p6ia1OeZ&GX>@PCc0dZjw5tJ4@7}Hw2~D!jlK?|Ej|@p+Lm{br5gqIEVCr9M=spILR0`z9o-okG*BXD^DX~_&xyUJF9$orkE&R`$S$!~EpKE_ zq-%1C*A1t7(-$_G>4F7%dC2#r^a7OLHX*sUO2+LAjC6N?PtUg7&N;0}@z<+kOndHf z;Zc=4bE$&QFO?HsCA!AkUn_+;bt!eroOoPt(I^UyvfOyn}Isu8zYBw#d zrA4wfd?Gg=jidHMHZMMYRv#G5LMqbh7d~xfvcIRP@gHo^NS(IjtG%S%DF#bGXB*@+ zPA1+1&vRBoa)F#|AyC*kxDzUP`3@v`5V0rH+tXYoJm^VdegW9 ztNMlZ#SAs5fY)jl#4I2i`K&!y`tA6X9)A+ zVueu6`}|JSFMixgtDjRAFb!K5f67*^sz9$RlD>Ut#wsGi(NOi?!OVFz{x4M9O>gW8 z>#qDBkBPSck_Bu(E7b)^ETJscDREI#`8VRP0a^kmi!+W`6{OyRufEKFSuvi1-v{B- zs_8Zs+X3d(zQ9>9^$$E^(br`Q*dShsNR?}-&T63!mkI;!gxylGp>soK<~q8Gu8+G} zw)X7zQ!ipZp1eL9*q9F=O1!yoPf&6TQ%u=-e-ac?kG`?mCq9Gfk>O8IB$ciYs`;W7 zTaJ|?P(u&pYET1O#d{CFF{rQmq~Hb%5TV$-$bK^`zVtX>4L3!Y1H!5_ z9(C*6N}L+s=om*Gp5cdFDc6ciuvL#sQlyvGswd4$pFE=U*zCZBvUxAKOJJF(nDTI5 zp8l$!^E$Gx#^12g`OuS% zQJQAU;@|r%>1Q4lJudj6KO?DhMMC9@-N_%hs&~D7e3~|VNBl!ICS+-E>JK*U$6MXT zRi_NDzCPTruzSCxl=Z9Pk}=uL9i43_@~a5EEL=|fwRD6!# zx4Z^nIKJvesSq~HW8=LV{41mFx$AO%%2z-ndTj3cE`NHuQIy#j=B<<8Yicp~H;17s z#%rD9#*$F;ikOLQC0W}@M=n`?swjd|Pf!l(N>1%-kWdkf1l6x6WXUK=-IDkqeTBU7 zSmlT*uY?Y*6QO8FIy3?M-nsgW>TDah%Wh)X%oPHFlbQMIllaHL(F^8|I-%SNf;&7) zwqqhoK*!mPajk`Vsm1-h2bzMi0FD~JN0yg+WP8oC;u#rpRD3pWwU$7Ids8p}VQBs< zU(F==)V5Q?!iq4QyfVu=@t4f`J{-8~@qimJj&)`R$e z8FT9{txXRUc&%G?Jr!1dj(a6!CBJ>hp0XR`6CvM3CAHlqgNa9l?*7`CaY8_X!ml)= z^faEX2UX{J9(!+Y70rDHxgz9O>_f^fwl(i{ca4qDD}t()nwtCXF<4JQjmhf%o^nsS z6EiLQRV&tFJSxPzDZ65z{?j|x-TOU9Tf7V|ZC+u84egCy9^FWelcVb(-<~$U^?Zi# zGs866k^Io7{XuRodE~09_R?3^=;qVy zziic6)L6;=>g^Q<@%@FY4RFb*ba$Hikll`@+#Y7c7~<$(7NLjk=iTiGj7 zi4h;@x}3Z-Nz->P&*{FC+=jY)I_=Rmp}uH@Sg+NP+~#yS*UX%hcTz&-qHb{F zUAuwwN*Sdu39{7FX~sfdlVx__V#Jc=(w_+q)gPX|sK!$etA6F}E5#lo{1P*+7qJ%G z_Wi-(OG5Ssb%iB1m!{@sb&69!e7(v9>ZFg~GKm-LvzD)F(}SGoG`C-; z6oK^nCx^8~Eh7o;OT^{QcMFB?IOOuH-IV+agG2YGIc4C?uwsU?@iw8AA|KM8ZyTtZ z*m!4H#$dCcn6^@^H}M`eH(SOhbbc#BGiR?dKg8ZPk!`eFrYLsJc z2h~tvX@dpmkdrqpx(DHwen$d$Jv*5nU&q~c+_CMxf0CAMbKhT6A24tCOCG({dr5~C zAG806;meqn&YowrnR?@a+7^VwAg6I7pw+p08`EO-*|jL4cc(0_Cc`ezy{}%~0Y&dj z_#*+~;FO43?jCmq+ScrflP&;bJhd%;`rzA~xD zbD${sao>Z*`5Z3*%6gyhecz+v!Qjc5BI?UlIaR`eq9d6J`y>e4KoloTkTz9_%Dp?CM^#n11kw{L^5YA=-#f%6 zs4AQWSvmKk*B4-YdgiA<9${XF?!NkQ6T!JFS_YB4^xwQ!T*u;`*dEP(h2)esBAr?H z2K-S=jCrK^(d=rG{WS=c*E>`uu9eoiBi`uyu|0McUb}TWcCX0@5313qmFU|N@h!9? z&w?&O(LaCNiU?^N-5n`$QLbWdt`sly=SCMWGLCEe|4Ey-!u<)HTSXS<$+Mxuv7W?i(G=L|JAJE?*j!vz-6rqTFCc z#e94+!T8$J>QmJ@ok@I}eFeuMp`XWL(_L%$9OA{Jvy(r|YvKMW=#xsOn*ld>I1J!6 z5BQSTj7{A|d+ybzC&~ujf8|S+X zDb+G~6{+dmwE&f!T+2-;*C+F&j^Jd(<)iQgwQnV(I8AG7(vwbg!Po3_@Fw3zQRT^( zz7nspl5IVrcmVo`sBdT1Z~PiX9OuS)69@C5P>&*A6WqqesmN&WXsDf=+dG@0i^5C~ z=ikD9>zlqfX}UXs=b+sX^SX(TU_(#Z*&=O`BcoV|Ygzy=_ST zZ2Q~={rH8;BTEIp`5!;%X}q{2Kaue3p&d|eb5qYuoJ7LOG97I#_9OmKQfJnOGn1<& zV-70;%$^FV7p-=;QvwjXjh6BjTUC55b*Vdp?WymDbCa^O2hrVeap-QDlZU~)Wwuza z`vLo_&Uw4@P*R2O>J#!lP=qtYk(BS7ew*k@JE&_IzU1%u;n(O+p>xh|W#3I+KuIuo9)3P@WOHh^}wekAHpfG=RVTHo|aLMxv90m4k7h)faag*Sg&r z@_cGjYy9MIR6)7v_T8y*`*E|VY4fouRIWyFW&Y~S&LPJ5rqk&r7(VFX|FcL)MV~ue zUjJe}-5>+Qv#XE(vphD8-!lWea*T(Ic+Ms=9J?peRJOMlyc^t}*ZkPieu{AYW%4InoTM1pil<^~-pLOR*?+a_E ze%UMgZl=UXMqP7PTaGs2Z8Uj#C>f|W^po+w(JdRlyYMMumCKzv+B^E<#fP}H=SXbe z34Gm2N&RzQyYuXR0LWm3oohBq*0EFGQa0IM?fRyW0DnivD1UsM`A2&Wfz|MSn^JN* z`Rh#BT&s1}4{}s7L?3C&eeKl3!=LjTqo!96e!Nl-1xQuRoSprADEn*QJm^dZ>Otu2 zl?Gnf_!o7xHA(S)_IdoOm}}~xGBBw%5ZAi$_s65y+gh)wDrNz4zobz?(TV=1*rG&tSrTV*l&1;&tws zed=L)d%H0AESsMITSDn40m%W%C~xC5>Vce~@GQz)?q$bD=98VPKu?HGgMv%qyktkg zZHJJuffxOTs%iGSl|E*~F7g1JmG9U>?V#a2{^RMM?~kd|J+F8se{mG4FO)U1T2V#* zb7@Tcbk?9Qmo32vaJBLrtD@g$wP%1_SOroY0^YfQw<3wN(O)2uQTev61Z#dTWyrEJ zDPDS})$cskSw1#iLZ4UJ5ZF-SHbvqk#tl2e4J9pBTAxQwZ)|&Kt%#{$>CXqP(LDb> z4_=kpeWMeQPj8Yj+GZ!5F|FU4Ke4ON=6x}x`%f?=!1*dkV;23Mbs8j*cZrY2Z+B^lY*((isocv1?ewK(M$55F?TebEv_1duQxVpttX$++y;Z(mVbPzyGUGC zj}OQ!zh$rt`lEr6?RmVb!?ij@z($o#WuO1AUvZZEUv$pA4kYFEp1kyDKt=1nWC*@2 z(>KUDyVG_0>o^~y{niq!r`jvBp=RjOXGj$BV!vA%c#%2=rT_8L3_eVPh>9R#2#iX8YPTvtSsu?A&~*<4H2V0jS<~oAN=Y88N$w3YsCJh z$WoATwyo^NuE|Y~%d>ljwd>b-s3A%myi)yyblJenHgDb5%&CuDr@Y5eA-P(^H zOyRQihvJ_oyU-7L^wCvq{V92x9x)Mdg@@? zRaN=b2nj7(Pl4+|6kGp=Y3|vDH!|rRxM$~8@LqT$Ex*;@Cs%#*;x*=eZ^xJuH<@`E zIcf%93hEz!{ZF}j4vrq>Pw2}nnS7%zbpt&EDdR8C zyG%lwkjjbge&~p#vcN8>-FaMf?teQDq>jwZ zahNOydjY=X8?nPU66eJ;(8jz+3TANNSjSFHgvSUx{Q0ozEgdg}emNvEY#>2dS@-@I zS)HE4X2=Z5g^Zr!jugM}CtpM%)yvZh^$aw;KTPt<%0SodVqRSFjAzyB{_$QyoEyE6fb=BnM~tN#}@v0y{~S?Hu;Se z;f0=RlhE#j5)a7ghL`LB^BE`izQys|N_Tw%=Sx&|lm*`=7%K?#ZV(F}71TFYNCXY= zfh)ftvg~S1Jjk#QUMMi=A-4i4CgXi%{|?97!E4F_X6Il6^BGEZ3&%~$@t3F8YKb%cmszTZ|- z2D}NSQtY_6q8GFN*bBx$^er&LB{Qb>7WUSvvj(;7^YdA8%rt)jGkXFhKgw{ z3dG<2fDk zD|dynbL$oDTAd0Gspo~|?9smD84oqFX))-_K6Eg^*@r|I6-4vk!17$h7kVCk?s?>z zK-{1p0=^7y&xWSNy}mfK#oLM>&@(djYm4Kn8O$(c)YP=Euj@CY2!g>&lK(ASg!IN* zH6qo-qWH@^F{Ph$E_7gRdbxz8$dL_G?uxmHtXcL9(0PDFlST)mEp(&U4ej7@_2@44 zU`-6|tG)X^Pb*6M=h?V`#E0s^py~bnFe>TlJIKj#1axq=6F))pxk`+N(565@I<0P# z$AwPDX@h7xk;Lh+Z~d!bv_X7bM5=w@*oUJj542oTxZgbM?OBPx#?UJ&az7Oga|biZ zYvjX9F4WH&)VH79UfBIm!O^OqsN%n3+54-r^5g&Nx%YMbrCofv_FVZ=iM_C z757ZMl{Aj31XRP&pQ}s%6`R;;2tr-FMJFMdrUiA02z&ZgXj{Za)Ja{QMxbi-T;S~Y zqOe$8>_pOP8mJT z?QwC-w@*{lq#>vXXh9giX%QKryJ;w;&Ufbk?B1I&GoLA}V;U`Srf_945T^xQYuR}_ z)3z3|hKOO|5@PuMcOG!I>$?|M18k!v2BsDFYWUrV`^gxHeu~_09k&fZ9MW-=z>jjdHa1ewRRZ_l0S~1-|SoPh{m{EgCDk+ClNP z|L#up;YQgnaaw;$3=Di27VwuAQBo>6HD0 zgHFl$44{t^gYb;vVTU5&o%U8yA8!9xEoxJZ79)OGc!mM4Af!TNzNl#W=I^JN=WNSe zJ|?AopKFg9z!OuwaS3~kh1>;sbr0J%Of;un{){|u5l3WY5&u=6bZl_o`47vr3hLmm z@EU;&eC6!zw7tR)YZu_45s4LvN5+Gh;A@`k4fm{TIXh4IB6)j1VI4#L&lLCX$44~!%iK$OA^Jr(yPszL$!qAiEG77i54<3E8oc3}Obe1nIlCXl_dd$PPv!*LzU0;wVWNLr2qy#xvI@LTz5 z>&q>&xX3=6k7Vh3Wd<5rjERmc{!+)2wh8qIs}g)v?JS4n13%*2XyXSM(l+pbmd$uT z#jS?_4A|VHcUblg<%JHM)?|o8k3e=8i6;y9i;jTHe|aBd8hbt7kvhulO~-1wHQ(ZU znr&-seNqRXCOO2RDr*Yan-mdJ(#rYfw6S zIf_KWAA^P_WYf)xH%_Xd#tNATe8z^9_^UPqVlZV3P2Oe{g?486Xbw+!9qePPu`ONs zBKdV552Eq!R`v?{N?aLri*$ywQS`zDA73w&78zqZkpV-O)bu>)E{DvdK%hANRDjV# z=icgPk*xKy%!!$)??9#Bg4|@DhdIhuSGTBR)5``S$TILp^Y+5~wRWN3wnO9MQ(yhL zN*@Yo9joRxzBV20rso-R$dV=?6Q83=Kk!>G;F@ zP7beaMDEjYe~^T!UZ#Xnm+OnbGHUAaUk70!q572SrkieH4c5!bae4$3PcU@)fqS%7 zV$n?sq?g1cwu;C+r(3MU$_s%&blJO+Cdp>RAAdeWe3dkjs4kxsUxYk_SW6z+wQIi~ zv$>v@B}ifS{$#A+`)-F;XQt)f+{|xSF%@?3j%Excf0|eTNOtHF1l2UhI$Av@C8z_R z3S<%L>8a1$?Bm^sgLGe@u5^sd&uqg(Aj>{tImyC|2$8tt1-54@R;Y~9Ym8-l{9DtN z=$LO{p$EFa82gk zlG57h-VzZmKrKc8<3=jl7=aSCR2-1AD;2lSfxY?( zPUeQl!$+mD67r-5=p_xt8r+8*FzH8ppud z03WX`lqgcVI4-C5S|GVRqtyG#ZMb8zCXkbXK@}bla*{N$@jKyf96r8}*VKqbM$s#7 z_=umsR92qDQcM_9m)CLt4)HC|%lT4AZ-=3y4qhjl4iT12ImnI$dB~H97nAvy3lOt= zpHPc|&_c}Ag;T@7YQ0J*<=3o-4AW&*&W#6n)D{2(q{tKb?E2As2~hIK21%9anF;&zHj{xv&G=iSCrwgGLKBvr=FGZKPo{2k3Ti$``h z8>XDV2pQ*&jLDjYTkdn+nbU4#xJVfh&%Cw2^?TrH(-a&@mQF*e{Xtk|bLst9HXxvS zZ`)$sL8;r@Te0lK1=1o67BS?|3d%_~F(v)6yE19|kXxM@OM->>tAdF2Q%`8R)vTlD za9HOPgfcqBs9^itj-XD|&;zp|;#LYo^<}+F5qsK8#wr1ah{hG?-ZTC+h)cB{*Wbq# zbgCxBQ3S8nN&6(}ljfcT4)#EFAnS!a-@Yg3MB?Le8m%16e4z@Xh#dGUaNLc=ri(;PrT}s{u1EXrTna>ot zIpw(RGs9qro+h%!pvLv;h!?+_fSdT~5uYwUHsU8Ya=09M1k$An!FJU{U{+u9(Z|zb zWHkavjUS;Jxu0a;aLlYZ4b^wc?Hrx31>9yX9^L;v==3~aNDc9ouM={0?A+sGuZfR- zqeIhQbtYxhi!+f|I$$nE9m+o9LE>7DsE%@e$Xa>i-|~*03QyR!4Qg~*yU7=&B;mEv zsB*^#Hc@)E!U2~Vn=t9!^PR6z2nI9H|@(e@K`7FI2;C<2&)Np6b+A9 z-4gNAwm|(rO@6%_Ij$GW_Rn3or|_&!Zyg>YyO(=os&zTA<`W~1{00_xe2TC8@Jx6+gF zjVmiluS&^g2YY8<54zXgLU-MALVrcI=fykTmZ~;n^I1dh8NUk-LX(6sbON;$F)JC| zh*#}Lh5#ZbBKsjT9+2=00Nk;}{jF^xAxk-9roQubU|@#)5D@Avv#TFD^u)sv*$xBB zkCB{l+EJ53_vr751h@V{oGtto&!le$I8v3BDb7#o@6a1va$87EGE0=K#s%5W)Y_F^ zyez;rBev*?jg9)HtR%JWCZyld3y|U7->!-2M<#sN=Gb`nRvwo#!`>}4$yt^R*G<0g z{&c<2GVLq-W0Aa0WN|dor;o)Q6D-pn6f7?~%irTvD9l(KQsziAd zuNzm7}^&z<~EF-a&TvJgB(VL(YRafi={;fC3pW;b(VQ2$g1b&nM6$#ddw}rmVe& zN0*UDwYrv9Tt#o8Tk*L2TSb!Hbr4K5#1@Uc!OACHRhSu$rgpUm!&u}HS<;cajrWY#*4NK2- z)2<&VXK=Ig>i$ml77*UN$0B4 zd669lPo3cAI~n>tb_LrFJC@}4nt1=UQthi@CtD8Q)ydPihA8a58Z!Te0fUpiG%>vk zsaD%0B6H|8J2CQ6>Fjjj!o1=i>Wkw-H;-}}%HELT38|y!xB9g=>X~nOxO>Pc2aJ?C z-t+Epya$3=)q1pTgwR0+CvT6sti@_s#3Dw;?n3)C5Q4&4vZQGVZr9r{g*ndt3|vwm z&!=j6SuB|n4~JjoXoZjxO7yLAMYseKazvWI5n6ff?SYw1JA?&<5s<5L@pT{jX3x{l zl_@cv#Udkil+!HR^ru1T{2ZI0y=Bs`K&RS{*XZ(S3BYhAcRUc$F?jDe%+2sXOzq$^ zTb?&&1=X#UDf}l7N`2>$nNYc0eVgsE#;U(Pk{ABz0@UQ{3ejhx9wSOyC4vRXfmb5xBr&Tv};JvXIPp!Vdzmq83c8N2e6w)?c z0x){ArM+DkkqA;6^N`knAfsLslIDZ#w`_Vu86gh~TBKVZKuQ21W!^FUXBb+&`9gZv zIR6B*Z{RcjiTxg$KWRs-)$UN+dcri`ReMmNATJ22uE@yhatk2AmdRK2VDENmyjr$wgy2*%mc3PF6?{%aVYG41Y%>*A5Svy~H7HowBl zqshrn&D$M70CT>w@v~1`x>=uVM)tSV`1h#7ncP~&g}&A7!0=}?#;4c3d#r#L8BJ_y@BF(z)sbijF$iA@uL-IS{m(^y)iB z^5JClpoxi%Klle*CXU?b(nAA!yoH!?a{w@4RDQ$(?YoI0M)X}xov?2!(IJ97IO{}h z!9of7N8zwQr|%o~d9!*U;o+LJtzXrA(N0fU0cvHaqm>G$klU)HdUA?Z=xF{c*PMv$ zO-3X7%|qweQUwUecJd@Z_QzZyTS!|{IIOhvO~uF47N=oF{kdi7EY1f>67SJ~|`ne`R!J=}BAvmf-O5 z@}3P$m_hPTm*H4%$f}Z;D7Xe~yHniEtMAndJsbrD?+j0>%C^u=R2@}hhX!r^-TR)z z-OUjfuPYyNKr?EhZDxk@+(kt*Xf(vDkPsUY46{6ss60gV)qaxJ$v`0e`@9(ulOKt1 z-Jtp(^u=$|e{?-1|A+I5%wtDus;atgDv#;9<)K_|OoI!;|2?GkJGS+fUC&%iJ?Y4# zR)wRox^xNCvZ)s?+U|d0_9m@32CJGy#afT@>BW@-q(@V(`h5!0dasGFgDoclQFkAo zk%hBcTav7zzuL>pty-`7U-D-HPuc=SW4wDnD45ja6eAb{w_QA8zGfxvIJut49<)DT z6^_eUs1BQy%F)2=qJ&jSIStm?XT}Ff-Ho zfLZS~&EWuWCdBQXqFKNztUPfN#<_Xf2u4PGRi%5b0zo zn>lnCix`rG7}Zn?p-Y zWrj1tYUg7q*Gu~cbuHAZ0F3w91g%Xo+Z5=>y>e&`*UHH@%ME51#e1GBZ#ya7?-HPk zu2>p*Mw~f*lp3UN0)iv@p+RWEy7Ch3xL=WE;j#%`DuU57FjHPfnoyuoNWoyLJ=z#p zo~H%vcwpA-iMVP(&)3INyS0FFj@hUbbkblY&|+BfBM1k)nTdIEQyi&x?jWz%iY{aE z@@ZBdJiWQ$H+?*=WMK5@U>Fdvm_WL$S1<4p>!B z+uinw=1B)E40i#EA#VNqY_AUOQ_$M~mUq$}qxy0NQ#~J-hIa9uhR@V>It0!eRbxxW zRbn*?eCrZ3d%&jc*LJmekPnhLmmtuNnUf9eu3-JX-5J+P3{tMK;KX8H_*ypBP%frf37KZ`EDiug%H0z2T02H>Mr{D@nhwLxVqo>zk?{B>$VnMOb_jYB=vhH2kV&`Y-HvE zmzy)k@pti*jS9Win%gs@fes({&PY z%q5Md1bU@GYi3j^HydXIs?9UA&mt2azZKU^f4`q4Q%zd3H9q4rUk;iro9d{C@ z^N#EleLbF2@LI9mH}iHY$iDH;!4Iv9Nc_0&JrS)a5dm6~zFx^5TpWqAE829}6%H8tDwT z46$nalYQg%@%+)8hPoHjV#p_K?2CPN*l_E{)+YThOPT&B@FAqOYOIy^aM}yf-g4u? zTUgZ{Usy{^h8Lvn6Fy5FIU~o)T-u*med{iW9|`yqrWpfa#t96}iIbN@#i+M%mRCL{dFI@34ex|j2`5UN|*^Sa-6d0g)L&Hkr%sB=- zS_aezAhPrOY{y(4Kkl#M%ikRl4o6xrXg@ZUc=h30U5yU?tEgu9kZG>A$Jm%MbamtX z(VC);XV#EIPF_~s$Jr~g3-uY4RZg~(VmJ3P`82L4^X=OGJ~Qt4F}G5>1T+YGN{vsD z-1mkg?1F-0<*z~V^3ZODI;=b|DOy24o&@U3zC|feP2C?iC{09v@K=1{yd$6&H}t_9d62`aRAG75Pi!O&s6MA8CTpj%%%f3+RvbMt`6F`!S{FrFMZ2^%#5HaPVNf z>U}jza?4w#X`%ON)e{tV(R}%tS$~RQwSd}Bb)n|NxV6f-`t2``GRY0Aks6zA_^J2B z$`y@W=QDG-UzD;xKKuQ7|JpteKUqrAQVwltH^SsS+e$QU3`}c{nhL+IN)Bm@SZVcu zlv&o6l$#M7jr5@_qmPE4aDP75ebBJ;(Sw?CHJp}hXQXcRBFvi0|Na^;KxMYQoHWI~8ecuY_E58a|DpW*_YFc;^<>ng=sq0&d+VOI8%%dyhZ`yJ zibCX}_pOD+*f*@L7V^F52As0}=zQJ&#c1;ny+AZp-|NbxVjQQ%_u)XkMftH$h*4^i z8%d+%R?(`d{Zxc%#G)aHCXTG=__E!)`st`Mq-|7tox+qOrr7q$8^)VHWFolM^u+w9 zCE!YiYFj8V5pI%L$yb5eAMJ@3{z3k!{Mu*#r!=3>W5AQS6#Yr){I$GI?bS#x_pAh- z2~=mW;N!3nNyqW(=b(o|%x!f-1%b>us5*8Sg7ss5|M2QkT*)j<*^%JZj~)`2yhrC|5-)XqN_ z=oubnwooin01w%WHE|AdEVw%A(e*u^=w&qK}TtPpYZE3iHuf_Pm)|A#waY|7qTwbcJf|o_ zx=NKL#n^SyX)27jUA8nDMk3m&RpA2W+!G#$zqRRcZ$zM)%andJ)5^~jWS8iMdMr>pcQ$bA>)S{cuWSbsTG;Y% z(LaI6PsAMj3%WEz14$0Lt>nw`V^l$BHN|#KuBDaQTIL$Q7CLaee{4o7h*)J;y{F;B z2*eP=XO6V!LuylQWQ;G$SDSun(`5_j&V*R4V$|l91Co9!kq0M^8S@yjJ^22b(+o#q zf9Qz(h$yeVb;n`)_|LcWw?nq;1OBr1+P+;z<&fhp56IyUW#~p$IrUeTGIZq`_x0$E zBwPEk>;0#^vZ%0_SbcfErn_VKzo!R3CXUNFxwOp%Cq8U<7<5PFDag6qHUdb>ICf?h z*k3}+!1y@vDyP@%1eJ4ChSxab19&i1BgB`RtX(2x{azlU0e7&rQwKcuFOQan+dTjI zjSuiC_i2q3+#CZls-}-QSeIqdoOMjgiUrkzM5v!eg8!>yrXO=4_UO7j}A1`I)%N~ zVu7+d6rw&@`eaD3~7CPvcdx-IHP|j&`(E?6Ff71C*)U@!Lx3K>*Ve zW#jXeXQfuRSHjdBI`}AIgEG*$Avom@>}%}=G}!%l`**%i8c>-q?_l=I9%Q=z8?Vxc zwR!&XF(scrDmni0QfzFbnq^v8>KL+lJW)3LC`!|Rs(y47l+-E)0TyWKFu>_EWpqdT z_mwaxoWjcxgiQ#UvTjrS#ddjTtrE~si56;bNHn#x1d4YsZFt|%$)5en%%GBnPBHd- z(00!Tz|ZnLGjS!FoySTH@qshp-_Z<|=zzr1sO*{45s!RiZ~WtfB1~JC!@a29>*em$ zZbmG1te~yOG*`Nz1Yjpyrg| zY=EG|!GR%LQ%#<8sUz_>g$oo3K}Fn$U+RW3sv&FOx<-6;G7C&li$=o}@y?BCRoS5- z@^Duol-7PkFPmuT6N{vO;S35PA7|zvcnY+*&t*~5W8nRR?9-v|OXV*mwtFj?H&TEk z;R5MwZ_)E=!^-f&fQW{%>KE0L(zMq!)HBL<#jZ)y+vsRZR7V9r-_x*Mc6+aUT(Bkp zrqTtx=sY;romNK$(}}U<${!Yo4qQlsJZx$$eSW@{waNv?}7kw!_}U!R*UY zWE8wh;>m>6(axG;fZ$Xlik}su9jmbV=j}8W@TS%lfA`F5_aX@;<>%GBLsHgqAb+&+ zU8e@buDtGe*ze$S8l}9=(?ijrcBE(%`gh=E_=3ptwhLVVQCqFadd_bq72M(LH{1-pvaYg^M9Bxw5 zQ1%GiEcMd~Abwi-6;OC)T9@^F{d?%BM)bd7BGGwI!r0TUYoX{$`0|PXSd#1>NNg5u zI4;FsLYfW`nXt$9FnWha2usmT$CcvrLHA6KdOFbY(91>EM8(0!oa#+Mz6DhVU$Zpu zilm3}!iu8@9bKzN{;uy^*8bpBaae5(mK(jGF|j%B!hmQJ9!CJvc&x8o7qw~S-)c-0 z_LPNJ86&Y{0jWUtev_5T9e1gMi3Wv-Prcl25=xdv+TzC#v7;{YfVxRKs6|Zeh!Sw6 z*w)mW;r^yyUQT6h#LiG32I&r7qofiuQ%_K$I#Jz#+ktfIIuCw28xu0Q9fm#rEq3rj zU=_7wmS5kylI6#Z0tlq!X}hGQDLcP6pLJl<)AL6=T`eiG`Xa(!9s&`ce8Iv+Ls*NG zye53tP*)lApkLcMp+SqVJDKOP1`E*!Bf`iB;1$ohJVq_Fe5i4FcsVL$C-%weFh5*{<;#27N)6jdA)z+R751VDJn&g(1Fwbw`V^Hih&O!fq)=|LV8fOIaHUZG1 zyM}vGz82h;I*OJ&`+f0u_gMlT6LfDsDR?`ZbMo-Z)X|R{)F5t2=r)w3Z+6cMF*XJT z`r%Jy8e@@bxRX%@JFyEmdI&U_MDc0uMbqi0iqhOc9L`pWm0L>`g7(0cy&NQg&3AF0 z=(0xJ{@`sJGTt6d`+f#H`}0hA7m9_pJwe5+HT$=<%r}YB>6u^zMr_)B#y|9wbpEGJ z#zy1>2SI_LhaT$oRH|LO0%tM-k$Js(c+~v}$V?k4FTlWbA2q_GzW<6{A4cHFnI8FQ z`;eB)Z{LDdFI^v~L_cas)O@yj@M&k}fp=dzY>F6YvRTm~u_Eq!R5xL(qvg|rqm~s- zluVQ(a{GhZ{1e|*NL%!O_m24}``(++ZguZhUWu6QKyYcLI|^~eP=I-}05K8+e}3<8 z1blmMe0|&loiFe2HNKCj&t7%juWlR`*|}TkK?rP9+sb`>w(=lXaf0-F`DkQ~U+du~ zE0w9JtB2ZWUqA4s)z*qBq!%*IzqRoK`qJNo#xSsj#3J>Xo*~DF8>`-P@$Q zF0rE*wtHf3SyY~T>qia7=cHHkNr`CI`4!yKK6kPr=J_hopv+R{PP-hkKXCqP(7N?Y zJZ~bLF#WBntMW_0l;k96j1n*vIohhgc{Vxap`YOgGhF#naM$Dmos_|WmNqV(L%-ck z@9CMaK*~*nMm=mkt^}8@5Jp?AxB7duCbL4H3jO+kNuPo6NP82g3|-uNv9R=_ju$Pq zT!k_r^uo;u6Zw0UoLrp5=_xEsYT`wzHr>WAe1t?IQ=hBNc$&5N$+2G2&+r`tww6le zqP*P0t~aNmOZ6ftczFPCM|V#d*qWPldZRKExW4C0kmaHx^C4tdX-R**E=ccY0cH+~ z&$x^!?7g~sk`%EJhoGZ)GO3TOyH}}-#B#+Y+CRKl_}q`1;Q?h@avOnrR z`vZGx<${5rWO=Y${X)U^bIay6jZX+nRN=T#MFlf(q8@Mf@M`1P$QJv-9wf1W*qsdt z_KX)cd$u;7IdP!eia&u1ZLje&z^_lm*vc~L7Ekg&t>n0c7d$AT?U1Ip4q+yyDJ;%~ zUB|sUZDYrq;!%@qfNQ3P2a~zUNy+48f&rnpXoLvx)z$d}2+);~Cj7o%KqI#(hZ-w^ zOMjyN(7Hh>g!N4UNc}MAD3F#RoQ)AE(D7PQNM(K_;epF-an;0}((jGuE$%h!G>)C} z5FTa%?qI+0_WT?QBHnmftmzgc?vwZj0i|=#HmN>mc2z_=d`Z`jZ3R(k-;!_Xp1prG4)|Up zsLypOQJYJc{iJ8GYu{MtLo2A?qY7f_!_Jz4v$+vH6kp66`l|AN3|-A&diAMRwoju;lXi+n#_%WE zH6+vN^upbO(;)?Uj?}k?hg3VITvfCbtAs_|OUmi=OA1_DHkc0d2p{g#=8KJ!X#NvJ zHfkTk4dOu4B#CRT5Qnkulw=$C$nF5$Z_-Q$pUE1YV`I8i{aG;lr$IYnX)jFaqNsk| zzlc57bZm4m7ohXb!sYV}AhRoaviGfXyuRTZPRC*YmWJP&&q$WuIdYWF-I;tfa;nat zjShc+%rtdP`}HTQs;Ic(tfu+=uXnEZS( zkQaz^Ll@7c`=+f%3shn;h6YUx6*65FXTA_zlFgYPuFZNWTkuJ{!PIAxrY6K)l~tfU zxYVibN&9@0M;Ht>j8E#l-3C+V#ypj-JpV?B34jKkvjd679#v`gha{ zeD|Omfn#Di`POn0-ZnPW96H3-e)ELFC02K^ zcH(a1$CaFvBm5T#An2*?&TOkS4_sIyL+o`EN&gB~ztEoiu=bx)X3T3P@ktL!&ve#~?mt1ha!c3Qb$7k$=9XRm1rM|7`k8-` zW^ONn!KO|Df@jk=I1hagDH4x7<>S$M3JtBESrUHD>m+@=e=iu?N5OygxA-20xZ~Dh zl`yO~3D{NQaOQmQfkE|ru=A68AN>}7iE|82cY$x2L{qyR4;mBAPlM&On_j@0_2Sv#lCz%2K z;gb>G-mR|6Jq4)NRxSEZ3tZf~p>uInmFz36rl>2PT|ZgmZ@}bVQdT|dj5@D6fAh57 z`BoU`2AXJ?+L{&sZ@t2Dim%niBaT#+@#uyPlyE2wM{;F%_PXMqew+PDbvx^&@7F)N zeryeszt75W|B^=4v=H3KzVcjxOWI8RY190LMra&sT_QVr+%PM^v`+g7=X|Lxx#3tV zoFc*j*Az5Gknm$J6LwL_C=8kucS?B%xnIw1Ss}XM-nm>?xdnXldxKEBO%Gz85ddq1 z+G*EZvZ-=g>Qv&}w+(z~a!#IWe%?Y?;tQ8Y_~>y^aLC)K(na^hYWd8%A>-a5<}+?# z(CZ?^BK~+=hy~(~7aJ)9Ul?3GuAvE(Cm5&)T83zc+M!+LyFRsqE+*Nx-UACn(*`pa zX~CG)y7sx(e2Sv=dmnX$?`Fb~j~Z;VJCr2YujsWGmzIch2%V0HgD?5VREnYuYCVM* zoLXpMkMSuw0BPI>-TA0 ze-Qq6ps`j;LYQ}zv882pH{PgIAG#K?!$g)bJE(*|aUtH!$<9ZwtlX6y7zEz*^#6&j zU{y?KdB|dRPxM?|UEzYWx~JBcg1pl=Mf1Nu)ndocFvve0+c#BSYvg1hS~DaVQ0^UG z?lCu5frh_gFRn&$tMER#J?lNW=NAXjdIPvuulsDp*B1rxqVK@eKm1q`q?K{1BJ=yMH`k=d5!XBhU!U6GtPp!q#glPVZ?NyE z&3Stj%`wgC^$TUUnHW@J@%pD@jzzbbsL2y{9*S)%@AJafn@vni$iM!4;q=O$==GOn zf}P<}=0Qi);@EUwOD~dO%F-Kmcr2WKG(1bcoChds#QeVHGS4$MYgw6{@*H-4Q}?~! zVhqJSn&FnRmN3*~RAOcBRpYjvi%16_N>j75;NipToo5{onr_j&!-BDIB@)l+us90r zyWY(3{0((?o^8NO9P&nMCMTK3Dr>K#5ArQmBYwSb(Um3%B5jP%!GxylTcC#nFUh2F z$h!+vWJUbV963=0no*I&iSenMBNW<)!YAIEqDX)I%5H1VeK#3YavXhY`{Bar1e0|E zvEtKF&B-knMB2iqAonE~`tI@)_(hPM`iNuwGk0l9{1&0ggc%e#ZFNHJ6j()Cv_w_!skkF_Lq}AQUC)%j?Sw`*307T3 zRgrUF?H*zwD>MuYW{;nmb_2#xSTI|JuA+;YQT{)g#z$`tpC%M8((n7+GS^wa8?Q3+ zLREa%j#pA@jciIr{x|pZRQJ^wW{C}#&L3nb+cjmY|2tx>Q54;JL&p;fZJWFu zp-C0a#1R>BW~Xy`Ju!v1+=zCnB6d^w5%;*p=;Tzh4C^#}g5UIO*G+fLXPBF6dEV+* zpBcgHk7EHmD*DfW;W;Q~=h8bfLTCeHrgnpRVuqhNTCdx)wija01d?~}97k`${wnar zvS~f{)1k#gzw5RGuh8l$h_)0~z|B(-*C+GAgX*iHDJzYQeiJI>u^+p!TA|0$oafpX zsLP(ieb4HTR~5+0!_HU?_`JZ>*zsaazumA*;QFCq_}-wJEkfcye{OL)IV!VWU-*3P zqv8-5p2?9l118{dicwUg1A6bZ`85;faM&KXtgSB^Y>p4c7UA zGe-Yq->)viDPBDl22J7Evs1jL6GC<>S`_L4(!|V^#o6f|^#Wf?8Y|o3sTe3JImPyR z=w#!IZZroHNG5df)@^qEyBi=c?+i*1()=ZKoBQ5rO~Dq9h9E|IRDGk?hBT`Yi2ujl ze?~R+J@LaR7K#BxktRhzK@ z5=!VqK%|5akP;vyxrguXf8X4cnToSd^~?>)QB%x6Ax8+rayE_4852*>cZi%&K4E&ok(Ga%zoHQMZ=C2 z)#Mew8CwP3}9`7ToKC#fQ>s50#Xa9uI5XT0QMgU%vi@feV2X%M%Ybzmke>V z6Py2sk9o?e7T+F+xOL^Rv)*yM)nld1cHUVe7k{2-TafkaX&^r}si~Avc{iWEThA;) z-~7yyZ>^%JZ-BBd?n)+T?w8rHf`VI$J_O=;o8x5q2kFN(vf~4tP1?6EU(C45ns9&P zU6I@t^YEjlOT`OrGVx#~-IVF8b@y4iJZ_Hv-5*M-{Au+ntVU{lpl}lxNL|p18KQgF ze94-1nNqs`fc%uwR)a(iOXU|Dymzj-W(LG)fRTL zcc1PzRil1oeSo!@D?K&QIY%)hqgywsQ^^SdUf}ik>(P^y6#TO%^l@rZV7sn)%|O48 z&&0!xaqU}W+C)>YIaTKPe`3DudF8#`;jil$miVtru~gPE3hFUJRv{n+Z1&KlYQlSdi&}p`+>x@8;j+)m-{-Zesn#G$m7Jv9eLN!Flq(CA9t97z z#^N*VFn>qG_cp{K_x?9WnQ9msryF}Wnejb8tL=JN7&C%(OZkq5TWM{7;O|ZRZ;lQy zuVUx#!$I@GSPKwXbh5{miFa*FE5;lGSY;3a4sZjQvz5mbr&>Od8Ou~qYdS3Wt)_l# z%XZz!M%s+68oT5O?#?=kvcEFO6MJ3ZW;TkxTeHK`^%&xbm&=;Gc5Y3-?kaojr^2}# z#8bz0%_2MpEpgmyJ-%p7IfGx`v=p(x(38|su|nu@jE{+HwN3q~UUjuB+kFyZH#Zz@PirJHVQ-e>cMJ)|nQ0 zHbGBdVWn*P2GV>7xz9d-(S#42Vd;BOa%{LLh^^(J@|wm7pRXB$AH>#leab4T4a^R5 zdo>v2i!!)B@U~5|l6`n_zg^_h?Vl`_;`uTYzyA25&&(W7H>Lu1tessV=kCsPSuPlR zlAz!Ss4!ur5%Di)9KZrTl=HoPRYlipuGMy`<#7sakkUEj-?rlc@%Z0#lm@izd#E)A z5>8}G5yin3!J~o{9faELJ<=D5V>0Li%<-&C>1$@;*^$Y|@x2+a|y9xBD zn~ZwcbfH|%f`k|3`NvK)fAquss$#A7%-fM4XZu&*4kRpG|C=HyB>T6f7{PP$9UpOp zL(U;{SnJy<@Yz;XFhXV=nTBr)e1K*NPPD@Ld@8>$H*I=@?aC^>1ZrV^%F#(tS;DK( zeDCQ>q0X*58J^F1dfTz#=Uby2Kj}asHIvEwmTNnf{x3j-pO28!iE2Q|etZ*l`O3J` z74X6(kJuO>bp#~1NPXN>Yq&Vax#;ceOeqaaApSns|J~^WeJ7KJy@uYAob1j@nh<;U z3#{xVId~HJUW}vN+w(i@f$N~<+4xw-#*?pk!mksxhBuEM3UZRD1gOiJzW17cUFM$}er#3ZGCr?1K4e@WkElroiBZvY9$laHaM z?546___P9?&Zql-C$j%obd1&3I2RuAsQ{%ljQ$&^a0oi?V>nnfnB#0Xf~qX&8tx5l zzLe_zjX41pt|8RFYhCwH;O3{&`{SPqDqW2onB(4g+B5;7f#Bod{M9cPA9J3Up_PQLb)Th^?ZU>lzrCa3Doxv#Myy|Pc=RlN z^W?q%qv2lPNv%t3+@;qGQ#|s9q{q9I)zsA1CbNa>voYJMQ42(uVe4v}a;^U(R$77N zd}i~Epv#{>D++*j!&j%LNBPdphuMHb*vChDZ8wzO-CIX}1s1v-OZ+NznXl}TY_q8s zM_fGOoYv1Tzq+p(&%H&=1uk0(Xa~3aGXv`vRZPVh2k57unpie3j^ERF{IIjT{aoDR zrq?N)HL9aSy~&fB7Wk_-&2P$&2sncp;g}=uN-ay{|H!^%A;5Ssz2g3Fr@rg+-=bow zJbT2J!c+nn_eT!}|NrVC80PEy>qu@fPVoP_ku|Uwd_=y+GRZ6Sqe(GmMEDY-PABT!BqhN3}~abs_{HE`~{ znSXX{)n?bL{f$2b_^XZ1R+o@Xwr|gCu%c!u5?Fcv52G4H9JPf^TS|}0lgJ-k4xgvX z>ZKbamQtqz;2%&IB9s_ZSO5GXJO)pxCK}LQ}cT#(DRhOU%%cECQ`M59q!t`dkJ#Yv{+-m zErQI!h$&R%-CGT|zQWVpkWjtfv#z=Or*c>r&SZRTAG&q8`J9C<5zw`YLD9=5S0m@< z7dMuAx+Vfg%7WMhPpT^`U*KVE$(%l0gl9wfI8q5s-s{k;Vz{E|KF^nUaoM~!)* z=DlqB>=gT4PVxiWg2#*e9+qzuJO>ip?q-+3$BWs+Il0o~2_c8aboVg1_h7(HlmY1EVn8UkBA>XIE5CV zy5k2Cmv2YZczAmDAie1oROm-u?deT2N&MR}^cx2Cd94Y+0<&2zW#qXj|BHF!End-Q41Q8-F>d2b?@R1;>^~zpdL}%<`y)gXc3kEOKn?YcT zC|@HPr^OAJK40cjkIHOhy4SAw?Bxwpm!!WczHSbP&O+_3&KOpV#_p zUy{$UFlpatQ})TdQQ~+$X4Gq2_x#f-rq07f`9wYP<^n)U^XSWI;ad*?;`aQ zE_O6`?jYuZGF|sGUF*4`f1hA^5K`=D0xel-SVI!JVjxW3`wP{ALE1&$aq-7{0%-Vv z3G!h-d3<9daE&&*@mysbeqhGmS?y>{JA!J;Ba)QyT}T*sl&K@EnKBqlSas|Gh@Z-h<~Q^{{F`b-@6gDkc(`F zZ_`Dclzr8AzgX=$VrbNG;965U)v`qHMiLkl!g&|`5I>pL_G62d0;d;iy?WAd3{tuh z8?PN7tJTP>J@bC#;P-lQttlM}qc+3Ue0%o-7$nSjA1h*NS_U|ZM;b=Fb2x~I%+)MZ49vCRdtqGlN7t$8`#-*3H!8-sN5C1u69d?_ zon3hct!>sf06z6W#!YMP_W=Fy++2tVXY7}9&8?OySx_tOk|@o7aVdM|NiOXh6?T11 zuyoxd@?+jlzpV#>9eM2bh~-mBCNrp&Y}iV6R;Z_Cp<{J|Ry=U(U8ga88g}Q z{TTWfW0L+ifL`{mp;ZfdFr3o2BxrV4MC#09t5LGY^A~DSNU9fRN0_eBLEk}gIa>MP z7N)nWLAtGI5_HAb6@(eR+^c#gt zkAC_y9Xf0>2T7aaf)}8{)l4G;k^Jqc(i>xzp-qHYLH()UyNd#JV-L_coY*-1&Q*r(TR09NUZ%7XOgNk4XD z@yw)*by1htrL7Y&wOc2?572*MYFcy2r@^Y7n|-X^L09KKuTw?YdcGK;pUtg5!HOUk zD>4`Dfi+GN2FnhB*^&MVFqvN^2G^7t$C~bgONA+!`o94 z%!n5O7KN1;CwLJDRru5TtOrZ5^`(c+<@1hiUn=>$8liqx%uf-t12Th#!SYQqw&3)E z9~uz2;&KakOpbRHB$d-WkT+xc== zXGQoA8=XnUiV|q|KVK4L{H8GZyOMGSR|3)QWz@40F{8=h-VYxWM^or-5d`c^#HD6% zg}`CM@3mH;MiJDs*yG%}v5EaosJ?Uo+fco#M8cppxsN|o8O3?jrg_Q4l_28rN9@S1)g~tYK}(Bx!|(0 zUH3;BPESqM(;1z6JXQ3c-S%fi(p?#uuJ;e8BRL~yGg)d-8w;A7!!{J9QwbxH(O-RV zWX=Ru{)>2OyzcPJwSNOn)m|>^zA)>?g6%lN(5TTD^JuJ5<2T!9HL)1mq`-j?Dydoi zc8aLJ9*qKLP_U+9)fZ>roG_w^5^iimM{`>z3tybBA$U64b^VFAYp5oFu&{`Vrqdp| zUcME|f3iAATzkHoC1zVNOquBO2Q1F>V~DOrFj$bVK2sG#(b3($-}J(Ww_vnFz*cMJ z#c-Wu52VX{vrJAeNc?e!u(Q|Iv%Ft%<|TL@{b2;Y$U8h2Yq!xF+J5N%cX;yv!8oA) z^w+`CG+D^WuEJFEhbECumDzV(o7m9hj`XcCa#J&O=|eVjy-v?-Za=I;JE_~UVXxEX z*QXsQ*zCY@f!QW%;|FtzqP5XTe>LxxqEX%g+`RMDOGtf^rSUV2GxOPeu*@N; zy1=Gc1a-%&t+kKyctqjCcd7iEiCiOU3ANfrTMyGJyHXFMNUA5Yv$dKarQ`w;%I_+H z%};q!ULBKG?2<@)@%MNtyEZKQW`yrFbpE&vs-TEilpnVYq$Q^@KX{tz!n@;>xxH4< zW>V;WDa_9@f`_*;O{iq8|0|qEXI;C*AYi+xSJ|$Z?|Hrt>wq|zpIu2eOFC_eN5{G{ z%oZCaBTxJ3>!H<%2!#cR68oDE{iDfzUxP=89w;X}ISlF|$-!Sl2lKg>gM%wAKdsz< z7+Mu(Ty>{BVtPiolR=$rc@)_4;i(b%8GbNOmJ6h{Uhi|>(%4EVo$6fBZkw_kQoYzE zI!>?ry`K}rk*txu8q4c<$}!D_;7lC(G;ivnI8V{HI(f=2Pz~3uUI~z4*&a6x(Kc?vrN<|@lyLQDVVl={P9=wDSZ*ROj^&m{q!33}O-pH`3-kjdLp9tv(aYY_ zzJl*eXdB@okifzQ|J^prMapJ$qF0{mjD{Io7K(DJ9L$O!eU9}r7hQ4Y=j6r(eu;@J z(8#%}JL2w~eD8E^mSThQzUNt?`ZTOhg<0EIfr>WM#){~jYJYZqy%2z+G*zEQ72&Ob zbuF?;Ro@+peJTi<`zne4xo^I)_oTn!BK^~voU+gf=7arz=eenR7&$=*KLZk<_BY8R`;Hj+)bGpt?VIcVsYV!`QcGD#AqmOeB z-tv-}wxZsvq;Pi!?^j8D6}YLxARg()YUX6G>;f;!c??Qh{F0pTveL3Lzsm?`mF=rR zI_-P@;rCA|Jsp$|GN(>*#a*Pb>BR%VA=52Ek-geF9!ehYV=-MUmWz87%zH>Yv}F;2 zG?PJ`xUs*4Y&=^5Y+AJ7p4l-+a+stb?`0?B_>%pF&evdx(7!ao7Y^z0!=i(3(7`+T zW*VyCx4EB5GMuOJ-QLU_Tb*7Qs@4#7C8>pvgJkCPx{5doKGO{4r3ASP31gn5H{~n~ zpldxq&Nx5l40}?(Pi!srZ&R7uiT`-Y!TeP|hZpax`*y9Exud4Ao) zsp6URB6qbSDv{ti6-2RtBoV4g##Wno5G9$+pED0N?}i3calw7R1Y;E^9|kG4v(8<+ zuT@{#FdQ`U<2Smig??W%b^fdOwUuVkkLT?$^uR&VekRhPUXXsx1_f4c9FS2@5pBA8 zlKd>z;G;_9T)`x5di)eA5nLLr5?Q!VpHS=Fw~;4RI#zPN#V5>l*iSI2bJqEj;B7Y@ zt40G|>}m8>W1@+(+hMI1ZruduZ-RS>0-vd{{YEWXP@ZpHxHiT;cST@2daEy!R)g>O zPAJd3rn8}>I5?>DvL(6tvq=W5{?kXu;x&;)sBeUdv(ZG(lE z7*1i7m0QODpr{O;_%>>xpv5m*{ps~@$8-5z{4iPaVNYdN;M4z(JSRC#yjJGG3K zN}T-@0U3(oSHD*qW&ikNZ+Dd3hLQGr&ceMrl8l${PD zx9t8jai6N7MBi4`SpEBlrBp4_k0^3c7t=7B`^iG;Sxylo17v{NFuUpOW8Fwh>7TSa zN6IJj&)_Cr(*yV}*=hnR?EKb$LM10U*ar&WY(fha7(cXD9*TX@~DN)h9@4Fzk+{M!a zbki~+EAs%DOz*<$^;@v&@4>VsTIEBf%r&EHW5MRc@B{@-UF#^q>=S*``{#$0Z{*oO zWeqk=6#xZOR>gAEh1^|=D{T!EuovZ$;u0r%x#xUEXY~ztHNlyp3B_T|>KaByct`1b z6~1$s$z2v^YZChR(pZO~CzjUTGk$F}(sk59{$agUs10YO z(e9MpUew8!0s)mLlTbb&+<((RnqWMABOIpmZ96Al$+~wdu6MtmQW?nURrT`40Wj^lbi?r?%?wJ>)Or{Np2DgI5=euv7$gp|h1djhcaX zCKvCehgr2gcjvkY@wlbxLBAO49s63-{I>9L-E|Rv)KU^L>rZ-|`SoP>vp-Q)NnqLO zs4cWg@!Jtl=DPYAF?k)s&bzMekV0vn#rx3SG#+N~e+Yj}T;?!bwaO12M3vc^gnVrU zQ!Zm1t(+k7pm7NqB_u23Ns9tyM^OK_s3_{fNU?FY(6XG|l~&5NRwRsR2=by|o4Ej% z(-AZJw$2qz{i!71YSv&lHS^$7BHAaR+)?Cq+E-yOK8e2PJa&5rR$u*7w$&*qgAxe= zN&wZpP=QLHdil<-sX)<(a8`F%Bpb@Ir-Yh zIkAy&)HimsBHPpauST3@Y9C|!qDzrJeidKg@*mu8w5EQht&eXzf3SXZK$JuC7LGy< zJn0J+VmtgfR`q1FEpX}!Fb47pEOiK^b7!KQvoG4!$$Zv5@ybkZ@5n?*pdxPwfv%uz zn@x45aLTmNR=YN~+;h1zM%Z#&N?AT_BA*jmzC2DGw;@{c&bW?Ul)wf4Ua$7M7x&A^ zR-M({vElSTleSu211RuIfE&lPL={s9qS0|&|wW9Aw$RGBhrQLOU^_2>E&^Zu`^l#eT z!fuCNuh5xTa7y_;aOiQf&oI{)Xqc%_E=ZAD4Y^ zwYnti==1e|uCBxP60j1DqS8gq$A}(WRrkafJ>B`fhgiX-@1ost{RS@&Dmb>da872`8 zo^j}H5qedv?c}+m2c_5y+B#O>wYHZM;V+=>%but2pejDwXpvs{l9nJYTRD;n65b4+ zq(g6O;1HSa+>>QBRqvmKzjC{<& zkmv>YF_g!fP=FK?tfD;>$`9F|_>viH6}nmz-nbD?WUd&j8SO9xJofZ$qy}%Ebo4^& z4=?6F-@kvCOy?S_Pdcw@p1Ql^dJ=I$P%PT4F4sp~+jB2$7us?Rwf-(1S!onANZjw_ zeaer*=45d<8#SqU9Kc%UF?f2LU(K$7pEAw{ zF&6bw*W=;CqLs-88-eQIBNOWq*5mYbGTndG;YFi{c4$3nxZF%?6;{$cNzSuMX=Sz% zikQ>HyjW{gut{#^)ni|m%6sx~!uGw8Ke~|n8_&xsW~P~1+f0e!&DDLL;|qM#Aw}3b z>n%Iy(ewjicDw}Y5O9`OXfmI2-e&dk_wT*Li(`N2^q)p9Js!3s zipeFua!4!RDGPCA5xBRxbyRm?UCrO42yj<0p3Y|$LV-(xPijPxLT-?`V|5@u@UK4o)szFFzVX___VWf?J&|$vu{!k z?bR6(_by!?@cO}*>@!{9*eo4v4Z^; zJXZG;l2_uNPO8R8o$X+-c^q|7@>W> z=|eX`rIy(muVA3~I7L^f_JQBmh9MBgB(j?J@~Hxbm1#AOFL`u}DqVg%uV&$yN4e4k z#c#9umETj7wcM8_;t8eR9q>focSrFAP0Vs;>Zeb^4UXU6w$@xr^C;(IgGY{|9Z-X} zi0b1xM-K6KGEZhiMZprQmm;(3_%N;tZpZuXD+GzC!HRCiI63FAolRY0%ogY!XNsw2 znt2IZ^75R7n;Z5=OE*la5sU%K}c7yvMZ-J|T zkJ8pf>-4rxI&&mKFf3{CZ7Bk=s2%PbI{oU`i1j{KR8$ldplW{;>h~{&DNQp5{1y8H zBQ!ZR)s0*)VRi?CyF}@OM15ySYnxgRIq`WS=XbPTD?n!6jf7n{7(#t_#m4>D5VZ`0 zY@TcA1j5=6&TUbb+J0trJ=s;riR`$*Y>B?B|+CV%Q;c%jPCjk;$67wxa?KZ2ojck5<0p`USItK z1ejtO)O*e!1kYdmUmSy>Z{VtA`jF7+Ja@N~UF+Pz<~b?OQQ!lc8*2r}$J0a{W#VdR ze9srr{wC|=#QG@8ItM2B@YpRJL4{5hbbATJ$lMO!KL^5szEe%Ib2|ffwxah~IgE2} z1^sZbzomwTQnTumx5^J=;h#9hcT(|1c~f;DdINW#-svktlwN?Jy6I%XjFP zF1Z8I9NZuNws1c#R=c(=GmIXV3-2_d}N*RwCy%|5JW+7Y{eWVno$v{u&RL%Uw zTWr`p!8g%}hqM>rLc!FtlxRA%(S*_=GdUARhkfzG(l*24BQx*VpkzXT5)d|YlZ#yA zz0wGUrfSqqZXJ-#5L9eO0FFqbOf11K94^>H+UQaI5t!xh>8LZD7ATE~^>D`R;_7re zwQwADrDbN5B1&{YYM#huoKNe_Ll5Yqriunu2<4MBn)|}nsXc5z!FF3c$$tQ@4jV*- z)zsqQ3>-9&lCA+qkgTWjF!^-Pnf&i2uDoK?kU&g;z$IWbjp(8#nCesl>AUkGm3pXI z8>DB0(k#Hy0(;Y=+Nlf9#7*2oV}6ySJK(jJsd>;fhHAv+L0S-HfWvl*ky*uexrnT_ zjlRe3!Vu77|FldQeQ_f~G~(9`Y`>X0wx8gzjT(_=DP}H#|ElJtjds77@^9R8k{hv> z@h#4O=7YW7%D|2BQYN$6&)}dbo$_?z3)tTxs?dxns_vXRj9WHsVORD5T~WPAfGY)2 z&(LP!Gj#Xq1*02UgU+JrL36Hlq$f(pf$b1LmOY!}Z=8oCYzq#0AD}d6aoxYUDd0q;}woNWog55}(&4eGX|DeC{Cj3;F1An%oMp((#NkGYm z?q?!$rx?qdHBEjLRS5KX?O!;9?(T!)7(KYJPavY*1)(PE)r83v(J|CsZUgs`meru| zio;$nF|HXh4BD`EGTg?clg`2OpnHsi66V3+0b)MxCH;mgQFD3pc!DnbWl9GF?bEE6 z@&U|j-&hfvzL{S~t)7L#iHH(n42m9O2ytHQi z84m>DL_5|E1a+CXlj%X*NTls6YZ;Ge3XWtQ6+PWlHDl|C$!are{9I*wXe;v>f9a0( zIZhsb*Eho1i)k3fJ219>a-o_x(!05NhyrV&VnyO4(v7M6p#vFzG=dl|K7Pfv$3FfE z8;zVcYPNugDj#4N%kDI)byO!9TY(R;X1|5QD$i3)ERRM^+WSQ-8Y@r1-i~ZiJxILu zJv?L9vjwXc5b#`cb#yikz0m4(-RR&B&TmwDeLgJ&)qwJk!Y$P_<^SZ34N6a$Dp#Zg z4e$ec3f)Fui(r%#c{V_xX%K+^Z(X#xZ<#g&tND75LCN0^lCh9|sTlI#Dfqy~hga5{ z&L(vg<}-uApYL7{xh!jdFS56n3G$rFj=Jx(d7g6NHmd)olJ1xum;Fj4A2G=w6tzWHGeK+3%89Gb^W(*1S+54cMSb{u?!h7vmc|EsvJ zr;vxm#l_+K|IGKo!o%@@mzDs&Y$h~#aqB5@ZH+@dF75<=Y6{XP4IDidpDu^Ybu+6y z{r48YbO->yt8+l1P!qEq0B3iTAKo`d+ThBqJG5;D<=eN<(`$5_0tgyH0?W-n3gpI7 z88s)w$O+Hr=sS1nVRPMjKoOVINV@{`+;d_NvaiTHHvTkzb3v**uKaVsiP57_ITO=o zk1&9DLoIUKOW?}C{f{CV(c=J=2XP+occY{CKdEp1YM7${M>yx{!NNMFqc+CZLW`W; z=6m_go@w(oJ%O4qa>adX@npqP;2ePsriC}s34wSmff(j8Awww0iYR*`b@NjRUZjuU`_Ls31Fj&E4G{ ze}$8S+iGrXeck`)Q?EWgXZ;2c>MI%b#KxCJ^RhS`{dWZ|R#^E!sC16_ANp|o$$y1l z{-4UDz|j0(JP7|-e6IrqQ+7wJ%qAupJOSv7#9<2%s|bDyMCg53xh^!)=`di*K2M4n zJm|Rb=irg_b2Ije`>o))QLqLM9 zC-o@z_h_H*B1Kd~KPy*7t+z;VoJ~6(-+FZ>l8Bh2jIPbJskB2wLltlF0V($w`pyqO zpHcI1^g@~%2hfjdomUkN$mm5_8+9Gy7|f!++BD_jPuLVex@O$nd_NGa!6tv{XsME# zMQOOy^AbRKsn|BL8ABtvvFmcT=7UB3(Q_=+6wF@Ab^E05WNkLtb4TCp*+zzKC&))n z&{vW4CXb|7tQVeqfiWly&r;NJV}OHb=d(r9-Yl6m`$fFF9DDeii~a!3seepwK@NDm zF8E}!s>LldbzNS*#Z>k<5=yFGt8JS-)1pIz$ zNo?Eu^(35PR@bZmJ|U*wsyvzuz7(x_P^>A;aw@;O$Mvwcd~F$bE;C;#?ct?#_loAk z3z1%i#(lx!+Rj-TjQxQ`0%pY|;DsM*P5O3Dlz@*E2Rm>4YC)W_LDyeP0c}58<4=ASig6)trlCI}sr$Sm(?& z*_j6ipw83uT4yz1$~q|->;E>+{3%0%v`}sFD$s?tY9~LHYj~nc$vEQ<<8W*4F7ei6 z77L{9*!b$aE^yOlvOgcID{|k=Om^Ra87_=yufc<`opmTx<_0!l2V4z#Bm7x&e;eLal8=U8A1K?GX=$!2|+K7vkfHGrym z8NNG}x0IQ6?+ppU7+qY|hi@m=KH&t3!Vj@r*l?x)6pintuM98Aa+-(``S&N+ zDKK(GB0_+$;|!ONuI;75o=%)EDk>7!o~dhuIv?_#PRP_`Y?--k?wP?4wlc{mc|e5& z*eE9166wgrmGb=B==_qfE{j_R3IdMey>7ce^~spbLcJnW>m&x9%m^wquzQA7pthn5 zf_gZ|@J_Ex({G1()YsX(u9dr=)&!WQX+M0;7H^y$kXWBDfo|%2nVQ|b97TfgJ1Y9O zk;*o1^Tg=NveO>~hI#)JMMAe6b+>^an&oF4#P*$mj=PdDycNIb^)X&z1tbYG#(pzs zg#riG-Sb*Sri%Vro{Kbx_rkn~tK5ISN_<<2v-(>i_}gwamaLebJ0Ed&a6A z85xa)Zs^3rp)C-reI>7t&)K;}L=b#XXA6)fh#&UT&{DAZw}hXYc~W45vf-QSbBR3o zfB$doX}Ml_(W!TjU0xWe%BR&_DLLmCK#i(LoWg01OHazXUO=&mMvvPTO-}~FzV9w* ze*=_NMoU|kJMC-i6)`kZVHRsgr(*#0=`F_$b}pGyXZ=NUOSHNX_9C=SKFzwCP*-3o zmDOUu2%7VYs(8%*dLJ^U*VUCTX{guWVOoVBHEf0w9n;5wYGvK)x;Z&YB>SX_WqZzq znC0V>j(Pq-)_=a8w+`CjyojNXBfOut~0fF z&HZjPBVjv2#xUEnwRjHK$@i~5E`#~iBG%bFy}?&IPBRNT3wM+qX}itW1TWW7?bnKR z6%~v%PfZ~h()L7{R#imGGq7so@ur?1NA=ESdQ`c?3bI(rr=3@X>M1tWaiRc6^eFww zNtCXxj_&@Z3_CXtB{#y&jpbyKPam*f>nz!1Z*@_)Z4;F`NuMInFFUT#t02SAPAm=< zp4t2z$0bL7*QoU$o+cW3rmO0|R&-KyMZ6x=6LL1};5++uOz>VAf3Rgm)%CIMx=ysi z2gRN@O>+_KLjyQ$dEpZHW9o|TEidpeN)9?3V*J%>`38a70YFa~_~r}FH}5(sDCs#0 z9XjMmOmctvs77udJ}M9NoS?Zqs52K@i(+vmhL3gEO^+abQqkm2s4l$YH z1|!d2c=vhy$uEs)xY)v%=%XNCDY>vQ*Q@R1oHuRwWQNiVBf`f4XZ?@B=y>qWBK9Ap zrRD`FiD|{UNer+8z5w;}O6PKTLC0`%cCf)Kny{c(sIPaITXWT#6E&-&vKdc0G%&mp zr%>D#HrjEuqtcrzW^h%un*^b$e+5LsRvzVAo3kHLo<1)xtts<+Citi9f1(vata78r zB09XkOAn-h;LcSEY>3-)5q^;~L>J!Yr}SrHj}A*^--JMjvaaKqp@Txv1FCVJ)j(lj zAxU2+9(?hT>XT19U#2^Ek6K}@sJpy__~J-7z#AFA{AzTCY0s*uY*9O2^V|q^mZEWV zjrnm_V%5M+yEg*Sup#}6mqqcFYU}dHioII=jA6nKu!WWV*shi-J^VC2KAepP4h;KgeosPpCf& zs9E*f_wU|aaX2v@K^W^nM$GKoYZKJ7d&9@OX_x|GY_5ivU~7Bly#>z|`rFAo&0B`t z-#U1MUdoGFn~fqn2hWh23I1cQaN4Jo(Mn!z_iKs|rULo~1voTIfRFoHM-XU0U2sw} zW>WB(*t4>-E}XxSJ>m5wecypR^(G*PJ@8|^oKKiJdpy1%a2Tr!(g&RZT?AgWi@V2q zip8^*SS-G!c!7~EFOn*$2vJs7t!hTP#yVKV9UW`4UBh< zNbE^vfH(al@h;G`;^|=w@NuU9Yip@r`p?Gr|DsLV053txbV$00T6oRBEj7ZvDUnPD zoTy9%6K5oHzUgZoSWtU_YtN5?h}ox7{~6OJ$p8W!__O@~X#A^z;_JD&IY~{(@13qV zR?gH#u9%1%5_E!%y6js5WoBa9WaH*6I-j%NL2-#%E==q;M$NCL21L8>?Eu9LPqE8# zcEYe~vp8$LY?ee(P1v1H8W#XnC&L+3gu~Te(D`%ub%~-d^vx7o#oxD6BV8Lc4}L`h zbpr1L%D}E z5%)&SW=BTD8sWgMtcm%n*Q(ufRD&_z)y@cOMXf?IG5t1*AUM}n`eSILc(#|X?WLrv ztV7|;I-+2kq%*lQHd+;=$~`}xv4@{{|r((t$}a5PHA>U4wSo;yO6<97Szn>1+)K* zqGYA{7oT^e*KIhe*uO>EBbOYEcQk}V^`Ai`J%?tNJP{O&{DDyx>5k4FP?n5(9-vip zz{Yvdp%Y)MFa~jcRB8MR++0_q6vpg0;O`&}8`dCzQ{5`=3Hc9M~wcHRI?23 zd?Hm?v*02GQFd_@GP&$*ye&AwdyP}2x4L2(uRIigRsCL<*ov;Ufz0j`8w5V@qoHo_Q~WTY4c>vJ%QYOpnRpb5N@pdEw7Q@2YFtO>g<6( zHA+(tNfWljA1Fsx?Q6v5Zh$ zd&vM76U3x&Zu!soHu#=lRM5d4@uFiMFB-yO;o}zso_@{yaLaqRYrsAVFx`wNgA0z^ z=vfUNH>;*ymi;vS1G`g1a^`GU^pf0^upYcjq9Cc4{b+{&CJY31M=jrkitd~@KA6C1 zT&8hIb-3m*Z-iELx0@y5->JK;PILgwrx@3iy3fsB(HhBE|je3hr%|3#VG8->tJWbbM`lPU20cMpyvYKQQ!-Hmp?E-B6q0 zbNn__&D+)=_xZ{=gi>PjXWMjg+cl7;l-BJpZjDC+nmq${GKLB~K!u{VUNcb7OJWP}b2K zuVkpIV?VSb$5e1Z@rj*Pn~UrP*uf38DDTak_Vp|~$B3oOl-3oX>Y1flvw!mkB-CLo zgpMm`*eyN{!%$!p&AMF2CagcXB}1RIe@?%LO!xH7RNO&6t60HH8U1`@rB#9hFp!(hxr7i29 zL+sSQ26r<#iMV`J6@8wZ>K`544cjReZ9-~n??{dj{tXeT1ts#}n-#Q4{S4&movg8G z8zqB7c>aN_R?=REK8ID^o#5+Xk3+4)*d> z6CVrXf42w4$l!dLW?REIUB4USkJ$(K*EgiDGot6@Nr~|Fe5bP)eQrm1?;x&&PRi+4 z?97!D7+O)}DY)37L)TvneS&NUofd_znsqOYxlhxG&oZ&ZM80HItNIFsI&W5h>}12b zpi1DlakXIup_F5o~DHB;j96%J<_x(qyOB`jE8Kj+F!O zopnj^`M;0=5Z%#;=h`9Pse~jz3PyVABE}Sc=gVm_HMz1^tnhbnt$C50iCWVL=C>V? z3;FQKuXoqe$>!E&5ye*F+{&GS%MdDv*YMzD`O`EBYMTZAr9DK|#Sr9a82M`&*crf_ zJRoaxDL=#zZMf-;$k9y*>iimse-n>A`r~N) zDT_k-Y%}9T6eS`$Vo-ZCpXBDKVeqjdwDupZUu>`@5w$w>=l@0BTSi6MhW*|nq9Q6V zf*_p|($YvXl;jA~C5SYLfRqD>#Ly~83?)Oibb|_rf^_EyNVhb@Fz?BI?+?#@*V=2x z`@GLu`{Qt3GhA`T5x?Vq=#J&S|J}UV?M1C0BY4{p#(Uk-bICj;msmHtMCT~aSLaev zwmNwUbX5U1X`LWU*MR89>PH^#j+(fdxpB+U_?Dp3R#yhHo)%3zH2zuLb@3~;A%Toe z{V;Xsk@DIaykZh9*1E)pU9dQ97Jy|7%2XepdO1xzvF1};%g@gWXS&(Fpp!?eo zaj(s*_$AfLC?R8;Jr`?o+m?0_byA7oO?&$c3YUZFqBN;5(&oIZYS%n3%Qb6KtXVh} z<|o#bYSM`5#LD-^d{Z=7?&@vAV&@td?Ah~{&3UwcPSO(wvSLX`QokKkizVhI+_H@# zHnysgrSY5lE|*{Q(dDR7xM1-aZ-em3FiUy2p{|t(c&8d2vAy|gQ7;Aw1bMwijg;0O zU7cfJUEXfcb$)KI7#uYAXjD@5;dgd>GLH|hG9C>P{BHO@(r6MFQ_aW61ATs}xOP

-vBob%4$!A)qzAQ|&QoVv*~|I@L6(zS8okjr=QBf0N9%?gDd#+gqA;41Oue`+#( z@U1sn#{yr>lv=*8S$uYHl!eVj6g17|xF2Mi7+Y-K>Dx|e*^+Bq`sSzHRhE!C>=|_P<$>@ zj%=57zw9~#Sk&$ zvgXkk_mxYUn8}d|`@UB1;z4P(bXgx^)B4j41SVF0Cf)dHVRifQx`y40gBVX@o#K1t zzM!Qxl9S>a(hsK}=S5X4xW?O$h&^j4AI^9^eMPyX1o1(sMK|VwEZa^JHOyD$Pt@}1} zfy)7h2)wwHbpH|R{Gb_wyDWdB?I@V{TEJO%Yi;%-jF;T4M48=%s8Lp<4)O@wd4v4Wxdah zmhb)?)ak!9_Hg=8#a5@Z?h%faTK5fE%Z|I6ef<~YGtG%c@95*oP$HEQQsP_q4J_Wx zhFJm=6Y{YTk%6C_Nrp3=eV;-el}mzYCcWW`IEQh z94wjgV*x9z=M^KmCN&+OC8OStL-c;FJC*cma7Zhf7a3|i_+lKA8nGZeqw*m&?G<9a zNZO*ZnEX=$P1>f`q^pH)TT9#z?x+ybeUaXG!|RdB8G{3=SHiN8B2 znSKyjE@kv>w$G?~XFhDq_d7AP_eGw>UMp%MSzjUJ%}6m{=|Tn@(~09_y(#6v!1_U) z$DC6=!jt@tzz)q9<5kDiif;ETeQn9c7N|nI0mErS^Y76}qHo_Ct#Y3|No19Ud3bv8 z*RJN6p(xG$>e51X$;z5f4!b_B*ETJc3aBCv^UUSZ+++W4k1ISi&n=B(o-Y{nBzxV_ zP#e3XQ?BynV`^_j-t{YhUtMEf<Vn&Rk$y{gB;fP|~;JTe9#8 zq59YK*DRqW@4;f@H~IR5)caKrt~eCvtqxYAuq7YIX8*3;lUKN$J~HzoBWKm!0{891 zl_ig_Om5u& zYe5x!-P7&1=flC9k4ldXIFWqDwWd@hvZuotdJV!#+eM`s4hWqW-p9!*o6Y(yW|)Uz zNAy*`E8Si+`mshSYp~0vajJvceiCYZL}J~)7oX?KkMsA{R$q{##+Ln?VfKRcPoo*H>~^J z@7ryYw>#Oz@5Ftij9oN-I5<8vF#e>ij1ssZYQ}_x5Dnx0Cvnfd-wX3!*qxRnw9j=i zixq^bQGPP{Y0J5~tela&C?j@_gzhuj^x7tOX6HQ|Xa~#)G34@eo-BTcKhlWy9an#U|MC{X{adCUzym+zdO?vv%7Db0%_nD;9_30dXPD&=8Pd34Mm z&!gOLT0+uXckK#$>b9s|XbeJ-!nR(HcMKdy?!d4Orim$aZ@#UIq$}FiV-8BaL~M{` z&90I%Y7Km=m05l7zQL;QDaMXDGoJ5+>3TvRJuoZUN_@T~5F)B+lIqd1CR`L=bPxjk8^I9G^hGJfZ{D`5?j&8m%%j zMB=$sQS@`hE737x%C#(D@R#ROr_=@+v{U!=_|mt@p#&hg=MT zbyX;PG`MOT?{HNt&+HA5j-4VOrr7!f!S7bUFQxr|yV~kred+Jx+pZqFq*JAUgg&L<^@gJdu zLqTV8lU0aQhRm|BKg2G0z2Rue+FHf=0TG3rzcIhUHuV~qRil9s526zdUGJ9;J3kj9 zsc4xrw$z)>qmOF6E$Kqj`gyQ(ZLemwvjyIF0}}IHeR>f4K~tJ{Lpk$k#YQ^p+tJMf zm3M}$G~Dl=DW~~PY;=r_95;+OtJuzr-M@RkxcE@0ayH|k0%72Dbm;^B)k)f3!r&$J z?@vczTN;j$Oy!}&4>A>AlteN_hxf}(6xG)mmtud7OcG}alv8e($Os+W|51JG)|SQk z?e7Mj~>XMQHnZLbX3%E zlk{rWJnegn{IWx#s)P*cE4G`q&DZ1{{U*1bAE#a(Pa0;)Ob9n1>?k6*!b`EP%}a)w zJa~c|3o9Y>urX%5Sz~_91yYrAgpbQO`x9YH_Lw=}lcUPz%X8y;-+Jq6>X;B2+53eD z69ak$YS(y+jz^c37G90|$~DjuZa(K%ugr)!G}z9|jTl+KCj}YjH2p-@vnKpN4BERR zY?fL*F+csJGRZ89i|x+?qxCLNLko3-ooZ=1o#=y3$=kR7nPFW& z@8gxj#3vJ%AgZCBY@+3M@AJs!_*Zg`{8mWK^^26OgsOiX>p8i`+q=%lC>#6+*%w+W zYqrnK!^TdUW|kmQ{ka7o8ou2n95T`>y?yhdN_jUzTM3R(aZvSRDT_C{)miUfOBZxf((Uz zkw}osMNm9i@tvIR(EZ;dc7fIU(%?$utiit;o;PMQ90vr(r}Dc_(Yd)>>LU#TfE>0-TP9Tcr?_I2TwevgkbAn5D=+)~Y9aXip6Cgw1 zmf`s#-Dk`e0$PGPOS?osT$GEKv6wh%*`IX~`e={BVhCGwQ!|`AN886VyE79Q$ zo=GF2m%K|DWp?o#ob*xgste&GX==RC!q{t9uYR+)sGJC`xh^cDihP_v(hIn7kP;F; zyH8AEQtMI;l&?b8wS*--FaE2enn*dHF(}wgGSyCtiFpOOs0E0NDu}!k8t%}9vcay| zKY#xHQO@I}rrr!$i|Z8ND_@>x|NbqH+-_9)zA3Znr@2+P>h71i|3rIm)vpsd25|KS54JUX5of*Ng&QKob_7H! z5x2>L2{}LIUyEJCr4%jAy7!1I8}GFq`fe8X*+!Z9ZB{R#%Bq(N@m@HKFXi`9{Au3v zxgLXR9C!9gJGRMslF;l{vpva$l=oHR(XZxr=GwU5fQcKU0;RL^$W?NhZ+(|WG7sy} z_GpUHfxcn!M^6AqimnKK^7yQMp9s#7zAOdJ;_=vC6nBe!4S0>;-qqsK#bEGwDqipo z71wWrbwl(b*Y<<`Vmwb=K&?zEOyJo+BL@{Bfli>B1oBSvf9GUpYhz0=OkuwJ1Dz3= zFj7XXJ{hbN0VL3R2s9km7+_=3-ot*r0U5TL8Uu&!4&uSpGsEClkR zID%4KTlzq6x8syG_DoUId&kl(fH2|)pSR7fADlkd;k5(G1T-+P?e6;KjZb^pZ|QL;aV_wF}Xg;Chw5U7H_oxoAEC1=50ZWjiz4+ z25^ccNM`?^jhFwe!S#Rn$u-f}#dD?4j~7;ZA8u=qO7H7T*1B5k9wqRa==)!&n&r9o zNsDccmxEFdk9(?L1lK@tK~rqTLwDCNiHMr{TYCtVc@kg43Yrii05lpqlk$Czr@)M{Ixl*J6$Up(Sbk|uit)gvmQhvfO_%H@2?-RqOP;4S`Rm?JkC#+^8nV6Go&pm z4cN~7V=(Vj260E2jIH|R^pA^Kt3%ghkH7BM)Hd^)z5IFaI^D86u6NiD(neeeDS#`Q&W5zsoxrw8f@(KJKS&zpnL6*43VAF%9(d1OgGbWJ1R$ zqp*1N=v)MMDW?Nd19B04I2Uw-PZh8n2q=$2a2ye{13M&8Qr_wtIMRnd%R*?XqofYU zTNXd>E_!tHVl)AhSjOw*w-2)Cu@qPuaIK50^xMbv?N;Hrs&GG@2r{?Dj|MfP3OC8$ z%mcc}AW{I@ldeD*zk)<8CEJ2u|KP*M&gsB{QfQB%pBe&WPhpkck$S`wu5Thy=I{IU zA#?=J?`(IrFaJgRYg4ZoPwrY)q9|IHN4wL8Duf@%%KSv~ArL~5+vIwr&;hD>`t7!}{A)Mt-)??a=TnMxWG?)I zjfwETy@=F;gE>z|7=Atch0fKtWC$ko&&L|aPmWMyO}-MQsd4A~+Ok!*rCJWFT@S8= z*Wp!UeZ3dAshU@!zI!S${~b`tFg(FF?U{d=oObUcjYLGD;&@F&`L`EhtWI(dzE?Ek z#H(In-dw(Bu!U*xbce>H+FLqbmZy39^H6El&flFJj;)o7sc7>p<{l+q&lkHK=`4Nx zTakOp;bCr#vwp@@)p?;|%j=%PWv0WYed)~|o4Im^vK(&beUj_HGRq98plpv^z1wJ& z55tipBZ7}~k3sfY$D_)Hd_AIf(&pMmML0P`j*N|+&4HqDb}!wFl=qi%KXOS6%A`Oc zoW(?QiFMi^Yqom2E<01(;@hKq{Ee#R@qQ&IZh#S2^v0&;bi|c1t#t~;-n^<=w!Mxe z>q(Z`&y2mv>$@6Jk@*qQB?itSl5nm3YVz_qvRu zlCDeEf%| zS6EE~zo93~;p)G)9=XW!Ob`1LX6Fmapg-PWZ^h%b%ci#;H|lh4BI%iPz*glb`tQA{ z$gbg)8_a*CCsy?Mb2-ozirj;L=50-j#dgb4giKWUXb}cFyt8w_Gj{8>evAz|X~ZB# zx-g5#CpJSl=I$ANq$QV(j32Ff`7etZ9E!EnmmPA26L=#Y9@wBiS=*))#>* zE@kxx1G3eb{;w!Qtj?>&kFDe58$1p^kD6tKiaKe#4Z!tggnQG6igXq}eDV8B*XGOM z96odgY-Nz*zMiAx;pS8#1QNvLMi<^Yc))G|C$n&jD?DxYGca{K`SJj67rWRs8F)Oy zEhpys&;eG6HQv@8G+D|xl;%hX5AvR{&7S4RG=DfmK{kIb*1YP;-BW0l5!RD7K*^#o z{2?9{BUJO`mU=xJqfp?;s~C)YIh@;nPeV`fk!LU`$E3e$do$AH{k6`;B>D2-^$aLmfu%=G(8Hd*~??${joI2Q|)SHu5YR)jA7#$ zHDu62&1tJCIF{^dwxr}p9W#2m_VE}Kyw}jIRa!&jvqlypDde+E!TY2@yM)JgFlYQ= znfEq2ou{fTqX^D=cQ(=I|8#MeldzL48@y@lXzAP96NLE`>yG3&qQWlf%9KB$!F+{p zI2>T-$FcZjt-eT{)BPP4iw{rHdmj5!hRzNL3m=!v;7qZ5&^ZS~*{G+WW~t?|B3Y%5 z*Q%5BMcI}eTG@)=)z$_-VNLYBkRyC0^3{nmE2+{`NoA)9Xaw4NSG=&t%Xey8>RCWd zt`F+q*YrRhn{tc;F>~{re}Exjq&WUy?rmd!Xl!ZqjRoYp$Hv`J6Ob?EO403v!zs1< zk`l4$Ig$xQluTKy?qkr5hBeQtE$9_@vZ=^#jvfT1Ua%NBXz0N;yT^Ea|6!fHJ&G%* zFY)tIUTKY)voIc&;BbJk1{kFt-G$y)c#a?}BttwvKWAA!h+VR%oq1*AhE4a|qL!?m zHkR7?a+$lP-jQ$Qz~qqgW`^%t zkpXevZj)V^MM?PGk@7kYq>;vOnHeGse;Dm|D3KZ@zgqjkVWCN_Lc-etNxUrVE93$ap)Q zYcNo?n(FS`Nx?i1SU>8M)ag%dVD&Gajv;%h?+E$CrmCSz@wn*98YhMF)REm~3rgkg zZ#KVXbTX<>fO&8-d3t(d0xCIAyZ+c!no+au^?p`>QPi*p?f~y+{du)|$bxrYCG*ud zrvmg5invkmz3~$|cZ3NvwXmmPt!w9sSEG8wdP!}}1~;^=xdkwQeE!O}a5U=;z(aF$icAFmXTP9PKIqJpM%gEE6qrXdPtxD;a-RK6Jb(^^=bO7s~bT3KRim3$mmDS7$%PJE#{%Ye7u{caSCxrzg_CNFMhDG3j^d6fjK2?*{jrT~mKf@5V09GK~E=SnH5xip{LnfM$R`e=RI!@;xA2%YIn;y_C`lKWo{j zsLi!DdcAJCNlO;e?bZ^_KPI%bSG0cD%i`rBGir-YY8-1(@3q7R+{K>eCVGP5II_Tf*8Spj5*NDh8K0eLpy3^ zScwp6*Y#{r0`lnwI0zRsbv%Rhv^O8krffCs^`f;^&tO8iAUZ^q$?Cv>rc?}bfG`1d zjLy23Bt(015J=p!V}t+C!HfSA{}OnC52Sz-*r7cF!VnP|N<&p;fLM1SfLLx4hF>|L z3fQHx-=1wwONE=gOVph#xl*+9H*S=K`@;<}&3;~^?r5@B zVBiXK!SCWP(ChglajSsYzX`S37i_X_*%ia?mfn}Lmmut`p|mY}XDxp|h-Lfqt5{uX zJ}B9{VF0zV!tM&WAUVg#tM5aR=y$TW;>O2b%39Mip8dWCf)F!Aw{Nf$S338E1Gf8~zaZ5JpL^l*^)2AA?0*D2COUu8p)b=av%JfFFayUchjCkS)e z@+XihwaxHlk;d+yFJiER?$-|USo@@F&-R?G`UkJm4uxu_Bm~rClh>rjYf0JoO?v;W zY2Ubh`vz03fGpP{QpqfSPY+g!&i%P;B`whj?OvkjckhE2V+Ymwc@?zlTcO@v5`r&l zxK$wnx1baxGG~^O`#;_)D29p~^wA?T@`i-444T&%8(byyoXkncr-nu=U){O%c0wSw zJ@sRn-C{t3C=EFX57lIHUwix$?L#m`;JF8)(L^3FvjIrlU zgVqLR^<^`U&0vP9=EVdPsTdYiKdJ}egC^O)- zxS&~3JDsO}DS60@eRTeCPPn#*OK}yVGTpQjn)je0`T~b`ByYfY?tom}QyB4adG~{^2DU};_$wo%w90w-KX2w8~uz4K=#Adk|DWIk2aZMo#zRQ!sQG>6%# z66~uu@sFWn<)(E`_4<&#$FCP;?-zS;rFuE*Q@nAc+m*sGLXvWcpaX(QCrEevu(VgM zuK8(P_|MyHOH7gyUR*F0-8B1fnzwvcR#Km99vo;}CG+*5(Aw>F*okU=0?2o$reiSj zBy!Gkq1yXv=}h=fDBE)$0+@#?!@U+R#@ZLtO2fjium$_o+wscu7Qsk95sn4nR)RqL z$lex|5O0h(uN7M!uWjnbq?__q-3c0T<26+q z(JJOF&DA_#5s=X9w~$lN{pwXZLQB$ftlqw4USy)FsZ6kd-f@|yS7+aIWf1cerHOi; z2_9G$io(-K8~B%xgTs=#(W&x{-Tp9(_@c5F$xC0@+NGdS_827$ZohNrC_zzv#3#{o zl7{UNzreb>w~Y^=Xf@bUkIgQ_m*LfYH{LX_RvX|>`!`{#C-q0?m?5@!cW=9SVQOV( z)ca#mDF;?%YTNxxrNIO7tR0y`cFWWyIEaw{ZAiLX=J+XmalQ#Grc)~#kYXc3WK#EU zLyD)L7+93UQOF0drumB6JavCu>!ZAMgv;(xn#GyZ>8@EV=}d3YtlJYwdkGDVh~#z- zFuvaN(HCdwNNuesMxxb+O8OV4@Y77tsov!B275m!djlae#Eu-}%~*7PxPW);^29p_ zn4HDXM2?+zmF4YWyzPA#T8~TKbQYnnvcfbw^Ov+2#E(C>aK|yJ{`!LU_?%wD8R%u- zaHsRG2&4_Rm(53C(*0Z$3}`=&(K5DCRt<;%SZF2_**DY6FnVVi4)tzFbLS?l)qjt2 zsZxhmeZn$kEzV@@mmNwJj9B4_CJIdyTA2kU+=LR*H{&%?=6)k1t=9%E?s8V6x=o4S6e}^6TUD@;qWZkq*kHR9i#qoiAiej&mTwDLX@OrVtS#+^U~S$ zAFsG^bT1u=yHJrt@;RNLcgo@`YD%kTc@=89`#IyD1KK(EzK8aEe#IYY!nq<8ToPSZ z$K2y`Iqg)U)e~ug?Qeo=_!c7D0sCgU5w1i2!)nKC8;^yPQA@9BA#^6`4?oLl8V~bG zJvqsh`3AEqN=~Y}TTwk}dcSsWZ)mU2#($%P+@?1c%qd z`Mu>)HTJ*SRzw_b^5 zk1ZYgZjjaS*gczTvo~IXvUkPwF{3!6hfaKkMyV*~m>lRBngd*YmsW8~-r{&W&hP{L zW@j090`J=n9y*_``u0hp+q(Upd?5#u*<7I&o5qn3ipZcZYjj1!*ZxW>MZ<<0ghyUL z0+VLUF)mlUCKVUs zitkLe`G`9y|Zv$(@SfX3{u)JINl9b z39+geR@E>RwqF}OmmzLh-=y6lf=Z<2u)>=5(zZ1gen^OwZ`3I+D|4>hjsi8)HRZ8a z0v9^L&TIQu(@VFfoh^lM#;47qOxT`yMBzMJFD#xnMYsboz}!f~G=C17dTv~gou??f zJOQf!8tE;rR{Ni=8&0Lka zPT1avHCaC>KSK6MEVYQlNKG zx&kw`Wm8GRn(I*nC&rF4rS(gw-YmM02$t{my?Pef!EgDN?Rn`l8(s3&34I`R7_ITs zpn|Arik^VUrBLK^mAF)~`D@)%zPS&k_7Sx>XKUv3a_mv*^!e^gZ5}_JGx5P>k$8u$O`_pyxREdvWCvH~+v95UY!9VT z>;*E`2gOe~Vjan^oIfC>liAt-Vbe_$yOv5Z0z#cS?bZ)prRo0qgd0cr4Y8$tKFDsL zw3~!waf++_{&^i5mmi*w`qKchq|{3KdUnk$RVs^FuhVS^zZ`JiLCQ)i;_h{a_&Be_ zn8lsoWrX-{{APGHob_v9{uLzIK=sKJY8H0s_H~dM8Mm)bD$8=T2xB*kahE0;y76Vh z*|hY1l1JG3OM<%6o<1I6|WKc{Xxva0sm!WCdh_y=^rcTO|*bH_N{1pl64~mL$JYwVH0hih-NEE9bb~62-dT63AZu9`HL$73P8- z8$Q%bF)UYQW`SYC_~;8*Z$>@rQ~cFG(~*rp=AJ?Q;bA#7M7;>zSpO54>Pa=b_NqQ;X)K1}!sb9C#bEKvw z4qQ+dcAk9QAOOFkiRzjtnnHn(r$JWjc@H#TB`^tJJt^DA)ell$rN0+-n*4BaS)9r# z5$rHC6?W7UB+>^~bF*yIcOhY~y<=OQ&qon;P2_fGc`5Gl5-+$80gNY0D-oTWlcRLY_!g*;ZUI)M zFEHm;>n~%6Dz&BGCuJnLof+PMM#|Ybj)vqvP4di?sj(e5fQ+vF*)xYzJWGyE;-8OC zJbz~Om+<;%v|Xr3(K#`c1?_qjQv75;ar`hMGU|`;wSiPF1z6KnjdZ534Yzwf=9&pX z*E75@P)LmQz^~P8_j5JDmt;eCzB2dLE@=$iOE2GoG0URplx%lP=|49jJ(VqPx+_Bj zcm>1ce-*y|{S`Ynr^2YEVLq(jB)#WUO(yh7ImnYsSvTUT9fx42;zYqI2%te(AW04R z?~$nRP5e*CSgn}cP^%K(w$1dkS52n}O1!~jg0#I4*7c3vk})%ddPD5{lqdxU=a6fuayUtIrFnN9&U<;} zKR^7%`c?4WQYzA@bio#wZ3yxcB|~vw(d#cIlQBR74}MAA7LbRMu&~)(u|$vg46VDbpi$%jD$upV9)EXHmlk8WSvbWnRZhYOGY4ZuOXTQ0~; zzwhrlQE{)Q8yo;VO-#@HH_AJ~vHls>SgFTnvkjh(s0+wobIOaNb-Qu<9FQR%M?YBc zI%l)x)_(sSbDq*tOA$>otlIWH+wHud5GLP}${2c(A}jW}@=`x6*|^ACEqsq&jS}kR zbiw#z>AC5Z0XFa){(QD_d3OF)d`^~zG`~B2wf%B$n$orRs(K*#!vRQ&&BKj}%Ez=& zo7Dx7r}%6?l)L{Su_;^p(h(*gz|9K$hCG}cii^}1f2t^XG(DqatMRd0v`fYu0(d4Ui%rK* ziPy);9^1`+5g2BI4*R^cgkJH5eXH4UpFAK#l$6U!-l_eonzARUD?t)KPinRqxDRMo zSp0jcOw%SZd6srHNskpB$(Mgr-#0P%AJ2W11CO9Hi-<%}atMTs1_uWpPd53SYoZ?A zAZJq$c8?&WY;F77k^^MT{@Oiw_zq+PPQYz;7TUFV%!j7{q9{%8S0iPsqOf%Y3h5(e zTWFlm1do^u2MRi6gv5ZiVNiO397v`t563IKl0=fD_kn)d3Yo zZhuCZ*W%KEMFZ4H%oAEM7Y%;zuQwtx(jIDS0tGDfNQZwnfuR3JHpspMG+O*W?32&l zQkCOad=P|HXhZDAW07H0R<23R34A5ca_l}V+oFwa}TXw|gMXm+gMI5Qn6^Pat!3l^~Kf)#RT574a(e6`!*7oTSR z0?n!3H)Q%2c5|0zKG^O;?5<5IS>ozFVjCl0a{vfgeWwMmOaOA@Vt`VTp|9?Sh|6y?b zm#@kHr(oUx;F?9*1Fw67)pjV&Yc`p|cO|n5q&Mfc0Tx$$)&#mSYF~twC(Er>K$(fG zJb_^xP@V%s(U4}x_EVN;!9?U#=H5>MQ4|Ttj9B5Vx^Pv7MStJ&U9ay-2?;M{DbN$5U=A4l1oh)T~`e&t+#h+CH#ONPz z4?tsgWWn4~ZNQ&nhrmi&S@BvJar*n3Y|`vuO>K@kUp*W6?MNoUOJD$xy?nE#Lo?>H zoVIB)aphp#IyUbD-r=M2J-QPBq~Q|tF0h4F?^g@aVwB8iic2ggF2KfhbZoLWzS_Lc z5HKIkkx-U6H6+%u8~w2pt3k6`s3CyQl)QUM&$4a<1p^hI&}V<6_$j^$*>!IbxdXfxC5onL{Kf3;C#>+5d75d zx;vKy9OAweM#z6*$oQ?fAAX^G| z&w=j4&}xE7i;2;eK?F%-F+X(Q|IjvooxblPk$_f43*U#q;&S=|&i6VtyZKw2s#kT3 zSy9S}4Qod3Q?+3V2i%J0RQRDq5z8-X{75>5tgjax$uqsWQMoDlvs>V zddfqE$HV6v6MJo1Q?b^u&ZF4scA5CXsnXe2_vM;Q`h_AabpC+m&{*$?!)d0$XHlfI zw5Z$nQJi>&=l=>(^zWsI{3J!JuyO~e_~HDvCQ^Vo-;L;g@)kxx=~_1@OA*q;UgpzN zl-R0L-L=S@Zo2@KXjJq#Vh8o^>07S?#?X*Tbq}qCIr}h*Q z_a@jJSipYJ_}9xLp5dOdeS{^M2#K3tJP{34zsop$Joo)Ch-Ep*F5D-^T3{!|Oc?R= zRIO5E57y9f^|pPp=xF?B)SFg3wlU#GrG?#V9^!GqGy5UQh7Co!Hejm>_rI@~DR!8u z$$G(nphhV_idZPRimutjxOE<>q`$333XpdWQsye07~i~MlOtZ{{FEtX`S;h$t6kgy z<=f|KsePg&*Ovj^*rdfOtmJ)Mf;lajf0gJ@QLf=J%jYO)Md`#Ue(8%9IUA)OH4A!& zHm%C9*6&IMr?CEwopKF|o86NU`DQ=^qA`ZA(Y4<4^y8>&xng}O2=lg7^Q8>O&u`~T zVvZa3!C+LL4o5}2WVAAa3zYhkGgRLlQE+v_ij>uVHtdV_-`9bw z!)49^N+Q#ISY5VugTRese(I>uuoL9SE6@_!PGztCadb_98skm~54;c~D@$#wlQr1r zRFV0+3)067-M}P_aMwxiewtZKfhF(mT)04&=36Qz3|E1ek+~b6*S3u9V$11C)ZWhI zSc`9tk7;n+-(BySwPp9D3uPhh+QwnN_?Hi@R8+a%!hWG{L3l*vt==eol}4e5mFB7> z*;YZbTh~L+`51*i8TbP#j zVo&ZqD#w7^i%@X;l>;fWl5P z%x8m?bJz<9NrPsAavJ6N6rA{|+WqBBA{)kF5Dp2_@wwSdHp*a(>YaKx>*izeF26N* zz|{Vr{HxKZH3rT9OFS!7sWs&Bm~ki(bTMBuQ#~m^G=7Z;4*6nrn~icf*|z1yp9k>q zVk&VzOaaeM7cjMY_v|shmezuZ80p$t+U6&--=cQodTww$;?lgUlH;gnxaDUH7mW**%HoZ%_ zI_D4YKmtu?K#!Z(HTb&}QL2S9>J5Jl;QVd{T40A^^u0WFL2>{iMhsxBVH;l&c+wMf5dU5}LsgU`NagB~hfsNm#8+nrEK%|Co&1$zsIS zZExS5^|{Ld{(S1_Wt-H_zX!-Ypp5fU**W4j zoCH5v{pu+l^zkFdWIFuqcUOValF|FB-0Er2hX=-L z4Z;PYbM@dl(Ub2h63`U#tcT?rJM=v-*O<{8WOUUxb~k+}qCk66eAxHRQLLU6&SRfk z&7BGdn;ga_In7F)xK1yeDaj(e>8(gUn3LC@FB!N!lnhXD&nrzU$?_R?u024Zz%C`N z$dPCg36y0m7Z173cOwY@nW^-JUcxPa!C9K5U?b=#$OBWnOvyELqcP%(E~S-qMmIbT zJ@lgb1ud(L(z})W-yS~+PO4y(GwUrLuJ3y4qYi)Jx?Tp2ebUjQq0S#)lHNxoC}?jX z^7^}DzlbU<^Bfpmrfv@%ZlSLaW;@#ffS9u_A z#lA&!1I|<;R({`6mE})-7c^Jl;4VwBa0t=?k{`K!5Z?-R-C;VID`%@lpGe4O@Kf-2$#9v6brXZT_Ug$;GnJvMOxc2EmADehWVV6MDJ+_S11qXJrK9ew$k7S?8BK%ub< zb78|0KqxbEHPN`T0*p+r{Q< zG3U4ztyaPAmlr;o5!c3dckBGYyOOWgM@u^X*p3*LOu<^C@}XQeI^7toyhmP+Py1p5 zS4>UIuH?sN@BahgKIMqXl+2tGD4$*9nH;E>a!~CuPDm1Wc`>^F^J;iLb@+ik2UFA- zlS43zK>OyYAB)%D=KOmg{l4NsUwu2{d_Qjp5Xlq9dt^s|EM9THyWVhqI`Zj`2$agq z1AcKwVE%Rdc{UP0ihgIv%c-oJz*#)nnv;>8M8;3tH$t6~MK;4mTn~(mAz<2Esx{sz zA*H89f1*`vtGN;({{3#w3M=D@w~b2(B3eY)IS#8-R}hv^HzS;Bl0w8W(8>CIU<(tw zeT#?o(qdtezo2H@M}u=Kj10^>U(D@(M?Jl*R=CA+h=nQ$otQzR&}A^fz^6~G;vc~D z9K}joPS*$_#iS_F5=8)bVv@w}T+Iq(xH9F&!PvcfSZiS(H90)`jPsCLL3=~HS(NFp zbv5N=c10_(ws*~Jg!b?LOo#6zSO+~jWJI|X<*NBrRz%#_WH?m#hnuh~Ka6_fek#pL z2lZ8%CxYMaI#Nz_pJG#XZP*`FH#m2L9B!i0Pw(lxEywLeQhA`&vdMvNJGYSFl*e&8cm>?q|r9rI(vpSgY+ zJsn%UrDzyDmfb)aC!SkK>)IrE;VB`GE=nP~-)wwj1&F}`;{1@98@ns zlpFs$T8hcUBZe<5xI_{Z2St*M=4JT%4*cQrM~^Z)FjhIda8q>hByQnLXlDstc6-_+^_~FQYs0b)B$W#=8(9sfJw`A#( zVET3W5~TB5+l7SWe@402|G+E#Pbeh&_m`bD-mUI-GV=Qu_5$~j5b|YL@tvU#Afy7` z13P%i=L8fFW&^o@QO&jsHVTCCwR0}YDUJacKd3}yrbie7NdL4|K+~l8)FE*VApBx{ zROT@kLPd!sf_ynnINZhru=RZH5evvVMoieaYVJ24&H4=iBfB!4JmgT??=V{}{M+$A zWif9^Ut2!=+SFqLD5-tg)?M0F;2vuY9sbnze_#g6`_c|Y4p#v~^MU|k*!LeZ1_(CF zeiMu&=Ea?mzmfbc;<&GjXJ5xb=0{VRVsgQog-%nkSZowu>ecM1i6w@}G00neh4Fr= zBAzj80x%XY@nYO`7!d_jV}6{SYm{m|`rtA|z~oew=N)I03hx)G_SzFDQ|=Sa*aQ4U z@3dVkzy>UgBUkdEZ&U(7$dOUx_KiQJ_#M*aQ7Mj7s$XbJ26?U+cRDv07PN`BT(=bXI9k?3|yXo#|{wlrog$E{o2qKE=vS)LbyYaEo%rKrn+YE## zi07VP)FS2v9EYhywkFHSTlKzlAY?CbbT8!m6aXas*M@I$C7iT#$iN9>;azImqxWm5 zMeeaDU$&eCL?m$${Ki+S2)W&U#aN2gWIlPTmB1#L9E+xcD70^qSdI9Mrpb!X< zLDp7tlwWVYra`)W_|x;0SPBLZ{EG%U7qLJwwCi? zv$*T)8=+IycA{H+!|F#a!XReDS7m~IJ91}&!QAL)1Ma@O;C=(2!D79?uEJuyzv$Sc z6+P&$zk7|$KXmUn)dlr5L&P9QXWJ=j2{|wY_h{P3yf$K~ zrq2(sZpqwEFV&2h%ZgD;u4dxtpmS5}1|fzHf@X&j(QN%io@3R8Yl?-)8xB=N4dxr|vj7D0vf;+h zw80k8qJ=>OQ_z>sV4>fAxHWp`TM#vq(zwO;B-om6{9JvL1>$-_M*4lq=dFyw3vwt* z?xeHR*+VH!l1J|zpH7-ReXmO=S7$15^l_l*5|rn$hi0>LcVD(pcGL0ubsVgS(z$3J zt+|ZAYcmp70B0Jc;{|Mj#_vnu0D)&Ck0y-hSa`%3eZGxV3QlHDfsy~vl(ePtSWA2g~Oav2OGf0tk*8t4glz$tCS^BfWwk}2et#72 z^2!@255C){nI-(t;#87~wcSI)Tp9Wx#O_l;lDcEi-_n++k>dA z;)kfoWY~QBf`|eZRN2K(gb%rNt(Bfh+JT~ZBCLUp7W zhP)8!ANAF(DOSG;CEcZ%;Xdjwr|p#l3t7Z3^CDt|%^udJtvXE7_J{+$KoT$kMfSZY zPO!7DefK>Q^_6N2c7CiYlY)L$zmY1AX)`@d0f$f2-ZpArHPF+_B>8tl_MiFc)gSLY zs8eg8JQ|W8cjUq~o9uY6;CnR+<&+&lDjFBM)VUYak&;)^_DFgWo?O=v1$!y=?_jK~ z#UcAnQR=|Z@wK-H9^F})mL#=|UbwU~=gnmb$S^ET=HZ<{ask){NNAD(flWQft?i6X zRjXJ#YB#t!YbQF$_0(@i8LxpY;P4uWa_|V0>QEQWTC(Qpyf;7awFFbNxsgyfJkoL# z_asy|TBmX?_*1RgakEZvdV%Ljj>Y#%h=RuyWHSzZuoHK}3o$>?TBnMae`fDr-CZSLayR-?d9XktFW|Qb%E_3X; z?C7+zstV*NW~!Rit?e;F%@7OWG5@pSI#Ip>Z@?uyo|w5JH!Y* zpu68s^^(=)1C4FHC5s?YTCLCiz;{o|>=riH+O@{W*ElHl(QgkUazb8Igxe^n;Gb#n z)U1rGHpl2=+SkA&{q4SByXUmml?Tord4FEc`T5ra`PJ2ugN{5{ddKb2J=@wqV9SA! z{4=-Rt#d%;96hu!xT`A?s+x9YPEIK4`^HS_>&t3!59FN>)RdevnJcm_ITLJk(OHJ_ z{P^$dWbARu=|VGOt=K~N=^hp9W9R<|q-kdCb)_a3VpY`{{`9ekgm$|>^~f!v!A#yx zAuB4_&_xQ2?ZtdbX^VTy&5OwZSRzZ>pgsKH|_T-YV#wNwXyK!h!O9JGoK$v zJ&hOH6}Oi??SI_N+)d2P%GY_Uuty7ZHK(y+3B-E4&tKA+OhhK|Za;2kRM-Rp$Fequ zu9W|}JY3(wne#h#$?6*QGi_S?p1E@aO#6iW)1q10SKVvo595E_VRmP%LJiu*d!6z59=gzm8e_jfgse`Uepu z)&Wk_`Jq#n&2MGy8MbbHe$#8#SxD+brbaG_WUF}T?djBg+BF9Dl{MJoj=6s{B?w)M zeQ0M^?c`@%CEvmVU1bJeooF_6uFH03qR7d#{Y5XE2F^aO^r`yby+4fxe&gP<+e2lh z4=R-zxP>@-^;sZ60F;#8kZN1*N9NY6?UV!MnAblkmisu&Z3)YlPmShSY)}{6~29@jb=aplT$s?Fa zgFq`BJTG14d^`wPo;d52(ywFn-29+?S+Jj2t4)BkvI%(mBbfQ0mBIGgEl8FrFEnIX(k9OP>iW9@aCWXS$iNwcy=dbh#ZL%VaFiq3-3 z)R2e{90i{3wLO-{<7FOc2Agz=Sb^k-K<#F*x$Yo-pdrP(f5;13nmr~fBxN^r1q^LX zOt{`0nFtkCUzOrlq}Lz(s=!O;ecqjj_*H%+M=II(#DOEX!Knpm&IhL3qy!~*i}SFC z7->i#jQW>7y>3)QNa}_TB64kHW>C`B_>~JV!OnBI2ajBRdA1*fbyCYNIZ7N>dYFD* z$gcOA(%p_pi&hUF&}SG4L2TbMN$@l4%FgH=f2n5PM~OFXO@u`%|?S zVz7cbv;OVxiWADT%kwdB4{gMKkb0Ze{cAMmjCI!Gj>I?hu&|1P^x3#0=0f+?ie!ObDX$W+ax)VKF0^^>{dC}pfPkU7TKKvC$ZhI zRModP(?)=?s#zQU=P@l!-y=F+IbxlJ!Q;NiCRAhd`9tNV8KxVbZNp*$K&!kdxwL5~ zIlS#%q~oqcP&}b%s_@C&;*WcSZ;7UEn>F2^e^H)@fSF9*wUCFYDMO%rIpAg*AX4dMe93P25* ziSQd`1#uuQNz(S4%cc~F8#qj~w>5Fx9Dn0=^>0uTIIs%4&Ig;xe*+aP6(U}*<3gDf z9j#!|{j_G*@fbQd1q1|>%r3mN6cnxFJiFKac@A_NV4m9GO=qu9rh=G-Ta6(1ydK0Y zc+G)+?H{DnmZZ%e_www%;rVMuPKM7xz(QYfZ~HwWD1PuSpoF0>36zvc+N<=kVgY;4 z7OcCB&VxhZO7%c-mTs^o;Q>apbH}tIE(dO3AOM1iF7O&pidB@j(uMcm$A&Cm+mha_ z8ux)&g=6p5DFZf$Z*0n|g35ghl-?~6OyZlRv2Z$Wxs(TjN)k`68t3Xh`&R{Q6-1Mi zgM9zjU}3*hSYh2R5|sH!oVIBTFKm-L)eo{T@3$wOPbh{2>f8g7LB|zALU1LxUuE@r zn`~|g&MTRJNlXh~UpzB69>qC8Fx#0(vN6)g5BxaypLw*at@*o5!bx%ziBj`T6OkQiRFo;{T*!v{k$*EiG+~SlP_g z$&gaH^b|zN?pBY9n?ha%MTCA1+zC4jmVH*XZqsofdag@SzckIpurfPbBPP!K;{jcX zm4JSSrfcVm4>U=FT0`zz8c_F*6Tj~(Iiqn~5_tA2WS{DZnBvLMr->p5mL&VY$q?UN z4)$eDsFqpAFE1L;BpmW8iqh&%aQm4CT3~ne2cJ8?ffH9`AMgBM6+Zee`}O~rq|$$` z{J*V6^`E8t&(i%rQRn`@a)SQHBmF13`rpy?`|n=VOkLvx@p|!Cq%j1``=#;q3~S|7 zAIFtc1qDj5f>gyi6yqlFG*tFzirgGulYYQ5W!z5S4qdneO6U-n%}izrod^M4l1!&=F4hD18SU5;_%_>>5rA zrePrdgdR903qj*}(7fq)WrEuKm?*)99r_+As+1opw>BKJ~F(}1nSfD@8WGtuQ1l1gUzI$rf{-aJ>U1e!w zf?@|mx3D?itO}DcK_7pH=en>XaQai%VZ}9N1LK}o#dz8+csoRK5Y(D?4d#r*GEB*- zgtjHj#T#C2O>d^9L@nyV1@APnss%N5B`Bmd55o=Tq29Bp&5>;}n!ILG2u=s}9Rr)` zLtmyvBryr|x>YO~NgFG$pES(DOmV~cTX$RsG(mw*(;Yb&qhAJ49jI^`MmxE3?%6zK zcv?Rgfn|tlKX}ZLwnvPV9#IXhbg|`$4%2K%aZc<9RYch^4?RM{7yhLkJa?2kQZW{H zImcATsd+@u;Yb+H#lQgZqWLFfF+ZGGXm#BnqbJh9chq6_3|SFjRBp{1!rbI(uhOZj z9gg%k3?SEfD6HR7zNf-3U^v336^&nDAg!tQX@0tl;oNaiHqzU$-;TOaFTTi#`RAi| z@WAg2MMVL~x2*zNfjuPC{f}n8%Pu0TDzeX&rpF{Q{|0*Jr?djUCD7(oi(-PRiHcY= zF~#go1#}$&ADty$Sl5$D^NtE&FJX8WYnyxU$&o9e5z48qWrA3L!#c)fC|uDPJDSqg zI_@#!Ipk;Tn-A}COl{~{YQjN2n&_9*VKrwwhyA{Rn-w08{rJ&@QpX};CJ*5eYL1FQ zd=A8YA&W_8v%nRnDps4i&u|ruQ%Z=g5ya34bQm%@*Bx!wv&Sf9n%WqxuB+&|Gl3g- zm9(oh`kJnWGmfBejzK$taHghRZx+YtK}~0a77(;<1|6>04u#Bq#2yEMuRs|?HY`0) zyrXHed!(_q0+<~ox-r@g=ced$kf&4f#542wbIbTDQ>Osb&>O#z{)(9t*X|0WVkkWM zWcev=hQZb{B4v+JfyK}ka9fm6LXB?%a2B@Ai-xg>VIolrx;Ie)w51`c8_K`*;_YGC z%GO7%cEWkV4IvTjg2#)fo$)#T_(faf9JW+>ubwOBA zFOJLOwf-Viz-zt6u*_`pN1nBm$N(r1K?~-KYtC?qu#apyQhw{x&@dMwP>v=KN{1Bo z(lXJA^3PvRlVuV*#P&FS(8+Hki?LxkX~qNA9Uh~I2~8%nM>bMM+H3`z*N=Twh7n&3 z>>sJ=4{n|*edOo+ZDs}$6$ErpI9|gs*2^-CWkudmtYD^-4dHHV(8BmLL40C&Lli$% zp!64WC2p*l>%yDqtM{wauxiQx^c`60&Nnr$X|!bJ*t`dawDO|r6H9%{+rByT-{Qx( zlO=oHFnDwc#i&2GvUz;k?ywUomGco{npGKS#GYy7D>T(&rm9lIkz>_8;zpM6=G>TO zglba&f!l_M!BfRZA;}>oL=Sect*4)%bcuVLM~{x!tKrSfA3W_}#(Nfmn^*J_y0@HD z8Q(X`{}2_$i`n{`*gVVp5)5snO<=DIt*ch){GH!PC5@|BMH*XA0ps&St&j$*ji^aq z@3Vug_pt+Ii`T{~%kB(?0cUeAd>*`R-~B>4xreiGGV70<;Yb|xfqJ=APAi~&7cD$iRKIX713`N7Q?%#O%i29eng=A1$ zm|MoTHoJJ;+i-@Byj1CC*??h|&$Z-YNUM>E;eDuPeKEN(c#{ToiVLekno*`)Pgwl$ z8k)JBwL)1ds91OlnhFe3z%|{vzdB%YgNuj}%XM!qLsn?fLlh?GaI{KC8k-)1qi~9% z;iHrrbOIyNxxcTz%o?0>9bSf-eu~AN=W6|#5k-v_WX9s2 zoRA-`?%BKG2E>J5@%f1|v_>$vlW^u-P%qTPv{8?x|2v9Y=*Wz=Q??J%%Zf;5Zz}gXd5Rguz`1;?MY(_aHqMar&EX=c$Cht(^6RO>ZZ#XIceqH-VC# zQZ^I#^zu+_6HV}ZlyIGOh-5zH4(uq=6N}pM)4j2%d2?_;I&@uMrDRAemO<~-T&QCz z;^zlu?hb|JXinEL{o3NoD`}_$om!N<(9j6b_gYcKoAOrZ?T`-ywWd8N<9Vvru&_T6 zs%`i%)fJW1UA~l)S{)6)38YPO(Jb2~L=Zoy0U=;v61Y5nsiLOP{0Tv5H=3jJ?qFV1^Lpgvi*y`|_{ zP_q!IXt?yxqanN(xdOja$((UUWEHEUJs5w9MHp;c^BHAXQc?UsDo_t^5#;`3Y&3rM z5WWc&c*?k42l?_E0gX=ytZi>rkvy6sNo>T|X0t6u+1sC5Y>IEXoB`J@k_x>1>E(5R z3anxUHyl<(w5*H%np^Uq_T3u6ZC)Tunu>|;huU1i8J5jObncD59$Wj?SPj?B%e~>q zX|AlQ!3#PVr2W({c2P5Ah@JJ5zV0X_Ax97pxxnzdPF~Y^SHZF4U#JTx-!K_ygpmoBkb8^S zyI6jB&1%5TcA3knMbFVv?N~DyP5?U$dlLxGgh{o_pY*v!8U->Lb@ zC9YPMPfQ<|uDYVL$yKC;1XQvQIXyOK_qhwkRv)#r`jd8B&wZLD7Bo0OzUOFta~Me- zmo4HJLC3Rv&pi!6KUf`98vfQ*J2_CglI5&|zYg#qxe)-<+ zkud8N0cdaSa4HIm`@VIE6;5&$aRqg$Q@^Oi?tpbqQ$~YxmR8nP$r0)R6}a`)UlZWO zC6u)L0e*`H)xfq@#bB%!IoK7M z&mh*~6|7lwMpV(aECzdU)4htYa23hXCkXn;&)JCMyEsjAH(wXA5(GVHZ0lP*zJu?> zyJdBfRyj^@!?pI8t+=3wLmc!s_fWu@Qwku52@7O)I_-+jdeamaZMyKUJ=i_XhMAhr|(}KZ!cpO2w`Fy`E z-|q57e1aQ8hRE?aSRcivx4JS-g5rx%Pl=S{S>%W@mz3%IdLJ%)zxV z-*5WSHTQH6axl~bmt5BtXD@rV#jlt;TJ{8+)G zatlfAp*-TWt?#UyorruF#hvb#o;YDg~E1{3YvU7Y> zNx?TWV;oorLktGV(4YYZr#5k49rDLQVuV@2e0@dM_XaSh(|oxVnvlJ20(>5(01XHb zvvIg_@>FbPfZwN5lX`#TMj5j)5}tb9w0R>`3se85Z~1L)>nO-8+OVb&9$~~EwPL(l zO(D*t->4s6uibO)&UlL}6Kx3xzUKyK@{E$;y2x8~p(bgOf*QJPC>+2hzfJMzKAkZC z{H<-tf-HV76=>Y@7Nji)r4RQs0YA$51{wd>xYWS4O7|2Pqotvgq9y4BkxnF3pD$*L zUPnF&+x^F6%-5QNU(r~4qEPoyu5b2ciFh*rEXacS@?Fv<{FOl% zFPn6edGjab@Ic{y>RO_$>ES)7AKhXieoZ+k(vwOa$i5<0cHhAStvf)+tv9>9}n{DY_86{CC#7;(LA?d zO@Grwn7K&MWQR7IxQ{iLQA_Z)*1YS`d$d+YkB)p4KP=R!bFE>H<xUMwdpjtds7Vy%J^u(JXi6XJ{9dA9fM9 zq1v3kS=Dk`OaE#oiCaG-c5>fy=X|VG+Hn8Ts=79HLM9U0#rdk>8wOXEilP#c$5! zdhNV-OhJ04PE_NX-pw+fOket*~uEwWX_!>bxGc#qV z>M`wN`=MwAn-DHcmwtl2e5GVOu9JQS>R#BvqYnMT9=y)*ce#PZs+6|p$5tssq3p{h=qXH}NR$qu+<2iB?4&i}-%JiE z{4^~moGT>YxQ1L#$(-49xhFtEEgX9}r(2KetHAoeeo*i+)L5PguDWUu8v?BZJ_qs9 z)+W!jrd}sMXN$YRdEd>k+e(pGd_Sdn&Ud}q9->V?g1+c;rS!?}8USA=lPE}0w2W0@ zdFqJjzl)IB zy5yr_yvKO%rky-Gb(Q?PW7e3-5t;y&D0=T9Ou9nPrF{>O9ucL zMo|kKDA|2svyNa|O?5@RtE(dbNsoVY9_Qp3)+_{v7FH4Ejh*LdK8C4$l$KbuUOF?C ziDG|SBg9p+&{NHpCyWZ&sF8+Ne{A143-dXJLFF;L|EL3%V}e1iS>3ahoRZ;+C#e7f zU;4$Anrq}pXOe?WTC5P*Qao>0?m(^klc_hjm5pfM6V+K9ePl{H4_Z*|`wHuP5$0;} zaoY0)l?)q)ffGc{3=t*f#0i`3dVmiKFe-?hr5O?_FcnOr0)6V zyZ}R@zJTKGBn-j2dpIQK%Zzg&3FtVxKA{g*Mq6_hSWp+DeqQwe&1bZkyO!fl#qedq zz?(0Wk)-Sa86aOmHQ{_MUS(%2s(_4 z@@)qmvqsk)tUJq?5__|v1col$QfU9jNghvcy$x%|9BMY2}yumNh>(X(nui#tEh8qmN_DSD%i3zprpBO9MrF^3m`$QNrhDTmbp3xv1 z29jaj0{uHcpaU$oL!4Op5vfMCN7nMPDpBXuOC2_*Z!h8+Tk(t~1!UV=ZJXd5BjS*; z;LA&OGOUEWa?Qk<9XtwbG8*>aE19&41?PxgeEKejW>R!aRrd{?9v7Xl9PRId)y(a` zimelHf`Bjv+JY45j0PCOc6{Amz+w6Ju$+E-04#E#JNrMse6-?fQm`yjUFWxWi1e=E z@2bws)}u8KHs(wPBHIMQL<`aqS<#Oqwb#iH#VAzf^Ug%Nk(sps&hSC|{0|IZf<00i zEA#Trrd+eW!oQ?1EV5n14s_Blv6IRLKODz87;%=QZH_EIijj7oYBBKIfzza5=w$na z5uBsB$_5FTu=6|gylvt;qb(nsvQ3#@vCa3u3k^bYyCHWYiQgXc^=!)O<)Q`R{) z%#E|B8Pp(3P_M`k-YX0SHOJbifI z(FE~bStpy__@}NUcay?QE%T{AXa=X3TY5N75qy1lPj*8YG9VH$#CZz`m`u5E%|q+> z3QbxFimm;x@=7>g@hTO#KEEmd#{(SAo!~K=Dci2+1S4?uz-k81S<~njl1`{2FYKr$ z`YC+YP)Ou-?p6ia1OeZ&GX>@PCc0dZjw5tJ4@7}Hw2~D!jlK?|Ej|@p+Lm{br5gqIEVCr9M=spILR0`z9o-okG*BXD^DX~_&xyUJF9$orkE&R`$S$!~EpKE_ zq-%1C*A1t7(-$_G>4F7%dC2#r^a7OLHX*sUO2+LAjC6N?PtUg7&N;0}@z<+kOndHf z;Zc=4bE$&QFO?HsCA!AkUn_+;bt!eroOoPt(I^UyvfOyn}Isu8zYBw#d zrA4wfd?Gg=jidHMHZMMYRv#G5LMqbh7d~xfvcIRP@gHo^NS(IjtG%S%DF#bGXB*@+ zPA1+1&vRBoa)F#|AyC*kxDzUP`3@v`5V0rH+tXYoJm^VdegW9 ztNMlZ#SAs5fY)jl#4I2i`K&!y`tA6X9)A+ zVueu6`}|JSFMixgtDjRAFb!K5f67*^sz9$RlD>Ut#wsGi(NOi?!OVFz{x4M9O>gW8 z>#qDBkBPSck_Bu(E7b)^ETJscDREI#`8VRP0a^kmi!+W`6{OyRufEKFSuvi1-v{B- zs_8Zs+X3d(zQ9>9^$$E^(br`Q*dShsNR?}-&T63!mkI;!gxylGp>soK<~q8Gu8+G} zw)X7zQ!ipZp1eL9*q9F=O1!yoPf&6TQ%u=-e-ac?kG`?mCq9Gfk>O8IB$ciYs`;W7 zTaJ|?P(u&pYET1O#d{CFF{rQmq~Hb%5TV$-$bK^`zVtX>4L3!Y1H!5_ z9(C*6N}L+s=om*Gp5cdFDc6ciuvL#sQlyvGswd4$pFE=U*zCZBvUxAKOJJF(nDTI5 zp8l$!^E$Gx#^12g`OuS% zQJQAU;@|r%>1Q4lJudj6KO?DhMMC9@-N_%hs&~D7e3~|VNBl!ICS+-E>JK*U$6MXT zRi_NDzCPTruzSCxl=Z9Pk}=uL9i43_@~a5EEL=|fwRD6!# zx4Z^nIKJvesSq~HW8=LV{41mFx$AO%%2z-ndTj3cE`NHuQIy#j=B<<8Yicp~H;17s z#%rD9#*$F;ikOLQC0W}@M=n`?swjd|Pf!l(N>1%-kWdkf1l6x6WXUK=-IDkqeTBU7 zSmlT*uY?Y*6QO8FIy3?M-nsgW>TDah%Wh)X%oPHFlbQMIllaHL(F^8|I-%SNf;&7) zwqqhoK*!mPajk`Vsm1-h2bzMi0FD~JN0yg+WP8oC;u#rpRD3pWwU$7Ids8p}VQBs< zU(F==)V5Q?!iq4QyfVu=@t4f`J{-8~@qimJj&)`R$e z8FT9{txXRUc&%G?Jr!1dj(a6!CBJ>hp0XR`6CvM3CAHlqgNa9l?*7`CaY8_X!ml)= z^faEX2UX{J9(!+Y70rDHxgz9O>_f^fwl(i{ca4qDD}t()nwtCXF<4JQjmhf%o^nsS z6EiLQRV&tFJSxPzDZ65z{?j|x-TOU9Tf7V|ZC+u84egCy9^FWelcVb(-<~$U^?Zi# zGs866k^Io7{XuRodE~09_R?3^=;qVy zziic6)L6;=>g^Q<@%@FY4RFb*ba$Hikll`@+#Y7c7~<$(7NLjk=iTiGj7 zi4h;@x}3Z-Nz->P&*{FC+=jY)I_=Rmp}uH@Sg+NP+~#yS*UX%hcTz&-qHb{F zUAuwwN*Sdu39{7FX~sfdlVx__V#Jc=(w_+q)gPX|sK!$etA6F}E5#lo{1P*+7qJ%G z_Wi-(OG5Ssb%iB1m!{@sb&69!e7(v9>ZFg~GKm-LvzD)F(}SGoG`C-; z6oK^nCx^8~Eh7o;OT^{QcMFB?IOOuH-IV+agG2YGIc4C?uwsU?@iw8AA|KM8ZyTtZ z*m!4H#$dCcn6^@^H}M`eH(SOhbbc#BGiR?dKg8ZPk!`eFrYLsJc z2h~tvX@dpmkdrqpx(DHwen$d$Jv*5nU&q~c+_CMxf0CAMbKhT6A24tCOCG({dr5~C zAG806;meqn&YowrnR?@a+7^VwAg6I7pw+p08`EO-*|jL4cc(0_Cc`ezy{}%~0Y&dj z_#*+~;FO43?jCmq+ScrflP&;bJhd%;`rzA~xD zbD${sao>Z*`5Z3*%6gyhecz+v!Qjc5BI?UlIaR`eq9d6J`y>e4KoloTkTz9_%Dp?CM^#n11kw{L^5YA=-#f%6 zs4AQWSvmKk*B4-YdgiA<9${XF?!NkQ6T!JFS_YB4^xwQ!T*u;`*dEP(h2)esBAr?H z2K-S=jCrK^(d=rG{WS=c*E>`uu9eoiBi`uyu|0McUb}TWcCX0@5313qmFU|N@h!9? z&w?&O(LaCNiU?^N-5n`$QLbWdt`sly=SCMWGLCEe|4Ey-!u<)HTSXS<$+Mxuv7W?i(G=L|JAJE?*j!vz-6rqTFCc z#e94+!T8$J>QmJ@ok@I}eFeuMp`XWL(_L%$9OA{Jvy(r|YvKMW=#xsOn*ld>I1J!6 z5BQSTj7{A|d+ybzC&~ujf8|S+X zDb+G~6{+dmwE&f!T+2-;*C+F&j^Jd(<)iQgwQnV(I8AG7(vwbg!Po3_@Fw3zQRT^( zz7nspl5IVrcmVo`sBdT1Z~PiX9OuS)69@C5P>&*A6WqqesmN&WXsDf=+dG@0i^5C~ z=ikD9>zlqfX}UXs=b+sX^SX(TU_(#Z*&=O`BcoV|Ygzy=_ST zZ2Q~={rH8;BTEIp`5!;%X}q{2Kaue3p&d|eb5qYuoJ7LOG97I#_9OmKQfJnOGn1<& zV-70;%$^FV7p-=;QvwjXjh6BjTUC55b*Vdp?WymDbCa^O2hrVeap-QDlZU~)Wwuza z`vLo_&Uw4@P*R2O>J#!lP=qtYk(BS7ew*k@JE&_IzU1%u;n(O+p>xh|W#3I+Px;&q+isZ`jWXkYCZrR86i1Rzs-~ENB$lsEZY#Fa zd3>uFICa7D024;V7c#XIk>ROPT*>9Gei?mQ|*v{S3V-O^(ZXxzD0X7(Sc zz$Ux*fX1CiriQj!6xej>dqCsPEfRCgXa#=py9G4vJUT73*Q&s;5sxjPapzWfIc~H9 zzeYUPK;zD%Q$l;a3jAVV^Xjas2H6)Wi=j$Q?p zl7kVBUKu&wiUI&_B@@J_BPM6LUIBo2F}&^Gcw6iNyJ zw33jV#)bj_Z6gmvp`-vnHwgLs{QMyQWP5sg+C9V9*Vn`6r>s4HxczKsl0ym=0O$gt z62Jm)0=eL@&0PfU_jh^x4ZvG9+&d1Schq@%ds`g17vg(OB)F4e>xUZ+vY5s8DXO#y)Zqnibg^Yr1?Z7|DG(*tb{<~7(aFNbdf zZqI(eBc}ygYUPg)dA7m!hFjO=XG)+gyYjvCiBmHgat!x$KzoEarI8y(fc~L?XPANd z80M*N3M0S_)W=XyQF5Gh11L4Etkqa=@_T7Bt@AizrjeR@8}2E9meC9?sM0!&+Q|=T zUnXs|;#fXjm#-#d%M}O@v=+>oH)LAnk7i6!E{o7WYk+eWG+K^*R(xIo4-2$L-8=#o zjf;-b^RhB<-K6SJIyQIEe$h6K9Rov(sf z18Q74D9}AlXTjxq;-{7l=+Le1Yysxv)U7v)xHLd73|R!B^}?Lpr9;)wtsmDGA!v1J zOP@4XjEsZ=y2aHjx^qwIVe#S|3HJ0rTL<9#yZr0BEnl3Ypbi6cOSy6NFkMNK_ezh} zg;FK$dfjJgpuN}{|^Idn@M zZFS{c%|sD!{||RKpj%zqQt8p!hxA5)nd|LvK)1TIm5G*?hkds`d}np-kU;l1+{mxd z-2$Z^tpnFCef$`Qiq+|JB{>2n79cIv<56^j(%vw*W=RbV&pcP^Z@RZQvn`EthX-2IrMEt!<#*}(=F;Eux5diqku~2QtC959 zbF^N}t?jiOHwDmVLfs;I?=k6J;=SkTIsVGw&Aqs%0XhoQsg~Dz6Kyo8rvlnL)c0;o zuY`NV&}Pj=HyzMkp)MI^NjIJ&>vn*yx!g|NS9|p1#88{w(lyGptv&HGr9e*3M+yM6qht~4u>t^ntPy)SQs7-mj<-Lr$$oVdG@+uvJp}+7HbN<|04*aNGSb0@ z0^St>Xzv*${vQgwh(pWvjW8$>K!L{uG?OaVCIvP;C zDj@DGF8!nAV1mVKI*I#MI_EVsbu?gjRNz)_Y&kS#hsTu89rG^Gxb)m`cX&lBricP?>gN{@L!@zB#hEpq^4xtF&Ub$dY`5}zFm)Rxm7JGR48BXz$9XzJvM3U7zZK? zJ(1@E#hI7q16#IUpi`UF)h+6COs+sviLsVY3usCZ;A~Z(+m-W%HG#&hTT?pkaVoBS zHqd}QFQBD8R|h#Ye1=1>J4Jn6n&#O1sg@S^q#6Nq?%48w-nbPT+;#7UfIQNnx6&uW zee&;#*D{BrI}N#Y4ZpRjGSZ>Px;&q+isZ`jWXkYCZrR86i1Rzs-~ENB$lsEZY#Fa zd3>uFICa7D024;V7c#XIk>ROPT*>9Gei?mQ|*v{S3V-O^(ZXxzD0X7(Sc zz$Ux*fX1CiriQj!6xej>dqCsPEfRCgXa#=py9G4vJUT73*Q&s;5sxjPapzWfIc~H9 zzeYUPK;zD%Q$l;a3jAVV^Xjas2H6)Wi=j$Q?p zl7kVBUKu&wiUI&_B@@J_BPM6LUIBo2F}&^Gcw6iNyJ zw33jV#)bj_Z6gmvp`-vnHwgLs{QMyQWP5sg+C9V9*Vn`6r>s4HxczKsl0ym=0O$gt z62Jm)0=eL@&0PfU_jh^x4ZvG9+&d1Schq@%ds`g17vg(OB)F4e>xUZ+vY5s8DXO#y)Zqnibg^Yr1?Z7|DG(*tb{<~7(aFNbdf zZqI(eBc}ygYUPg)dA7m!hFjO=XG)+gyYjvCiBmHgat!x$KzoEarI8y(fc~L?XPANd z80M*N3M0S_)W=XyQF5Gh11L4Etkqa=@_T7Bt@AizrjeR@8}2E9meC9?sM0!&+Q|=T zUnXs|;#fXjm#-#d%M}O@v=+>oH)LAnk7i6!E{o7WYk+eWG+K^*R(xIo4-2$L-8=#o zjf;-b^RhB<-K6SJIyQIEe$h6K9Rov(sf z18Q74D9}AlXTjxq;-{7l=+Le1Yysxv)U7v)xHLd73|R!B^}?Lpr9;)wtsmDGA!v1J zOP@4XjEsZ=y2aHjx^qwIVe#S|3HJ0rTL<9#yZr0BEnl3Ypbi6cOSy6NFkMNK_ezh} zg;FK$dfjJgpuN}{|^Idn@M zZFS{c%|sD!{||RKpj%zqQt8p!hxA5)nd|LvK)1TIm5G*?hkds`d}np-kU;l1+{mxd z-2$Z^tpnFCef$`Qiq+|JB{>2n79cIv<56^j(%vw*W=RbV&pcP^Z@RZQvn`EthX-2IrMEt!<#*}(=F;Eux5diqku~2QtC959 zbF^N}t?jiOHwDmVLfs;I?=k6J;=SkTIsVGw&Aqs%0XhoQsg~Dz6Kyo8rvlnL)c0;o zuY`NV&}Pj=HyzMkp)MI^NjIJ&>vn*yx!g|NS9|p1#88{w(lyGptv&HGr9e*3M+yM6qht~4u>t^ntPy)SQs7-mj<-Lr$$oVdG@+uvJp}+7HbN<|04*aNGSb0@ z0^St>Xzv*${vQgwh(pWvjW8$>K!L{uG?OaVCIvP;C zDj@DGF8!nAV1mVKI*I#MI_EVsbu?gjRNz)_Y&kS#hsTu89rG^Gxb)m`cX&lBricP?>gN{@L!@zB#hEpq^4xtF&Ub$dY`5}zFm)Rxm7JGR48BXz$9XzJvM3U7zZK? zJ(1@E#hI7q16#IUpi`UF)h+6COs+sviLsVY3usCZ;A~Z(+m-W%HG#&hTT?pkaVoBS zHqd}QFQBD8R|h#Ye1=1>J4Jn6n&#O1sg@S^q#6Nq?%48w-nbPT+;#7UfIQNnx6&uW zee&;#*D{BrI}N#Y4ZpRjGSZ>Px;&q+isZ`jWXkYCZrR86i1Rzs-~ENB$lsEZY#Fa zd3>uFICa7D024;V7c#XIk>ROPT*>9Gei?mQ|*v{S3V-O^(ZXxzD0X7(Sc zz$Ux*fX1CiriQj!6xej>dqCsPEfRCgXa#=py9G4vJUT73*Q&s;5sxjPapzWfIc~H9 zzeYUPK;zD%Q$l;a3jAVV^Xjas2H6)Wi=j$Q?p zl7kVBUKu&wiUI&_B@@J_BPM6LUIBo2F}&^Gcw6iNyJ zw33jV#)bj_Z6gmvp`-vnHwgLs{QMyQWP5sg+C9V9*Vn`6r>s4HxczKsl0ym=0O$gt z62Jm)0=eL@&0PfU_jh^x4ZvG9+&d1Schq@%ds`g17vg(OB)F4e>xUZ+vY5s8DXO#y)Zqnibg^Yr1?Z7|DG(*tb{<~7(aFNbdf zZqI(eBc}ygYUPg)dA7m!hFjO=XG)+gyYjvCiBmHgat!x$KzoEarI8y(fc~L?XPANd z80M*N3M0S_)W=XyQF5Gh11L4Etkqa=@_T7Bt@AizrjeR@8}2E9meC9?sM0!&+Q|=T zUnXs|;#fXjm#-#d%M}O@v=+>oH)LAnk7i6!E{o7WYk+eWG+K^*R(xIo4-2$L-8=#o zjf;-b^RhB<-K6SJIyQIEe$h6K9Rov(sf z18Q74D9}AlXTjxq;-{7l=+Le1Yysxv)U7v)xHLd73|R!B^}?Lpr9;)wtsmDGA!v1J zOP@4XjEsZ=y2aHjx^qwIVe#S|3HJ0rTL<9#yZr0BEnl3Ypbi6cOSy6NFkMNK_ezh} zg;FK$dfjJgpuN}{|^Idn@M zZFS{c%|sD!{||RKpj%zqQt8p!hxA5)nd|LvK)1TIm5G*?hkds`d}np-kU;l1+{mxd z-2$Z^tpnFCef$`Qiq+|JB{>2n79cIv<56^j(%vw*W=RbV&pcP^Z@RZQvn`EthX-2IrMEt!<#*}(=F;Eux5diqku~2QtC959 zbF^N}t?jiOHwDmVLfs;I?=k6J;=SkTIsVGw&Aqs%0XhoQsg~Dz6Kyo8rvlnL)c0;o zuY`NV&}Pj=HyzMkp)MI^NjIJ&>vn*yx!g|NS9|p1#88{w(lyGptv&HGr9e*3M+yM6qht~4u>t^ntPy)SQs7-mj<-Lr$$oVdG@+uvJp}+7HbN<|04*aNGSb0@ z0^St>Xzv*${vQgwh(pWvjW8$>K!L{uG?OaVCIvP;C zDj@DGF8!nAV1mVKI*I#MI_EVsbu?gjRNz)_Y&kS#hsTu89rG^Gxb)m`cX&lBricP?>gN{@L!@zB#hEpq^4xtF&Ub$dY`5}zFm)Rxm7JGR48BXz$9XzJvM3U7zZK? zJ(1@E#hI7q16#IUpi`UF)h+6COs+sviLsVY3usCZ;A~Z(+m-W%HG#&hTT?pkaVoBS zHqd}QFQBD8R|h#Ye1=1>J4Jn6n&#O1sg@S^q#6Nq?%48w-nbPT+;#7UfIQNnx6&uW zee&;#*D{BrI}N#Y4ZpRjGSZ>1.0 CFBundleSignature ???? + CFBundleURLTypes + + + CFBundleURLSchemes + + commandbar + + + CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen - UIMainStoryboardFile - Main UIRequiredDeviceCapabilities armv7 @@ -35,5 +42,22 @@ UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + + + + diff --git a/Example/CommandBarIOS/LaunchScreen.storyboard b/Example/CommandBarIOS/LaunchScreen.storyboard new file mode 100644 index 0000000..e431a34 --- /dev/null +++ b/Example/CommandBarIOS/LaunchScreen.storyboard @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/CommandBarIOS/SceneDelegate.swift b/Example/CommandBarIOS/SceneDelegate.swift new file mode 100644 index 0000000..44ed14e --- /dev/null +++ b/Example/CommandBarIOS/SceneDelegate.swift @@ -0,0 +1,27 @@ +// +// SceneDelegate.swift +// CommandBarIOS_Example +// +// Custom SceneDelegate for use with older iOS versions that don't support @main outright +// + +import Foundation +import UIKit +import SwiftUI + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + let contentView = HomeView() + + // Use a UIHostingController as window root view controller. + if let windowScene = scene as? UIWindowScene { + let window = UIWindow(windowScene: windowScene) + window.rootViewController = UIHostingController(rootView: contentView) + self.window = window + window.makeKeyAndVisible() + } + } +} diff --git a/Example/CommandBarIOS/ViewController.swift b/Example/CommandBarIOS/ViewController.swift deleted file mode 100644 index 7ed2b0a..0000000 --- a/Example/CommandBarIOS/ViewController.swift +++ /dev/null @@ -1,99 +0,0 @@ -import UIKit -import CommandBarIOS - -class ViewController: UIViewController { - - var commandbar = CommandBar(options: CommandBarOptions(["orgId": "641ade4d", "launchCode": "preview_4686" ])) - - // TODO: Remove after demoing - var button: UIButton? = nil - - override func viewDidLoad() { - super.viewDidLoad() - // Create a UIImageView and set its frame to match the size of the view - let imageView = UIImageView(frame: view.bounds) - // Set the image to be displayed - let backgroundImage = UIImage(named: "Background") - imageView.image = backgroundImage - // Set the content mode to scale the image to fit the view - imageView.contentMode = .scaleAspectFill - // Add the UIImageView as a subview of the view - view.addSubview(imageView) - // Send the UIImageView to the back so that other content appears on top - view.sendSubview(toBack: imageView) - - // Setting up the title label -// let titleLabel = UILabel() -// titleLabel.text = "Welcome!" -// titleLabel.textAlignment = .center -// titleLabel.font = UIFont.boldSystemFont(ofSize: 48) // Increase the font size to 30 -// titleLabel.numberOfLines = 0 Allow multiple lines -// titleLabel.lineBreakMode = .byWordWrapping // Wrap within the screen width -// titleLabel.translatesAutoresizingMaskIntoConstraints = false -// view.addSubview(titleLabel) - - // Adding constraints for the title label -// titleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true -// titleLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true -// titleLabel.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor, constant: 20).isActive = true -// titleLabel.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -20).isActive = true - - // Setting up the button -// let helpButton = UIButton(type: .system) -// helpButton.setTitle("Open HelpHub", for: .normal) -// helpButton.addTarget(self, action: #selector(openHelpHub), for: .touchUpInside) -// helpButton.translatesAutoresizingMaskIntoConstraints = false -// view.addSubview(helpButton) -// - // TODO: Remove after demoing - button = UIButton(type: .custom) - button!.frame = CGRect(x: 297, y: 756, width: 90, height: 48) - - // Customize the button appearance - button!.backgroundColor = UIColor.clear - button!.layer.cornerRadius = 4 - button!.layer.borderWidth = 0 - button!.backgroundColor = UIColor.clear - button!.setTitleColor(UIColor.black, for: .normal) - - button!.addTarget(self, action: #selector(buttonTapped), for: .touchDown) - button!.addTarget(self, action: #selector(buttonReleased), for: .touchUpOutside) - button!.addTarget(self, action: #selector(openHelpHub), for: .touchUpInside) - view.addSubview(button!) - } - - @objc func openHelpHub() { - self.button?.backgroundColor = UIColor.clear - commandbar.delegate = self - commandbar.openHelpHub() - } - - // TODO: Remove after demoing - @objc func buttonTapped() { - if #available(iOS 13.0, *) { - let color = UIColor( - red: CGFloat(0x36) / 255.0, - green: CGFloat(0x62) / 255.0, - blue: CGFloat(0xF1) / 255.0, - alpha: 0.2 - ) - - self.button?.backgroundColor = color - } else {} - } - - @objc func buttonReleased() { - self.button?.backgroundColor = UIColor.clear - } - -} - -extension ViewController : HelpHubWebViewDelegate { - func didReceiveFallbackAction(_ action: [String : Any]) { - commandbar.closeHelpHub() - let alertController = UIAlertController(title: "Fallback Received", message: "An fallback action was triggered in HelpHubWebView.", preferredStyle: .alert) - let okayAction = UIAlertAction(title: "Okay", style: .default, handler: nil) - alertController.addAction(okayAction) - UIApplication.shared.keyWindow?.rootViewController?.present(alertController, animated: true) - } -} diff --git a/Example/CommandBarIOS/Views/Button.swift b/Example/CommandBarIOS/Views/Button.swift new file mode 100644 index 0000000..ebb0da9 --- /dev/null +++ b/Example/CommandBarIOS/Views/Button.swift @@ -0,0 +1,51 @@ +// +// Button.swift +// CommandBarIOS_Example +// +// Created by Michael Cavallaro on 12/17/23. +// Copyright © 2023 CocoaPods. All rights reserved. +// + +import Foundation +import SwiftUI + +struct CustomButton: View { + var title: String + var fullWidth: Bool + let action: () -> Void + + init(title: String, fullWidth: Bool, action: @escaping () -> Void) { + self.title = title + self.fullWidth = fullWidth + self.action = action + } + + init(title: String, action: @escaping () -> Void) { + self.title = title + self.action = action + self.fullWidth = true + } + + var body: some View { + Button(action: self.action) { + HStack { + if (fullWidth) { + Spacer() + } + + Text(title) + .font(.headline) + .foregroundColor(Color.white) + + if (fullWidth) { + Spacer() + } + } + .padding() + } + .background(Color.black.opacity(0.8)) + .cornerRadius(10) + + } +} + diff --git a/Example/CommandBarIOS/Views/Color.swift b/Example/CommandBarIOS/Views/Color.swift new file mode 100644 index 0000000..a7874be --- /dev/null +++ b/Example/CommandBarIOS/Views/Color.swift @@ -0,0 +1,100 @@ +import Foundation +import SwiftUI + +extension Color { + func uiColor() -> UIColor { + + if #available(iOS 14.0, *) { + return UIColor(self) + } + + let components = self.components() + return UIColor(red: components.r, green: components.g, blue: components.b, alpha: components.a) + } + + private func components() -> (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) { + + let scanner = Scanner(string: self.description.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)) + var hexNumber: UInt64 = 0 + var r: CGFloat = 0.0, g: CGFloat = 0.0, b: CGFloat = 0.0, a: CGFloat = 0.0 + + let result = scanner.scanHexInt64(&hexNumber) + if result { + r = CGFloat((hexNumber & 0xff000000) >> 24) / 255 + g = CGFloat((hexNumber & 0x00ff0000) >> 16) / 255 + b = CGFloat((hexNumber & 0x0000ff00) >> 8) / 255 + a = CGFloat(hexNumber & 0x000000ff) / 255 + } + return (r, g, b, a) + } + + static func random() -> Color { + let red = Double.random(in: 0..<1) + let green = Double.random(in: 0..<1) + let blue = Double.random(in: 0..<1) + return Color(red: red, green: green, blue: blue) + } + + init(uiColor: UIColor) { + self.init(red: Double(uiColor.components.red), + green: Double(uiColor.components.green), + blue: Double(uiColor.components.blue), + opacity: Double(uiColor.components.alpha)) + } + + func lighter(by percentage: CGFloat = 30.0) -> Color { + if let uiColor = self.uiColor().lighter(by: percentage) { + return Color(uiColor: uiColor) + } + return self + + } + + func darker(by percentage: CGFloat = 30.0) -> Color { + if let uiColor = self.uiColor().darker(by: percentage) { + return Color(uiColor: uiColor) + } + return self + + } + + func adjust(by percentage: CGFloat = 30.0) -> Color { + let components = self.components() + return Color(red: min(Double(components.r + percentage/100), 1.0), + green: min(Double(components.g + percentage/100), 1.0), + blue: min(Double(components.b + percentage/100), 1.0), + opacity: Double(components.a)) + } +} + + +extension UIColor { + var components: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { + var red: CGFloat = 0 + var green: CGFloat = 0 + var blue: CGFloat = 0 + var alpha: CGFloat = 0 + getRed(&red, green: &green, blue: &blue, alpha: &alpha) + + return (red, green, blue, alpha) + } + func lighter(by percentage: CGFloat = 30.0) -> UIColor? { + return self.adjust(by: abs(percentage) ) + } + + func darker(by percentage: CGFloat = 30.0) -> UIColor? { + return self.adjust(by: -1 * abs(percentage) ) + } + + func adjust(by percentage: CGFloat = 30.0) -> UIColor? { + var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0 + if self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) { + return UIColor(red: min(red + percentage/100, 1.0), + green: min(green + percentage/100, 1.0), + blue: min(blue + percentage/100, 1.0), + alpha: alpha) + } else { + return nil + } + } +} diff --git a/Example/CommandBarIOS/Views/GradientView.swift b/Example/CommandBarIOS/Views/GradientView.swift new file mode 100644 index 0000000..77921b4 --- /dev/null +++ b/Example/CommandBarIOS/Views/GradientView.swift @@ -0,0 +1,78 @@ +import SwiftUI +import UIKit + +struct GradientView: View { + + @State private var stage: Double = 0 + private let maxStages: Double = 10.0 + + private let startColor: Color = .purple + private let endColor: Color = .blue.darker(by: 2) + + private let timer = Timer.publish(every: 0.1, on: .main, in: .commonModes).autoconnect() // adjust as needed + + var body: some View { + ZStack { + ForEach(0..<(Int(maxStages)), id: \.self) { i in + gradient(for: i) + .opacity(opacity(for: i)) + .animation(.linear(duration: 0.4), value: self.stage) + + } + } + .edgesIgnoringSafeArea(.all) + .onAppear{ + Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { _ in + withAnimation { + self.stage = (self.stage + 1) + } + } + } + } + + private func gradient(for index: Int) -> LinearGradient { + let points = gradientPoints(for: index) + return LinearGradient( + gradient: Gradient(colors: [startColor, endColor]), + startPoint: points.0, + endPoint: points.1 + ) + } + + private func gradientPoints(for index: Int) -> (UnitPoint, UnitPoint) { + switch index { + case 0: + return (.topLeading, .bottomTrailing) + case 1: + return (.top, .bottom) + case 2: + return (.topTrailing, .bottomLeading) + case 3: + return (.trailing, .leading) + case 4: + return (.bottomTrailing, .topLeading) + case 5: + return (.bottom, .top) + case 6: + return (.bottomLeading, .topTrailing) + case 7: + return (.leading, .trailing) + case 8: + return (.topLeading, .bottomTrailing) + default: + return (.topLeading, .bottomTrailing) + } + } + + private func opacity(for index: Int) -> Double { + let adjustedStage = (self.stage - Double(index)) / self.maxStages + return max(0, 0.5 * cos(2 * Double.pi * adjustedStage) + 0.5) + } +} + + +struct GradientView_Previews: PreviewProvider { + static var previews: some View { + GradientView() + } +} diff --git a/Example/CommandBarIOS/Views/HomeView.swift b/Example/CommandBarIOS/Views/HomeView.swift new file mode 100644 index 0000000..95d0033 --- /dev/null +++ b/Example/CommandBarIOS/Views/HomeView.swift @@ -0,0 +1,52 @@ +// +// HomeView.swift +// CommandBarIOS_Example +// + +import SwiftUI + +// 1. Import CommandBar IOS SDK +import CommandBarIOS + +struct HomeView: View { + var ORG_ID = "641ade4d" + + var body: some View { + VStack(alignment: .center) { + ZStack { + GradientView() + VStack { + Spacer() + VStack { + LogoView() + .shadow(color: Color.black.opacity(0.3), radius: 10, x: 0, y: 5) + Text("Welcome to CommandBar!") + .multilineTextAlignment(.center) + .font(.title) + } + Spacer() + VStack() { + CustomButton(title: "Trigger Test Event") { + // 3. Track Events + CommandBarSDK.shared.trackEvent(event: "test_event") + } + } + }.padding(.horizontal) + + if ORG_ID == "" { + VStack(alignment: .leading) { + Toast(message: "Org ID not set.") + Spacer() + } + } + + } + } + .onAppear { + if (ORG_ID != "") { + // 2. Boot CommandBar by using the shared instance + CommandBarSDK.shared.boot(ORG_ID, with: CommandBarOptions(user_id: UUID().uuidString )) + } + } + } +} diff --git a/Example/CommandBarIOS/Views/LogoView.swift b/Example/CommandBarIOS/Views/LogoView.swift new file mode 100644 index 0000000..2600fd7 --- /dev/null +++ b/Example/CommandBarIOS/Views/LogoView.swift @@ -0,0 +1,25 @@ +// +// LogoView.swift +// CommandBarIOS_Example +// +// Created by Michael Cavallaro on 12/17/23. +// Copyright © 2023 CocoaPods. All rights reserved. +// + +import SwiftUI + +struct LogoView: View { + var body: some View { + Image("Logo") // your app icon's filename + .resizable() + .aspectRatio(contentMode: .fill) + .clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous)) + .frame(width: 100, height: 100) + } +} + +struct LogoView_Previews: PreviewProvider { + static var previews: some View { + LogoView() + } +} diff --git a/Example/CommandBarIOS/Views/Toast.swift b/Example/CommandBarIOS/Views/Toast.swift new file mode 100644 index 0000000..d1c13ce --- /dev/null +++ b/Example/CommandBarIOS/Views/Toast.swift @@ -0,0 +1,25 @@ +import SwiftUI + +struct Toast: View { + var message: String + + @State private var animationScale: CGFloat = 0 + + var body: some View { + VStack(alignment: .leading) { + HStack { + Image(systemName: "exclamationmark.triangle") + Text(message) + } + .foregroundColor(.white) + .padding(10) + .background(Color.black.opacity(0.7)) + .cornerRadius(10) + .scaleEffect(animationScale) + .animation(.spring(response: 0.3, dampingFraction: 0.5, blendDuration: 1)) + .onAppear { + animationScale = 1 + } + } + } +} diff --git a/Example/Podfile b/Example/Podfile index 134665a..c86530b 100644 --- a/Example/Podfile +++ b/Example/Podfile @@ -1,6 +1,6 @@ use_frameworks! -platform :ios, '12.4' +platform :ios, '13.0' target 'CommandBarIOS_Example' do pod 'CommandBarIOS', :path => '../' diff --git a/Example/Podfile.lock b/Example/Podfile.lock index 80b10cc..b0accb2 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - CommandBarIOS (1.0.5) + - CommandBarIOS (1.1.0) DEPENDENCIES: - CommandBarIOS (from `../`) @@ -9,8 +9,8 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - CommandBarIOS: fa6fe132824f41fa8ade49143ed9de6b1d7802e0 + CommandBarIOS: 3fa819a1fa27f3b0d39da577519e58e717b9f8b3 -PODFILE CHECKSUM: 8684a213cc602300bf551c745cd181775198b472 +PODFILE CHECKSUM: 6d9bb10e6d829f27934a51717623c1fd87cac734 COCOAPODS: 1.14.2 diff --git a/Example/Pods/Local Podspecs/CommandBarIOS.podspec.json b/Example/Pods/Local Podspecs/CommandBarIOS.podspec.json index 9582aa8..08580f4 100644 --- a/Example/Pods/Local Podspecs/CommandBarIOS.podspec.json +++ b/Example/Pods/Local Podspecs/CommandBarIOS.podspec.json @@ -1,6 +1,6 @@ { "name": "CommandBarIOS", - "version": "1.0.5", + "version": "1.1.0", "summary": "HelpHub and Copilot Command Bar for iOS.", "description": "TODO: Add long description of the pod here.", "homepage": "https://github.com/tryfoobar/CommandBarIOS", @@ -13,12 +13,13 @@ }, "source": { "git": "https://github.com/tryfoobar/CommandBarIOS.git", - "tag": "1.0.5" + "tag": "1.1.0" }, "platforms": { - "ios": "12.4" + "ios": "13.0" }, "source_files": "Sources/CommandBarIOS/**/*.swift", + "resources": "Sources/CommandBarIOS/**/*.{png,jpeg,jpg,storyboard,xib,xcassets}", "swift_versions": "5.0", "swift_version": "5.0" } diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock index 80b10cc..b0accb2 100644 --- a/Example/Pods/Manifest.lock +++ b/Example/Pods/Manifest.lock @@ -1,5 +1,5 @@ PODS: - - CommandBarIOS (1.0.5) + - CommandBarIOS (1.1.0) DEPENDENCIES: - CommandBarIOS (from `../`) @@ -9,8 +9,8 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - CommandBarIOS: fa6fe132824f41fa8ade49143ed9de6b1d7802e0 + CommandBarIOS: 3fa819a1fa27f3b0d39da577519e58e717b9f8b3 -PODFILE CHECKSUM: 8684a213cc602300bf551c745cd181775198b472 +PODFILE CHECKSUM: 6d9bb10e6d829f27934a51717623c1fd87cac734 COCOAPODS: 1.14.2 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 30e0fff..a9e5bd7 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -7,74 +7,117 @@ objects = { /* Begin PBXBuildFile section */ - 18AF18A371DAB09048B438460A99D0F9 /* CommandBarOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDEA3A390C7A5DA4991B3E7291F77F19 /* CommandBarOptions.swift */; }; + 1476DB70E8DA67490EDFC70BCEB037D9 /* Options.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5EBDEBFBD6F726F8EBF4597C8608C66 /* Options.swift */; }; + 1F7191CF57EDFE93F59BA6BCFAE50BA1 /* Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D67889A306BFA0BE242BDA1423722CD /* Util.swift */; }; + 2334A2E1EEDD1DEB1A561434EDF522D4 /* Spinner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60807E3BF783150AAB83EEAE7B676384 /* Spinner.swift */; }; 271D9ACDEFF8DA9BE018220CA3EE381F /* Pods-CommandBarIOS_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 515BD9511ECA7252E62981CE3B475040 /* Pods-CommandBarIOS_Tests-dummy.m */; }; - 296682E43DD325395E53B3AF4B6E1133 /* CommandBarIOS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0778ED0794915C3D4EE5E46390EEBAA2 /* CommandBarIOS-dummy.m */; }; - 31EF8E946A5D5D1A1F756E7D307501CF /* CommandBarIOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F81137031249F1E204C16481C62E9BFD /* CommandBarIOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 2DB9BF8A8C9AB30BC82165C4519AACC0 /* ContentBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD066775C7E795798DC1D2DCBBAD15E7 /* ContentBlock.swift */; }; 375A3570C873DC3BB5E444CC77533135 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; - 4ADDBEE3C3CE5BE9872E2E1524DCB327 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; - 53ECD6CE82C969104A06A1C624E269BC /* HelpHubViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F00A4277BE34BC0CC10E72DFD63107F7 /* HelpHubViewController.swift */; }; + 39CDDFBE0C1C10BD0D8D6042E9E80F5B /* SurveyRatingBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E5BCD3701DEF15FE6865CA6B331F2B3 /* SurveyRatingBlock.swift */; }; + 39F9ECB7C8F1D0D291DB6854ECC34224 /* InternalSDK.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3173CDABAFD028DC489C96410149DD92 /* InternalSDK.swift */; }; + 3AD72E99FB9A44A4209AE8653A0C2924 /* CommandBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6DB2BB6A3EB79EE8C0425AF20B239A3F /* CommandBar.swift */; }; + 4016542B80ED91AFE3FCB98EF548DD2B /* Actions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 779B544D8CA45922AB3279411740AC6D /* Actions.swift */; }; 5E33BB68E15225681C221A7BCE83EF73 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; - 908EF4FC97F9498C5292F59D2E4688ED /* HelpHubWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 578B347352B3BF27FFDBF57E6D1FBC7E /* HelpHubWebView.swift */; }; - A5AC9CA1954B13F30030AC6A52689B80 /* CommandBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 703EEF2FE771B673B3F77DF2EEB86962 /* CommandBar.swift */; }; + 617FE8F789F0B5914A5992CE092A5FA3 /* ButtonGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D6B9B33E50490394761EF613B4FB2C5 /* ButtonGroup.swift */; }; + 76EBDBA8598F1EC1D2EBB5BD56EFB291 /* Config.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0907E99C01A2CE39B17BCDDD7BC2609E /* Config.swift */; }; + 7A8A04B085D0D8CF487D3A290DB86820 /* SDK.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33A6A4112E276D47CC5FB7980D382CA /* SDK.swift */; }; + 8123A31D6B12CBD5801028A2EC17A622 /* Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9D3F3B33DBCFB99BADD0B359D97CA0A3 /* Events.swift */; }; + 8DE5C943D6C5CCA2117CF0F0DC9B0B36 /* CloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DFFE3FD3F497ACFA066B7822F19A462 /* CloseButton.swift */; }; + 8F8F46E301A273B8D91D77FB67B90663 /* CommandBarIOS-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 583F02EB2636F145BE08595A470C84D2 /* CommandBarIOS-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A3DE18786419431EBD4C4452DC6D544E /* HelpHubWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DF3AAE9C1EC2822EB299EEDDCC79B86 /* HelpHubWebView.swift */; }; + A9C7428059FEC2846FCBD57F6634D21C /* BottomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56F9C72F84FAA22EFCCA80A96E3F7843 /* BottomSheet.swift */; }; + AA24585A59FAF417CEBFF5FDE3A97254 /* Color.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55F5203E0A897505E2FC72351841BEAE /* Color.swift */; }; + AB865F316991E11BB34B14E40325AE9D /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03012A70096844B1E367B8E6F737AEE0 /* Button.swift */; }; + BDCA75ED374B8C15AEEDAA2AFC79A593 /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = E60B0515E7E71905AD2E32AC6A09A57A /* Image.swift */; }; + C2D20D6A48A4E415A28ECFAB8DCA5D31 /* Rules.swift in Sources */ = {isa = PBXBuildFile; fileRef = 765760F6145C9C21E9ECC6ED667C45CB /* Rules.swift */; }; + CA0070C6242C50069BDEE3C16BD6A8DC /* NudgeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73E2FDCECB52A12C7B0B8B4956F5CAA6 /* NudgeView.swift */; }; CB7D63194963AD3D7DCF1C50EC3A89DD /* Pods-CommandBarIOS_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E43CB0041A0E679ADCCC403A77DC49B /* Pods-CommandBarIOS_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D65A89EEB33FB906D267E2E00B2FE7CE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; + D78417CAF277564CBE73786786360248 /* HelpHubViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8EDB9297FE6FF616EDB873D76314ED1 /* HelpHubViewController.swift */; }; + D8B36E1EF6BAD1D05FD827BE59B90B50 /* Nudges.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6549D2B34727781499A85DBEEB993454 /* Nudges.swift */; }; + D92141CF573820FD3CAA2E3946444B31 /* NudgeWindowManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5AAF8F0395DD95E0FC4F15327D74639 /* NudgeWindowManager.swift */; }; + DCDC24267D2CF22E53F28CE2411707F4 /* Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71FC52B9EB8CF85A3A0C1782D417D24A /* Video.swift */; }; DE8966D9DDC32BD5E1F32594D92F0B3B /* Pods-CommandBarIOS_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = AFFE2B6A0D4157DAE9916DDB711EDDB5 /* Pods-CommandBarIOS_Example-dummy.m */; }; + E461CA29B8985E46FC904C40B2020363 /* CommandBarIOS-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 40B4B40E5342EB16654738BF938EC588 /* CommandBarIOS-dummy.m */; }; EBD4CDE6E5BC08A713742DA9B53A5BD6 /* Pods-CommandBarIOS_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0335B849997FEDD72AD0635B88000E91 /* Pods-CommandBarIOS_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + FFFCEB1D36A4A44580CF8F5AE3AC253A /* Analytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE767260FDC18E34E0DDCE0C0B75A034 /* Analytics.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 3007127ED9892733396586228F18F62E /* PBXContainerItemProxy */ = { + 077A2A22662D7EE329C53F2EDFEF2669 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = BEF9C21ABF8843AD6FC046F2A58B2B1D; - remoteInfo = "Pods-CommandBarIOS_Example"; + remoteGlobalIDString = 1A5C426E3579F3BD712FDAB630F0FBA8; + remoteInfo = CommandBarIOS; }; - 4BC04C7534601BAE99A4D165626C0A76 /* PBXContainerItemProxy */ = { + 42E8D5F3AFF14ED9F40357540F713DC4 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; proxyType = 1; - remoteGlobalIDString = 1A5C426E3579F3BD712FDAB630F0FBA8; - remoteInfo = CommandBarIOS; + remoteGlobalIDString = BEF9C21ABF8843AD6FC046F2A58B2B1D; + remoteInfo = "Pods-CommandBarIOS_Example"; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 03012A70096844B1E367B8E6F737AEE0 /* Button.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = ""; }; 0335B849997FEDD72AD0635B88000E91 /* Pods-CommandBarIOS_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-CommandBarIOS_Example-umbrella.h"; sourceTree = ""; }; 05463FACEB0440DF91273FE265F92F67 /* Pods-CommandBarIOS_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-CommandBarIOS_Tests.modulemap"; sourceTree = ""; }; 0560156DCF68BC126399FC40E13C8CCF /* Pods-CommandBarIOS_Example */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-CommandBarIOS_Example"; path = Pods_CommandBarIOS_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 0778ED0794915C3D4EE5E46390EEBAA2 /* CommandBarIOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "CommandBarIOS-dummy.m"; sourceTree = ""; }; + 0907E99C01A2CE39B17BCDDD7BC2609E /* Config.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Config.swift; sourceTree = ""; }; 10633049ABF6884985AD82B2E6D4B49F /* Pods-CommandBarIOS_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-CommandBarIOS_Example-frameworks.sh"; sourceTree = ""; }; 24C3F0AC5FD53EE187421A98F864CD9A /* CommandBarIOS */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = CommandBarIOS; path = CommandBarIOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 2BC933536484A6A526982634D8F81096 /* Pods-CommandBarIOS_Example-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-CommandBarIOS_Example-Info.plist"; sourceTree = ""; }; - 33DC37B5B5E4308117BB624C8FB42FC9 /* CommandBarIOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = CommandBarIOS.debug.xcconfig; sourceTree = ""; }; + 3173CDABAFD028DC489C96410149DD92 /* InternalSDK.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = InternalSDK.swift; sourceTree = ""; }; 34834821C4E0424E5D67E57EE20156F7 /* Pods-CommandBarIOS_Tests */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-CommandBarIOS_Tests"; path = Pods_CommandBarIOS_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3CE81AB79FEBAB0C8FC662A559E23A3E /* Pods-CommandBarIOS_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-CommandBarIOS_Tests-acknowledgements.markdown"; sourceTree = ""; }; + 3DF3AAE9C1EC2822EB299EEDDCC79B86 /* HelpHubWebView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HelpHubWebView.swift; sourceTree = ""; }; + 40B4B40E5342EB16654738BF938EC588 /* CommandBarIOS-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "CommandBarIOS-dummy.m"; sourceTree = ""; }; + 4D67889A306BFA0BE242BDA1423722CD /* Util.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Util.swift; sourceTree = ""; }; + 4D6B9B33E50490394761EF613B4FB2C5 /* ButtonGroup.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ButtonGroup.swift; sourceTree = ""; }; 4DF207E3341C6E9BE8D8E7EF8A73A7C5 /* Pods-CommandBarIOS_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-CommandBarIOS_Example-acknowledgements.markdown"; sourceTree = ""; }; + 4DFFE3FD3F497ACFA066B7822F19A462 /* CloseButton.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CloseButton.swift; sourceTree = ""; }; 515BD9511ECA7252E62981CE3B475040 /* Pods-CommandBarIOS_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-CommandBarIOS_Tests-dummy.m"; sourceTree = ""; }; - 530DACA2C8E10EBE3903CC7F294BD0D0 /* CommandBarIOS.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = CommandBarIOS.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 578B347352B3BF27FFDBF57E6D1FBC7E /* HelpHubWebView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HelpHubWebView.swift; path = Sources/CommandBarIOS/HelpHubWebView.swift; sourceTree = ""; }; - 599962948BC271487E4474055F53AB7F /* CommandBarIOS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "CommandBarIOS-prefix.pch"; sourceTree = ""; }; + 55F5203E0A897505E2FC72351841BEAE /* Color.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Color.swift; sourceTree = ""; }; + 56F9C72F84FAA22EFCCA80A96E3F7843 /* BottomSheet.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = BottomSheet.swift; sourceTree = ""; }; + 583F02EB2636F145BE08595A470C84D2 /* CommandBarIOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "CommandBarIOS-umbrella.h"; sourceTree = ""; }; 5C3927EA1AE23CAE7644367F26683AAE /* Pods-CommandBarIOS_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-CommandBarIOS_Example-acknowledgements.plist"; sourceTree = ""; }; - 703EEF2FE771B673B3F77DF2EEB86962 /* CommandBar.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CommandBar.swift; path = Sources/CommandBarIOS/CommandBar.swift; sourceTree = ""; }; + 60807E3BF783150AAB83EEAE7B676384 /* Spinner.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Spinner.swift; sourceTree = ""; }; + 6549D2B34727781499A85DBEEB993454 /* Nudges.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Nudges.swift; sourceTree = ""; }; + 6DB2BB6A3EB79EE8C0425AF20B239A3F /* CommandBar.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CommandBar.swift; sourceTree = ""; }; + 6E5BCD3701DEF15FE6865CA6B331F2B3 /* SurveyRatingBlock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SurveyRatingBlock.swift; sourceTree = ""; }; + 71FC52B9EB8CF85A3A0C1782D417D24A /* Video.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Video.swift; sourceTree = ""; }; 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 73E2FDCECB52A12C7B0B8B4956F5CAA6 /* NudgeView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NudgeView.swift; sourceTree = ""; }; + 765760F6145C9C21E9ECC6ED667C45CB /* Rules.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Rules.swift; sourceTree = ""; }; + 779B544D8CA45922AB3279411740AC6D /* Actions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Actions.swift; sourceTree = ""; }; 842D42AB8A2A2ED88FF8117E26013859 /* Pods-CommandBarIOS_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-CommandBarIOS_Example.debug.xcconfig"; sourceTree = ""; }; 8D6010A0F46B835115A6155B19217F7F /* Pods-CommandBarIOS_Tests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-CommandBarIOS_Tests-Info.plist"; sourceTree = ""; }; + 90610A84481FAF3ACAFBD5926368FB39 /* CommandBar.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = CommandBar.png; path = docs/img/CommandBar.png; sourceTree = ""; }; + 92D158746C522D82EE04AA9F35E094CE /* CommandBarIOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = CommandBarIOS.modulemap; sourceTree = ""; }; 95CC59761A02B39CD10A5754E533418E /* Pods-CommandBarIOS_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-CommandBarIOS_Tests.debug.xcconfig"; sourceTree = ""; }; - 9B72989FA87AB0184A68E665A1A4B20F /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; + 9D3F3B33DBCFB99BADD0B359D97CA0A3 /* Events.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Events.swift; sourceTree = ""; }; 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 9E43CB0041A0E679ADCCC403A77DC49B /* Pods-CommandBarIOS_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-CommandBarIOS_Tests-umbrella.h"; sourceTree = ""; }; 9E4E8584E88649AAFE86983BE725CD08 /* Pods-CommandBarIOS_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-CommandBarIOS_Tests-acknowledgements.plist"; sourceTree = ""; }; A1BFF639C3F37F0714D100DBBD4B2971 /* Pods-CommandBarIOS_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-CommandBarIOS_Example.modulemap"; sourceTree = ""; }; + A408E16BCAB18CD395B3539751445809 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; + A70AF0F873154ACD2FEC4FA4E521C288 /* CommandBarIOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = CommandBarIOS.release.xcconfig; sourceTree = ""; }; AFFE2B6A0D4157DAE9916DDB711EDDB5 /* Pods-CommandBarIOS_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-CommandBarIOS_Example-dummy.m"; sourceTree = ""; }; + B80A4E2FC20C6930C00947A7E3B3CD06 /* CommandBarIOS-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "CommandBarIOS-Info.plist"; sourceTree = ""; }; B88F91FB460AFB11775FE964C05AB3CF /* Pods-CommandBarIOS_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-CommandBarIOS_Example.release.xcconfig"; sourceTree = ""; }; - C1E4F4EA3D99999391B58CCDB1AF9763 /* CommandBarIOS.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = CommandBarIOS.modulemap; sourceTree = ""; }; - C5A9EAA5E4858D06FCBFA88D67B6348A /* CommandBarIOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = CommandBarIOS.release.xcconfig; sourceTree = ""; }; - C6517115226D6CF256A8856CF51CB538 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; - CDEA3A390C7A5DA4991B3E7291F77F19 /* CommandBarOptions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CommandBarOptions.swift; path = Sources/CommandBarIOS/CommandBarOptions.swift; sourceTree = ""; }; - EFCC4839A07A47D14A312477BEDC9143 /* CommandBarIOS-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "CommandBarIOS-Info.plist"; sourceTree = ""; }; - F00A4277BE34BC0CC10E72DFD63107F7 /* HelpHubViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = HelpHubViewController.swift; path = Sources/CommandBarIOS/HelpHubViewController.swift; sourceTree = ""; }; - F81137031249F1E204C16481C62E9BFD /* CommandBarIOS-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "CommandBarIOS-umbrella.h"; sourceTree = ""; }; + BF3DD2F30B9E4E8075DADAEAFD6006A9 /* CommandBarIOS-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "CommandBarIOS-prefix.pch"; sourceTree = ""; }; + C33A6A4112E276D47CC5FB7980D382CA /* SDK.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SDK.swift; sourceTree = ""; }; + C5EBDEBFBD6F726F8EBF4597C8608C66 /* Options.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Options.swift; sourceTree = ""; }; + CD066775C7E795798DC1D2DCBBAD15E7 /* ContentBlock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContentBlock.swift; sourceTree = ""; }; + CE767260FDC18E34E0DDCE0C0B75A034 /* Analytics.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Analytics.swift; sourceTree = ""; }; + D1CB82D62C785A83172511B3556124DB /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; + DCA101DFC3A3C70F13B86D01500DD11E /* CommandBarIOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = CommandBarIOS.debug.xcconfig; sourceTree = ""; }; + E4E4437B683BA58024D225BBD44D9270 /* CommandBarIOS.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = CommandBarIOS.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + E60B0515E7E71905AD2E32AC6A09A57A /* Image.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = ""; }; + E8EDB9297FE6FF616EDB873D76314ED1 /* HelpHubViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = HelpHubViewController.swift; sourceTree = ""; }; + F5AAF8F0395DD95E0FC4F15327D74639 /* NudgeWindowManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NudgeWindowManager.swift; sourceTree = ""; }; FBA3F61958993B363D52C4934D7FF3B4 /* Pods-CommandBarIOS_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-CommandBarIOS_Tests.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -87,11 +130,11 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 97D7431DC514631D2F37189C63558DAA /* Frameworks */ = { + E4F2788DA3EF28A09ADE8CA60521CE1C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 4ADDBEE3C3CE5BE9872E2E1524DCB327 /* Foundation.framework in Frameworks */, + D65A89EEB33FB906D267E2E00B2FE7CE /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -106,25 +149,66 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 0345D8CC887E7BDBE91F750D7CA89709 /* Pod */ = { + 037E4DE1873B99C13A6C694C26F00EFF /* Nudges */ = { isa = PBXGroup; children = ( - 530DACA2C8E10EBE3903CC7F294BD0D0 /* CommandBarIOS.podspec */, - C6517115226D6CF256A8856CF51CB538 /* LICENSE */, - 9B72989FA87AB0184A68E665A1A4B20F /* README.md */, + 73E2FDCECB52A12C7B0B8B4956F5CAA6 /* NudgeView.swift */, + F5AAF8F0395DD95E0FC4F15327D74639 /* NudgeWindowManager.swift */, + 21BA53554CECBF0B0D395F8A188D60C0 /* Content */, ); - name = Pod; + name = Nudges; + path = Sources/CommandBarIOS/Nudges; + sourceTree = ""; + }; + 0450770A5684A155963DEAEB78281A3C /* Development Pods */ = { + isa = PBXGroup; + children = ( + 4DFFE718A3D890A06DA23F122AEF293E /* CommandBarIOS */, + ); + name = "Development Pods"; + sourceTree = ""; + }; + 215B74F409046960CDD7F8D1C32BC5A3 /* HelpHub */ = { + isa = PBXGroup; + children = ( + E8EDB9297FE6FF616EDB873D76314ED1 /* HelpHubViewController.swift */, + 3DF3AAE9C1EC2822EB299EEDDCC79B86 /* HelpHubWebView.swift */, + ); + name = HelpHub; + path = Sources/CommandBarIOS/HelpHub; sourceTree = ""; }; - 2145987A48B72095420961DA4E4C5576 /* CommandBarIOS */ = { + 21BA53554CECBF0B0D395F8A188D60C0 /* Content */ = { isa = PBXGroup; children = ( - 703EEF2FE771B673B3F77DF2EEB86962 /* CommandBar.swift */, - CDEA3A390C7A5DA4991B3E7291F77F19 /* CommandBarOptions.swift */, - F00A4277BE34BC0CC10E72DFD63107F7 /* HelpHubViewController.swift */, - 578B347352B3BF27FFDBF57E6D1FBC7E /* HelpHubWebView.swift */, - 0345D8CC887E7BDBE91F750D7CA89709 /* Pod */, - F92D8630D8725F8A9C4F451E120107BA /* Support Files */, + CD066775C7E795798DC1D2DCBBAD15E7 /* ContentBlock.swift */, + 6E5BCD3701DEF15FE6865CA6B331F2B3 /* SurveyRatingBlock.swift */, + ); + name = Content; + path = Content; + sourceTree = ""; + }; + 4C903CA161F82BC5A9BDC1FAE5DC2859 /* Helpers */ = { + isa = PBXGroup; + children = ( + 55F5203E0A897505E2FC72351841BEAE /* Color.swift */, + ); + name = Helpers; + path = Sources/CommandBarIOS/Helpers; + sourceTree = ""; + }; + 4DFFE718A3D890A06DA23F122AEF293E /* CommandBarIOS */ = { + isa = PBXGroup; + children = ( + D7FF65D903FFF4FD2D80862F2558A4A0 /* Analytics */, + DBBE1E9D5FC714EA0696AF0A9EF9CC4E /* CommandBar */, + 57233A9DB7307EF381B5E3E293C8AE6C /* Components */, + 4C903CA161F82BC5A9BDC1FAE5DC2859 /* Helpers */, + 215B74F409046960CDD7F8D1C32BC5A3 /* HelpHub */, + 037E4DE1873B99C13A6C694C26F00EFF /* Nudges */, + A0651B63A56D5A8C4E66954576F59705 /* Pod */, + B3946BCD92B2DB2748C915A8222A9B40 /* Support Files */, + 5DC71E5D6B713F727450D7DD9A8D9B14 /* Types */, ); name = CommandBarIOS; path = ../..; @@ -147,6 +231,19 @@ path = "Target Support Files/Pods-CommandBarIOS_Example"; sourceTree = ""; }; + 57233A9DB7307EF381B5E3E293C8AE6C /* Components */ = { + isa = PBXGroup; + children = ( + 56F9C72F84FAA22EFCCA80A96E3F7843 /* BottomSheet.swift */, + E60B0515E7E71905AD2E32AC6A09A57A /* Image.swift */, + 60807E3BF783150AAB83EEAE7B676384 /* Spinner.swift */, + 71FC52B9EB8CF85A3A0C1782D417D24A /* Video.swift */, + E2F4B5396F41E9A3E692E2B4A586241D /* Buttons */, + ); + name = Components; + path = Sources/CommandBarIOS/Components; + sourceTree = ""; + }; 578452D2E740E91742655AC8F1636D1F /* iOS */ = { isa = PBXGroup; children = ( @@ -164,6 +261,19 @@ name = "Targets Support Files"; sourceTree = ""; }; + 5DC71E5D6B713F727450D7DD9A8D9B14 /* Types */ = { + isa = PBXGroup; + children = ( + 779B544D8CA45922AB3279411740AC6D /* Actions.swift */, + 0907E99C01A2CE39B17BCDDD7BC2609E /* Config.swift */, + 6549D2B34727781499A85DBEEB993454 /* Nudges.swift */, + 765760F6145C9C21E9ECC6ED667C45CB /* Rules.swift */, + 4D67889A306BFA0BE242BDA1423722CD /* Util.swift */, + ); + name = Types; + path = Sources/CommandBarIOS/Types; + sourceTree = ""; + }; 63B684BAB2A0BA095C0F4A63D4CB3D8C /* Pods-CommandBarIOS_Tests */ = { isa = PBXGroup; children = ( @@ -190,11 +300,37 @@ name = Products; sourceTree = ""; }; + A0651B63A56D5A8C4E66954576F59705 /* Pod */ = { + isa = PBXGroup; + children = ( + 90610A84481FAF3ACAFBD5926368FB39 /* CommandBar.png */, + E4E4437B683BA58024D225BBD44D9270 /* CommandBarIOS.podspec */, + A408E16BCAB18CD395B3539751445809 /* LICENSE */, + D1CB82D62C785A83172511B3556124DB /* README.md */, + ); + name = Pod; + sourceTree = ""; + }; + B3946BCD92B2DB2748C915A8222A9B40 /* Support Files */ = { + isa = PBXGroup; + children = ( + 92D158746C522D82EE04AA9F35E094CE /* CommandBarIOS.modulemap */, + 40B4B40E5342EB16654738BF938EC588 /* CommandBarIOS-dummy.m */, + B80A4E2FC20C6930C00947A7E3B3CD06 /* CommandBarIOS-Info.plist */, + BF3DD2F30B9E4E8075DADAEAFD6006A9 /* CommandBarIOS-prefix.pch */, + 583F02EB2636F145BE08595A470C84D2 /* CommandBarIOS-umbrella.h */, + DCA101DFC3A3C70F13B86D01500DD11E /* CommandBarIOS.debug.xcconfig */, + A70AF0F873154ACD2FEC4FA4E521C288 /* CommandBarIOS.release.xcconfig */, + ); + name = "Support Files"; + path = "Example/Pods/Target Support Files/CommandBarIOS"; + sourceTree = ""; + }; CF1408CF629C7361332E53B88F7BD30C = { isa = PBXGroup; children = ( 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, - D47DD9025F5BCDBF95D42A38CC7231B8 /* Development Pods */, + 0450770A5684A155963DEAEB78281A3C /* Development Pods */, D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */, 939D723E41CDF8FE51E6A6A8595112F1 /* Products */, 59EDB8EB103EA198433BB151018225CA /* Targets Support Files */, @@ -209,53 +345,63 @@ name = Frameworks; sourceTree = ""; }; - D47DD9025F5BCDBF95D42A38CC7231B8 /* Development Pods */ = { + D7FF65D903FFF4FD2D80862F2558A4A0 /* Analytics */ = { isa = PBXGroup; children = ( - 2145987A48B72095420961DA4E4C5576 /* CommandBarIOS */, + CE767260FDC18E34E0DDCE0C0B75A034 /* Analytics.swift */, + 9D3F3B33DBCFB99BADD0B359D97CA0A3 /* Events.swift */, ); - name = "Development Pods"; + name = Analytics; + path = Sources/CommandBarIOS/Analytics; sourceTree = ""; }; - F92D8630D8725F8A9C4F451E120107BA /* Support Files */ = { + DBBE1E9D5FC714EA0696AF0A9EF9CC4E /* CommandBar */ = { isa = PBXGroup; children = ( - C1E4F4EA3D99999391B58CCDB1AF9763 /* CommandBarIOS.modulemap */, - 0778ED0794915C3D4EE5E46390EEBAA2 /* CommandBarIOS-dummy.m */, - EFCC4839A07A47D14A312477BEDC9143 /* CommandBarIOS-Info.plist */, - 599962948BC271487E4474055F53AB7F /* CommandBarIOS-prefix.pch */, - F81137031249F1E204C16481C62E9BFD /* CommandBarIOS-umbrella.h */, - 33DC37B5B5E4308117BB624C8FB42FC9 /* CommandBarIOS.debug.xcconfig */, - C5A9EAA5E4858D06FCBFA88D67B6348A /* CommandBarIOS.release.xcconfig */, + 6DB2BB6A3EB79EE8C0425AF20B239A3F /* CommandBar.swift */, + 3173CDABAFD028DC489C96410149DD92 /* InternalSDK.swift */, + C5EBDEBFBD6F726F8EBF4597C8608C66 /* Options.swift */, + C33A6A4112E276D47CC5FB7980D382CA /* SDK.swift */, ); - name = "Support Files"; - path = "Example/Pods/Target Support Files/CommandBarIOS"; + name = CommandBar; + path = Sources/CommandBarIOS/CommandBar; + sourceTree = ""; + }; + E2F4B5396F41E9A3E692E2B4A586241D /* Buttons */ = { + isa = PBXGroup; + children = ( + 03012A70096844B1E367B8E6F737AEE0 /* Button.swift */, + 4D6B9B33E50490394761EF613B4FB2C5 /* ButtonGroup.swift */, + 4DFFE3FD3F497ACFA066B7822F19A462 /* CloseButton.swift */, + ); + name = Buttons; + path = Buttons; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 3A1D4B0E6730DB63E8FA8AF3A54A73C8 /* Headers */ = { + 1F9D71747368A6CBCCEAE4847185E601 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - EBD4CDE6E5BC08A713742DA9B53A5BD6 /* Pods-CommandBarIOS_Example-umbrella.h in Headers */, + 8F8F46E301A273B8D91D77FB67B90663 /* CommandBarIOS-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 3EE0616E46C3740C074C3D92A9CC201C /* Headers */ = { + 3A1D4B0E6730DB63E8FA8AF3A54A73C8 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - CB7D63194963AD3D7DCF1C50EC3A89DD /* Pods-CommandBarIOS_Tests-umbrella.h in Headers */, + EBD4CDE6E5BC08A713742DA9B53A5BD6 /* Pods-CommandBarIOS_Example-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 8A6F216705BC105F373E011869227F64 /* Headers */ = { + 3EE0616E46C3740C074C3D92A9CC201C /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 31EF8E946A5D5D1A1F756E7D307501CF /* CommandBarIOS-umbrella.h in Headers */, + CB7D63194963AD3D7DCF1C50EC3A89DD /* Pods-CommandBarIOS_Tests-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -264,12 +410,12 @@ /* Begin PBXNativeTarget section */ 1A5C426E3579F3BD712FDAB630F0FBA8 /* CommandBarIOS */ = { isa = PBXNativeTarget; - buildConfigurationList = 044B292FA13E3173A7E5B91BDAAE4AB2 /* Build configuration list for PBXNativeTarget "CommandBarIOS" */; + buildConfigurationList = 8C5B9841815BFDC0BA3F7328313D1579 /* Build configuration list for PBXNativeTarget "CommandBarIOS" */; buildPhases = ( - 8A6F216705BC105F373E011869227F64 /* Headers */, - 89A79CD212F9E87F366F56B942FA58B2 /* Sources */, - 97D7431DC514631D2F37189C63558DAA /* Frameworks */, - 223D6E72751F65E44862B85266ED8209 /* Resources */, + 1F9D71747368A6CBCCEAE4847185E601 /* Headers */, + 573769A31DD58F421C3E073BDBEECBC4 /* Sources */, + E4F2788DA3EF28A09ADE8CA60521CE1C /* Frameworks */, + 7CB7487CD1FA3DC1F56F1BD23A42AB87 /* Resources */, ); buildRules = ( ); @@ -292,7 +438,7 @@ buildRules = ( ); dependencies = ( - 9C93D229C1C20F13405153BDBDC68515 /* PBXTargetDependency */, + BB42077FD34445F543352A35FB9C6DDC /* PBXTargetDependency */, ); name = "Pods-CommandBarIOS_Tests"; productName = Pods_CommandBarIOS_Tests; @@ -311,7 +457,7 @@ buildRules = ( ); dependencies = ( - 2BA4E3189A30F3CD554F324CAD4F9470 /* PBXTargetDependency */, + 8B47AFA9452E78F57FBE514C323BA95D /* PBXTargetDependency */, ); name = "Pods-CommandBarIOS_Example"; productName = Pods_CommandBarIOS_Example; @@ -348,14 +494,14 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 223D6E72751F65E44862B85266ED8209 /* Resources */ = { + 527ECCDE387047BF3CB1BFAD259DE238 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - 527ECCDE387047BF3CB1BFAD259DE238 /* Resources */ = { + 7CB7487CD1FA3DC1F56F1BD23A42AB87 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -372,55 +518,144 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 6C3C43B1371FF1E486745C523ED029EC /* Sources */ = { + 573769A31DD58F421C3E073BDBEECBC4 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 271D9ACDEFF8DA9BE018220CA3EE381F /* Pods-CommandBarIOS_Tests-dummy.m in Sources */, + 4016542B80ED91AFE3FCB98EF548DD2B /* Actions.swift in Sources */, + FFFCEB1D36A4A44580CF8F5AE3AC253A /* Analytics.swift in Sources */, + A9C7428059FEC2846FCBD57F6634D21C /* BottomSheet.swift in Sources */, + AB865F316991E11BB34B14E40325AE9D /* Button.swift in Sources */, + 617FE8F789F0B5914A5992CE092A5FA3 /* ButtonGroup.swift in Sources */, + 8DE5C943D6C5CCA2117CF0F0DC9B0B36 /* CloseButton.swift in Sources */, + AA24585A59FAF417CEBFF5FDE3A97254 /* Color.swift in Sources */, + 3AD72E99FB9A44A4209AE8653A0C2924 /* CommandBar.swift in Sources */, + E461CA29B8985E46FC904C40B2020363 /* CommandBarIOS-dummy.m in Sources */, + 76EBDBA8598F1EC1D2EBB5BD56EFB291 /* Config.swift in Sources */, + 2DB9BF8A8C9AB30BC82165C4519AACC0 /* ContentBlock.swift in Sources */, + 8123A31D6B12CBD5801028A2EC17A622 /* Events.swift in Sources */, + D78417CAF277564CBE73786786360248 /* HelpHubViewController.swift in Sources */, + A3DE18786419431EBD4C4452DC6D544E /* HelpHubWebView.swift in Sources */, + BDCA75ED374B8C15AEEDAA2AFC79A593 /* Image.swift in Sources */, + 39F9ECB7C8F1D0D291DB6854ECC34224 /* InternalSDK.swift in Sources */, + D8B36E1EF6BAD1D05FD827BE59B90B50 /* Nudges.swift in Sources */, + CA0070C6242C50069BDEE3C16BD6A8DC /* NudgeView.swift in Sources */, + D92141CF573820FD3CAA2E3946444B31 /* NudgeWindowManager.swift in Sources */, + 1476DB70E8DA67490EDFC70BCEB037D9 /* Options.swift in Sources */, + C2D20D6A48A4E415A28ECFAB8DCA5D31 /* Rules.swift in Sources */, + 7A8A04B085D0D8CF487D3A290DB86820 /* SDK.swift in Sources */, + 2334A2E1EEDD1DEB1A561434EDF522D4 /* Spinner.swift in Sources */, + 39CDDFBE0C1C10BD0D8D6042E9E80F5B /* SurveyRatingBlock.swift in Sources */, + 1F7191CF57EDFE93F59BA6BCFAE50BA1 /* Util.swift in Sources */, + DCDC24267D2CF22E53F28CE2411707F4 /* Video.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 83F6C7BA6E37E2654199257FCE899208 /* Sources */ = { + 6C3C43B1371FF1E486745C523ED029EC /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - DE8966D9DDC32BD5E1F32594D92F0B3B /* Pods-CommandBarIOS_Example-dummy.m in Sources */, + 271D9ACDEFF8DA9BE018220CA3EE381F /* Pods-CommandBarIOS_Tests-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 89A79CD212F9E87F366F56B942FA58B2 /* Sources */ = { + 83F6C7BA6E37E2654199257FCE899208 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - A5AC9CA1954B13F30030AC6A52689B80 /* CommandBar.swift in Sources */, - 296682E43DD325395E53B3AF4B6E1133 /* CommandBarIOS-dummy.m in Sources */, - 18AF18A371DAB09048B438460A99D0F9 /* CommandBarOptions.swift in Sources */, - 53ECD6CE82C969104A06A1C624E269BC /* HelpHubViewController.swift in Sources */, - 908EF4FC97F9498C5292F59D2E4688ED /* HelpHubWebView.swift in Sources */, + DE8966D9DDC32BD5E1F32594D92F0B3B /* Pods-CommandBarIOS_Example-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 2BA4E3189A30F3CD554F324CAD4F9470 /* PBXTargetDependency */ = { + 8B47AFA9452E78F57FBE514C323BA95D /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = CommandBarIOS; target = 1A5C426E3579F3BD712FDAB630F0FBA8 /* CommandBarIOS */; - targetProxy = 4BC04C7534601BAE99A4D165626C0A76 /* PBXContainerItemProxy */; + targetProxy = 077A2A22662D7EE329C53F2EDFEF2669 /* PBXContainerItemProxy */; }; - 9C93D229C1C20F13405153BDBDC68515 /* PBXTargetDependency */ = { + BB42077FD34445F543352A35FB9C6DDC /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = "Pods-CommandBarIOS_Example"; target = BEF9C21ABF8843AD6FC046F2A58B2B1D /* Pods-CommandBarIOS_Example */; - targetProxy = 3007127ED9892733396586228F18F62E /* PBXContainerItemProxy */; + targetProxy = 42E8D5F3AFF14ED9F40357540F713DC4 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 1749148B204A9AB34AB8F48FB0B2505E /* Release */ = { + 1D9618C2728DB007BE658D7F52849179 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = C5A9EAA5E4858D06FCBFA88D67B6348A /* CommandBarIOS.release.xcconfig */; + baseConfigurationReference = 842D42AB8A2A2ED88FF8117E26013859 /* Pods-CommandBarIOS_Example.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-CommandBarIOS_Example/Pods-CommandBarIOS_Example-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-CommandBarIOS_Example/Pods-CommandBarIOS_Example.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 4AD44956035A980A71C6E1E00452C829 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 95CC59761A02B39CD10A5754E533418E /* Pods-CommandBarIOS_Tests.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-CommandBarIOS_Tests/Pods-CommandBarIOS_Tests-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-CommandBarIOS_Tests/Pods-CommandBarIOS_Tests.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 66C2E711556A00913B3BB833C2BAFA5B /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DCA101DFC3A3C70F13B86D01500DD11E /* CommandBarIOS.debug.xcconfig */; buildSettings = { ARCHS = "$(ARCHS_STANDARD_64_BIT)"; CLANG_ENABLE_OBJC_WEAK = NO; @@ -435,7 +670,7 @@ GCC_PREFIX_HEADER = "Target Support Files/CommandBarIOS/CommandBarIOS-prefix.pch"; INFOPLIST_FILE = "Target Support Files/CommandBarIOS/CommandBarIOS-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.4; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/CommandBarIOS/CommandBarIOS.modulemap"; PRODUCT_MODULE_NAME = CommandBarIOS; @@ -445,15 +680,14 @@ SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; - 6AFD08F1850883A8C7E575184FE8A612 /* Debug */ = { + 738E9E0DE5D04866A22923ECD5A9BB05 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 842D42AB8A2A2ED88FF8117E26013859 /* Pods-CommandBarIOS_Example.debug.xcconfig */; + baseConfigurationReference = FBA3F61958993B363D52C4934D7FF3B4 /* Pods-CommandBarIOS_Tests.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; ARCHS = "$(ARCHS_STANDARD_64_BIT)"; @@ -466,12 +700,12 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-CommandBarIOS_Example/Pods-CommandBarIOS_Example-Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-CommandBarIOS_Tests/Pods-CommandBarIOS_Tests-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.4; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-CommandBarIOS_Example/Pods-CommandBarIOS_Example.modulemap"; + MODULEMAP_FILE = "Target Support Files/Pods-CommandBarIOS_Tests/Pods-CommandBarIOS_Tests.modulemap"; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -480,12 +714,46 @@ SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Release; }; - 6C98B09FF5CCB107837D1A84E8F3A4F1 /* Release */ = { + 888EAB86A45051DA68E586AA7A68B1E6 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = A70AF0F873154ACD2FEC4FA4E521C288 /* CommandBarIOS.release.xcconfig */; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_WEAK = NO; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/CommandBarIOS/CommandBarIOS-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/CommandBarIOS/CommandBarIOS-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/CommandBarIOS/CommandBarIOS.modulemap"; + PRODUCT_MODULE_NAME = CommandBarIOS; + PRODUCT_NAME = CommandBarIOS; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 8DE5143C03248BB6CD542DE3963D6F3A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -520,13 +788,16 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; + DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_RELEASE=1", + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -535,19 +806,20 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.4; - MTL_ENABLE_DEBUG_INFO = NO; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; STRIP_INSTALLED_PRODUCT = NO; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; SYMROOT = "${SRCROOT}/../build"; }; - name = Release; + name = Debug; }; - 8E6A8FF58D100B7F9B1943F455C00F02 /* Debug */ = { + 9E406C6AAF85E580207CD97B0044DEAB /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -582,16 +854,13 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_DEBUG=1", - "DEBUG=1", + "POD_CONFIGURATION_RELEASE=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -600,121 +869,19 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.4; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; STRIP_INSTALLED_PRODUCT = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; SYMROOT = "${SRCROOT}/../build"; }; - name = Debug; - }; - 904CD12D29EC11E204FD85868D3FF0E0 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = FBA3F61958993B363D52C4934D7FF3B4 /* Pods-CommandBarIOS_Tests.release.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-CommandBarIOS_Tests/Pods-CommandBarIOS_Tests-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.4; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-CommandBarIOS_Tests/Pods-CommandBarIOS_Tests.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; name = Release; }; - D28D1C82B896B60A308F7802E96FF6BC /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 95CC59761A02B39CD10A5754E533418E /* Pods-CommandBarIOS_Tests.debug.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-CommandBarIOS_Tests/Pods-CommandBarIOS_Tests-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.4; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-CommandBarIOS_Tests/Pods-CommandBarIOS_Tests.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - E9D71695289B1EC57A880343A80B06C4 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 33DC37B5B5E4308117BB624C8FB42FC9 /* CommandBarIOS.debug.xcconfig */; - buildSettings = { - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_ENABLE_OBJC_WEAK = NO; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/CommandBarIOS/CommandBarIOS-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/CommandBarIOS/CommandBarIOS-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.4; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/CommandBarIOS/CommandBarIOS.modulemap"; - PRODUCT_MODULE_NAME = CommandBarIOS; - PRODUCT_NAME = CommandBarIOS; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - F8B44AFDBFD5F461C3EB52F19157872B /* Release */ = { + D0BD9217C7D7213B0C636BBEC206E375 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = B88F91FB460AFB11775FE964C05AB3CF /* Pods-CommandBarIOS_Example.release.xcconfig */; buildSettings = { @@ -731,7 +898,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = "Target Support Files/Pods-CommandBarIOS_Example/Pods-CommandBarIOS_Example-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 12.4; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-CommandBarIOS_Example/Pods-CommandBarIOS_Example.modulemap"; @@ -752,38 +919,38 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 044B292FA13E3173A7E5B91BDAAE4AB2 /* Build configuration list for PBXNativeTarget "CommandBarIOS" */ = { + 1F2A00F7317381B3919D9459CBDCC0D8 /* Build configuration list for PBXNativeTarget "Pods-CommandBarIOS_Example" */ = { isa = XCConfigurationList; buildConfigurations = ( - E9D71695289B1EC57A880343A80B06C4 /* Debug */, - 1749148B204A9AB34AB8F48FB0B2505E /* Release */, + 1D9618C2728DB007BE658D7F52849179 /* Debug */, + D0BD9217C7D7213B0C636BBEC206E375 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 1F2A00F7317381B3919D9459CBDCC0D8 /* Build configuration list for PBXNativeTarget "Pods-CommandBarIOS_Example" */ = { + 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - 6AFD08F1850883A8C7E575184FE8A612 /* Debug */, - F8B44AFDBFD5F461C3EB52F19157872B /* Release */, + 8DE5143C03248BB6CD542DE3963D6F3A /* Debug */, + 9E406C6AAF85E580207CD97B0044DEAB /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { + 502957DD10EE69D43E1C3A73BC787C4D /* Build configuration list for PBXNativeTarget "Pods-CommandBarIOS_Tests" */ = { isa = XCConfigurationList; buildConfigurations = ( - 8E6A8FF58D100B7F9B1943F455C00F02 /* Debug */, - 6C98B09FF5CCB107837D1A84E8F3A4F1 /* Release */, + 4AD44956035A980A71C6E1E00452C829 /* Debug */, + 738E9E0DE5D04866A22923ECD5A9BB05 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 502957DD10EE69D43E1C3A73BC787C4D /* Build configuration list for PBXNativeTarget "Pods-CommandBarIOS_Tests" */ = { + 8C5B9841815BFDC0BA3F7328313D1579 /* Build configuration list for PBXNativeTarget "CommandBarIOS" */ = { isa = XCConfigurationList; buildConfigurations = ( - D28D1C82B896B60A308F7802E96FF6BC /* Debug */, - 904CD12D29EC11E204FD85868D3FF0E0 /* Release */, + 66C2E711556A00913B3BB833C2BAFA5B /* Debug */, + 888EAB86A45051DA68E586AA7A68B1E6 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Example/Pods/Target Support Files/CommandBarIOS/CommandBarIOS-Info.plist b/Example/Pods/Target Support Files/CommandBarIOS/CommandBarIOS-Info.plist index 0b89d70..dc59427 100644 --- a/Example/Pods/Target Support Files/CommandBarIOS/CommandBarIOS-Info.plist +++ b/Example/Pods/Target Support Files/CommandBarIOS/CommandBarIOS-Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0.5 + 1.1.0 CFBundleSignature ???? CFBundleVersion diff --git a/Example/Pods/Target Support Files/CommandBarIOS/ResourceBundle-CommandBarIOS-CommandBarIOS-Info.plist b/Example/Pods/Target Support Files/CommandBarIOS/ResourceBundle-CommandBarIOS-CommandBarIOS-Info.plist new file mode 100644 index 0000000..c6a5ff8 --- /dev/null +++ b/Example/Pods/Target Support Files/CommandBarIOS/ResourceBundle-CommandBarIOS-CommandBarIOS-Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + ${PODS_DEVELOPMENT_LANGUAGE} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0.10 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSPrincipalClass + + + diff --git a/Package.swift b/Package.swift index f984d97..94c98d3 100644 --- a/Package.swift +++ b/Package.swift @@ -5,7 +5,7 @@ import PackageDescription let package = Package( name: "CommandBarIOS", - platforms: [.iOS("12.4")], + platforms: [.iOS("13.0")], products: [ // Products define the executables and libraries a package produces, making them visible to other packages. .library( diff --git a/README.md b/README.md index 50acd3b..05a5ea4 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Build](https://github.com/tryfoobar/CommandBarIOS/actions/workflows/ci.yml/badge.svg)](https://github.com/tryfoobar/CommandBarIOS/actions/workflows/ci.yml) -Copilot & HelpHub in IOS +Nudges, Copilot & HelpHub in IOS ## Requirements @@ -31,30 +31,78 @@ dependencies: [ ## Usage -### `CommandBar` +### 1. Import the SDK -`init`: +``` +import CommandBarIOS +``` + +### 2. Initialize the SDK + +Boot CommandBar as early as possible in your app with your org ID from [CommandBar](https://mobile.commandbar.com). Optionally, you can pass a user_id for your currently logged in user to boot. + +``` +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + // Calling `.boot` prepares the SDK for use within your app + CommandBarSDK.shared.boot("") + + // (Optionally) Pass in a user_id with CommandBarOptions + CommandBarSDK.shared.boot("", CommandBarOptions(user_id: "")) + return true + } +} +``` + +### 3. (Optional) Get notified of CommandBar boot status -- `options` (required): An instance of the `CommandBarOptions` class that holds the options for the `HelpHubWebView``. - - `orgId` (required): Your Organization ID from [CommandBar](https://app.commandbar.com) - - `spinnerColor` (optional): Optionally specify a color to render the loading Spinner +``` +// Inherit the CommandBarSDKDelegate protocol +class AppDelegate: UIResponder, UIApplicationDelegate, CommandBarSDKDelegate { -`openHelpHub()`: Opens HelpHubWebView in a BottomSheet modal + var window: UIWindow? -`onFallbackAction`: If you need to handle fallback actions from the HelpHub web view, you can conform to `HelpHubWebViewDelegate` protocol and implement the `didReceiveFallbackAction(_:)` method. The `CommandBar` class itself is already conforming to this protocol and forwarding the callback to its own delegate which you can set on your instance of `CommandBar` like `commandbar.delegate = self` + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + // Calling `.boot` prepares the SDK for use within your app + CommandBarSDK.shared.boot("") + } + + // Conform to the protocol + func didFinishBooting(withError error: Error?) { + // If CommandBar failed to boot for some reason, an error will be passed, otherwise it will be null + } +} +``` -### `HelpHubWebView` +### 4. (Optional) Track Events -`init`: Loads HelpHub in a WebView. The WebView won't load its content until options are set via `helpHubWebView.options = CommandBarOptions()` +You can use the `trackEvent` method to trigger Nudges. Right now, this is all this method is used for. Configure your Nudge Targeting to trigger when some event that you define is fired. See more on our [docs](https://www.commandbar.com/docs/guides/personalization/who-when-where/#by-event). + +Once CommandBar is booted you can call `CommandBarSDK.shared.trackEvent("")`. Please check out our Example app for usage as well as the sample below: + +``` +struct MyView: View { + var body: some View { + Button(action: { + CommandBarSDK.shared.trackEvent("") + }) { + Text("Tap me!").padding() + } + } +} +``` -- `options` (optional): An instance of the `CommandBarOptions` class that holds the options for the `HelpHubWebView``. - - `orgId` (required): Your Organization ID from [CommandBar](https://app.commandbar.com) - - `spinnerColor` (optional): Optionally specify a color to render the loading Spinner -- `onFallbackAction` (optional): A callback function to receive an event when a Fallback CTA is interacted with +### 5.(Optional) Run the Example App -## Example +To run the example project, first clone the repo, then: -To run the example project, clone the repo, and run `pod install` from the Example directory first. Open `Example/CommandBarIOS.xcworkspace` in Xcode and run the project. +1. `cd CommandBarIOS/Example && pod install` +2. Open `Example/CommandBarIOS.xcworkspace` in Xcode +3. Navigate to `HomeView.swift` and replace the `ORG_ID` variable with your Organization's ID from [CommandBar](https://mobile.commandbar.com) +4. Run the App 🎉 ## License diff --git a/Sources/CommandBarIOS/Analytics/Analytics.swift b/Sources/CommandBarIOS/Analytics/Analytics.swift new file mode 100644 index 0000000..8cf37c9 --- /dev/null +++ b/Sources/CommandBarIOS/Analytics/Analytics.swift @@ -0,0 +1,139 @@ +import Foundation + +class Analytics { + static let shared = Analytics() + + private var orgId: String? = nil + private var options: CommandBarInternalOptions? = nil + private var userId: String? = nil + private var session: String? = nil + private var serverQueue: [EventPayload] = [] + + func setup(orgId: String, with options: CommandBarInternalOptions? = nil) { + self.orgId = orgId + self.options = options + self.session = genSession() + + Analytics.shared.identify() + } + + func identify() { + guard let organization = Analytics.shared.orgId else { return } + + let properties = UserProperties(id: self.options?.user_id) + let body = AnalyticsIdentifyBody(organization_id: organization, distinct_id: self.options?.user_id, properties: properties) + guard let bodyData = try? JSONEncoder().encode(body) else { + print("CommandBar Analytics: Error building identity request") + return + } + + + guard let url = self.options?.getAPIUrl(for: .analytics, with: "/t/identify/") else { + print("CommandBar Analytics: Error building identity request") + return + } + + var request = URLRequest(url: url) + + request.httpMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.httpBody = bodyData + + let task = URLSession.shared.dataTask(with: request) { (data, response, error) in + if let error = error { + print("CommandBar Analytics: Error identifying user") + print(error) + } + } + + task.resume() + } + + func log(eventName: EventName, data: EventAttributes) { + switch(eventName) { + case .surveyResponse: + self.addEventToServerQueue(type: .log, name: eventName, attrs: data) + // Always flush until full analytics is built out + self.flushServerQueue() + } + } + + // Generated in the same way we do on the web + private func genSession() -> String { + let len = 12 + let factor = pow(10.0, Double(len)) + let randomValue = Double.random(in: 1...9) + let result = floor(factor + randomValue * factor) + return String(Int(result)) + } + + + // Just handles one event in the queue but it will support multiple as soon as that is setup (if we want it to be) + private func flushServerQueue() { + guard let organization = Analytics.shared.orgId else { return } + + + let events = self.serverQueue + + let body = AnalyticsTrackBody(events: events, organization: organization, id: Analytics.shared.userId) + + guard let bodyData = try? JSONEncoder().encode(body) else { + print("Error decoding body") + return + } + + guard let url = self.options?.getAPIUrl(for: .analytics, with: "/t/") else { + print("Error forming URL") + return + } + var request = URLRequest(url: url) + + request.httpMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.httpBody = bodyData + + let task = URLSession.shared.dataTask(with: request) { (data, response, error) in + if let error = error { + print(error) + } + } + + task.resume() + } + + + private func enrichEvent(type: AnalyticsType, name: EventName, attrs: EventAttributes) -> EventPayload { + let context = EventPayload.Context(page: nil, userAgent: nil, groupId: nil, cbSource: nil) + let payload = EventPayload( + context: context, + userType: .endUser, + type: type, + attrs: attrs, + name: name, + id: Analytics.shared.userId, + session: session, + search: nil, + reportToSegment: false, + fingerprint: nil, + clientEventTimestamp: Date().getCurrentTimeStamp(), + clientFlushedTimestamp: Date().getCurrentTimeStamp() + ) + + return payload + } + + private func addEventToServerQueue(type: AnalyticsType, name: EventName, attrs: EventAttributes) { + let enrichedEvent = self.enrichEvent(type: type, name: name, attrs: attrs); + self.serverQueue.append(enrichedEvent); + } + +} + +extension Date { + func getCurrentTimeStamp() -> String { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSSSZ" + formatter.timeZone = TimeZone(abbreviation: "UTC") + return formatter.string(from: self) + } +} diff --git a/Sources/CommandBarIOS/Analytics/Events.swift b/Sources/CommandBarIOS/Analytics/Events.swift new file mode 100644 index 0000000..b6d072b --- /dev/null +++ b/Sources/CommandBarIOS/Analytics/Events.swift @@ -0,0 +1,179 @@ +// TODO: Organize better + +struct NumberResponseEvent: Codable { + var type: String + let value: Int + let emoji: String? + let max: Int + + init(value: Int, max: Int, emoji: String? = nil) { + type = "number" + self.value = value + self.emoji = emoji + self.max = max + } +} + +struct StringResponseEvent: Codable { + var type: String + + let value: String + + init(value: String) { + type = "string" + self.value = value + } +} + +struct ArrayResponseEvent: Codable { + var type: String + let value: [String] + + init(value: [String]) { + type = "string" + self.value = value + } +} + +enum ResponseEvent: Codable { + case number(NumberResponseEvent) + case string(StringResponseEvent) + case array(ArrayResponseEvent) + + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + if let x = try? container.decode(NumberResponseEvent.self) { + self = .number(x) + return + } + if let x = try? container.decode(StringResponseEvent.self) { + self = .string(x) + return + } + if let x = try? container.decode(ArrayResponseEvent.self) { + self = .array(x) + return + } + throw DecodingError.typeMismatch(ResponseEvent.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for ResponseEvent")) + } + + func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + switch self { + case .number(let x): + try container.encode(x) + case .string(let x): + try container.encode(x) + case .array(let x): + try container.encode(x) + } + } +} + +struct Status: Codable { + let is_preview: Bool + let is_live: Bool +} + + +protocol EventData: Codable { + var type: EventType { get set} +} + +enum EventType : String, Codable { + case surveyResponse = "survey_response" +} + +enum AnalyticsType: String, Codable { + case track = "t" + case identify = "i" + case log = "l" + case availability = "a" + case error = "e" +} + +enum EventName : String, Codable { + case surveyResponse = "Survey response" +} + +enum UserType: String, Codable { + case admin, likelyAdmin = "likely-admin", endUser = "end_user" +} + +struct FormFactorConfig: Codable { + var type = "modal" +} + + +struct NudgeEvent: Codable { + struct NudgeStepEvent : Codable { + var id: String + var title: String + } + + var id: String + var trigger: PushTrigger + var template_source:String + var slug: String + var frequency_limit: String = "no_limit" + var step:NudgeStepEvent + var status: Status +} + +struct EventAttributes: Codable { + var type: AnalyticsType + var response: ResponseEvent? + var nudge: NudgeEvent? + var formFactor = "modal" +} + +struct EventPayload: Codable { + struct Context: Codable { + struct Page: Codable { + let path: String? + let title: String? + let url: String? + let search: String? + } + + let page: Page? + let userAgent: String? + let groupId: String? + let cbSource: String? + } + + + let context: Context + let userType: UserType + let type: AnalyticsType + let attrs: EventAttributes? + let name: EventName? + let id: String? + let session: String? + let search: String? + let reportToSegment: Bool + let fingerprint: String? + let clientEventTimestamp: String + let clientFlushedTimestamp: String? + + enum UserType: String, Codable { + case admin, likelyAdmin = "likely-admin", endUser = "end_user" + } +} + +struct AnalyticsTrackBody: Codable { + let events: [EventPayload] + let organization: String + let id: String? +} + + +struct UserProperties: Codable { + var id: String? = nil; +} + +struct AnalyticsIdentifyBody:Codable { + var organization_id: String + var distinct_id: String? + var properties: UserProperties +} diff --git a/Sources/CommandBarIOS/CommandBar.swift b/Sources/CommandBarIOS/CommandBar/CommandBar.swift similarity index 76% rename from Sources/CommandBarIOS/CommandBar.swift rename to Sources/CommandBarIOS/CommandBar/CommandBar.swift index fd59c34..0b33352 100644 --- a/Sources/CommandBarIOS/CommandBar.swift +++ b/Sources/CommandBarIOS/CommandBar/CommandBar.swift @@ -1,16 +1,16 @@ import WebKit -public class CommandBar { - private var options: CommandBarOptions; +class CommandBar { + private var options: CommandBarOptions_Deprecated; - public weak var delegate: HelpHubWebViewDelegate? // Add this property + weak var delegate: HelpHubWebViewDelegate? // Add this property private weak var presentedNavigationController: UINavigationController? // Add this property - public init(options: CommandBarOptions) { + init(options: CommandBarOptions_Deprecated) { self.options = options } - public func openHelpHub() { + func openHelpHub() { DispatchQueue.main.async { let viewController = HelpHubViewController(options: self.options) viewController.delegate = self @@ -25,14 +25,14 @@ public class CommandBar { } } - public func closeHelpHub() { + func closeHelpHub() { presentedNavigationController?.dismiss(animated: true, completion: nil) presentedNavigationController = nil } } extension CommandBar : HelpHubWebViewDelegate { - public func didReceiveFallbackAction(_ action: [String : Any]) { + func didReceiveFallbackAction(_ action: [String : Any]) { self.delegate?.didReceiveFallbackAction(action) } } diff --git a/Sources/CommandBarIOS/CommandBar/InternalSDK.swift b/Sources/CommandBarIOS/CommandBar/InternalSDK.swift new file mode 100644 index 0000000..cd1cb4a --- /dev/null +++ b/Sources/CommandBarIOS/CommandBar/InternalSDK.swift @@ -0,0 +1,106 @@ + +protocol CommandBarInternalSDKDelegate: AnyObject { + func didBootComplete(withConfig config: Config) + func didBootFail(withError error: Error?) + + func didTriggerOpenChat(withType type: String) +} + +// MARK: Internal SDK +final class CommandBarInternalSDK : CommandBarInternalSDKDelegate { + internal final var LAUNCH_CODE: LaunchCode = .prod + + var orgId: String? = nil + var options: CommandBarInternalOptions = CommandBarInternalOptions(launch_code: .prod) + var config: Config? = nil + + // Update when you need to test localhost + + weak var delegate: CommandBarInternalSDKDelegate? + static let shared = CommandBarInternalSDK() + + var isReady: Bool = false + + func boot(orgId: String, with options: CommandBarOptions? = nil) { + self.orgId = orgId + self.options = options != nil ? CommandBarInternalOptions(from: options!, with: LAUNCH_CODE) : self.options + + guard let url = self.options.getAPIUrl(with: "/organizations/\(self.orgId!)/config/") else { + print("Warning: Could not boot CommandBar") + return + } + + let task = URLSession.shared.dataTask(with: url) {(data, response, error) in + guard let data = data else { + print("Warning: Could not boot CommandBar") + CommandBarInternalSDK.shared.didBootFail(withError: error) + return + } + + do { + let decoder = JSONDecoder() + let config = try decoder.decode(Config.self, from: data) + + // Once we've decoded the condig, setup Analytics + Analytics.shared.setup(orgId: orgId, with: self.options) + + DispatchQueue.main.async { + CommandBarInternalSDK.shared.isReady = true + CommandBarInternalSDK.shared.didBootComplete(withConfig: config) + } + + } catch let error { + print("Warning: Could not boot CommandBar") + DispatchQueue.main.async { + CommandBarInternalSDK.shared.didBootFail(withError: error) + } + } + } + task.resume() + } + + func triggerNudges() { + guard let config = CommandBarInternalSDK.shared.config else { return } + + // TODO: Can probably hook up some sort of background queue to enqueue to from here + if let nudge = config.nudges_v2.filter({ nudge in + return nudge.is_live && !nudge.archived && nudge.trigger == .whenConditionsPass + }).first { + NudgeWindowManager.shared.renderNudge(nudge) + } + } + + + func triggerNudges(withEvent event: String) { + guard let config = CommandBarInternalSDK.shared.config else { return } + + if let nudge = config.nudges_v2.filter({ nudge in + return nudge.trigger == .onEvent(PushTrigger.OnEventMeta(event: event)) && nudge.is_live && !nudge.archived + }).first { + NudgeWindowManager.shared.renderNudge(nudge) + } + } + + + public func trackEvent(event: String) { + CommandBarInternalSDK.shared.triggerNudges(withEvent: event) + } + + + func didBootComplete(withConfig config: Config) { + CommandBarInternalSDK.shared.config = config + + CommandBarInternalSDK.shared.triggerNudges() + CommandBarInternalSDK.shared.delegate?.didBootComplete(withConfig: config) + } + + func didBootFail(withError error: Error?) { + print("Failed to boot CommandBar: \(String(describing: error))") + CommandBarInternalSDK.shared.delegate?.didBootFail(withError: error) + } + + func didTriggerOpenChat(withType type: String) { + CommandBarInternalSDK.shared.delegate?.didTriggerOpenChat(withType: type) + } + +} diff --git a/Sources/CommandBarIOS/CommandBar/Options.swift b/Sources/CommandBarIOS/CommandBar/Options.swift new file mode 100644 index 0000000..39468e2 --- /dev/null +++ b/Sources/CommandBarIOS/CommandBar/Options.swift @@ -0,0 +1,96 @@ + +// MARK: Public +protocol CommandBarOptionsDelegate: Codable { + var user_id: String? { get set } +} + +public struct CommandBarOptions : CommandBarOptionsDelegate, Codable { + public var user_id: String? = nil + + public init(user_id: String? = nil) { + self.user_id = user_id + } +} + + +// MARK: Internal +internal enum LaunchCode: String, Codable { + case prod = "prod" + case labs = "labs" + case localDev = "local-dev" +} + +internal struct CommandBarInternalOptions : CommandBarOptionsDelegate, Codable { + var user_id: String? + internal var launch_code: LaunchCode + + internal init() { + self.launch_code = .prod + self.user_id = nil + } + + internal init(launch_code: LaunchCode, user_id: String? = nil) { + self.user_id = user_id + self.launch_code = launch_code + } + + internal init(from options: CommandBarOptions, with launch_code: LaunchCode = .prod) { + self.user_id = options.user_id + self.launch_code = launch_code + } + + internal func getAPIUrl(for resource: InternalAPIResource = .api, with path: String) -> URL? { + let baseURLStr = self.getBaseURLStr(for: resource) + if var components = URLComponents(string: baseURLStr) { + components.path = path + + return components.url + } + + return nil + } + + internal func getBaseURL(for resource: InternalAPIResource = .api) -> URL? { + let urlStr = self.getBaseURLStr(for: resource) + return URL(string: urlStr) + } + + internal func getBaseURLStr(for resource: InternalAPIResource = .api) -> String { + var baseURLStr = "https://api.commandbar.com" + + switch(self.launch_code) { + case .labs: + baseURLStr = "https://api-labs.commandbar.com" + break; + case .localDev: + baseURLStr = "http://localhost:8000" + break + default: + if resource == .analytics { + baseURLStr = "https://t.commandbar.com" + } + } + + return baseURLStr + } + + enum InternalAPIResource { + case analytics + case api + } +} + +public struct CommandBarOptions_Deprecated { + var orgId: String + var userId: String? + var spinnerColor: String; + var launchCode: String; + + public init(_ dict: [String: Any]) { + orgId = dict["orgId"] as! String + userId = dict["userId"] as? String + spinnerColor = dict["spinnerColor"] as? String ?? "#3662F1" + launchCode = dict["launchCode"] as? String ?? "prod" + } +} + diff --git a/Sources/CommandBarIOS/CommandBar/SDK.swift b/Sources/CommandBarIOS/CommandBar/SDK.swift new file mode 100644 index 0000000..dd74660 --- /dev/null +++ b/Sources/CommandBarIOS/CommandBar/SDK.swift @@ -0,0 +1,68 @@ +import Foundation +import JavaScriptCore + +public protocol CommandBarSDKDelegate : AnyObject { + func didFinishBooting(withError error: Error?) +} + +// Optional Protocol methods +extension CommandBarSDKDelegate { + func didTriggerOpenChat(withType type: String) {} +} + +// MARK: Public SDK +public final class CommandBarSDK { + private static let sharedInternal = CommandBarInternalSDK.shared + private var commandbar: CommandBar? = nil + public static let shared = CommandBarSDK() + + + var isReady: Bool = false + var orgId: String? = nil + var options: CommandBarOptions? = nil + + weak var delegate: CommandBarSDKDelegate? + weak var privateDelagate: CommandBarInternalSDK? + + public init() { + self.orgId = nil + self.options = nil + } + + public func boot(_ orgId: String, with options: CommandBarOptions? = nil) { + self.orgId = orgId + self.options = options + self.commandbar = CommandBar(options: CommandBarOptions_Deprecated(["orgId": orgId, "launchCode": "prod" ])) + + CommandBarSDK.sharedInternal.boot(orgId: orgId, with: options) + } + + + public func trackEvent(event: String) { + CommandBarSDK.sharedInternal.trackEvent(event: event) + } + + public func openHelpHub() { + guard let orgId = CommandBarSDK.shared.orgId else { return } + + commandbar?.openHelpHub() + } + +} + +extension CommandBarSDK : CommandBarInternalSDKDelegate { + func didBootComplete(withConfig config: Config) { + CommandBarSDK.shared.isReady = true + CommandBarSDK.shared.delegate?.didFinishBooting(withError: nil) + + } + + func didBootFail(withError error: Error?) { + CommandBarSDK.shared.delegate?.didFinishBooting(withError: error) + } + + func didTriggerOpenChat(withType type: String) { + CommandBarSDK.shared.delegate?.didTriggerOpenChat(withType: type) + } +} + diff --git a/Sources/CommandBarIOS/CommandBarOptions.swift b/Sources/CommandBarIOS/CommandBarOptions.swift deleted file mode 100644 index 3f04b3c..0000000 --- a/Sources/CommandBarIOS/CommandBarOptions.swift +++ /dev/null @@ -1,14 +0,0 @@ - -public struct CommandBarOptions { - var orgId: String - var userId: String? - var spinnerColor: String; - var launchCode: String; - - public init(_ dict: [String: Any]) { - orgId = dict["orgId"] as! String - userId = dict["userId"] as? String - spinnerColor = dict["spinnerColor"] as? String ?? "#3662F1" - launchCode = dict["launchCode"] as? String ?? "prod" - } -} diff --git a/Sources/CommandBarIOS/Components/BottomSheet.swift b/Sources/CommandBarIOS/Components/BottomSheet.swift new file mode 100644 index 0000000..3a62875 --- /dev/null +++ b/Sources/CommandBarIOS/Components/BottomSheet.swift @@ -0,0 +1,148 @@ +import SwiftUI + +struct ViewHeightKey: PreferenceKey { + static var defaultValue = CGFloat(0) + typealias Value = CGFloat + static func reduce(value: inout Value, nextValue: () -> Value) { + value = max(value, nextValue()) + } +} + +struct BottomSheet: View { + var onCloseAction: (() -> Void)? + @Binding var showSheet: Bool + var content: () -> Content + + @GestureState private var translation: CGFloat = 0 + @State private var offset: CGFloat = 0 // New State variable + @State private var contentHeight : CGFloat = 0 + + struct Handle: View { + private let width: CGFloat = 60.0 + private let height: CGFloat = 5.0 + + var body: some View { + RoundedRectangle(cornerRadius: self.height / 2) + .frame(width: self.width, height: self.height) + .foregroundColor(Color.gray.opacity(0.3)) + .padding(10) + } + } + + + var main: some View { + Group { + Rectangle() + .fill(.white.opacity(0)) + .frame(width: UIScreen.main.bounds.width, height: 30) + .overlay( + Rectangle() + .fill(Color.black.opacity(0.3)) + .frame(height: 30) + .shadow(color: .black, radius: 25, y: 0) + .mask(Rectangle().gradientMask( + Gradient(colors: [.clear, .black]) + )), + alignment: .top + ) + .offset(y: 10) + + VStack { + Handle() + self.content() + } + .frame(width: UIScreen.main.bounds.width) + } + } + var body: some View { + ZStack { + if showSheet { + VStack(spacing: 0) { + + if #available(iOS 14.0, *) { + main.background(Color(UIColor.systemBackground).cornerRadius(16, corners: [.topLeft, .topRight]).ignoresSafeArea(.all, edges: .bottom)) + } else { + main.background(Color(UIColor.systemBackground).cornerRadius(16, corners: [.topLeft, .topRight]).edgesIgnoringSafeArea(.bottom)) + } + + } + .frame(width: UIScreen.main.bounds.width) + .transition(.move(edge: .bottom)) + .offset(y: self.offset) + .gesture(DragGesture() + .onChanged { value in + if value.startLocation.y < value.location.y { + self.offset = value.translation.height + } + } + .onEnded { value in + let velocityThreshold: CGFloat = 1200.0 + let swipeValid = self.offset > UIScreen.main.bounds.height * 0.25 || value.predictedEndTranslation.height > UIScreen.main.bounds.height * 0.25 || value.predictedEndLocation.y - value.startLocation.y > UIScreen.main.bounds.height * 0.25 || -value.predictedEndTranslation.height > velocityThreshold + + if swipeValid { + withAnimation(.easeOut(duration: 0.3)) { + self.showSheet = false + onCloseAction?() + } + } else { + withAnimation(.spring()) { + self.offset = 0 + } + } + } + ) + } + }.onAppear(perform: { + DispatchQueue.main.async { + withAnimation(.spring(duration: 0.3)) { + self.showSheet = true + } + } + }) + } + +} + +struct RoundedTopRectangle: Shape { + var cornerRadius: CGFloat + func path(in rect: CGRect) -> Path { + var path = Path() + path.move(to: CGPoint(x: 0, y: cornerRadius)) + path.addLine(to: CGPoint(x: 0, y: rect.maxY)) // down + path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY)) // across + path.addLine(to: CGPoint(x: rect.maxX, y: cornerRadius)) //up + path.addArc(center: CGPoint(x: rect.maxX - cornerRadius, y: cornerRadius), radius: cornerRadius, startAngle: Angle(degrees: 0), endAngle: Angle(degrees: 90), clockwise: true) + path.addArc(center: CGPoint(x: cornerRadius, y: cornerRadius), radius: cornerRadius, startAngle: Angle(degrees: 270), endAngle: Angle(degrees: 180), clockwise: true) + path.closeSubpath() + return path + } +} + +struct RoundedCorner: Shape { + + var radius: CGFloat = .infinity + var corners: UIRectCorner = .allCorners + + func path(in rect: CGRect) -> Path { + let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius)) + return Path(path.cgPath) + } +} + +// MARK: Extensions + +extension View { + func gradientMask(_ gradient: Gradient) -> some View { + self.mask(LinearGradient(gradient: gradient, startPoint: .top, endPoint: .bottom)) + } + + func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View { + clipShape( RoundedCorner(radius: radius, corners: corners) ) + } +} + +extension CGSize { + static func add(_ lhs: CGSize, _ rhs: CGSize) -> CGSize { + return CGSize(width: lhs.width + rhs.width, height: lhs.height + rhs.height) + } +} diff --git a/Sources/CommandBarIOS/Components/Buttons/Button.swift b/Sources/CommandBarIOS/Components/Buttons/Button.swift new file mode 100644 index 0000000..ae190d5 --- /dev/null +++ b/Sources/CommandBarIOS/Components/Buttons/Button.swift @@ -0,0 +1,35 @@ +import SwiftUI + +struct CMDButton: View { + var title: String + var variant: NudgeContentButtonBlockMeta.ButtonType? + var fullWidth: Bool = false + var action: (() -> Void)? + + var backgroundColor: Color { + return (variant ?? .primary) == .primary ? Color.black : Color.white + } + + var foregroundColor: Color { + return (variant ?? .primary) == .primary ? Color.white : Color.black + } + + var borderColor: Color { + return (variant ?? .primary) == .primary ? Color.black : Color.gray.opacity(0.5) + } + + var body: some View { + Button(action: action ?? { print("not implemented")}) { + Text(title) + .frame(maxWidth: fullWidth ? .infinity : nil) + .padding(.vertical, 11) + .padding(.horizontal, 12) + .font(.system(size: 14, weight: .semibold)) + .background(backgroundColor) + .foregroundColor(foregroundColor) + .overlay(RoundedRectangle(cornerRadius: 5) + .stroke(borderColor, lineWidth: 1) ) + .cornerRadius(5) + } + } +} diff --git a/Sources/CommandBarIOS/Components/Buttons/ButtonGroup.swift b/Sources/CommandBarIOS/Components/Buttons/ButtonGroup.swift new file mode 100644 index 0000000..9532586 --- /dev/null +++ b/Sources/CommandBarIOS/Components/Buttons/ButtonGroup.swift @@ -0,0 +1,35 @@ +import SwiftUI + + +// TODO: Move NPS functionality to later +enum ButtonGroupVariant { + case primary + case inclusive +} + +struct ButtonGroupView: View { + let variant: ButtonGroupVariant + let options: [Option] + let content: (Option, Bool) -> Content + @Binding var selection: Int + + init(variant: ButtonGroupVariant = .primary, options: [Option], selection: Binding, @ViewBuilder content: @escaping (Option, Bool) -> Content) { + self.variant = variant + self.options = options + self.content = content + self._selection = selection + } + + var body: some View { + HStack { + ForEach(options.indices, id: \.self) { index in + let isSelected = variant == .inclusive ? index <= selection : index == selection + Button(action: { + selection = index + }) { + content(options[index], isSelected) + }.frame(maxWidth: .infinity) + } + } + } +} diff --git a/Sources/CommandBarIOS/Components/Buttons/CloseButton.swift b/Sources/CommandBarIOS/Components/Buttons/CloseButton.swift new file mode 100644 index 0000000..e1effb2 --- /dev/null +++ b/Sources/CommandBarIOS/Components/Buttons/CloseButton.swift @@ -0,0 +1,37 @@ +import SwiftUI + +struct CloseButton: View { + let action: () -> Void + + var body: some View { + Button(action: action) { + Image(systemName: "xmark") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 12, height: 12) + .foregroundColor(.gray) + + + } + .buttonStyle(PlainButtonStyle()) + } +} + + +struct StarButton: View { + @State var filled = false + let action: () -> Void + + var body: some View { + Button(action: action) { + Image(systemName: filled ? "star.fill" : "star") + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: 12, height: 12) + .foregroundColor(.gray) + + + } + .buttonStyle(PlainButtonStyle()) + } +} diff --git a/Sources/CommandBarIOS/Components/Image.swift b/Sources/CommandBarIOS/Components/Image.swift new file mode 100644 index 0000000..11bcb1d --- /dev/null +++ b/Sources/CommandBarIOS/Components/Image.swift @@ -0,0 +1,42 @@ +import SwiftUI + +struct AsyncImage: View { + @ObservedObject private var loader: ImageLoader + + let url: URL + + init(url: URL) { + self.url = url + self.loader = ImageLoader() + } + + var body: some View { + content.onAppear { loader.load(from: self.url) } + } + + private var content: some View { + Group { + if let image = loader.image { + Image(uiImage: image) + .resizable() + .aspectRatio(contentMode: .fit) + } else { + // Replace with whatever placeholder you want to use + ActivityIndicator(isAnimating: .constant(true)).padding(.vertical) + } + } + } +} + +class ImageLoader: ObservableObject { + @Published var image: UIImage? + + func load(from url: URL) { + URLSession.shared.dataTask(with: url) { data, response, error in + guard let data = data, let image = UIImage(data: data) else { return } + DispatchQueue.main.async { + self.image = image + } + }.resume() + } +} diff --git a/Sources/CommandBarIOS/Components/Spinner.swift b/Sources/CommandBarIOS/Components/Spinner.swift new file mode 100644 index 0000000..26ffc1f --- /dev/null +++ b/Sources/CommandBarIOS/Components/Spinner.swift @@ -0,0 +1,15 @@ +import SwiftUI + +struct ActivityIndicator: UIViewRepresentable { + + @Binding var isAnimating: Bool + var style: UIActivityIndicatorView.Style = .medium + + func makeUIView(context: UIViewRepresentableContext) -> UIActivityIndicatorView { + return UIActivityIndicatorView(style: style) + } + + func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext) { + isAnimating ? uiView.startAnimating() : uiView.stopAnimating() + } +} diff --git a/Sources/CommandBarIOS/Components/Video.swift b/Sources/CommandBarIOS/Components/Video.swift new file mode 100644 index 0000000..00bc16a --- /dev/null +++ b/Sources/CommandBarIOS/Components/Video.swift @@ -0,0 +1,110 @@ +import SwiftUI +import AVKit +import Combine +import WebKit + +struct YoutubeVideo: UIViewRepresentable { + + var youtubeVideoID: String + + func makeUIView(context: Context) -> WKWebView { + + WKWebView() + } + + func updateUIView(_ uiView: WKWebView, context: Context) { + + let path = "https://www.youtube.com/embed/\(youtubeVideoID)" + guard let url = URL(string: path) else { return } + + uiView.scrollView.isScrollEnabled = false + uiView.load(.init(url: url)) + } +} + +struct AsyncVideo: View { + let url: URL + + + var body: some View { + VideoPlayerView(url: url) + } +} +struct VideoPlayerView: View { + + @ObservedObject var videoLoader: VideoLoader + @State private var player: AVPlayer? + + init(url: URL) { + videoLoader = VideoLoader(url: url) + } + + var body: some View { + ZStack { + if videoLoader.loading { + ActivityIndicator(isAnimating: .constant(true)) + } else { + if #available(iOS 14.0, *) { + VideoPlayer(player: player) + .aspectRatio(contentMode: .fit) + .onAppear { + self.player = AVPlayer(url: videoLoader.url) + self.player?.play() + } + } else { + AVVideoPlayerView(url: videoLoader.url) + .aspectRatio(contentMode: .fit) + } + } + } + } +} + +struct AVVideoPlayerView: UIViewControllerRepresentable { + var url: URL + + func updateUIViewController(_ uiViewController: AVPlayerViewController, context: UIViewControllerRepresentableContext) { + } + + func makeUIViewController(context: Context) -> AVPlayerViewController { + let controller = AVPlayerViewController() + let player = AVPlayer(url: url) + controller.player = player + player.play() + return controller + } +} + + + +class VideoLoader: ObservableObject { + + @Published var loading: Bool + var url: URL + + init(url: URL) { + self.url = url + self.loading = true + loadVideo() + } + + func loadVideo() { + let asset = AVAsset(url: self.url) + let playableKey = "playable" + + asset.loadValuesAsynchronously(forKeys: [playableKey]) { [weak self] in + var error: NSError? = nil + let status = asset.statusOfValue(forKey: playableKey, error: &error) + switch status { + case .loaded: + DispatchQueue.main.async { + self?.loading = false + } + case .failed, .cancelled: + print("Failed to load URL: \(error?.localizedDescription ?? "Unknown error")") + default: + break + } + } + } +} diff --git a/Sources/CommandBarIOS/HelpHubViewController.swift b/Sources/CommandBarIOS/HelpHub/HelpHubViewController.swift similarity index 92% rename from Sources/CommandBarIOS/HelpHubViewController.swift rename to Sources/CommandBarIOS/HelpHub/HelpHubViewController.swift index d84d552..360d0af 100644 --- a/Sources/CommandBarIOS/HelpHubViewController.swift +++ b/Sources/CommandBarIOS/HelpHub/HelpHubViewController.swift @@ -3,10 +3,10 @@ import WebKit public class HelpHubViewController: UIViewController { var helpHubView: HelpHubWebView! - private var options: CommandBarOptions + private var options: CommandBarOptions_Deprecated public var delegate: HelpHubWebViewDelegate? // Add this property - public init(options: CommandBarOptions) { + public init(options: CommandBarOptions_Deprecated) { self.options = options super.init(nibName: nil, bundle: nil) } diff --git a/Sources/CommandBarIOS/HelpHubWebView.swift b/Sources/CommandBarIOS/HelpHub/HelpHubWebView.swift similarity index 73% rename from Sources/CommandBarIOS/HelpHubWebView.swift rename to Sources/CommandBarIOS/HelpHub/HelpHubWebView.swift index 62740a4..a885bf3 100644 --- a/Sources/CommandBarIOS/HelpHubWebView.swift +++ b/Sources/CommandBarIOS/HelpHub/HelpHubWebView.swift @@ -2,7 +2,7 @@ import UIKit import WebKit public class HelpHubWebView: WKWebView, WKNavigationDelegate, WKScriptMessageHandler { - public var options: CommandBarOptions? = nil { + public var options: CommandBarOptions_Deprecated? = nil { didSet { self.loadContent() } @@ -40,49 +40,6 @@ public class HelpHubWebView: WKWebView, WKNavigationDelegate, WKScriptMessageHan @@ -110,8 +72,8 @@ public class HelpHubWebView: WKWebView, WKNavigationDelegate, WKScriptMessageHan (function() { window._cbIsWebView = true; var o="\(options.orgId)",n=["Object.assign","Symbol","Symbol.for"].join("%2C"),a=window;function t(o,n){void 0===n&&(n=!1),"complete"!==document.readyState&&window.addEventListener("load",t.bind(null,o,n),{capture:!1,once:!0});var a=document.createElement("script");a.type="text/javascript",a.async=n,a.src=o,document.head.appendChild(a)}function r(){var n;if(void 0===a.CommandBar){delete a.__CommandBarBootstrap__;var r=Symbol.for("CommandBar::configuration"),e=Symbol.for("CommandBar::orgConfig"),c=Symbol.for("CommandBar::disposed"),i=Symbol.for("CommandBar::isProxy"),m=Symbol.for("CommandBar::queue"),l=Symbol.for("CommandBar::unwrap"),d=[],s="\(options.launchCode)",u=s&&s.includes("local")?"http://localhost:8000":"https://api.commandbar.com",f=Object.assign(((n={})[r]={uuid:o},n[e]={},n[c]=!1,n[i]=!0,n[m]=new Array,n[l]=function(){return f},n),a.CommandBar),p=["addCommand","boot"],y=f;Object.assign(f,{shareCallbacks:function(){return{}},shareContext:function(){return{}}}),a.CommandBar=new Proxy(f,{get:function(o,n){return n in y?f[n]:p.includes(n)?function(){var o=Array.prototype.slice.call(arguments);return new Promise((function(a,t){o.unshift(n,a,t),f[m].push(o)}))}:function(){var o=Array.prototype.slice.call(arguments);o.unshift(n),f[m].push(o)}}}),null!==s&&d.push("lc=".concat(s)),d.push("version=2"),t("".concat(u,"/latest/").concat(o,"?").concat(d.join("&")),!0)}}void 0===Object.assign||"undefined"==typeof Symbol||void 0===Symbol.for?(a.__CommandBarBootstrap__=r,t("https://polyfill.io/v3/polyfill.min.js?version=3.101.0&callback=__CommandBarBootstrap__&features="+n)):r(); - window.CommandBar.boot(\(userId), {}, { products: ["help_hub"] }); - window.CommandBar.openHelpHub(); + window.CommandBar.boot(\(userId), {}, { products: ["help_hub", "nudges"] }); + window.CommandBar.openHelpHub() })(); """ diff --git a/Sources/CommandBarIOS/Helpers/Color.swift b/Sources/CommandBarIOS/Helpers/Color.swift new file mode 100644 index 0000000..403b941 --- /dev/null +++ b/Sources/CommandBarIOS/Helpers/Color.swift @@ -0,0 +1,99 @@ +import SwiftUI + +extension Color { + func uiColor() -> UIColor { + + if #available(iOS 14.0, *) { + return UIColor(self) + } + + let components = self.components() + return UIColor(red: components.r, green: components.g, blue: components.b, alpha: components.a) + } + + private func components() -> (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) { + + let scanner = Scanner(string: self.description.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)) + var hexNumber: UInt64 = 0 + var r: CGFloat = 0.0, g: CGFloat = 0.0, b: CGFloat = 0.0, a: CGFloat = 0.0 + + let result = scanner.scanHexInt64(&hexNumber) + if result { + r = CGFloat((hexNumber & 0xff000000) >> 24) / 255 + g = CGFloat((hexNumber & 0x00ff0000) >> 16) / 255 + b = CGFloat((hexNumber & 0x0000ff00) >> 8) / 255 + a = CGFloat(hexNumber & 0x000000ff) / 255 + } + return (r, g, b, a) + } + + static func random() -> Color { + let red = Double.random(in: 0..<1) + let green = Double.random(in: 0..<1) + let blue = Double.random(in: 0..<1) + return Color(red: red, green: green, blue: blue) + } + + init(uiColor: UIColor) { + self.init(red: Double(uiColor.components.red), + green: Double(uiColor.components.green), + blue: Double(uiColor.components.blue), + opacity: Double(uiColor.components.alpha)) + } + + func lighter(by percentage: CGFloat = 30.0) -> Color { + if let uiColor = self.uiColor().lighter(by: percentage) { + return Color(uiColor: uiColor) + } + return self + + } + + func darker(by percentage: CGFloat = 30.0) -> Color { + if let uiColor = self.uiColor().darker(by: percentage) { + return Color(uiColor: uiColor) + } + return self + + } + + func adjust(by percentage: CGFloat = 30.0) -> Color { + let components = self.components() + return Color(red: min(Double(components.r + percentage/100), 1.0), + green: min(Double(components.g + percentage/100), 1.0), + blue: min(Double(components.b + percentage/100), 1.0), + opacity: Double(components.a)) + } +} + + +extension UIColor { + var components: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { + var red: CGFloat = 0 + var green: CGFloat = 0 + var blue: CGFloat = 0 + var alpha: CGFloat = 0 + getRed(&red, green: &green, blue: &blue, alpha: &alpha) + + return (red, green, blue, alpha) + } + func lighter(by percentage: CGFloat = 30.0) -> UIColor? { + return self.adjust(by: abs(percentage) ) + } + + func darker(by percentage: CGFloat = 30.0) -> UIColor? { + return self.adjust(by: -1 * abs(percentage) ) + } + + func adjust(by percentage: CGFloat = 30.0) -> UIColor? { + var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0 + if self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) { + return UIColor(red: min(red + percentage/100, 1.0), + green: min(green + percentage/100, 1.0), + blue: min(blue + percentage/100, 1.0), + alpha: alpha) + } else { + return nil + } + } +} diff --git a/Sources/CommandBarIOS/Nudges/Content/ContentBlock.swift b/Sources/CommandBarIOS/Nudges/Content/ContentBlock.swift new file mode 100644 index 0000000..7129310 --- /dev/null +++ b/Sources/CommandBarIOS/Nudges/Content/ContentBlock.swift @@ -0,0 +1,112 @@ +import SwiftUI + + +struct ContentBlock: View { + let formFactor: FormFactor + let content: NudgeContentBlock + let onAction: ((_ action: Action?) -> Void)? + + // TOOD: Annoying make better + var fullWidthButton: Bool = false + @Binding var surveyValue: Int + @Binding var surveyTextValue: String + + @State private var contentHeight: CGFloat = .zero + + func isYouTubeURL(_ urlString: String) -> Bool { + guard let url = URL(string: urlString) else { + return false + } + return url.host?.contains("youtube") == true + } + + + func handleAction(meta: NudgeContentButtonBlockMeta) { + if let conditional_actions = meta.conditional_actions { + let condition = conditional_actions.first(where: { condition in + if surveyValue == -1 { + return false + } + switch (condition.operator) { + case .eq: + return surveyValue == condition.operand - 1 + case .neq: + return surveyValue != condition.operand - 1 + case .gt: + return surveyValue > condition.operand - 1 + case .lt: + return surveyValue < condition.operand - 1 + } + }) + + if (condition?.action != nil) { + onAction?(condition?.action!) + } else { + onAction?(meta.action) + } + } else { + onAction?(meta.action) + } + } + var body: some View { + VStack { + switch content.meta { + case .markdown(let meta): + HStack { + Text(LocalizedStringKey(meta.value ?? "")) + Spacer() + } + + case .surveyRating(let meta): + RatingBlock(ratingBlock: meta, currentRating: $surveyValue) + case .button(let meta): + CMDButton(title: meta.label ?? "Button", variant: meta.button_type, fullWidth: fullWidthButton, action: { + handleAction(meta: meta) + }) + case .image(let meta): + if let nonNilURLString = meta.src, let url = URL(string: nonNilURLString) { + AsyncImage(url: url) + } else { + EmptyView() + } + case .video(let meta): + if let nonNilURLString = meta.src, let url = URL(string: nonNilURLString) { + + if (isYouTubeURL(nonNilURLString)) { + let strings = nonNilURLString.components(separatedBy: "/") + let videoId = strings.last ?? "" + YoutubeVideo(youtubeVideoID: videoId).scaledToFit() + } else { + AsyncVideo(url: url) + } + + } else { + EmptyView() + } + case .surveyTextShort(let meta): + TextField(meta.prompt, text: $surveyTextValue) + .font(.system(size: 14)) // Set the font size to 16 + .padding(.all, 8) + .background(RoundedRectangle(cornerRadius: 4).strokeBorder(Color.gray.opacity(0.5), lineWidth: 1)) + case .surveyText(let meta): + if #available(iOS 14.0, *) { + TextEditor(text: $surveyTextValue) + .font(.system(size: 16)) + .padding(10) + .background(RoundedRectangle(cornerRadius: 4).strokeBorder(Color.gray.opacity(0.5), lineWidth: 1)) + .frame(maxHeight: 150) + } else { + TextField(meta.prompt, text: $surveyTextValue) + .font(.system(size: 16)) + .padding(10) + .background(RoundedRectangle(cornerRadius: 4).strokeBorder(Color.gray.opacity(0.5), lineWidth: 1)) + .frame(maxHeight: 150) + .multilineTextAlignment(.leading) + .lineLimit(nil) + + } + default: EmptyView() + } + }.frame(maxWidth: fullWidthButton ? .infinity : nil) + } +} diff --git a/Sources/CommandBarIOS/Nudges/Content/SurveyRatingBlock.swift b/Sources/CommandBarIOS/Nudges/Content/SurveyRatingBlock.swift new file mode 100644 index 0000000..c1cd150 --- /dev/null +++ b/Sources/CommandBarIOS/Nudges/Content/SurveyRatingBlock.swift @@ -0,0 +1,225 @@ +import SwiftUI + + +struct StarButtons: View { + @Binding var selection: Int; + + let action: () -> Void; + let count: Int + + let starColor: Color = Color(.sRGB, red: 66/255, green: 66/255, blue: 77/255, opacity: 0.24) + let activeStarColor: Color = Color(.sRGB, red: 221/255, green: 158/255, blue: 35/255, opacity: 1) + let borderColor: Color = Color(.sRGB, red: 10/255, green: 10/255, blue: 15/255, opacity: 0.24) + let backgroundColor: Color = Color.white + let activeBorderColor: Color = Color(.sRGB, red: 255/255, green: 180/255, blue: 34/255) + let activeBackgroundColor: Color = Color(.sRGB, red: 255/255, green: 242/255, blue: 217/255) + + var body: some View { + let stars = Array(repeating: "", count: count) + + ButtonGroupView(variant: .inclusive, options: stars, selection: $selection) { option, isSelected in + ZStack { + Image(systemName: "star") + .resizable() + .scaledToFit() + .frame(width: 24, height: 24) + .foregroundColor(isSelected ? activeStarColor.darker(by: 20) : starColor) + .opacity(isSelected ? 1 : 0) + Image(systemName: isSelected ? "star.fill" : "star") + .resizable() + .scaledToFit() + .frame(width: isSelected ? 20 : 24, height: isSelected ? 20 : 24) // Original size + .foregroundColor(isSelected ? activeStarColor : starColor) + } + .frame(maxWidth: .infinity) + .padding(.vertical, 8) + .background(isSelected ? activeBackgroundColor : backgroundColor) + .foregroundColor(.white) + .cornerRadius(4) + .overlay( + RoundedRectangle(cornerRadius: 4) + .stroke(isSelected ? activeBorderColor : borderColor, lineWidth: 1) + ) + } + } +} + +struct EmojiButtons: View { + @Binding var selection: Int; + + let action: () -> Void; + let emojis: [String] + + let borderColor: Color = Color(.sRGB, red: 10/255, green: 10/255, blue: 15/255, opacity: 0.24) + let backgroundColor: Color = Color.white + let activeBorderColor: Color = Color(.sRGB, red: 255/255, green: 180/255, blue: 34/255) + let activeBackgroundColor: Color = Color(.sRGB, red: 255/255, green: 242/255, blue: 217/255) + + + var body: some View { + ButtonGroupView(options: emojis, selection: $selection) { option, isSelected in + Text(option) + .shadow(color: .init(.sRGB, red: 0, green: 0, blue: 0, opacity: isSelected ? 0.35 : 0), radius: 7, x: 0, y: 4) + .frame(maxWidth: .infinity) + .padding(.vertical, 8) + .background(isSelected ? activeBackgroundColor : backgroundColor) + .foregroundColor(.white) + .cornerRadius(4) + .overlay( + RoundedRectangle(cornerRadius: 4) + .stroke(isSelected ? activeBorderColor : borderColor, lineWidth: 1) + ) + } + } +} + +struct NumberButtons: View { + @Binding var selection: Int; + + let action: () -> Void; + let count: Int + + let borderColor: Color = Color(.sRGB, red: 10/255, green: 10/255, blue: 15/255, opacity: 0.24) + let backgroundColor: Color = Color.white + let activeBorderColor: Color = Color(.sRGB, red: 255/255, green: 180/255, blue: 34/255) + let activeBackgroundColor: Color = Color(.sRGB, red: 255/255, green: 242/255, blue: 217/255) + + var body: some View { + let numbers = Array(0...count).map { String($0) } + + ButtonGroupView(options: numbers, selection: $selection) { option, isSelected in + Text(option) + .frame(maxWidth: .infinity) + .padding(.vertical, 8) + .background(isSelected ? activeBackgroundColor : backgroundColor) + .foregroundColor(.black) + .cornerRadius(4) + .overlay( + RoundedRectangle(cornerRadius: 4) + .stroke(isSelected ? activeBorderColor : borderColor, lineWidth: 1) + ) + } + } +} + +struct RatingBlock: View { + let ratingBlock: NudgeContentSurveyRatingBlockMeta + + @Binding var currentRating: Int + + var labelColor: Color { + Color(red: 162.0 / 255, green: 162.0 / 255, blue: 169.0 / 255, opacity: 1) + } + + var RatingLabels: some View { + HStack { + Text(ratingBlock.lower_label ?? "Awful") + .fontWeight(.medium) + .font(.system(size: 12)) + .lineSpacing(15) + .foregroundColor(labelColor) + Spacer() + Text(ratingBlock.upper_label ?? "Amazing") + .fontWeight(.medium) + .font(.system(size: 12)) + .lineSpacing(15) + .foregroundColor(labelColor) + + } + } + + var body: some View { + VStack(alignment: .leading, spacing: 8) { + HStack(alignment: .top, spacing: 8) { + Group { + switch ratingBlock.type { + case "stars": + StarButtons(selection: $currentRating, action: { print("Rating!") }, count: ratingBlock.options ?? 0) + case "emojis": + if ratingBlock.emojis == nil { + EmptyView() + } else { + EmojiButtons(selection: $currentRating, action: { print("emojis") }, emojis: ratingBlock.emojis ?? ["🙁", "🙂", "🤩"]) + } + case "numbers": + NumberButtons(selection: $currentRating, action: { print("numbers")}, count: ratingBlock.options ?? 0) + + default: + EmptyView() + + } + } + } + .flexibleFrame(width: ratingBlock.type != "emojis" ? 40 : nil) + .frame(alignment: .leading) + + if (ratingBlock.upper_label != nil || ratingBlock.lower_label != nil) { + RatingLabels + } + } + } +} + +struct RatingButtonStyle: ButtonStyle { + let selectedMarked: Bool + let type: String + + func makeBody(configuration: Configuration) -> some View { + configuration.label + .padding(8) + .frame(width: type != "emojis" ? 40 : nil) + .foregroundColor(.white) + .scaleEffect(configuration.isPressed ? 0.95 : 1) + .animation(.spring()) + .buttonStyle(PlainButtonStyle()) + } +} + +extension Array { + subscript(safe index: Int) -> Element? { + indices.contains(index) ? self[index] : nil + } +} + +extension View { + @ViewBuilder + func flexibleFrame(width: CGFloat? = nil, height: CGFloat? = nil) -> some View { + if let width = width, let height = height { + self.frame(width: width, height: height) + } else if let width = width { + self.frame(minWidth: width, maxWidth: .infinity) + } else if let height = height { + self.frame(minHeight: height, maxHeight: .infinity) + } else { + self + } + } +} + +extension UIColor { + convenience init?(hexString: String) { + let r, g, b, a: CGFloat + + if hexString.hasPrefix("#") { + let start = hexString.index(hexString.startIndex, offsetBy: 1) + let hexColor = String(hexString[start...]) + + if hexColor.count == 8 { + let scanner = Scanner(string: hexColor) + var hexNumber: UInt64 = 0 + + if scanner.scanHexInt64(&hexNumber) { + r = CGFloat((hexNumber & 0xff000000) >> 24) / 255 + g = CGFloat((hexNumber & 0x00ff0000) >> 16) / 255 + b = CGFloat((hexNumber & 0x0000ff00) >> 8) / 255 + a = CGFloat(hexNumber & 0x000000ff) / 255 + + self.init(red: r, green: g, blue: b, alpha: a) + return + } + } + } + + return nil + } +} diff --git a/Sources/CommandBarIOS/Nudges/NudgeView.swift b/Sources/CommandBarIOS/Nudges/NudgeView.swift new file mode 100644 index 0000000..c7a3012 --- /dev/null +++ b/Sources/CommandBarIOS/Nudges/NudgeView.swift @@ -0,0 +1,244 @@ +import SwiftUI + +struct NudgeView: View { + let nudge: Nudge + let step: NudgeStep + let stepIndex: Int + + @State private var confettiEnabled: Int = 0 + @State private var cumulativeDrag: CGFloat = 0 + + @State private var appear = 0 + @State private var isSheetPresented = true + + @State private var viewOffset: CGSize = .zero + @GestureState private var translation: CGSize = .zero + @State public var surveyValue: Int = -1 + @State public var surveyTextValue: String = "" + + + @State private var height: CGFloat = 0 + + var onCloseAction: (() -> Void)? + // TODO: Cleanup to make accessing these things easier + var onAction: ((_ action: Action, _ nudge: Nudge, _ step: NudgeStep, _ surveyValue: Int, _ surveyTextValue: String) -> Void)? + + var width: CGFloat = 300 + var cornerRadius: CGFloat = 15 + var shadowRadius: CGFloat = 5 + var shadowOffsetX: CGFloat = 0 + var shadowOffsetY: CGFloat = 0 + var padding: CGFloat = 16 + + + func handleCloseAction() { + self.appear = 0 + onCloseAction?() + } + + func handleAction(action: Action?) { + guard let action = action else { return } + + self.onAction?(action, nudge, step, surveyValue, surveyTextValue) + } + + var HeaderStack: some View { + HStack { + Text(step.title).font(.headline) + Spacer() + if (nudge.dismissible && step.form_factor.type != .clip) { + CloseButton(action: handleCloseAction) + } + + } + } + + var ContentStack: some View { + let nonButtons = step.content.filter { $0.type != .button } + let buttonBlocks = step.content.filter({ $0.type == .button }).sorted { (lhs: NudgeContentBlock, rhs: NudgeContentBlock) -> Bool in + switch(lhs.type, rhs.type) { + case (.button, .button): + // Move primary buttons after secondary ones + if case let .button(lhsButtonMeta) = lhs.meta, case let .button(rhsButtonMeta) = rhs.meta { + switch (lhsButtonMeta.button_type, rhsButtonMeta.button_type) { + case (.primary, .primary), (.secondary, .secondary), (.none, .none): + return false + case (.primary, .secondary), (.primary, .none), (.none, .secondary): + return false + case (.secondary, .primary), (.secondary, .none), (.none, .primary): + return true + default: + return true + } + } + case (.button, _): return false + case (_, .button): return true + default: return false + } + + return false + } + + return VStack { + // TODO: Make content block conform to Identifiable and Equatable + ForEach(Array(nonButtons.indices), id: \.self) { index in + ContentBlock(formFactor: step.form_factor, content: nonButtons[index], onAction: nil, surveyValue: $surveyValue, surveyTextValue: $surveyTextValue) + } + + HStack { + if nudge.show_step_counter && nudge.steps.count > 1 { + Text("\(self.stepIndex + 1)/\(nudge.steps.count)").foregroundColor(.init(red: 110/255, green: 110/255, blue: 110/255)) + Spacer() + ForEach(Array(buttonBlocks.indices), id: \.self) { index in + ContentBlock(formFactor: step.form_factor, content: buttonBlocks[index], onAction: handleAction, surveyValue: $surveyValue, surveyTextValue: $surveyTextValue) + } + } else { + ForEach(Array(buttonBlocks.indices), id: \.self) { index in + ContentBlock(formFactor: step.form_factor, content: buttonBlocks[index], onAction: handleAction, fullWidthButton: true, surveyValue: $surveyValue, surveyTextValue: $surveyTextValue) + } + } + } + } + } + + + var Content: some View { + Group { + if step.form_factor.type == .clip { + VStack (alignment: .leading, spacing: 10) { + HeaderStack + ContentStack + } + .padding(.horizontal) + } else { + VStack (alignment: .leading, spacing: 10) { + HeaderStack + ContentStack + } + .padding() + .background(Color(UIColor.systemBackground)) + .cornerRadius(cornerRadius) + .scaleEffect(self.appear == 1 ? 1 : 0) + .onAppear { + withAnimation(.spring(response: 0.3, dampingFraction: 0.6, blendDuration: 0)) { + self.appear = 1 + } + } + .padding() + } + } + } + + var Modal: some View { + Content + } + + var Pin: some View { + Content + } + + var Popover: some View { + GeometryReader { geometry in + Content + .shadow(color: Color(red: 10/255, green: 10/255, blue: 15/255, opacity: 0.24), radius: 20, x: 0, y: 16) + .background(GeometryReader { + Color.clear.preference(key: ViewHeightKey.self, + value: $0.size.height) + }) + .offset(y: viewOffset.height + translation.height) + .gesture(enableDragGesture(geometry: geometry)) + .onPreferenceChange(ViewHeightKey.self) { height in + self.height = height + } + } + } + + var body: some View { + VStack { + self.renderFormFactor(for: self.step.form_factor.type) + } + .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: getAlignment(for: self.step.form_factor.type)) + } + + var Clip: some View { + BottomSheet(onCloseAction: onCloseAction, showSheet: $isSheetPresented) { + Content + } + } + + func renderFormFactor(for type: FormFactorType) -> some View { + Group { + switch (type) { + case .modal: + Modal + case .popover: + Popover + case .pin: + Pin + case .clip: + Clip + } + + } + } + + + func getAlignment(for type: FormFactorType) -> Alignment { + switch (step.form_factor.type) { + case .modal: + return .center + case .popover: + switch (step.form_factor.position) { + case .bottomLeft, .bottomRight: + return .bottom + case .topRight, .topLeft: + return .top + default: + return .center + } + case .clip: + return .bottom + case .pin: + return .center + } + } + + + func enableDragGesture(geometry: GeometryProxy) -> some Gesture { + DragGesture() + .onChanged { value in + self.viewOffset.height = value.translation.height + self.cumulativeDrag + } + .onEnded { value in + DispatchQueue.main.async { + let screenSize = geometry.size.height + let popoverHeight = self.height + let totalDragged = self.viewOffset.height + let top: CGFloat = 0 + let centerTop: CGFloat = screenSize / 3 + let centerBottom: CGFloat = (screenSize / 3) * 2 + let bottom: CGFloat = screenSize + let sizes = [top, centerTop, centerBottom, bottom] + let draggingUpwards = value.predictedEndLocation.y < value.startLocation.y + + var newOffset: CGSize = CGSize(width: 0, height: 0) + + if draggingUpwards { + let options = sizes.filter { $0 <= totalDragged } + let closest = options.max() ?? top + newOffset = CGSize(width: 0, height: closest) + } else { + let options = sizes.filter { $0 >= totalDragged } + let closest = options.min() ?? bottom + newOffset = CGSize(width: 0, height: closest - popoverHeight) + } + + withAnimation(.spring()) { + self.viewOffset = newOffset + self.cumulativeDrag = newOffset.height + } + } + + } + } +} diff --git a/Sources/CommandBarIOS/Nudges/NudgeWindowManager.swift b/Sources/CommandBarIOS/Nudges/NudgeWindowManager.swift new file mode 100644 index 0000000..7fce216 --- /dev/null +++ b/Sources/CommandBarIOS/Nudges/NudgeWindowManager.swift @@ -0,0 +1,192 @@ +import SwiftUI +import UIKit + +// MARK: Window +class NudgeWindow: UIWindow { + var nudge: Nudge + + init(nudge: Nudge, frame: CGRect) { + self.nudge = nudge + + super.init(frame: frame) + } + + init(nudge: Nudge, windowScene: UIWindowScene) { + self.nudge = nudge + super.init(windowScene: windowScene) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + + override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + let hitView = super.hitTest(point, with: event) + + // Do not return self or the root view if you want to ignore touches on them + if hitView == self || hitView == self.rootViewController?.view { + return nil + } + + return hitView + } +} + +// MARK: Window Manager +class NudgeWindowManager { + static let shared: NudgeWindowManager = NudgeWindowManager() + + weak var internalSDKDelegate: CommandBarInternalSDKDelegate? + private var nudgeWindow: NudgeWindow? + + private var currentNudgeView: NudgeView? = nil + private var currentStepIndex = 0 + + func renderNudge(_ nudge: Nudge) { + if !nudge.is_live || nudge.archived { return } + + self.showNudge(nudge) + } + + private func handleAction(_ action: Action, _ nudge: Nudge, _ step: NudgeStep, _ surveyValue: Int, _ surveyTextValue: String) { + NudgeWindowManager.shared.trackSurveyEvent(nudge, step, surveyValue, surveyTextValue) + + DispatchQueue.main.async { + switch(action) { + case .link(let linkAction): + // let operation = linkAction.operation ?? .blank + let value = linkAction.value + + if let url = URL(string: value) { + UIApplication.shared.open(url, options: [:], completionHandler: nil) + } + case .nudge(let nudgeAction): + NudgeWindowManager.shared.hideNudge() + if let nudge = CommandBarInternalSDK.shared.config?.nudges_v2.first(where: { + if let id = Int( $0.id) { + return id == nudgeAction.value + } + return false + }) { + self.currentStepIndex = 0 + NudgeWindowManager.shared.showNudge(nudge) + } else { return } + case .stepBack(_): + NudgeWindowManager.shared.goToNudgeStep(nudge, step: self.currentStepIndex - 1) + case .openChat(let openChatAction): + NudgeWindowManager.shared.internalSDKDelegate?.didTriggerOpenChat(withType: openChatAction.meta.type) + case .dismiss(_): + NudgeWindowManager.shared.hideNudge() + case .goToNudgeStep(let nudgeStepAction): + NudgeWindowManager.shared.goToNudgeStep(nudge, step: nudgeStepAction.value) + case .none(_): + NudgeWindowManager.shared.goToNudgeStep(nudge, step: self.currentStepIndex + 1) + case .click(_): + print("Unsupported") + default: + NudgeWindowManager.shared.goToNudgeStep(nudge, step: self.currentStepIndex + 1) + } + } + } + + private func trackSurveyEvent(_ nudge: Nudge, _ step: NudgeStep, _ surveyValue: Int, _ surveyTextValue: String) { + if let surveyContent = step.content.first(where: { return $0.type == .surveyRating || $0.type == .surveyText || $0.type == .surveyTextShort }) { + let nudgeStepEvent = NudgeEvent.NudgeStepEvent(id: String(step.id), title: step.title) + let nudgeEvent = NudgeEvent(id: nudge.id, trigger: nudge.trigger, template_source: nudge.template_source, slug: nudge.slug, step: nudgeStepEvent, status: .init(is_preview: false, is_live: true)) + + switch(surveyContent.meta) { + case .surveyRating(let meta): + switch(meta.type) { + case "emojis": + if let emojis = meta.emojis { + let emoji = emojis[surveyValue] + let responseEvent = NumberResponseEvent(value: surveyValue, max: meta.options ?? 0, emoji: emoji) + let attrs = EventAttributes(type: .log, response: .number(responseEvent), nudge: nudgeEvent) + Analytics.shared.log(eventName: .surveyResponse, data: attrs) + } + case "stars", "numbers": + let responseEvent = NumberResponseEvent(value: surveyValue, max: meta.options ?? 0) + let attrs = EventAttributes(type: .log, response: .number(responseEvent), nudge: nudgeEvent) + Analytics.shared.log(eventName: .surveyResponse, data: attrs) + default: + return + } + + case .surveyText(_), .surveyTextShort(_): + let responseEvent = StringResponseEvent(value: surveyTextValue) + let attrs = EventAttributes(type: .log, response: .string(responseEvent), nudge: nudgeEvent) + Analytics.shared.log(eventName: .surveyResponse, data: attrs) + default: + return + } + } + } + + private func goToNudgeStep(_ nudge: Nudge, step: Int) { + DispatchQueue.main.async { + NudgeWindowManager.shared.hideNudge() + NudgeWindowManager.shared.currentStepIndex = step + NudgeWindowManager.shared.showNudge(nudge) + } + + } + + private func showNudge(_ nudge: Nudge) { + guard nudgeWindow == nil else { return } + guard NudgeWindowManager.shared.currentStepIndex < nudge.steps.count else { + NudgeWindowManager.shared.hideNudge() + NudgeWindowManager.shared.currentStepIndex = 0 + return + } + + let currentStep = nudge.steps[NudgeWindowManager.shared.currentStepIndex] + + NudgeWindowManager.shared.currentNudgeView = NudgeView( + nudge: nudge, + step: currentStep, + stepIndex: NudgeWindowManager.shared.currentStepIndex, + onCloseAction: { + DispatchQueue.main.async { + NudgeWindowManager.shared.hideNudge() + } + }, + onAction: handleAction + ) + + // Try and get an active scene, fall back to the screens frame + let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene? + if (windowScene != nil) { + nudgeWindow = NudgeWindow(nudge: nudge, windowScene: windowScene!!) + } else { + nudgeWindow = NudgeWindow(nudge: nudge, frame: UIScreen.main.bounds) + } + + let hostingController = UIHostingController(rootView: NudgeWindowManager.shared.currentNudgeView) + + hostingController.view.backgroundColor = .clear + + + if currentStep.form_factor.type == .modal { + nudgeWindow?.backgroundColor = .black.withAlphaComponent(0.5) + } + + + nudgeWindow!.windowLevel = .alert + nudgeWindow!.rootViewController = hostingController + nudgeWindow!.makeKeyAndVisible() + } + + private func hideNudge() { + NudgeWindowManager.shared.currentStepIndex = 0 + if (nudgeWindow?.rootViewController) != nil { + NudgeWindowManager.shared.nudgeWindow = nil + NudgeWindowManager.shared.currentNudgeView = nil + } + } + +} + + + + diff --git a/Sources/CommandBarIOS/Types/Actions.swift b/Sources/CommandBarIOS/Types/Actions.swift new file mode 100644 index 0000000..5b9560d --- /dev/null +++ b/Sources/CommandBarIOS/Types/Actions.swift @@ -0,0 +1,432 @@ +struct AdminAction: Codable { + var type: String = "admin" + var value: String +} + +struct CallbackAction: Codable { + var type: String = "callback" + var value: String +} + +struct OpenBarAction: Codable { + var type: String = "open_bar" + var value: String? + var categoryFilter: Int? +} + +enum LinkActionOperation: String, Codable { + case router = "router" + case same = "self" + case blank = "blank" +} + +struct LinkAction: Codable { + var type: String = "link" + var value: String + var operation: LinkActionOperation? +} + +struct OpenChatAction: Codable { + var type: String = "open_chat" + var meta: Meta + + struct Meta: Codable { + var type: String + } +} + +struct DismissAction: Codable { + var type: String = "dismiss" +} + +struct StepBackAction: Codable { + var type: String = "step_back" +} + +struct SnoozeAction: Codable { + var type: String = "snooze" +} + +struct ClickAction: Codable { + var type: String = "click" + var value: String +} + + +struct BuiltInAction: Codable { + var type: String = "builtin" + var value: String +} + +struct WebhookAction: Codable { + var type: String = "webhook" + var value: String +} + +struct AppcuesAction: Codable { + var type: String = "appcues" + var value: String +} + +struct ScriptAction: Codable { + var type: String = "script" + var value: String +} + +struct VideoAction: Codable { + var type: String = "video" + var value: String +} + +enum HelpDocActionOperation: String, Codable { + case router = "router" + case same = "self" + case blank = "blank" + case help_hub = "help_hub" +} + +struct HelpDocAction: Codable { + var type: String = "helpdoc" + var value: String + var operation: HelpDocActionOperation? + var doc_metadata: DocMetadata? + + struct DocMetadata: Codable { + var content_type: String? + var date: String? + } +} + +struct CommandAction: Codable { + var type: String = "execute_command" + var meta: Meta + + struct Meta: Codable { + var type: String + var command: String + } +} + +struct NoAction: Codable { + var type: String = "no_action" +} + +struct NudgeAction: Codable { + var type: String = "nudge" + var value: Int +} + +struct GoToNudgeStepAction: Codable { + var type: String = "go_to_step" + var value: Int +} + +struct QuestlistAction: Codable { + var type: String = "questlist" + var value: Int +} + +enum Action: Codable { + case command(CommandAction) + case none(NoAction) + case click(ClickAction) + case link(LinkAction) + case openChat(OpenChatAction) + case dismiss(DismissAction) + case snooze(SnoozeAction) + case questlist(QuestlistAction) + case nudge(NudgeAction) + case goToNudgeStep(GoToNudgeStepAction) + case stepBack(StepBackAction) + case openBar(OpenBarAction) + + enum CodingKeys: CodingKey { + case type + } + + enum ActionTypes: String, Codable { + case command = "command" + case none = "no_action" + case click = "click" + case link = "link" + case openChat = "open_chat" + case dismiss = "dismiss" + case snooze = "snooze" + case questlist = "questlist" + case nudge = "nudge" + case goToNudgeStep = "go_to_step" + case stepBack = "step_back" + case openBar = "open_bar" + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let type = try container.decode(ActionTypes.self, forKey: .type) + + switch type { + case .command: + let commandAction = try CommandAction(from: decoder) + self = .command(commandAction) + case .none: + let noAction = try NoAction(from: decoder) + self = .none(noAction) + case .click: + let clickAction = try ClickAction(from: decoder) + self = .click(clickAction) + case .link: + let linkAction = try LinkAction(from: decoder) + self = .link(linkAction) + case .openChat: + let openChatAction = try OpenChatAction(from: decoder) + self = .openChat(openChatAction) + case .dismiss: + let dismissAction = try DismissAction(from: decoder) + self = .dismiss(dismissAction) + case .snooze: + let snoozeAction = try SnoozeAction(from: decoder) + self = .snooze(snoozeAction) + case .questlist: + let questlistAction = try QuestlistAction(from: decoder) + self = .questlist(questlistAction) + case .nudge: + let nudgeAction = try NudgeAction(from: decoder) + self = .nudge(nudgeAction) + case .goToNudgeStep: + let goToNudgeStepAction = try GoToNudgeStepAction(from: decoder) + self = .goToNudgeStep(goToNudgeStepAction) + case .stepBack: + let stepBackAction = try StepBackAction(from: decoder) + self = .stepBack(stepBackAction) + case .openBar: + let openBarAction = try OpenBarAction(from: decoder) + self = .openBar(openBarAction) + default: + throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Invalid type")) + + } + } + + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + switch self { + case .command(let command): + try container.encode(ActionTypes.command.rawValue, forKey: .type) + try command.encode(to: encoder) + case .none(let none): + try container.encode(ActionTypes.none.rawValue, forKey: .type) + try none.encode(to: encoder) + case .click(let click): + try container.encode(ActionTypes.click.rawValue, forKey: .type) + try click.encode(to: encoder) + case .link(let link): + try container.encode(ActionTypes.link.rawValue, forKey: .type) + try link.encode(to: encoder) + case .openChat(let openChat): + try container.encode(ActionTypes.openChat.rawValue, forKey: .type) + try openChat.encode(to: encoder) + case .dismiss(let dismiss): + try container.encode(ActionTypes.dismiss.rawValue, forKey: .type) + try dismiss.encode(to: encoder) + case .snooze(let snooze): + try container.encode(ActionTypes.snooze.rawValue, forKey: .type) + try snooze.encode(to: encoder) + case .questlist(let questlist): + try container.encode(ActionTypes.questlist.rawValue, forKey: .type) + try questlist.encode(to: encoder) + case .nudge(let nudge): + try container.encode(ActionTypes.nudge.rawValue, forKey: .type) + try nudge.encode(to: encoder) + case .goToNudgeStep(let goToNudgeStep): + try container.encode(ActionTypes.goToNudgeStep.rawValue, forKey: .type) + try goToNudgeStep.encode(to: encoder) + case .stepBack(let stepBack): + try container.encode(ActionTypes.stepBack.rawValue, forKey: .type) + try stepBack.encode(to: encoder) + case .openBar(let openBar): + try container.encode(ActionTypes.openBar.rawValue, forKey: .type) + try openBar.encode(to: encoder) + } + } + +} + +struct LabeledAction: Codable { + var cta: String; + var action: Action +} + + +enum FrequencyLimit: String, Codable { + case no_limit = "no_limit" + case once_per_session = "once_per_session" + case once_per_user = "once_per_user" + case untilInteraction = "until_interaction" +} +// +//protocol PushTrigger: Codable { +// var type: String { get set } +//} +// +//struct WhenConditionsPass: PushTrigger { +// var type: String = "when_conditions_pass" +//} +// +//struct WhenPageReached: PushTrigger { +// var type: String = "when_page_reached" +// var url: String +//} +// +//struct OnCommandExecution: PushTrigger { +// var type: String = "on_command_execution" +// var command: String +//} +// +//struct OnEvent: PushTrigger { +// var type: String = "on_event" +// var event: String +//} +// +//struct WhenElementAppears: PushTrigger { +// var type: String = "when_element_appears" +// var selector: String +//} +// +//struct OnUserConfusion: PushTrigger { +// var type: String = "on_user_confusion" +//} +// +//struct OnRageClick: PushTrigger { +// var type: String = "on_rage_click" +//} +// +//struct SmartDelay: PushTrigger { +// var type: String = "smart_delay" +//} +// +//struct WhenShareLinkViewed: PushTrigger { +// var type: String = "when_share_link_viewed" +//} + +enum PushTrigger: Codable, Equatable { + + enum CodingKeys: CodingKey { + case type + case meta + } + + struct WhenPageReachedMeta: Codable { + let url: String + } + + struct OnCommandExecutionMeta: Codable { + let command: String + } + + struct OnEventMeta: Codable { + let event: String + } + + struct WhenElementAppearsMeta: Codable { + let selector: String + } + + case whenConditionsPass + case whenPageReached(WhenPageReachedMeta) + case onCommandExecution(OnCommandExecutionMeta) + case onEvent(OnEventMeta) + case whenElementAppears(WhenElementAppearsMeta) + case onUserConfusion + case onRageClick + case smartDelay + case whenShareLinkViewed + + static func ==(lhs: PushTrigger, rhs: PushTrigger) -> Bool { + switch (lhs, rhs) { + case (.whenConditionsPass, .whenConditionsPass), + (.onUserConfusion, .onUserConfusion), + (.onRageClick, .onRageClick), + (.smartDelay, .smartDelay), + (.whenShareLinkViewed, .whenShareLinkViewed): + return true + + case let (.whenPageReached(meta1), .whenPageReached(meta2)): + return meta1.url == meta2.url + + case let (.onCommandExecution(meta1), .onCommandExecution(meta2)): + return meta1.command == meta2.command + + case let (.onEvent(meta1), .onEvent(meta2)): + return meta1.event == meta2.event + + case let (.whenElementAppears(meta1), .whenElementAppears(meta2)): + return meta1.selector == meta2.selector + + default: + return false + } + } + + static func !=(lhs: PushTrigger, rhs: PushTrigger) -> Bool { + return !(lhs == rhs) + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let type = try container.decode(String.self, forKey: .type) + + switch type { + case "when_page_reached": + let meta = try container.decode(WhenPageReachedMeta.self, forKey: .meta) + self = .whenPageReached(meta) + case "on_command_execution": + let meta = try container.decode(OnCommandExecutionMeta.self, forKey: .meta) + self = .onCommandExecution(meta) + case "on_event": + let meta = try container.decode(OnEventMeta.self, forKey: .meta) + self = .onEvent(meta) + case "when_element_appears": + let meta = try container.decode(WhenElementAppearsMeta.self, forKey: .meta) + self = .whenElementAppears(meta) + case "when_conditions_pass": + self = .whenConditionsPass + case "on_user_confusion": + self = .onUserConfusion + case "on_rage_click": + self = .onRageClick + case "smart_delay": + self = .smartDelay + case "when_share_link_viewed": + self = .whenShareLinkViewed + default: + throw DecodingError.dataCorruptedError(forKey: .type, in: container, debugDescription: "Invalid type") + } + } + + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + switch self { + case .whenPageReached(let meta): + try container.encode("when_page_reached", forKey: .type) + try container.encode(meta, forKey: .meta) + case .onCommandExecution(let meta): + try container.encode("on_command_execution", forKey: .type) + try container.encode(meta, forKey: .meta) + case .onEvent(let meta): + try container.encode("on_event", forKey: .type) + try container.encode(meta, forKey: .meta) + case .whenElementAppears(let meta): + try container.encode("when_element_appears", forKey: .type) + try container.encode(meta, forKey: .meta) + case .whenConditionsPass: + try container.encode("when_conditions_pass", forKey: .type) + case .onUserConfusion: + try container.encode("on_user_confusion", forKey: .type) + case .onRageClick: + try container.encode("on_rage_click", forKey: .type) + case .smartDelay: + try container.encode("smart_delay", forKey: .type) + case .whenShareLinkViewed: + try container.encode("when_share_link_viewed", forKey: .type) + } + } +} diff --git a/Sources/CommandBarIOS/Types/Config.swift b/Sources/CommandBarIOS/Types/Config.swift new file mode 100644 index 0000000..7d3d3f1 --- /dev/null +++ b/Sources/CommandBarIOS/Types/Config.swift @@ -0,0 +1,6 @@ + +struct Config: Codable { + var nudges_v2: [Nudge] +} + + diff --git a/Sources/CommandBarIOS/Types/Nudges.swift b/Sources/CommandBarIOS/Types/Nudges.swift new file mode 100644 index 0000000..9120828 --- /dev/null +++ b/Sources/CommandBarIOS/Types/Nudges.swift @@ -0,0 +1,394 @@ +struct NudgeConditionalAction : Codable { + enum Operator: String, Codable { + case eq, neq, gt, lt + } + var `operator`: Operator + var operand: Int + var action: Action? +} + +struct NudgeContentMarkdownBlockMeta: Codable { + var value: String? +} + +struct NudgeContentImageBlockMeta : Codable { + var src: String? + var file_name: String? + var size: String? +} + +struct NudgeContentVideoBlockMeta : Codable{ + + enum VideoType: String, Codable { + case url = "url" + case command = "command" + } + + var type: VideoType + var src: String? + var command: String? +} + +struct NudgeContentHelpDocBlockMeta: Codable { + var type = "command" + var command: String? +} + +struct NudgeContentButtonBlockMeta: Codable { + enum ButtonType: String, Codable { + case primary = "primary" + case secondary = "secondary" + case snooze = "snooze" + } + + var label: String? + var action: Action + var button_type: ButtonType? = .primary + var conditional_actions: [NudgeConditionalAction]? +} + +struct NudgeContentSurveyTextBlockMeta: Codable { + var prompt: String +} + +// TODO: Make better enum +struct NudgeContentSurveyRatingBlockMeta: Codable { + var lower_label: String? + var upper_label: String? + var options: Int? + var emojis: [String]? + var type: String +} + +struct NudgeStepContentSurveyTextShortBlockMeta : Codable { + var prompt: String +} + + +struct NudgeContentListBlockMeta : Codable{ + enum ListType: String, Codable { + case single = "single" + case multiple = "multiple" + } + + enum DisplayType: String, Codable { + case dropdown = "dropdown" + case list = "list" + case grid = "grid" + } + + var options: [String] + var display_type: DisplayType + var list_type: ListType + +} + +enum NudgeContentBlockType:String, Codable { + case markdown = "markdown" + case image = "image" + case video = "video" + case helpDoc = "help_doc_command" + case button = "button" + case surveyText = "survey_text" + case surveyRating = "survey_rating" + case surveyTextShort = "survey_text_short" + case contentList = "survey_list" +} + +struct NudgeContentBlock: Codable { + var type: NudgeContentBlockType + var sort_key: Int? + var meta: NudgeContentBlockMeta + + enum CodingKeys: String, CodingKey { + case type, sort_key, meta + } + + init(type: NudgeContentBlockType, meta: NudgeContentBlockMeta, sort_key: Int? = nil) { + self.type = type + self.meta = meta + self.sort_key = sort_key + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + type = try container.decode(NudgeContentBlockType.self, forKey: .type) + sort_key = try container.decodeIfPresent(Int.self, forKey: .sort_key) + + let metaDecoder = try container.superDecoder(forKey: .meta) + meta = try NudgeContentBlockMeta(from: metaDecoder, type: type) + } +} + +enum NudgeContentBlockMeta: Codable { + case markdown(NudgeContentMarkdownBlockMeta) + case image(NudgeContentImageBlockMeta) + case video(NudgeContentVideoBlockMeta) + case helpDoc(NudgeContentHelpDocBlockMeta) + case button(NudgeContentButtonBlockMeta) + case surveyText(NudgeContentSurveyTextBlockMeta) + case surveyRating(NudgeContentSurveyRatingBlockMeta) + case surveyTextShort(NudgeStepContentSurveyTextShortBlockMeta) + case contentList(NudgeContentListBlockMeta) + + init(from decoder: Decoder, type: NudgeContentBlockType) throws { + let container = try decoder.singleValueContainer() + + switch type { + case .markdown: + let value = try container.decode(NudgeContentMarkdownBlockMeta.self) + self = .markdown(value) + case .image: + let value = try container.decode(NudgeContentImageBlockMeta.self) + self = .image(value) + case .video: + let value = try container.decode(NudgeContentVideoBlockMeta.self) + self = .video(value) + case .helpDoc: + let value = try container.decode(NudgeContentHelpDocBlockMeta.self) + self = .helpDoc(value) + case .button: + let value = try container.decode(NudgeContentButtonBlockMeta.self) + self = .button(value) + case .surveyText: + let value = try container.decode(NudgeContentSurveyTextBlockMeta.self) + self = .surveyText(value) + case .surveyRating: + let value = try container.decode(NudgeContentSurveyRatingBlockMeta.self) + self = .surveyRating(value) + case .surveyTextShort: + let value = try container.decode(NudgeStepContentSurveyTextShortBlockMeta.self) + self = .surveyTextShort(value) + case .contentList: + let value = try container.decode(NudgeContentListBlockMeta.self) + self = .contentList(value) + default: + throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid type") + } + } + + func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + + switch self { + case .markdown(let value): + try container.encode(value) + case .image(let value): + try container.encode(value) + case .video(let value): + try container.encode(value) + case .helpDoc(let value): + try container.encode(value) + case .button(let value): + try container.encode(value) + case .surveyText(let value): + try container.encode(value) + case .surveyRating(let value): + try container.encode(value) + case .surveyTextShort(let value): + try container.encode(value) + case .contentList(let value): + try container.encode(value) + } + } +} + + +struct FormFactor : Codable { + var type: FormFactorType + + // Popover + var position: Position? + + // Pin + var anchor: String? + var is_open_by_default: Bool? + var is_showing_mask: Bool? + var advance_trigger: String? + var offset: OffSet? +} + +enum FormFactorType: String, Codable { + case modal = "modal" + case popover = "popover" + case pin = "pin" + case clip = "clip" +} + +enum Position: String, Codable { + case topLeft = "top-left" + case topRight = "top-right" + case bottomRight = "bottom-right" + case bottomLeft = "bottom-left" + case center = "center" +} + +struct PinDetail: Codable { + var anchor: String + var is_open_by_default: Bool? + var is_showing_mask: Bool? + var advance_trigger: String? + var offset: OffSet +} + +struct OffSet: Codable { + var x: String + var y: String +} + +struct NudgeStep : Codable { + var id: Int + var title: String + var content: [NudgeContentBlock] + var is_live: Bool + // Additional + var form_factor: FormFactor + var has_survey_response: Bool? +} + +enum NudgeType: String, Codable { + case announcement = "announcement" + case productTour = "product_tour" + case survey = "survey" +} + + +struct Nudge : Codable { + // Nudge Bases + var slug: String + var id: String + var organization: String + var trigger: PushTrigger + + var steps: [NudgeStep] + var is_live: Bool + var old_nudge_id: Int? + var archived: Bool + + // Nudge Additional + var template_source: String + var show_step_counter: Bool + var dismissible: Bool + var snoozable: Bool + var animatable: Bool + var share_page_url: String + var copilot_suggest: Bool + var copilot_cta_label: String + var copilot_description: String + var is_scheduled: Bool + var scheduled_start_time: String? + var scheduled_end_time: String? + var snooze_label: String? + var type: NudgeType? + + + static func buildFakeNudge() -> Nudge { + + let surveyRatingContent = NudgeContentBlock(type: .surveyRating, meta: .surveyRating(NudgeContentSurveyRatingBlockMeta(lower_label: "Hate it", upper_label: "Love It", options: 5, emojis: ["😡", "😐", "😍"], type: "emojis" ))) + let continueContent = NudgeContentBlock(type: .button, meta: .button(NudgeContentButtonBlockMeta(label: "Continue", action: .nudge(NudgeAction(type: "nudge", value: 1))))) + let doneContent = NudgeContentBlock(type: .button, meta: .button(NudgeContentButtonBlockMeta(label: "Done", action: .nudge(NudgeAction(type: "nudge", value: 1))))) + + let imageContent = NudgeContentBlock(type: .image, meta: .image(NudgeContentImageBlockMeta(src: "https://picsum.photos/536/354"))) + + let videoContent = NudgeContentBlock(type: .video, meta: .video(NudgeContentVideoBlockMeta(type: .url, src: "https://storage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"))) + let modalContent = [NudgeContentBlock(type: .markdown, meta: .markdown(NudgeContentMarkdownBlockMeta(value: "Let's walkthough some __Native Nudges__ and how they can be used! This is a **Modal Nudge**!"))), imageContent, continueContent] + + let modalContent2 = [NudgeContentBlock(type: .surveyTextShort, meta: .surveyTextShort(NudgeStepContentSurveyTextShortBlockMeta(prompt: "Enter your feedback"))), continueContent] + + let modalContent3 = [NudgeContentBlock(type: .surveyText, meta: .surveyText(NudgeContentSurveyTextBlockMeta(prompt: "Enter your feedback"))), continueContent] + + let popoverContent = [NudgeContentBlock(type: .markdown, meta: .markdown(NudgeContentMarkdownBlockMeta(value: "This is a **Popover Nudge**, it supports Markdown so [links](https://commandbar.com) work and multiple buttons! You can drag it around too, give it a try!"))), videoContent, continueContent] + + let clipContent = [NudgeContentBlock(type: .markdown, meta: .markdown(NudgeContentMarkdownBlockMeta(value: "This is a shiny new ✨ **Clip Nudge** ✨, exclusive to Mobile! You can dismiss by dragging down, but **don't forget to leave feedback!** 🙏"))), surveyRatingContent, doneContent] + + + let step1 = NudgeStep(id: 1, title: "Welcome!", content: modalContent, is_live: true, form_factor: FormFactor(type: .modal)) + let step2 = NudgeStep(id: 1, title: "Short Survey", content: modalContent2, is_live: true, form_factor: FormFactor(type: .modal)) + let step3 = NudgeStep(id: 1, title: "Long Survey", content: modalContent3, is_live: true, form_factor: FormFactor(type: .modal)) + let step4 = NudgeStep(id: 1, title: "Drag Me!", content: popoverContent, is_live: true, form_factor: FormFactor(type: .popover)) + let step5 = NudgeStep(id: 1, title: "Leave feedback", content: clipContent, is_live: true, form_factor: FormFactor(type: .clip)) + + let steps = [step5, step1, step2, step3, step4, step5] + return Nudge(slug: "test-nudge", id: "test", organization: "foocorp", steps: steps, is_live: true, old_nudge_id: nil, archived: false, template_source: "", show_step_counter: true, dismissible: true, snoozable: false, share_page_url: "/share", copilot_suggest: false, copilot_cta_label: "", copilot_description: "", is_scheduled: false, scheduled_start_time: nil, scheduled_end_time: nil, snooze_label: "Snooze", animatable: true, type: NudgeType.announcement, trigger: .whenConditionsPass) + } + + init(slug: String, id: String, organization: String, steps: [NudgeStep], is_live: Bool, old_nudge_id: Int?, archived: Bool?, template_source: String, show_step_counter: Bool, dismissible: Bool, snoozable: Bool, + share_page_url: String, + copilot_suggest: Bool, + copilot_cta_label: String, + copilot_description: String, + is_scheduled: Bool, + scheduled_start_time: String?, + scheduled_end_time: String?, + snooze_label: String, + animatable: Bool, + type: NudgeType?, trigger: PushTrigger) { + self.slug = slug + self.id = id + self.organization = organization + self.steps = steps + self.is_live = is_live + self.old_nudge_id = old_nudge_id + self.archived = archived ?? false + self.template_source = template_source + self.show_step_counter = show_step_counter + self.dismissible = dismissible + self.snoozable = snoozable + self.share_page_url = share_page_url + self.copilot_suggest = copilot_suggest + self.copilot_cta_label = copilot_cta_label + self.copilot_description = copilot_description + self.is_scheduled = is_scheduled + + self.scheduled_start_time = scheduled_start_time + self.scheduled_end_time = scheduled_end_time + self.snooze_label = snooze_label + self.type = type + self.animatable = animatable + self.trigger = trigger + } + + enum CodingKeys: String, CodingKey { + case slug, id, organization, steps, is_live, old_nudge_id, archived, + template_source, show_step_counter, dismissible, snoozable, share_page_url, copilot_suggest, copilot_cta_label, + copilot_description, is_scheduled, scheduled_start_time, scheduled_end_time, snooze_label, type, animatable, trigger + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + slug = try container.decode(String.self, forKey: .slug) + organization = try container.decode(String.self, forKey: .organization) + steps = try container.decode([NudgeStep].self, forKey: .steps) + is_live = try container.decode(Bool.self, forKey: .is_live) + old_nudge_id = try container.decodeIfPresent(Int.self, forKey: .old_nudge_id) + archived = try container.decodeIfPresent(Bool.self, forKey: .archived) ?? false + + // Nudge Additional + template_source = try container.decode(String.self, forKey: .template_source) + show_step_counter = try container.decode(Bool.self, forKey: .show_step_counter) + dismissible = try container.decode(Bool.self, forKey: .dismissible) + snoozable = try container.decode(Bool.self, forKey: .snoozable) + share_page_url = try container.decode(String.self, forKey: .share_page_url) + copilot_suggest = try container.decode(Bool.self, forKey: .copilot_suggest) + copilot_cta_label = try container.decode(String.self, forKey: .copilot_cta_label) + copilot_description = try container.decode(String.self, forKey: .copilot_description) + is_scheduled = try container.decode(Bool.self, forKey: .is_scheduled) + scheduled_start_time = try container.decodeIfPresent(String.self, forKey: .scheduled_start_time) + scheduled_end_time = try container.decodeIfPresent(String.self, forKey: .scheduled_end_time) + snooze_label = try container.decodeIfPresent(String.self, forKey: .snooze_label) + type = try container.decodeIfPresent(NudgeType.self, forKey: .type) + animatable = try container.decodeIfPresent(Bool.self, forKey: .animatable) ?? true + trigger = try container.decode(PushTrigger.self, forKey: .trigger) + + do { + if let intValue = try? container.decode(Int.self, forKey: .id) { + id = String(intValue) + } else { + id = try container.decode(String.self, forKey: .id) + } + } catch { + throw DecodingError.dataCorruptedError(forKey: .id, in: container, debugDescription: "Invalid value for id.") + } + } +} diff --git a/Sources/CommandBarIOS/Types/Rules.swift b/Sources/CommandBarIOS/Types/Rules.swift new file mode 100644 index 0000000..c87db73 --- /dev/null +++ b/Sources/CommandBarIOS/Types/Rules.swift @@ -0,0 +1,119 @@ +import Foundation + +enum Operator: String { + case isTrue = "isTrue" + case isFalse = "isFalse" + case isTruthy = "isTruthy" + case isFalsy = "isFalsy" + case startsWith = "startsWith" + case endsWith = "endsWith" + case matchesRegex = "matchesRegex" + case isGreaterThan = "isGreaterThan" + case isLessThan = "isLessThan" + case isBefore = "isBefore" + case isAfter = "isAfter" + case isDefined = "isDefined" + case isNotDefined = "isNotDefined" + case classnameOnPage = "classnameOnPage" + case idOnPage = "idOnPage" + case selectorOnPage = "selectorOnPage" + case classnameNotOnPage = "classnameNotOnPage" + case idNotOnPage = "idNotOnPage" + case selectorNotOnPage = "selectorNotOnPage" + case isOp = "is" + case isNot = "isNot" + case includes = "includes" + case doesNotInclude = "doesNotInclude" +} + +enum InteractionStateV: String { + case viewed = "viewed" + case completed = "completed" + case dismissed = "dismissed" +} + +struct NudgeInteractionCondition { + var type: String = "nudge_interaction" + var operatorV: Operator + var value: InteractionStateV + var nudge_id: Int + var reason: String? +} + +struct QuestlistInteractionCondition { + var type: String = "questlist_interaction" + var operatorV: Operator + var value: InteractionStateV + var questlist_id: Int + var reason: String? +} + +protocol ConditionProtocol { + var type: String { get set } + var condition_operator: Operator { get set } +} + +class ConditionBase: ConditionProtocol { + var type: String + var condition_operator: Operator + var field: String? + var value: String? + var reason: String? + var rule_id: String? + + init(type: String, conditionOperator: Operator) { + self.type = type + self.condition_operator = conditionOperator + } +} + +struct MultiValueCondition: ConditionProtocol { + var type: String + var condition_operator: Operator + var values: [String] + var reason: String? +} + +enum RuleExpressionType: String { + case AND = "AND" + case OR = "OR" + case LITERAL = "LITERAL" + case CONDITION = "CONDITION" +} + +protocol RuleExpression { + var type: RuleExpressionType { get set } +} + +struct RuleExpressionAnd: RuleExpression { + var type: RuleExpressionType = .AND + var exprs: [RuleExpression] +} + +struct RuleExpressionOr: RuleExpression { + var type: RuleExpressionType = .OR + var exprs: [RuleExpression] +} + +struct RuleExpressionLiteral: RuleExpression { + var type: RuleExpressionType = .LITERAL + var value: Bool +} + +struct RuleExpressionCondition: RuleExpression { + var type: RuleExpressionType = .CONDITION + var condition: ConditionProtocol +} + +struct NamedRuleReference { + var type: String = "named_rule" + var rule_id: Either // Using Either to represent Union + var reason: String? +} + + +struct Audience { + var type: String + var expression: RuleExpression? + var rule_reference: NamedRuleReference? +} diff --git a/Sources/CommandBarIOS/Types/Util.swift b/Sources/CommandBarIOS/Types/Util.swift new file mode 100644 index 0000000..90f2e9c --- /dev/null +++ b/Sources/CommandBarIOS/Types/Util.swift @@ -0,0 +1,32 @@ +enum Either: Codable { + case left(L) + case right(R) + + enum CodingKeys: CodingKey { + case left + case right + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + if let leftValue = try? container.decode(L.self, forKey: .left) { + self = .left(leftValue) + return + } + if let rightValue = try? container.decode(R.self, forKey: .right) { + self = .right(rightValue) + return + } + throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Data doesn't match")) + } + + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + switch self { + case .left(let value): + try container.encode(value, forKey: .left) + case .right(let value): + try container.encode(value, forKey: .right) + } + } +}