From 88022629e1c7eb8dc52da46ad3f8858791d40068 Mon Sep 17 00:00:00 2001 From: Melih Aksoy Date: Wed, 30 Oct 2019 17:27:53 +0100 Subject: [PATCH] WIP: feature/abstractions (#45) * Abstraction layer backup * Removed DataEntity, was unnecessary for now * Separated network, persistence, entities and interaction, closes #29 * Renamed binding * Removed build files, example tests Removed build files, example tests * Fixed build files were not being ignored all around app * Updated CI ymls * Small changes * Fixed legacy repository package names * Fixed CQ findings * Updated Fastlane * Packaging changes and version upgrades * Removed core from interactors * Version bumps * Added new module graph --- .circleci/config.yml | 56 +++++- .github/workflows/android.yml | 30 +++- .gitignore | 1 + Gemfile.lock | 16 +- {core => abstractions}/.gitignore | 0 abstractions/build.gradle | 17 ++ .../consumer-rules.pro | 0 abstractions/proguard-rules.pro | 21 +++ abstractions/src/main/AndroidManifest.xml | 3 + .../com/melih/abstractions/data/ViewEntity.kt | 3 + .../melih/abstractions/deliverable/Reason.kt | 6 + .../melih/abstractions/deliverable}/Result.kt | 13 +- .../com/melih/abstractions/mapper/Mapper.kt | 8 + .../com/melih/abstractions}/ResultTest.kt | 18 +- app/build.gradle | 11 +- app/proguard-rules.pro | 5 +- build.gradle | 14 +- core/build.gradle | 4 +- .../melih/core/base/lifecycle/BaseFragment.kt | 2 +- .../core/base/paging/BasePagingDataSource.kt | 26 +-- .../core/base/paging/BasePagingFactory.kt | 3 +- .../base/viewmodel/BasePagingViewModel.kt | 7 +- .../core/base/viewmodel/BaseViewModel.kt | 4 +- .../melih/core/extensions/UtilityExtension.kt | 32 ---- .../core/paging/BasePagingDataSourceTest.kt | 55 +++--- .../core/paging/BasePagingFactoryTest.kt | 8 +- data/definitions/build.gradle | 17 ++ data/definitions/consumer-rules.pro | 0 data/definitions/proguard-rules.pro | 21 +++ data/definitions/src/main/AndroidManifest.xml | 3 + .../com/melih/definitions}/Constants.kt | 2 +- .../kotlin/com/melih/definitions/Source.kt | 23 +++ .../definitions}/entities/LaunchEntity.kt | 4 +- .../definitions}/entities/LaunchesEntity.kt | 2 +- .../definitions}/entities/LocationEntity.kt | 4 +- .../definitions}/entities/MissionEntity.kt | 6 +- .../definitions}/entities/RocketEntity.kt | 6 +- data/interactors/build.gradle | 22 +++ data/interactors/consumer-rules.pro | 0 data/interactors/proguard-rules.pro | 21 +++ data/interactors/src/main/AndroidManifest.xml | 3 + .../com/melih/interactors/GetLaunchDetails.kt | 40 +++++ .../com/melih/interactors/GetLaunches.kt | 44 +++++ .../melih}/interactors/base/BaseInteractor.kt | 4 +- .../error/InteractionErrorReason.kt | 17 ++ .../interactors/sources/LaunchesSource.kt | 163 ++++++++++++++++++ .../src/main/res/values/strings.xml | 5 +- .../interactors/base/BaseInteractorTest.kt | 7 +- data/network/build.gradle | 20 +++ data/network/consumer-rules.pro | 0 data/network/proguard-rules.pro | 21 +++ data/network/src/main/AndroidManifest.xml | 3 + .../main/kotlin/com/melih/network/api}/Api.kt | 6 +- .../kotlin/com/melih/network/api}/ApiImpl.kt | 8 +- {repository => data/persistence}/build.gradle | 11 +- data/persistence/consumer-rules.pro | 0 data/persistence/proguard-rules.pro | 21 +++ data/persistence/src/main/AndroidManifest.xml | 3 + .../melih}/persistence/LaunchesDatabase.kt | 16 +- .../persistence/converters/BaseConverter.kt | 2 +- .../converters/BaseListConverter.kt | 2 +- .../converters/LocationConverter.kt | 6 +- .../converters/MissionConverter.kt | 4 +- .../persistence/converters/RocketConverter.kt | 6 +- .../com/melih}/persistence/dao/LaunchesDao.kt | 6 +- docs/module_graph.png | Bin 51442 -> 129138 bytes fastlane/Fastfile | 46 ++++- features/detail/build.gradle | 2 - .../com/melih/detail/data/LaunchDetailItem.kt | 10 ++ .../melih/detail/data/LaunchDetailMapper.kt | 18 ++ .../detail/di/modules/DetailFragmentModule.kt | 9 +- .../com/melih/detail/ui/DetailViewModel.kt | 21 +-- .../src/main/res/layout/fragment_detail.xml | 120 ++++++------- .../com/melih/detail/DetailViewModelTest.kt | 5 +- features/launches/build.gradle | 2 - .../com/melih/launches/data/LaunchItem.kt | 10 ++ .../com/melih/launches/data/LaunchMapper.kt | 18 ++ .../di/modules/LaunchesFragmentModule.kt | 15 +- .../com/melih/launches/ui/LaunchesFragment.kt | 14 +- .../launches/ui/adapters/LaunchesAdapter.kt | 15 +- .../ui/paging/LaunchesPagingSource.kt | 12 +- .../ui/paging/LaunchesPagingSourceFactory.kt | 6 +- .../melih/launches/ui/vm/LaunchesViewModel.kt | 6 +- .../src/main/res/layout/fragment_launches.xml | 2 +- .../src/main/res/layout/row_launch.xml | 119 ++++++------- repository/.gitignore | 1 - repository/src/main/AndroidManifest.xml | 2 - .../kotlin/com/melih/repository/Repository.kt | 16 -- .../interactors/GetLaunchDetails.kt | 55 ------ .../repository/interactors/GetLaunches.kt | 54 ------ .../repository/interactors/base/Reason.kt | 21 --- .../melih/repository/sources/NetworkSource.kt | 118 ------------- .../repository/sources/PersistenceSource.kt | 50 ------ .../repository/sources/NetworkSourceTest.kt | 104 ----------- .../sources/PersistanceSourceTest.kt | 73 -------- scripts/{ => cq}/detekt.gradle | 0 scripts/{ => cq}/dokka.gradle | 0 scripts/cq/jacoco.gradle | 53 ++++++ scripts/default_android_config.gradle | 4 +- scripts/default_dependencies.gradle | 59 +------ scripts/dependencies.gradle | 30 ++-- scripts/feature_module.gradle | 4 + settings.gradle | 13 +- 103 files changed, 1098 insertions(+), 921 deletions(-) rename {core => abstractions}/.gitignore (100%) create mode 100644 abstractions/build.gradle rename repository/proguard-rules.pro => abstractions/consumer-rules.pro (100%) create mode 100644 abstractions/proguard-rules.pro create mode 100644 abstractions/src/main/AndroidManifest.xml create mode 100644 abstractions/src/main/kotlin/com/melih/abstractions/data/ViewEntity.kt create mode 100644 abstractions/src/main/kotlin/com/melih/abstractions/deliverable/Reason.kt rename {repository/src/main/kotlin/com/melih/repository/interactors/base => abstractions/src/main/kotlin/com/melih/abstractions/deliverable}/Result.kt (70%) create mode 100644 abstractions/src/main/kotlin/com/melih/abstractions/mapper/Mapper.kt rename {repository/src/test/kotlin/com/melih/repository/interactors/base => abstractions/src/test/kotlin/com/melih/abstractions}/ResultTest.kt (80%) delete mode 100644 core/src/main/kotlin/com/melih/core/extensions/UtilityExtension.kt create mode 100644 data/definitions/build.gradle create mode 100644 data/definitions/consumer-rules.pro create mode 100644 data/definitions/proguard-rules.pro create mode 100644 data/definitions/src/main/AndroidManifest.xml rename {repository/src/main/kotlin/com/melih/repository => data/definitions/src/main/kotlin/com/melih/definitions}/Constants.kt (74%) create mode 100644 data/definitions/src/main/kotlin/com/melih/definitions/Source.kt rename {repository/src/main/kotlin/com/melih/repository => data/definitions/src/main/kotlin/com/melih/definitions}/entities/LaunchEntity.kt (87%) rename {repository/src/main/kotlin/com/melih/repository => data/definitions/src/main/kotlin/com/melih/definitions}/entities/LaunchesEntity.kt (86%) rename {repository/src/main/kotlin/com/melih/repository => data/definitions/src/main/kotlin/com/melih/definitions}/entities/LocationEntity.kt (87%) rename {repository/src/main/kotlin/com/melih/repository => data/definitions/src/main/kotlin/com/melih/definitions}/entities/MissionEntity.kt (73%) rename {repository/src/main/kotlin/com/melih/repository => data/definitions/src/main/kotlin/com/melih/definitions}/entities/RocketEntity.kt (78%) create mode 100644 data/interactors/build.gradle create mode 100644 data/interactors/consumer-rules.pro create mode 100644 data/interactors/proguard-rules.pro create mode 100644 data/interactors/src/main/AndroidManifest.xml create mode 100644 data/interactors/src/main/kotlin/com/melih/interactors/GetLaunchDetails.kt create mode 100644 data/interactors/src/main/kotlin/com/melih/interactors/GetLaunches.kt rename {repository/src/main/kotlin/com/melih/repository => data/interactors/src/main/kotlin/com/melih}/interactors/base/BaseInteractor.kt (88%) create mode 100644 data/interactors/src/main/kotlin/com/melih/interactors/error/InteractionErrorReason.kt create mode 100644 data/interactors/src/main/kotlin/com/melih/interactors/sources/LaunchesSource.kt rename {repository => data/interactors}/src/main/res/values/strings.xml (81%) rename {repository/src/test/kotlin/com/melih/repository => data/interactors/src/test/kotlin/com/melih}/interactors/base/BaseInteractorTest.kt (91%) create mode 100644 data/network/build.gradle create mode 100644 data/network/consumer-rules.pro create mode 100644 data/network/proguard-rules.pro create mode 100644 data/network/src/main/AndroidManifest.xml rename {repository/src/main/kotlin/com/melih/repository/network => data/network/src/main/kotlin/com/melih/network/api}/Api.kt (78%) rename {repository/src/main/kotlin/com/melih/repository/network => data/network/src/main/kotlin/com/melih/network/api}/ApiImpl.kt (88%) rename {repository => data/persistence}/build.gradle (82%) create mode 100644 data/persistence/consumer-rules.pro create mode 100644 data/persistence/proguard-rules.pro create mode 100644 data/persistence/src/main/AndroidManifest.xml rename {repository/src/main/kotlin/com/melih/repository => data/persistence/src/main/kotlin/com/melih}/persistence/LaunchesDatabase.kt (65%) rename {repository/src/main/kotlin/com/melih/repository => data/persistence/src/main/kotlin/com/melih}/persistence/converters/BaseConverter.kt (93%) rename {repository/src/main/kotlin/com/melih/repository => data/persistence/src/main/kotlin/com/melih}/persistence/converters/BaseListConverter.kt (93%) rename {repository/src/main/kotlin/com/melih/repository => data/persistence/src/main/kotlin/com/melih}/persistence/converters/LocationConverter.kt (63%) rename {repository/src/main/kotlin/com/melih/repository => data/persistence/src/main/kotlin/com/melih}/persistence/converters/MissionConverter.kt (81%) rename {repository/src/main/kotlin/com/melih/repository => data/persistence/src/main/kotlin/com/melih}/persistence/converters/RocketConverter.kt (63%) rename {repository/src/main/kotlin/com/melih/repository => data/persistence/src/main/kotlin/com/melih}/persistence/dao/LaunchesDao.kt (86%) create mode 100644 features/detail/src/main/kotlin/com/melih/detail/data/LaunchDetailItem.kt create mode 100644 features/detail/src/main/kotlin/com/melih/detail/data/LaunchDetailMapper.kt create mode 100644 features/launches/src/main/kotlin/com/melih/launches/data/LaunchItem.kt create mode 100644 features/launches/src/main/kotlin/com/melih/launches/data/LaunchMapper.kt delete mode 100644 repository/.gitignore delete mode 100644 repository/src/main/AndroidManifest.xml delete mode 100644 repository/src/main/kotlin/com/melih/repository/Repository.kt delete mode 100644 repository/src/main/kotlin/com/melih/repository/interactors/GetLaunchDetails.kt delete mode 100644 repository/src/main/kotlin/com/melih/repository/interactors/GetLaunches.kt delete mode 100644 repository/src/main/kotlin/com/melih/repository/interactors/base/Reason.kt delete mode 100644 repository/src/main/kotlin/com/melih/repository/sources/NetworkSource.kt delete mode 100644 repository/src/main/kotlin/com/melih/repository/sources/PersistenceSource.kt delete mode 100644 repository/src/test/kotlin/com/melih/repository/sources/NetworkSourceTest.kt delete mode 100644 repository/src/test/kotlin/com/melih/repository/sources/PersistanceSourceTest.kt rename scripts/{ => cq}/detekt.gradle (100%) rename scripts/{ => cq}/dokka.gradle (100%) create mode 100644 scripts/cq/jacoco.gradle diff --git a/.circleci/config.yml b/.circleci/config.yml index edbe35c..e4542dd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -76,12 +76,60 @@ jobs: - store_test_results: # for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/ path: features/detail/build/test-results - ## Repository + ## Abstractions - run: - name: Test Repository + name: Test Abstractions command: | - fastlane test_repository - ./gradlew repository:jacocoTestReport + fastlane test_abstractions + ./gradlew abstractions:jacocoTestReport + bash <(curl -s https://codecov.io/bash) + - store_artifacts: # for display in Artifacts: https://circleci.com/docs/2.0/artifacts/ + path: repository/build/reports/tests + - store_test_results: # for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/ + path: repository/build/test-results + + ## Definitions + - run: + name: Test Definitions + command: | + fastlane test_definitions + ./gradlew data:definitions:jacocoTestReport + bash <(curl -s https://codecov.io/bash) + - store_artifacts: # for display in Artifacts: https://circleci.com/docs/2.0/artifacts/ + path: repository/build/reports/tests + - store_test_results: # for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/ + path: repository/build/test-results + + ## Interactors + - run: + name: Test Interactors + command: | + fastlane test_interactors + ./gradlew data:interactors:jacocoTestReport + bash <(curl -s https://codecov.io/bash) + - store_artifacts: # for display in Artifacts: https://circleci.com/docs/2.0/artifacts/ + path: repository/build/reports/tests + - store_test_results: # for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/ + path: repository/build/test-results + + ## Network + - run: + name: Test Network + command: | + fastlane test_network + ./gradlew data:network:jacocoTestReport + bash <(curl -s https://codecov.io/bash) + - store_artifacts: # for display in Artifacts: https://circleci.com/docs/2.0/artifacts/ + path: repository/build/reports/tests + - store_test_results: # for display in Test Summary: https://circleci.com/docs/2.0/collect-test-data/ + path: repository/build/test-results + + ## Persistence + - run: + name: Test Persistence + command: | + fastlane test_persistence + ./gradlew data:persistence:jacocoTestReport bash <(curl -s https://codecov.io/bash) - store_artifacts: # for display in Artifacts: https://circleci.com/docs/2.0/artifacts/ path: repository/build/reports/tests diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 0972801..13de4f6 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -55,8 +55,32 @@ jobs: ./gradlew features:detail:jacocoTestReport bash <(curl -s https://codecov.io/bash) - - name: Test Repository + - name: Test Abstractions run: | - fastlane test_repository - ./gradlew repository:jacocoTestReport + fastlane test_abstractions + ./gradlew abstractions:jacocoTestReport bash <(curl -s https://codecov.io/bash) + + - name: Test Definitions + run: | + fastlane test_definitions + ./gradlew data:definitions:jacocoTestReport + bash <(curl -s https://codecov.io/bash) + + - name: Test Interactors + run: | + fastlane test_interactors + ./gradlew data:interactors:jacocoTestReport + bash <(curl -s https://codecov.io/bash) + + - name: Test Network + run: | + fastlane test_network + ./gradlew data:network:jacocoTestReport + bash <(curl -s https://codecov.io/bash) + + - name: Test Persistence + run: | + fastlane test_persistence + ./gradlew data:persistence:jacocoTestReport + bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3a8ee31..4cdb0a4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /.idea .DS_Store /build +**/build /fastlane/README.md /fastlane/report.xml /captures diff --git a/Gemfile.lock b/Gemfile.lock index b9db40d..192c06b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,7 +5,7 @@ GEM addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) atomos (0.1.3) - babosa (1.0.2) + babosa (1.0.3) claide (1.0.3) colored (1.2) colored2 (3.1.2) @@ -18,7 +18,7 @@ GEM unf (>= 0.0.5, < 1.0.0) dotenv (2.7.5) emoji_regex (1.0.1) - excon (0.66.0) + excon (0.67.0) faraday (0.15.4) multipart-post (>= 1.2, < 3) faraday-cookie_jar (0.0.6) @@ -27,7 +27,7 @@ GEM faraday_middleware (0.13.1) faraday (>= 0.7.4, < 1.0) fastimage (2.1.7) - fastlane (2.131.0) + fastlane (2.133.0) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.3, < 3.0.0) babosa (>= 1.0.2, < 2.0.0) @@ -37,9 +37,9 @@ GEM dotenv (>= 2.1.1, < 3.0.0) emoji_regex (>= 0.1, < 2.0) excon (>= 0.45.0, < 1.0.0) - faraday (~> 0.9) + faraday (< 0.16.0) faraday-cookie_jar (~> 0.0.6) - faraday_middleware (~> 0.9) + faraday_middleware (< 0.16.0) fastimage (>= 2.1.0, < 3.0.0) gh_inspector (>= 1.1.2, < 2.0.0) google-api-client (>= 0.21.2, < 0.24.0) @@ -52,7 +52,7 @@ GEM multipart-post (~> 2.0.0) plist (>= 3.1.0, < 4.0.0) public_suffix (~> 2.0.0) - rubyzip (>= 1.2.2, < 2.0.0) + rubyzip (>= 1.3.0, < 2.0.0) security (= 0.1.3) simctl (~> 1.6.3) slack-notifier (>= 2.0.0, < 3.0.0) @@ -98,7 +98,7 @@ GEM memoist (0.16.0) mime-types (3.3) mime-types-data (~> 3.2015) - mime-types-data (3.2019.0904) + mime-types-data (3.2019.1009) mini_magick (4.9.5) multi_json (1.13.1) multi_xml (0.6.0) @@ -114,7 +114,7 @@ GEM uber (< 0.2.0) retriable (3.1.2) rouge (2.0.7) - rubyzip (1.2.4) + rubyzip (1.3.0) security (0.1.3) signet (0.11.0) addressable (~> 2.3) diff --git a/core/.gitignore b/abstractions/.gitignore similarity index 100% rename from core/.gitignore rename to abstractions/.gitignore diff --git a/abstractions/build.gradle b/abstractions/build.gradle new file mode 100644 index 0000000..86354c0 --- /dev/null +++ b/abstractions/build.gradle @@ -0,0 +1,17 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: "de.mannodermaus.android-junit5" + +apply from: "$rootProject.projectDir/scripts/module.gradle" + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + + implementation libraries.kotlin + + testImplementation testLibraries.jUnitApi + testImplementation testLibraries.mockk + testImplementation testLibraries.kluent + + testRuntimeOnly testLibraries.jUnitEngine +} diff --git a/repository/proguard-rules.pro b/abstractions/consumer-rules.pro similarity index 100% rename from repository/proguard-rules.pro rename to abstractions/consumer-rules.pro diff --git a/abstractions/proguard-rules.pro b/abstractions/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/abstractions/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/abstractions/src/main/AndroidManifest.xml b/abstractions/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c706bc8 --- /dev/null +++ b/abstractions/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + diff --git a/abstractions/src/main/kotlin/com/melih/abstractions/data/ViewEntity.kt b/abstractions/src/main/kotlin/com/melih/abstractions/data/ViewEntity.kt new file mode 100644 index 0000000..6d9668e --- /dev/null +++ b/abstractions/src/main/kotlin/com/melih/abstractions/data/ViewEntity.kt @@ -0,0 +1,3 @@ +package com.melih.abstractions.data + +interface ViewEntity diff --git a/abstractions/src/main/kotlin/com/melih/abstractions/deliverable/Reason.kt b/abstractions/src/main/kotlin/com/melih/abstractions/deliverable/Reason.kt new file mode 100644 index 0000000..030a02e --- /dev/null +++ b/abstractions/src/main/kotlin/com/melih/abstractions/deliverable/Reason.kt @@ -0,0 +1,6 @@ +package com.melih.abstractions.deliverable + +abstract class Reason : Throwable() { + + abstract val messageRes: Int +} diff --git a/repository/src/main/kotlin/com/melih/repository/interactors/base/Result.kt b/abstractions/src/main/kotlin/com/melih/abstractions/deliverable/Result.kt similarity index 70% rename from repository/src/main/kotlin/com/melih/repository/interactors/base/Result.kt rename to abstractions/src/main/kotlin/com/melih/abstractions/deliverable/Result.kt index e34eea7..f81e27e 100644 --- a/repository/src/main/kotlin/com/melih/repository/interactors/base/Result.kt +++ b/abstractions/src/main/kotlin/com/melih/abstractions/deliverable/Result.kt @@ -1,12 +1,9 @@ -package com.melih.repository.interactors.base - -import kotlinx.coroutines.ExperimentalCoroutinesApi +package com.melih.abstractions.deliverable /** - * Result class that wraps any [Success], [Failure] or [State] that can be generated by any derivation of [BaseInteractor] + * Result class that wraps any [Success], [Failure] or [State] */ -@UseExperimental(ExperimentalCoroutinesApi::class) sealed class Result //region Subclasses @@ -22,7 +19,11 @@ sealed class State : Result() { //region Extensions -inline fun Result.handle(stateBlock: (State) -> Unit, failureBlock: (Reason) -> Unit, successBlock: (T) -> Unit) { +inline fun Result.handle( + stateBlock: (State) -> Unit, + failureBlock: (Reason) -> Unit, + successBlock: (T) -> Unit +) { when (this) { is Success -> successBlock(successData) is Failure -> failureBlock(errorData) diff --git a/abstractions/src/main/kotlin/com/melih/abstractions/mapper/Mapper.kt b/abstractions/src/main/kotlin/com/melih/abstractions/mapper/Mapper.kt new file mode 100644 index 0000000..aac38d2 --- /dev/null +++ b/abstractions/src/main/kotlin/com/melih/abstractions/mapper/Mapper.kt @@ -0,0 +1,8 @@ +package com.melih.abstractions.mapper + +import com.melih.abstractions.data.ViewEntity + +abstract class Mapper { + + abstract fun convert(t: T): R +} diff --git a/repository/src/test/kotlin/com/melih/repository/interactors/base/ResultTest.kt b/abstractions/src/test/kotlin/com/melih/abstractions/ResultTest.kt similarity index 80% rename from repository/src/test/kotlin/com/melih/repository/interactors/base/ResultTest.kt rename to abstractions/src/test/kotlin/com/melih/abstractions/ResultTest.kt index cc770df..a21f935 100644 --- a/repository/src/test/kotlin/com/melih/repository/interactors/base/ResultTest.kt +++ b/abstractions/src/test/kotlin/com/melih/abstractions/ResultTest.kt @@ -1,6 +1,10 @@ -package com.melih.repository.interactors.base +package com.melih.abstractions -import com.melih.repository.R +import com.melih.abstractions.deliverable.Failure +import com.melih.abstractions.deliverable.Reason +import com.melih.abstractions.deliverable.State +import com.melih.abstractions.deliverable.Success +import com.melih.abstractions.deliverable.handle import io.mockk.called import io.mockk.spyk import io.mockk.verify @@ -8,12 +12,17 @@ import org.amshove.kluent.shouldBeInstanceOf import org.amshove.kluent.shouldEqualTo import org.junit.jupiter.api.Test + class ResultTest { private val number = 10 private val success = Success(number) - private val failure = Failure(GenericError()) + private val failure = Failure(object : Reason() { + override val messageRes: Int + get() = 10 + + }) private val state = State.Loading() private val emptyStateBlock = spyk({ _: State -> }) @@ -37,8 +46,7 @@ class ResultTest { @Test fun `Failure should only invoke failureBlock with correct error`() { val actualFailureBlock = spyk({ reason: Reason -> - reason shouldBeInstanceOf GenericError::class - (reason as GenericError).messageRes shouldEqualTo R.string.reason_generic + reason.messageRes shouldEqualTo 10 Unit }) diff --git a/app/build.gradle b/app/build.gradle index 4eb083f..4d1af18 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,6 +3,7 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' apply from: "$rootProject.projectDir/scripts/default_android_config.gradle" +apply from: "$rootProject.projectDir/scripts/default_dependencies.gradle" apply from: "$rootProject.projectDir/scripts/sources.gradle" android { @@ -31,10 +32,14 @@ dependencies { androidTestImplementation testLibraries.espresso - // These libraries required by dagger to create dependency graph, but not by app - compileOnly project(':repository') + // These libraries required by dagger to create dependency graph and application compilation, but not used by app + + compileOnly project(':abstractions') + compileOnly project(':data:interactors') + compileOnly project(':data:network') + compileOnly project(':data:definitions') + compileOnly libraries.retrofit - compileOnly libraries.room compileOnly libraries.paging compileOnly libraries.swipeRefreshLayout diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index da2a358..ce0ec64 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -21,8 +21,5 @@ @com.squareup.moshi.ToJson ; } --keepnames @kotlin.Metadata class com.myapp.packagename.model.** --keep class com.myapp.packagnename.model.** { *; } - # Keeping entities intact --keep class com.melih.repository.entities.** { *; } +-keep class com.melih.definitions.entities.** { *; } diff --git a/build.gradle b/build.gradle index 232dd0a..d709464 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { ext.kotlin_version = '1.3.50' - ext.nav_version = '2.2.0-alpha01' + ext.nav_version = '2.2.0-beta01' repositories { google() @@ -9,7 +9,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' + classpath 'com.android.tools.build:gradle:3.5.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:0.9.18" classpath "de.mannodermaus.gradle.plugins:android-junit5:1.5.1.0" @@ -20,9 +20,9 @@ buildscript { } plugins { - id "io.gitlab.arturbosch.detekt" version "1.0.0" - id "org.jetbrains.dokka" version "0.9.18" - id "jacoco" + id 'io.gitlab.arturbosch.detekt' version '1.1.1' + id 'org.jetbrains.dokka' version '0.9.18' + id 'jacoco' } allprojects { @@ -97,7 +97,9 @@ task projectDependencyGraph { rootProjects.remove(dependency) def graphKey = new Tuple2(project, dependency) - def traits = dependencies.computeIfAbsent(graphKey) { new ArrayList() } + def traits = dependencies.computeIfAbsent(graphKey) { + new ArrayList() + } if (config.name.toLowerCase().endsWith('implementation')) { traits.add('style=dotted') diff --git a/core/build.gradle b/core/build.gradle index ef8cb83..0d9ae40 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -3,6 +3,7 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' apply from: "$rootProject.projectDir/scripts/default_android_config.gradle" +apply from: "$rootProject.projectDir/scripts/default_dependencies.gradle" apply from: "$rootProject.projectDir/scripts/sources.gradle" android { @@ -14,8 +15,7 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation project(':repository') - + implementation libraries.coroutines implementation libraries.fragment implementation libraries.paging implementation libraries.lifecycle diff --git a/core/src/main/kotlin/com/melih/core/base/lifecycle/BaseFragment.kt b/core/src/main/kotlin/com/melih/core/base/lifecycle/BaseFragment.kt index 53e1d0a..368a89e 100644 --- a/core/src/main/kotlin/com/melih/core/base/lifecycle/BaseFragment.kt +++ b/core/src/main/kotlin/com/melih/core/base/lifecycle/BaseFragment.kt @@ -9,8 +9,8 @@ import androidx.databinding.DataBindingUtil import androidx.databinding.ViewDataBinding import androidx.fragment.app.Fragment import com.google.android.material.snackbar.Snackbar +import com.melih.abstractions.deliverable.Reason import com.melih.core.R -import com.melih.repository.interactors.base.Reason /** * Parent of all fragments. diff --git a/core/src/main/kotlin/com/melih/core/base/paging/BasePagingDataSource.kt b/core/src/main/kotlin/com/melih/core/base/paging/BasePagingDataSource.kt index ff1ff69..a004f0e 100644 --- a/core/src/main/kotlin/com/melih/core/base/paging/BasePagingDataSource.kt +++ b/core/src/main/kotlin/com/melih/core/base/paging/BasePagingDataSource.kt @@ -4,12 +4,13 @@ import androidx.annotation.CallSuper import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.paging.PageKeyedDataSource -import com.melih.repository.interactors.base.Reason -import com.melih.repository.interactors.base.Result -import com.melih.repository.interactors.base.State -import com.melih.repository.interactors.base.onFailure -import com.melih.repository.interactors.base.onState -import com.melih.repository.interactors.base.onSuccess +import com.melih.abstractions.data.ViewEntity +import com.melih.abstractions.deliverable.Reason +import com.melih.abstractions.deliverable.Result +import com.melih.abstractions.deliverable.State +import com.melih.abstractions.deliverable.onFailure +import com.melih.abstractions.deliverable.onState +import com.melih.abstractions.deliverable.onSuccess import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -35,11 +36,11 @@ const val INITIAL_PAGE = 0 */ @UseExperimental(ExperimentalCoroutinesApi::class) -abstract class BasePagingDataSource : PageKeyedDataSource() { +abstract class BasePagingDataSource : PageKeyedDataSource() { //region Abstractions - abstract fun loadDataForPage(page: Int): Flow>> // Load next page(s) + abstract fun loadDataForPage(page: Int): Flow>> // Load next page(s) //endregion //region Properties @@ -63,7 +64,10 @@ abstract class BasePagingDataSource : PageKeyedDataSource() { //region Functions - override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback) { + override fun loadInitial( + params: LoadInitialParams, + callback: LoadInitialCallback + ) { // Looping through channel as we'll receive any state, error or data here loadDataForPage(INITIAL_PAGE) .onEach { result -> @@ -81,7 +85,7 @@ abstract class BasePagingDataSource : PageKeyedDataSource() { .launchIn(coroutineScope) } - override fun loadAfter(params: LoadParams, callback: LoadCallback) { + override fun loadAfter(params: LoadParams, callback: LoadCallback) { // Key for which page to load is in params val page = params.key @@ -104,7 +108,7 @@ abstract class BasePagingDataSource : PageKeyedDataSource() { /** * This loads previous pages, we don't have a use for it yet, so it's a no-op override */ - override fun loadBefore(params: LoadParams, callback: LoadCallback) { + override fun loadBefore(params: LoadParams, callback: LoadCallback) { // no-op } diff --git a/core/src/main/kotlin/com/melih/core/base/paging/BasePagingFactory.kt b/core/src/main/kotlin/com/melih/core/base/paging/BasePagingFactory.kt index 1a51f1e..ddd12b6 100644 --- a/core/src/main/kotlin/com/melih/core/base/paging/BasePagingFactory.kt +++ b/core/src/main/kotlin/com/melih/core/base/paging/BasePagingFactory.kt @@ -3,6 +3,7 @@ package com.melih.core.base.paging import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.paging.DataSource +import com.melih.abstractions.data.ViewEntity /** * Base [factory][DataSource.Factory] class for any [dataSource][DataSource]s in project. @@ -14,7 +15,7 @@ import androidx.paging.DataSource * * Purpose of this transmission is to encapuslate [basePagingDataSource][BasePagingDataSource]. */ -abstract class BasePagingFactory : DataSource.Factory() { +abstract class BasePagingFactory : DataSource.Factory() { //region Abstractions diff --git a/core/src/main/kotlin/com/melih/core/base/viewmodel/BasePagingViewModel.kt b/core/src/main/kotlin/com/melih/core/base/viewmodel/BasePagingViewModel.kt index 413a602..7a0caad 100644 --- a/core/src/main/kotlin/com/melih/core/base/viewmodel/BasePagingViewModel.kt +++ b/core/src/main/kotlin/com/melih/core/base/viewmodel/BasePagingViewModel.kt @@ -5,9 +5,10 @@ import androidx.lifecycle.Transformations.switchMap import androidx.lifecycle.ViewModel import androidx.paging.PagedList import androidx.paging.toLiveData +import com.melih.abstractions.data.ViewEntity +import com.melih.abstractions.deliverable.Reason +import com.melih.abstractions.deliverable.State import com.melih.core.base.paging.BasePagingFactory -import com.melih.repository.interactors.base.Reason -import com.melih.repository.interactors.base.State /** * Base [ViewModel] for view models that will use [PagedList]. @@ -18,7 +19,7 @@ import com.melih.repository.interactors.base.State * * If paging won't be used, use [BaseViewModel] instead. */ -abstract class BasePagingViewModel : ViewModel() { +abstract class BasePagingViewModel : ViewModel() { //region Abstractions diff --git a/core/src/main/kotlin/com/melih/core/base/viewmodel/BaseViewModel.kt b/core/src/main/kotlin/com/melih/core/base/viewmodel/BaseViewModel.kt index 6e7c440..525a772 100644 --- a/core/src/main/kotlin/com/melih/core/base/viewmodel/BaseViewModel.kt +++ b/core/src/main/kotlin/com/melih/core/base/viewmodel/BaseViewModel.kt @@ -4,8 +4,8 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.melih.repository.interactors.base.Reason -import com.melih.repository.interactors.base.State +import com.melih.abstractions.deliverable.Reason +import com.melih.abstractions.deliverable.State import kotlinx.coroutines.launch /** diff --git a/core/src/main/kotlin/com/melih/core/extensions/UtilityExtension.kt b/core/src/main/kotlin/com/melih/core/extensions/UtilityExtension.kt deleted file mode 100644 index c57840f..0000000 --- a/core/src/main/kotlin/com/melih/core/extensions/UtilityExtension.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.melih.core.extensions - -import android.view.MenuItem -import androidx.appcompat.widget.SearchView -import com.melih.core.utils.ClearFocusQueryTextListener - -/** - * Shorthand for [contains] with ignoreCase set [true] - */ -fun CharSequence.containsIgnoreCase(other: CharSequence) = contains(other, true) - -/** - * Adds [ClearFocusQueryTextListener] as [SearchView.OnQueryTextListener] - */ -fun SearchView.setOnQueryChangedListener(block: (String?) -> Unit) = setOnQueryTextListener(ClearFocusQueryTextListener(this, block)) - -/** - * Shortening set menu item expands / collapses - */ -fun MenuItem.onExpandOrCollapse(onExpand: () -> Unit, onCollapse: () -> Unit) { - setOnActionExpandListener(object : MenuItem.OnActionExpandListener { - override fun onMenuItemActionCollapse(item: MenuItem?): Boolean { - onCollapse() - return true - } - - override fun onMenuItemActionExpand(item: MenuItem?): Boolean { - onExpand() - return true - } - }) -} diff --git a/core/src/test/kotlin/com/melih/core/paging/BasePagingDataSourceTest.kt b/core/src/test/kotlin/com/melih/core/paging/BasePagingDataSourceTest.kt index 5750ad1..700bbfb 100644 --- a/core/src/test/kotlin/com/melih/core/paging/BasePagingDataSourceTest.kt +++ b/core/src/test/kotlin/com/melih/core/paging/BasePagingDataSourceTest.kt @@ -3,14 +3,15 @@ package com.melih.core.paging import androidx.paging.PageKeyedDataSource +import com.melih.abstractions.data.ViewEntity +import com.melih.abstractions.deliverable.Failure +import com.melih.abstractions.deliverable.Reason +import com.melih.abstractions.deliverable.Result +import com.melih.abstractions.deliverable.State +import com.melih.abstractions.deliverable.Success import com.melih.core.BaseTestWithMainThread import com.melih.core.base.paging.BasePagingDataSource import com.melih.core.testObserve -import com.melih.repository.interactors.base.Failure -import com.melih.repository.interactors.base.GenericError -import com.melih.repository.interactors.base.Result -import com.melih.repository.interactors.base.State -import com.melih.repository.interactors.base.Success import io.mockk.mockk import io.mockk.spyk import io.mockk.verify @@ -28,7 +29,7 @@ class BasePagingDataSourceTest : BaseTestWithMainThread() { val failureSource = spyk(TestFailureSource()) val data = 10 - val errorMessage = "Generic Error" + val errorMessageResId = 1313 @Nested inner class BasePagingSource { @@ -37,10 +38,9 @@ class BasePagingDataSourceTest : BaseTestWithMainThread() { inner class LoadInitial { @Test - fun `should update state accordingly`() { val params = mockk>(relaxed = true) - val callback = mockk>(relaxed = true) + val callback = mockk>(relaxed = true) runBlocking { @@ -54,10 +54,9 @@ class BasePagingDataSourceTest : BaseTestWithMainThread() { } @Test - fun `should update error Error accordingly`() { val params = PageKeyedDataSource.LoadInitialParams(10, false) - val callback = mockk>(relaxed = true) + val callback = mockk>(relaxed = true) runBlocking { @@ -65,7 +64,7 @@ class BasePagingDataSourceTest : BaseTestWithMainThread() { failureSource.loadInitial(params, callback) failureSource.reasonData.testObserve { - it shouldBeInstanceOf GenericError::class + it shouldBeInstanceOf TestFailureReason::class } } } @@ -75,10 +74,9 @@ class BasePagingDataSourceTest : BaseTestWithMainThread() { inner class LoadAfter { @Test - fun `should update state accordingly`() { val params = PageKeyedDataSource.LoadParams(2, 10) - val callback = mockk>(relaxed = true) + val callback = mockk>(relaxed = true) runBlocking { @@ -92,10 +90,9 @@ class BasePagingDataSourceTest : BaseTestWithMainThread() { } @Test - fun `should update error Error accordingly`() { val params = PageKeyedDataSource.LoadParams(2, 10) - val callback = mockk>(relaxed = true) + val callback = mockk>(relaxed = true) runBlocking { @@ -103,17 +100,16 @@ class BasePagingDataSourceTest : BaseTestWithMainThread() { failureSource.loadAfter(params, callback) failureSource.reasonData.testObserve { - it shouldBeInstanceOf GenericError::class + it shouldBeInstanceOf TestFailureReason::class } } } } @Test - fun `should use loadDataForPage in loadInitial and transform emmited value`() { val params = mockk>(relaxed = true) - val callback = mockk>(relaxed = true) + val callback = mockk>(relaxed = true) // Fake loading source.loadInitial(params, callback) @@ -126,10 +122,9 @@ class BasePagingDataSourceTest : BaseTestWithMainThread() { } @Test - fun `should use loadDataForPage in loadAfter and transform emmited value`() { val params = PageKeyedDataSource.LoadParams(2, 10) - val callback = mockk>(relaxed = true) + val callback = mockk>(relaxed = true) // Fake loading source.loadAfter(params, callback) @@ -142,25 +137,27 @@ class BasePagingDataSourceTest : BaseTestWithMainThread() { } } - inner class TestSource : BasePagingDataSource() { - + inner class TestSource : BasePagingDataSource() { val result = flow { emit(State.Loading()) - emit(Success(listOf(data))) + emit(Success(listOf(TestViewEntity(data)))) } - - override fun loadDataForPage(page: Int): Flow>> = result + override fun loadDataForPage(page: Int): Flow>> = result } - inner class TestFailureSource : BasePagingDataSource() { + inner class TestFailureSource : BasePagingDataSource() { val result = flow { emit(State.Loading()) - emit(Failure(GenericError())) + emit(Failure(TestFailureReason(errorMessageResId))) } - override fun loadDataForPage(page: Int): Flow>> = result + override fun loadDataForPage(page: Int): Flow>> = result } -} \ No newline at end of file + + inner class TestViewEntity(data: Int) : ViewEntity + + inner class TestFailureReason(override val messageRes: Int) : Reason() +} diff --git a/core/src/test/kotlin/com/melih/core/paging/BasePagingFactoryTest.kt b/core/src/test/kotlin/com/melih/core/paging/BasePagingFactoryTest.kt index 5829189..cfb6145 100644 --- a/core/src/test/kotlin/com/melih/core/paging/BasePagingFactoryTest.kt +++ b/core/src/test/kotlin/com/melih/core/paging/BasePagingFactoryTest.kt @@ -1,5 +1,6 @@ package com.melih.core.paging +import com.melih.abstractions.data.ViewEntity import com.melih.core.BaseTestWithMainThread import com.melih.core.base.paging.BasePagingDataSource import com.melih.core.base.paging.BasePagingFactory @@ -25,9 +26,10 @@ class BasePagingFactoryTest : BaseTestWithMainThread() { } } - inner class TestFactory : BasePagingFactory() { - - override fun createSource(): BasePagingDataSource = mockk(relaxed = true) + inner class TestFactory : BasePagingFactory() { + override fun createSource(): BasePagingDataSource = mockk(relaxed = true) } + + inner class TestViewEntity : ViewEntity } diff --git a/data/definitions/build.gradle b/data/definitions/build.gradle new file mode 100644 index 0000000..b234e17 --- /dev/null +++ b/data/definitions/build.gradle @@ -0,0 +1,17 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' + +apply from: "$rootProject.projectDir/scripts/module.gradle" + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + + implementation project(':abstractions') + + implementation libraries.room + implementation libraries.moshiKotlin + + kapt annotationProcessors.roomCompiler + kapt annotationProcessors.moshi +} diff --git a/data/definitions/consumer-rules.pro b/data/definitions/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/data/definitions/proguard-rules.pro b/data/definitions/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/data/definitions/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/data/definitions/src/main/AndroidManifest.xml b/data/definitions/src/main/AndroidManifest.xml new file mode 100644 index 0000000..8363ce0 --- /dev/null +++ b/data/definitions/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + diff --git a/repository/src/main/kotlin/com/melih/repository/Constants.kt b/data/definitions/src/main/kotlin/com/melih/definitions/Constants.kt similarity index 74% rename from repository/src/main/kotlin/com/melih/repository/Constants.kt rename to data/definitions/src/main/kotlin/com/melih/definitions/Constants.kt index 5d5e2dc..533f176 100644 --- a/repository/src/main/kotlin/com/melih/repository/Constants.kt +++ b/data/definitions/src/main/kotlin/com/melih/definitions/Constants.kt @@ -1,4 +1,4 @@ -package com.melih.repository +package com.melih.definitions internal const val DEFAULT_NAME = "Default name" internal const val EMPTY_STRING = "" diff --git a/data/definitions/src/main/kotlin/com/melih/definitions/Source.kt b/data/definitions/src/main/kotlin/com/melih/definitions/Source.kt new file mode 100644 index 0000000..289304f --- /dev/null +++ b/data/definitions/src/main/kotlin/com/melih/definitions/Source.kt @@ -0,0 +1,23 @@ +package com.melih.definitions + +import com.melih.abstractions.data.ViewEntity +import com.melih.abstractions.deliverable.Result +import com.melih.abstractions.mapper.Mapper +import com.melih.definitions.entities.LaunchEntity + +/** + * Contract for sources to seperate business logic from build and return type + */ +interface Source { + + //region Abstractions + + suspend fun getNextLaunches( + count: Int, + page: Int, + mapper: Mapper + ): Result> + + suspend fun getLaunchById(id: Long, mapper: Mapper): Result + //endregion +} diff --git a/repository/src/main/kotlin/com/melih/repository/entities/LaunchEntity.kt b/data/definitions/src/main/kotlin/com/melih/definitions/entities/LaunchEntity.kt similarity index 87% rename from repository/src/main/kotlin/com/melih/repository/entities/LaunchEntity.kt rename to data/definitions/src/main/kotlin/com/melih/definitions/entities/LaunchEntity.kt index 2a7bdbd..43779e8 100644 --- a/repository/src/main/kotlin/com/melih/repository/entities/LaunchEntity.kt +++ b/data/definitions/src/main/kotlin/com/melih/definitions/entities/LaunchEntity.kt @@ -1,8 +1,8 @@ -package com.melih.repository.entities +package com.melih.definitions.entities import androidx.room.Entity import androidx.room.PrimaryKey -import com.melih.repository.DEFAULT_NAME +import com.melih.definitions.DEFAULT_NAME import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/repository/src/main/kotlin/com/melih/repository/entities/LaunchesEntity.kt b/data/definitions/src/main/kotlin/com/melih/definitions/entities/LaunchesEntity.kt similarity index 86% rename from repository/src/main/kotlin/com/melih/repository/entities/LaunchesEntity.kt rename to data/definitions/src/main/kotlin/com/melih/definitions/entities/LaunchesEntity.kt index eaa55df..f6f3762 100644 --- a/repository/src/main/kotlin/com/melih/repository/entities/LaunchesEntity.kt +++ b/data/definitions/src/main/kotlin/com/melih/definitions/entities/LaunchesEntity.kt @@ -1,4 +1,4 @@ -package com.melih.repository.entities +package com.melih.definitions.entities import com.squareup.moshi.JsonClass diff --git a/repository/src/main/kotlin/com/melih/repository/entities/LocationEntity.kt b/data/definitions/src/main/kotlin/com/melih/definitions/entities/LocationEntity.kt similarity index 87% rename from repository/src/main/kotlin/com/melih/repository/entities/LocationEntity.kt rename to data/definitions/src/main/kotlin/com/melih/definitions/entities/LocationEntity.kt index 652c4d3..af217ef 100644 --- a/repository/src/main/kotlin/com/melih/repository/entities/LocationEntity.kt +++ b/data/definitions/src/main/kotlin/com/melih/definitions/entities/LocationEntity.kt @@ -1,7 +1,7 @@ -package com.melih.repository.entities +package com.melih.definitions.entities import androidx.room.ColumnInfo -import com.melih.repository.DEFAULT_NAME +import com.melih.definitions.DEFAULT_NAME import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) diff --git a/repository/src/main/kotlin/com/melih/repository/entities/MissionEntity.kt b/data/definitions/src/main/kotlin/com/melih/definitions/entities/MissionEntity.kt similarity index 73% rename from repository/src/main/kotlin/com/melih/repository/entities/MissionEntity.kt rename to data/definitions/src/main/kotlin/com/melih/definitions/entities/MissionEntity.kt index 971ec00..a8d1141 100644 --- a/repository/src/main/kotlin/com/melih/repository/entities/MissionEntity.kt +++ b/data/definitions/src/main/kotlin/com/melih/definitions/entities/MissionEntity.kt @@ -1,8 +1,8 @@ -package com.melih.repository.entities +package com.melih.definitions.entities import androidx.room.ColumnInfo -import com.melih.repository.DEFAULT_NAME -import com.melih.repository.EMPTY_STRING +import com.melih.definitions.DEFAULT_NAME +import com.melih.definitions.EMPTY_STRING import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) diff --git a/repository/src/main/kotlin/com/melih/repository/entities/RocketEntity.kt b/data/definitions/src/main/kotlin/com/melih/definitions/entities/RocketEntity.kt similarity index 78% rename from repository/src/main/kotlin/com/melih/repository/entities/RocketEntity.kt rename to data/definitions/src/main/kotlin/com/melih/definitions/entities/RocketEntity.kt index 7fd8c3d..1b3f01e 100644 --- a/repository/src/main/kotlin/com/melih/repository/entities/RocketEntity.kt +++ b/data/definitions/src/main/kotlin/com/melih/definitions/entities/RocketEntity.kt @@ -1,8 +1,8 @@ -package com.melih.repository.entities +package com.melih.definitions.entities import androidx.room.ColumnInfo -import com.melih.repository.DEFAULT_NAME -import com.melih.repository.EMPTY_STRING +import com.melih.definitions.DEFAULT_NAME +import com.melih.definitions.EMPTY_STRING import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/data/interactors/build.gradle b/data/interactors/build.gradle new file mode 100644 index 0000000..b09d7d2 --- /dev/null +++ b/data/interactors/build.gradle @@ -0,0 +1,22 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' + +apply from: "$rootProject.projectDir/scripts/module.gradle" +apply from: "$rootProject.projectDir/scripts/default_dependencies.gradle" + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + + implementation project(':data:definitions') + implementation project(':data:network') + implementation project(':data:persistence') + + implementation libraries.coroutines + implementation libraries.retrofit + + testImplementation testLibraries.coroutinesCore + testImplementation testLibraries.coroutinesTest + + compileOnly libraries.room +} diff --git a/data/interactors/consumer-rules.pro b/data/interactors/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/data/interactors/proguard-rules.pro b/data/interactors/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/data/interactors/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/data/interactors/src/main/AndroidManifest.xml b/data/interactors/src/main/AndroidManifest.xml new file mode 100644 index 0000000..86a5aa4 --- /dev/null +++ b/data/interactors/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + diff --git a/data/interactors/src/main/kotlin/com/melih/interactors/GetLaunchDetails.kt b/data/interactors/src/main/kotlin/com/melih/interactors/GetLaunchDetails.kt new file mode 100644 index 0000000..50fef98 --- /dev/null +++ b/data/interactors/src/main/kotlin/com/melih/interactors/GetLaunchDetails.kt @@ -0,0 +1,40 @@ +package com.melih.interactors + +import com.melih.abstractions.data.ViewEntity +import com.melih.abstractions.deliverable.Result +import com.melih.abstractions.mapper.Mapper +import com.melih.definitions.entities.LaunchEntity +import com.melih.interactors.base.BaseInteractor +import com.melih.interactors.base.InteractorParameters +import com.melih.interactors.sources.LaunchesSource +import kotlinx.coroutines.flow.FlowCollector +import javax.inject.Inject + +/** + * Gets next given number of launches + */ +class GetLaunchDetails @Inject constructor( + private val mapper: @JvmSuppressWildcards Mapper +) : BaseInteractor() { + + //region Properties + + @Inject + internal lateinit var launchesSource: LaunchesSource + //endregion + + //region Functions + + override suspend fun FlowCollector>.run(params: Params) { + emit(launchesSource.getLaunchById(params.id, mapper)) + } + //endregion + + + //region Parameters + + data class Params( + val id: Long + ) : InteractorParameters + //endregion +} diff --git a/data/interactors/src/main/kotlin/com/melih/interactors/GetLaunches.kt b/data/interactors/src/main/kotlin/com/melih/interactors/GetLaunches.kt new file mode 100644 index 0000000..0f3e601 --- /dev/null +++ b/data/interactors/src/main/kotlin/com/melih/interactors/GetLaunches.kt @@ -0,0 +1,44 @@ +package com.melih.interactors + +import com.melih.abstractions.data.ViewEntity +import com.melih.abstractions.deliverable.Result +import com.melih.abstractions.mapper.Mapper +import com.melih.definitions.entities.LaunchEntity +import com.melih.interactors.base.BaseInteractor +import com.melih.interactors.base.InteractorParameters +import com.melih.interactors.sources.LaunchesSource +import kotlinx.coroutines.flow.FlowCollector +import javax.inject.Inject + +const val DEFAULT_LAUNCHES_AMOUNT = 15 + +/** + * Gets next given number of launches + */ +class GetLaunches @Inject constructor( + private val mapper: @JvmSuppressWildcards Mapper +) : BaseInteractor, GetLaunches.Params>() { + + //region Properties + + @Inject + internal lateinit var launchesSource: LaunchesSource + //endregion + + //region Functions + + override suspend fun FlowCollector>>.run(params: Params) { + + // Start network fetch - we're not handling state here to ommit them + emit( + launchesSource + .getNextLaunches(params.count, params.page, mapper) + ) + } + //endregion + + data class Params( + val count: Int = DEFAULT_LAUNCHES_AMOUNT, + val page: Int + ) : InteractorParameters +} diff --git a/repository/src/main/kotlin/com/melih/repository/interactors/base/BaseInteractor.kt b/data/interactors/src/main/kotlin/com/melih/interactors/base/BaseInteractor.kt similarity index 88% rename from repository/src/main/kotlin/com/melih/repository/interactors/base/BaseInteractor.kt rename to data/interactors/src/main/kotlin/com/melih/interactors/base/BaseInteractor.kt index bb7605c..ffcca7f 100644 --- a/repository/src/main/kotlin/com/melih/repository/interactors/base/BaseInteractor.kt +++ b/data/interactors/src/main/kotlin/com/melih/interactors/base/BaseInteractor.kt @@ -1,5 +1,7 @@ -package com.melih.repository.interactors.base +package com.melih.interactors.base +import com.melih.abstractions.deliverable.Result +import com.melih.abstractions.deliverable.State import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow diff --git a/data/interactors/src/main/kotlin/com/melih/interactors/error/InteractionErrorReason.kt b/data/interactors/src/main/kotlin/com/melih/interactors/error/InteractionErrorReason.kt new file mode 100644 index 0000000..3242f88 --- /dev/null +++ b/data/interactors/src/main/kotlin/com/melih/interactors/error/InteractionErrorReason.kt @@ -0,0 +1,17 @@ +package com.melih.interactors.error + +import androidx.annotation.StringRes +import com.melih.abstractions.deliverable.Reason +import com.melih.interactors.R + +sealed class InteractionErrorReason(@StringRes override val messageRes: Int) : Reason() + +class GenericError(@StringRes override val messageRes: Int = R.string.reason_generic) : InteractionErrorReason(messageRes) + +sealed class NetworkError(override val messageRes: Int) : InteractionErrorReason(messageRes) +class ConnectionError : NetworkError(R.string.reason_network) +class EmptyResultError : NetworkError(R.string.reason_empty_body) +class ResponseError : NetworkError(R.string.reason_response) +class TimeoutError : NetworkError(R.string.reason_timeout) + +class PersistenceEmptyError : InteractionErrorReason(R.string.reason_persistance_empty) diff --git a/data/interactors/src/main/kotlin/com/melih/interactors/sources/LaunchesSource.kt b/data/interactors/src/main/kotlin/com/melih/interactors/sources/LaunchesSource.kt new file mode 100644 index 0000000..ad73cce --- /dev/null +++ b/data/interactors/src/main/kotlin/com/melih/interactors/sources/LaunchesSource.kt @@ -0,0 +1,163 @@ +package com.melih.interactors.sources + +import android.content.Context +import android.net.NetworkInfo +import com.melih.abstractions.data.ViewEntity +import com.melih.abstractions.deliverable.Failure +import com.melih.abstractions.deliverable.Result +import com.melih.abstractions.deliverable.Success +import com.melih.abstractions.mapper.Mapper +import com.melih.definitions.Source +import com.melih.definitions.entities.LaunchEntity +import com.melih.interactors.DEFAULT_LAUNCHES_AMOUNT +import com.melih.interactors.error.ConnectionError +import com.melih.interactors.error.EmptyResultError +import com.melih.interactors.error.NetworkError +import com.melih.interactors.error.PersistenceEmptyError +import com.melih.interactors.error.ResponseError +import com.melih.interactors.error.TimeoutError +import com.melih.network.ApiImpl +import com.melih.persistence.LaunchesDatabase +import retrofit2.Response +import java.io.IOException +import javax.inject.Inject +import javax.inject.Provider + +private const val DEFAULT_IMAGE_SIZE = 480 + +internal class LaunchesSource @Inject constructor( + ctx: Context, + private val apiImpl: ApiImpl, + private val networkInfoProvider: Provider +) : Source { + + //region Properties + + private val launchesDatabase = LaunchesDatabase.getInstance(ctx) + + private val isNetworkConnected: Boolean + get() { + val networkInfo = networkInfoProvider.get() + return networkInfo != null && networkInfo.isConnected + } + //endregion + + //region Functions + + override suspend fun getNextLaunches( + count: Int, + page: Int, mapper: Mapper + ): Result> { + val networkResponse = safeExecute({ + apiImpl.getNextLaunches(count, page * DEFAULT_LAUNCHES_AMOUNT) + }) { entity -> + entity.launches + .map(::transformRocketImageUrl) + .saveLaunches() + .map(mapper::convert) + } + + return if (networkResponse is NetworkError) { + launchesDatabase + .launchesDao + .getLaunches(count, page) + .takeUnless { it.isNullOrEmpty() } + ?.run { + Success(map(mapper::convert)) + } ?: Failure(PersistenceEmptyError()) + } else { + networkResponse + } + } + + override suspend fun getLaunchById( + id: Long, + mapper: Mapper + ): Result { + return launchesDatabase + .launchesDao + .getLaunchById(id) + .takeIf { it != null } + ?.run { + Success(mapper.convert(this)) + } ?: loadLaunchFromNetwork(id, mapper) + } + + private suspend fun loadLaunchFromNetwork( + id: Long, + mapper: Mapper + ): Result = + safeExecute({ + apiImpl.getLaunchById(id) + }) { + mapper.convert( + transformRocketImageUrl(it) + .saveLaunch() + ) + } + + private suspend fun List.saveLaunches() = run { + launchesDatabase.launchesDao.saveLaunches(this) + this + } + + private suspend fun LaunchEntity.saveLaunch() = run { + launchesDatabase.launchesDao.saveLaunch(this) + this + } + + private inline fun safeExecute( + block: () -> Response, + transform: (T) -> R + ) = + if (isNetworkConnected) { + try { + block().extractResponseBody(transform) + } catch (e: IOException) { + Failure(TimeoutError()) + } + } else { + Failure(ConnectionError()) + } + + private inline fun Response.extractResponseBody(transform: (T) -> R) = + if (isSuccessful) { + body()?.let { + Success(transform(it)) + } ?: Failure(EmptyResultError()) + } else { + Failure(ResponseError()) + } + + private fun transformRocketImageUrl(launch: LaunchEntity) = + if (!launch.rocket.imageURL.isNotBlank()) { + launch.copy( + rocket = launch.rocket.copy( + imageURL = transformImageUrl( + launch.rocket.imageURL, + launch.rocket.imageSizes + ) + ) + ) + } else { + launch + } + + private fun transformImageUrl(imageUrl: String, supportedSizes: IntArray) = + try { + val urlSplit = imageUrl.split("_") + val url = urlSplit[0] + val format = urlSplit[1].split(".")[1] + + val requestedSize = if (!supportedSizes.contains(DEFAULT_IMAGE_SIZE)) { + supportedSizes.last { it < DEFAULT_IMAGE_SIZE } + } else { + DEFAULT_IMAGE_SIZE + } + + "${url}_$requestedSize.$format" + } catch (e: Exception) { + imageUrl + } + //endregion +} diff --git a/repository/src/main/res/values/strings.xml b/data/interactors/src/main/res/values/strings.xml similarity index 81% rename from repository/src/main/res/values/strings.xml rename to data/interactors/src/main/res/values/strings.xml index 92cdbc9..13e42df 100644 --- a/repository/src/main/res/values/strings.xml +++ b/data/interactors/src/main/res/values/strings.xml @@ -1,9 +1,8 @@ + Something went wrong + There are no saved launches Network error Response is empty - Something went wrong Woops, seems we got a server error Server timed out - There are no saved launches - Seems there are no data and network diff --git a/repository/src/test/kotlin/com/melih/repository/interactors/base/BaseInteractorTest.kt b/data/interactors/src/test/kotlin/com/melih/interactors/base/BaseInteractorTest.kt similarity index 91% rename from repository/src/test/kotlin/com/melih/repository/interactors/base/BaseInteractorTest.kt rename to data/interactors/src/test/kotlin/com/melih/interactors/base/BaseInteractorTest.kt index 35d922c..5505f1a 100644 --- a/repository/src/test/kotlin/com/melih/repository/interactors/base/BaseInteractorTest.kt +++ b/data/interactors/src/test/kotlin/com/melih/interactors/base/BaseInteractorTest.kt @@ -1,5 +1,8 @@ -package com.melih.repository.interactors.base +package com.melih.interactors.base +import com.melih.abstractions.deliverable.Result +import com.melih.abstractions.deliverable.State +import com.melih.abstractions.deliverable.Success import io.mockk.coVerify import io.mockk.spyk import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -10,7 +13,7 @@ import kotlinx.coroutines.runBlocking import org.amshove.kluent.shouldBeInstanceOf import org.amshove.kluent.shouldEqualTo import org.junit.jupiter.api.Test -import java.util.* +import java.util.ArrayDeque @UseExperimental(ExperimentalCoroutinesApi::class) class BaseInteractorTest { diff --git a/data/network/build.gradle b/data/network/build.gradle new file mode 100644 index 0000000..cc02d5c --- /dev/null +++ b/data/network/build.gradle @@ -0,0 +1,20 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' + +apply from: "$rootProject.projectDir/scripts/module.gradle" +apply from: "$rootProject.projectDir/scripts/default_dependencies.gradle" + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + + implementation project(':data:definitions') + + implementation libraries.okHttpLogger + implementation libraries.moshiKotlin + implementation libraries.coroutines + implementation libraries.retrofit + + testImplementation testLibraries.coroutinesCore + testImplementation testLibraries.coroutinesTest +} diff --git a/data/network/consumer-rules.pro b/data/network/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/data/network/proguard-rules.pro b/data/network/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/data/network/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/data/network/src/main/AndroidManifest.xml b/data/network/src/main/AndroidManifest.xml new file mode 100644 index 0000000..32d8ca6 --- /dev/null +++ b/data/network/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + diff --git a/repository/src/main/kotlin/com/melih/repository/network/Api.kt b/data/network/src/main/kotlin/com/melih/network/api/Api.kt similarity index 78% rename from repository/src/main/kotlin/com/melih/repository/network/Api.kt rename to data/network/src/main/kotlin/com/melih/network/api/Api.kt index 2783559..bef517d 100644 --- a/repository/src/main/kotlin/com/melih/repository/network/Api.kt +++ b/data/network/src/main/kotlin/com/melih/network/api/Api.kt @@ -1,7 +1,7 @@ -package com.melih.repository.network +package com.melih.network -import com.melih.repository.entities.LaunchEntity -import com.melih.repository.entities.LaunchesEntity +import com.melih.definitions.entities.LaunchEntity +import com.melih.definitions.entities.LaunchesEntity import retrofit2.Response import retrofit2.http.GET import retrofit2.http.Path diff --git a/repository/src/main/kotlin/com/melih/repository/network/ApiImpl.kt b/data/network/src/main/kotlin/com/melih/network/api/ApiImpl.kt similarity index 88% rename from repository/src/main/kotlin/com/melih/repository/network/ApiImpl.kt rename to data/network/src/main/kotlin/com/melih/network/api/ApiImpl.kt index c56ffb8..ff195c6 100644 --- a/repository/src/main/kotlin/com/melih/repository/network/ApiImpl.kt +++ b/data/network/src/main/kotlin/com/melih/network/api/ApiImpl.kt @@ -1,7 +1,7 @@ -package com.melih.repository.network +package com.melih.network -import com.melih.repository.entities.LaunchEntity -import com.melih.repository.entities.LaunchesEntity +import com.melih.definitions.entities.LaunchEntity +import com.melih.definitions.entities.LaunchesEntity import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory import okhttp3.OkHttpClient @@ -14,7 +14,7 @@ import javax.inject.Inject internal const val TIMEOUT_DURATION = 7L -internal class ApiImpl @Inject constructor() : Api { +class ApiImpl @Inject constructor() : Api { //region Properties diff --git a/repository/build.gradle b/data/persistence/build.gradle similarity index 82% rename from repository/build.gradle rename to data/persistence/build.gradle index 843f46d..fcc536e 100644 --- a/repository/build.gradle +++ b/data/persistence/build.gradle @@ -3,6 +3,7 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' apply from: "$rootProject.projectDir/scripts/module.gradle" +apply from: "$rootProject.projectDir/scripts/default_dependencies.gradle" android { defaultConfig { @@ -17,15 +18,13 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation libraries.coroutines - implementation libraries.liveDataKTX - implementation libraries.retrofit - implementation libraries.room + implementation project(':data:definitions') + implementation libraries.moshiKotlin - implementation libraries.okHttpLogger + implementation libraries.coroutines + implementation libraries.room kapt annotationProcessors.roomCompiler - kapt annotationProcessors.moshi testImplementation testLibraries.coroutinesCore testImplementation testLibraries.coroutinesTest diff --git a/data/persistence/consumer-rules.pro b/data/persistence/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/data/persistence/proguard-rules.pro b/data/persistence/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/data/persistence/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/data/persistence/src/main/AndroidManifest.xml b/data/persistence/src/main/AndroidManifest.xml new file mode 100644 index 0000000..4d3d76b --- /dev/null +++ b/data/persistence/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + diff --git a/repository/src/main/kotlin/com/melih/repository/persistence/LaunchesDatabase.kt b/data/persistence/src/main/kotlin/com/melih/persistence/LaunchesDatabase.kt similarity index 65% rename from repository/src/main/kotlin/com/melih/repository/persistence/LaunchesDatabase.kt rename to data/persistence/src/main/kotlin/com/melih/persistence/LaunchesDatabase.kt index 636dbab..da7a83c 100644 --- a/repository/src/main/kotlin/com/melih/repository/persistence/LaunchesDatabase.kt +++ b/data/persistence/src/main/kotlin/com/melih/persistence/LaunchesDatabase.kt @@ -1,15 +1,15 @@ -package com.melih.repository.persistence +package com.melih.persistence import android.content.Context import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase import androidx.room.TypeConverters -import com.melih.repository.entities.LaunchEntity -import com.melih.repository.persistence.converters.LocationConverter -import com.melih.repository.persistence.converters.MissionConverter -import com.melih.repository.persistence.converters.RocketConverter -import com.melih.repository.persistence.dao.LaunchesDao +import com.melih.definitions.entities.LaunchEntity +import com.melih.persistence.converters.LocationConverter +import com.melih.persistence.converters.MissionConverter +import com.melih.persistence.converters.RocketConverter +import com.melih.persistence.dao.LaunchesDao const val DB_NAME = "LaunchesDB" @@ -26,7 +26,7 @@ const val DB_NAME = "LaunchesDB" RocketConverter::class, MissionConverter::class ) -internal abstract class LaunchesDatabase : RoomDatabase() { +abstract class LaunchesDatabase : RoomDatabase() { //region Companion @@ -48,6 +48,6 @@ internal abstract class LaunchesDatabase : RoomDatabase() { //region Abstractions - internal abstract val launchesDao: LaunchesDao + abstract val launchesDao: LaunchesDao //endregion } diff --git a/repository/src/main/kotlin/com/melih/repository/persistence/converters/BaseConverter.kt b/data/persistence/src/main/kotlin/com/melih/persistence/converters/BaseConverter.kt similarity index 93% rename from repository/src/main/kotlin/com/melih/repository/persistence/converters/BaseConverter.kt rename to data/persistence/src/main/kotlin/com/melih/persistence/converters/BaseConverter.kt index cc9d698..a0bb43f 100644 --- a/repository/src/main/kotlin/com/melih/repository/persistence/converters/BaseConverter.kt +++ b/data/persistence/src/main/kotlin/com/melih/persistence/converters/BaseConverter.kt @@ -1,4 +1,4 @@ -package com.melih.repository.persistence.converters +package com.melih.persistence.converters import androidx.room.TypeConverter import com.squareup.moshi.JsonAdapter diff --git a/repository/src/main/kotlin/com/melih/repository/persistence/converters/BaseListConverter.kt b/data/persistence/src/main/kotlin/com/melih/persistence/converters/BaseListConverter.kt similarity index 93% rename from repository/src/main/kotlin/com/melih/repository/persistence/converters/BaseListConverter.kt rename to data/persistence/src/main/kotlin/com/melih/persistence/converters/BaseListConverter.kt index 7bdc189..df5fe73 100644 --- a/repository/src/main/kotlin/com/melih/repository/persistence/converters/BaseListConverter.kt +++ b/data/persistence/src/main/kotlin/com/melih/persistence/converters/BaseListConverter.kt @@ -1,4 +1,4 @@ -package com.melih.repository.persistence.converters +package com.melih.persistence.converters import androidx.room.TypeConverter import com.squareup.moshi.JsonAdapter diff --git a/repository/src/main/kotlin/com/melih/repository/persistence/converters/LocationConverter.kt b/data/persistence/src/main/kotlin/com/melih/persistence/converters/LocationConverter.kt similarity index 63% rename from repository/src/main/kotlin/com/melih/repository/persistence/converters/LocationConverter.kt rename to data/persistence/src/main/kotlin/com/melih/persistence/converters/LocationConverter.kt index 399efb9..a4d375d 100644 --- a/repository/src/main/kotlin/com/melih/repository/persistence/converters/LocationConverter.kt +++ b/data/persistence/src/main/kotlin/com/melih/persistence/converters/LocationConverter.kt @@ -1,7 +1,7 @@ -package com.melih.repository.persistence.converters +package com.melih.persistence.converters -import com.melih.repository.entities.LocationEntity -import com.melih.repository.entities.LocationEntityJsonAdapter +import com.melih.definitions.entities.LocationEntity +import com.melih.definitions.entities.LocationEntityJsonAdapter import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi diff --git a/repository/src/main/kotlin/com/melih/repository/persistence/converters/MissionConverter.kt b/data/persistence/src/main/kotlin/com/melih/persistence/converters/MissionConverter.kt similarity index 81% rename from repository/src/main/kotlin/com/melih/repository/persistence/converters/MissionConverter.kt rename to data/persistence/src/main/kotlin/com/melih/persistence/converters/MissionConverter.kt index 1d25e9a..6a524e4 100644 --- a/repository/src/main/kotlin/com/melih/repository/persistence/converters/MissionConverter.kt +++ b/data/persistence/src/main/kotlin/com/melih/persistence/converters/MissionConverter.kt @@ -1,6 +1,6 @@ -package com.melih.repository.persistence.converters +package com.melih.persistence.converters -import com.melih.repository.entities.MissionEntity +import com.melih.definitions.entities.MissionEntity import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi import com.squareup.moshi.Types diff --git a/repository/src/main/kotlin/com/melih/repository/persistence/converters/RocketConverter.kt b/data/persistence/src/main/kotlin/com/melih/persistence/converters/RocketConverter.kt similarity index 63% rename from repository/src/main/kotlin/com/melih/repository/persistence/converters/RocketConverter.kt rename to data/persistence/src/main/kotlin/com/melih/persistence/converters/RocketConverter.kt index 66b3606..d98102b 100644 --- a/repository/src/main/kotlin/com/melih/repository/persistence/converters/RocketConverter.kt +++ b/data/persistence/src/main/kotlin/com/melih/persistence/converters/RocketConverter.kt @@ -1,7 +1,7 @@ -package com.melih.repository.persistence.converters +package com.melih.persistence.converters -import com.melih.repository.entities.RocketEntity -import com.melih.repository.entities.RocketEntityJsonAdapter +import com.melih.definitions.entities.RocketEntity +import com.melih.definitions.entities.RocketEntityJsonAdapter import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi diff --git a/repository/src/main/kotlin/com/melih/repository/persistence/dao/LaunchesDao.kt b/data/persistence/src/main/kotlin/com/melih/persistence/dao/LaunchesDao.kt similarity index 86% rename from repository/src/main/kotlin/com/melih/repository/persistence/dao/LaunchesDao.kt rename to data/persistence/src/main/kotlin/com/melih/persistence/dao/LaunchesDao.kt index 2490cdd..7d14666 100644 --- a/repository/src/main/kotlin/com/melih/repository/persistence/dao/LaunchesDao.kt +++ b/data/persistence/src/main/kotlin/com/melih/persistence/dao/LaunchesDao.kt @@ -1,16 +1,16 @@ -package com.melih.repository.persistence.dao +package com.melih.persistence.dao import androidx.room.Dao import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query -import com.melih.repository.entities.LaunchEntity +import com.melih.definitions.entities.LaunchEntity /** * DAO for list of [launches][LaunchEntity] */ @Dao -internal abstract class LaunchesDao { +abstract class LaunchesDao { //region Queries diff --git a/docs/module_graph.png b/docs/module_graph.png index 7add4b6e609205841326756ede652bfcf4d45178..eab7666beee4f17e4b46cc06004a7671d5a331b1 100644 GIT binary patch literal 129138 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 z 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
W!;4bmte_{PvZzh`!(a z5)DnJYs6C~Q!WJT4q?iFNt4;xA*W(+g0PXi>P{oMg^;yWnXI-Jiy7mAc`5R54PdfW z9_^17q6{KQkXm6jbv5nh)=vT~ur#gsBXgC8Cyx_awUy?f!-hR?#HO?{!n+&{2@ z8@u)Jl*f2}MVY;l8(p;1yL9K zb>sdl5r-j^fG7c6G?!!Ty0%wggkSgjjEUYJ@t2^V`JvmvZ7I&DY2 z7X-HyWbEwQygAddxv@#bn8)KE2`==r%Y3_OLWZsiQE4?0t_S7I8N%Vt%SdAX{ zJ4R{Z1q2<$s7C%X^I_Gf>4%YGmn(GTB}`_8dwcG~_x9%5vVNZ@U8x1u3A+cm6?Mck z&DohvGObG{wkC*hZ+9Ilzy-_nx#_Yd1unD@qP7hh%tq0L*jMZiv9I?eGy-eSNl2?c zanoJXf{-qD;BkX{VLg!nl^o#v9Fd_@f~T-d%Q-3N@+^xU*OwD#Ar0V^ad2b$@`>!t zFuVq%(jt)c)QpUROyx43E9}y;O#QnETEZJOR)vd;HlN&AqSLTam(|*j#(EH;DCYyY zQ>sxD)ZZM3x^LKkTG#Q$5f|5@0y0TU%GD~Qq$OOGSsLE#1y^W=yXaQ3(4=_L6Buo; zuRI)+mHhKFvEqrSlj9&>Ajas1OkW5Q_AC%JvNeR1v5s!@`w%(Q9c^{WY`HczGjrq0 z;)REUHyB{NyN+6Ho_uaDMy^*=re%9GSJ?(zcyp_Ane0(?G1-pP;qYB%UB(WM#iZsp zz8R}FDe1<6ar_w6ZXf)-n}iW4dI0f?VG`Z)i6Kwi0#iAVZwo%!+Gq|p(9Oai7_;Ak zEA@xFn+4xrEe*}u7`_IR{k!0@CN|wn&Q-vOOv1an)Ey=6`bGMa-vET%6@qN%2ITL2 zwEFNmJng~@gUz?@Ysu*;bmJkIy4|3%`)D zL<9k|_rRT-Wopcg9~wBj@k9H;@0NDofMyh{&wHDhreOn-KjN^oy((wwkqCOU@==Aq zI)~g#p5OHR^ZqR(FpDL>2dadfIGbKUu$RgcQjNY z;xX}?W`Fkg3&HlRBH<#JXe8-IjKs(R8^SD6lqRCT_+xD9{GDKe=}|@U=-GVL(_baX zM<@XjTU+qI0ZT=>))rO&F)}sU{EmR=+SWzo)|Hq;LA8&8Z^=|FqWL z%c>|tlh9RV5#MGA6Qm76V(s%@-I-MXH1c(94hG}MPloUWd>xaOs=R^3HuvryHA3)t zSJ6t&3m-mcuF9_DLHEiTIy9Gn)+v5c)*PxL#oQ{h5XB|b_v`jI|2+J)PAU|8>K;_j z-q=vSlZ@6;kZc$MiLW^__R#a!hwVy=Frb>M69t}m9e}~wu}7|` zutSlFCLJX1Ad&Qc>c%24o?ydRretrz=Mw1XSW?nmXZ1rnzMS~qySg9!~IUn{2y48X42Pf&v@kU9( z{HJE0yaq=+;e11WFZSCvyF@8;@{fnBKn$s4pkF}qi~DLtCai3uI084P1oY~=gL61= zs0fdmV0pd!hu}j8Bz;&WO4zz34UEE+P_{0d#l&;~FH`>Q2M!^pV9__7i@ntygTY({ zCxBv@Z!3e=hgi96m~dym{XIU$wzsQSq79)>EQbWSa4?;} z3esU86^bt<4JdZZk_KDwii=OpdlWqaH}ZWRIK`p*zQbgE-wGR$mY$t*`_hzb^WeKc z6`Xh0Fzmnyye2@~bW5F`5tq3I8mG8|>GuM{R9rSBxZM1G(b&k{@os5xI<)N0eA~6X z4pGXk${Y#0&siRy;8%tgNtydFB4c|Vjx}JdbO7z}svxIJP{s*io~_`dW=#!7DS5@B z-{|v2k=!7wo`DL#JJuU@% z=yyroXTOt%=kfMDGR`?eC6JekjHJZr_7wLI56|hyLX5-!=B)64AiQT<@1Ui8Sw8U2 zSi#kzb*SgtFN$J4MKAK3!U`bwWUovAAosspvfk@T&_k!av30%v0BO_RrHWLqf82yxl?1q4 zn~Cu)atjg^oj#qH>g8#@j31up$h?S>%qkipSJO;zW`hSt0T9iI&>HZsFi)-~O7Kk1tu7 z!Sm*^cZ~y_R^XNSIMw8ieY;N=kKO9G16iQvTIdrE2s|Kl(ma~@k;g}~enjaUW7j|S z&%@vz`{g5{)DVgugKNgonE}RQ!pPx1s5YbxOVMk~fHra#=3&0yyk`GYttnH?i5$G9 z^YKY93}5**fZ~to1Zkz38MfV=`$3}{sBZXs4yhV}@3}Ulbz~g_7QqC~PEQ$de{+Va zNUXHrEOE2p-b}LmfQl3y`Hbh;QK44DZG?R6rG01!wLCzjJ`9Re_%rv1NSd#m+$$8IjJGFUwd^{R2j};I z#4m{dfZ!8loNSWfBQvvX8Qn4`BAVaUUgp!G@!c>ySAxy*CeyPpY2_bILt$FhcMA$z z?^nbO;eWT~^+)gh{#^=4xaECeXr{WK{sFj!?oY2N$xpf`q3_T!Po9(j9#hwx|8DJi z{10U>+m!`>W=A*`vY+4SoR)S{U+KTS)E!gcA21Xa7S;$eq_ZUCrD+4L4_z9UEOqJ? zY~p>qjoe5HGa|-*q!+bL76yxcn0lda=EJ?Hrf?i_I@EjD(KSZfEodZmwSB9qpt1mC*Xurht76=l~w;24<)0ib9WLvrCdyvnt_Zr zg2XbHr_aOQFc34u5m`s@TzG8+>AdjTFB;C3Bdy1~V34G06XSCw2 zCK(`E81f!km@T?3>Rxm`T~ncvgE$Jb-i!CBN>+|SuyYpPNOocO24D^}PZ=jXFw zP2`<3R^6Uiic=y);}DOBf0f&=rnv-lTv0q~*uhi=X=&De}$& zF!<= z7{~C5#{izj7Lwb@f@YjgTT|AM{$+4e@1YH&&vGx3JeiiSeJoey@Y(p+3O}V5WgHG| zE>2E<07zRHGm;6YSXo6PA7?sph|+y(3zUK?evQsuY5mc8ssU^D9!DqdBZ;6Ev-T?} zGIlgAtvXgA43#K`^edx{`2$*~p-hgUwjVUL4o;y=jj=d6YM&xwNcdrKvnHA`ESpJ!L#Zv_sTZ*g(joLmsE&!-Zn6D50O&YLQWakpqX z0v{uy2`;Mt?tk|dpn*$!lor$2MpJO{2&AntgkbgnZdDw)NU^@U%F}r4`Q#M7XixEC zXC}4B)R?Y&vz3+xvn-oK0!zyfm(vKbGy~8%syy?soxz~U$l@QYJZO_}4FmQUH}hQh z=36uAyLy?TU6t>WW)L9~I`HaP4(2r`w4;zuR=jAgM_@#JH~1}NtH}NFz6I% z#dbY5>h1%`Rn62jSNgI*oDyIhs?=P!16SwiaR*VIXLJ~?B<7d!R6Hg5)bw~I0DLuT z4IX#=A2xu4n6(<@u)=0+9kp^~PXQP!fiI#{Y}TZ|nhvNiTh`gcj%~k(V@(nkd+{a8Vj*rp6_QZJPpfkdA)Rw_eY{v+k~Q-L#`-A3a^3Aq ztW#5$9{n|%bm1QzgvJJY^l)A#5jW9E;Hrg5=mcn6mX{ykkS0NWC~dACYjhOp3Mc4= zvYmUGR%A-%;sX!-SZg<4!ws`fqAi{SOCdPl(ZIrZLFG+@w1+%a9l#m}V&HL@f1)VLe!ZBj ziRJczw1Gm97EHj_4!>=8H}GM?13(KjFh(_R zRSKOmgw2&>R`4|Jcn>*4W7PcosQL9f+gLodqG2(@2ks)S%(ja7q$t`^rU&e%b3>wv z@Q^LuK?25Go~h*xPPqK+?4fVl+T`VbP@Ft+$ITa2t@~Co!q)k1oP_+22zF*t_6|t1 z$Ma5j{vN&9@?iUJ==e``x;oAl$w)KW3M}j^y$>H8W`LJ*;vL-|jwvLUv1Ot_6fq_! zwBc5%-i1g~X~L;nhzh-G^6&?(h)p2b+-qp^EAQe2I57-6>LX03 zdsuBIbm>2xKis0|>HKP`1Pv`Av(!97Bq$c6PlXt>ve9$&R_^6zR)($2_H>&!=G5G` zEAnh=I#+HY6;2O~0B9F5?8RONHg>KdzVx9;Xm^xNTet1DcfT~JV!5}kS4F=+3B^V0r>@z7KO!{-vvg_7ylIdA zpzgtsBzMfcYyV2$qi5R!-+aj1x5br<1j?k9%eosJw2+!pF>%S@WC@OB& z@q^bwo%@o^kK0?#VExWnpWs3!IEAjafsp8I$n&nzPkh}9v;#TJx5E#vray(^Lhb`O zHJLtL8rp7=m%!crnp=-ypC1;$2Q|Dt{>1=$gyd38QxA3*Ce&i6$Ywa4J8)@fiIwC} zL?<_hZHiibcL#7Uyy2iiJosz%VTw)a8vzpAR$#rGoIkZ)?|z9JRNeok1g!pdSQ>LI z-}4fbk3wbQme2mkVLox=Rxpq54D=wIj^fS!>PoE06h1v&_>@n}FS+*Zp(^@?1%W{I zJ~_CP$TKUJNT03{9MJQU>=h2o92Sn<_zKv76myNhdG;33ecCF35>sKuRfkdY&EAVY z7eNIchdofBBJtdm`<$;={KN)e9d!o5L?c|}lpXDD#wxzxBLHwUK*K2H z9=o~3nup_^IFwNnd2|8xcZk)yge&lI+lXm9>Bct;vOw7uYq994@SkExpBncHA?9nm z0C5Ak4kpR ze?I~T;1P?GrUzg+*bW*T_nf4SBSWpL8=%&RI}Xv))V-iEO|tcZ@n;IMTR>x(uRzdO z?9PPHtbrNisxm9}e+UfL9SlTfo~1-JgYcrP%8PK$A#L_abC&FAlbZ=|t^?5}^(JW@PRQp_#w@wipP<(=O-c6Yu$9CD*;v%P_w#2F z7>_^JuiH!aqU#bSF8lkzsIP<^=_2bL7#KJSbKrE>1+T(8$fSruV9t~+VcK(@j=v3J zHei<3p@}eMakJ4By6bKd{$59os}?dr9}vW=M<|LSKC37RWs|VS#h=5_gJoA-@ffp7 z06;-6=k@JD^-j_z>M_G z@d63-{b(&2WKx?nC#P~Vc{86iEQAe5-J$#{9Z4em?FGD-1x z4o{&9Rk&>Te?{y3=*;J{w|g(i>ud^)n7z>Q)7_ng4!!fg3+Je%0|1PcpDG;8^Vc^( zf&C$w%RAx@N012u1L*- z&#}eqacClZufHSi-EF}cj^bnP22NWSlGIB8P~@=*Wn5cs#Eo@B^9-;ULr<*B z{S8qI&+&u8*S}0`xgN*3xKu4)iHk@ zRB7E??+wb;;hdRO*QL27-Exl%25~by7uwRr$aA3Ajh~xc>W=7QfiN~P*aFLu%U+ZG z3ePHS4c?GesY37Avn4jgAMr2ERB-%@1dS_fw(qr%prj)^0m2k8C{iV#Hn3j;V`>bi zV|U4%Nj0uyoZ$>9^c-VBi?*VWB3%U`64mc%x~(pJT`Y{9WZ+d-(n7jt;wrKt4Q#OT zz*F|nQ)KtsyU!qDPYw0%60{i@wTbk7r6#Oq4SJI13DTK#qA;_lH~=EXfK9%=IWRli zSCY=Tz11bpWei`LXv|Q+RkuW0(uv5KI<8PoCJN zi^R&zV7#U~!*Oo{Wn-EWJ195cHsl^LC_&DCA;ccm0hA&*&zSvRUUnSPgqZSz&`_Kx zr-;^uNTug_eVHYI2wGOXpP|RiK^^`5YXk$3w=L6MuUb>$&X3t}Dl_78TSc;nVP}VR z3fwj#I?o|=&<=LX4=`&_@%Q(eVw9d|#{o-UZ=M#1!}Lm)QoW1x$9uMi;)2L4t~Bg> zpfQ|;)w>deZYDnbxLE#f5ulK0g~oka%c zcxEYeZ?ymWdF?tWIQHI*bhb>G0I|ge44nz4-+mHvgg$=(fS=Q&fT+DSS1e?3ilW!@ z3PYd$p(LUE!?}9qSw~E_vzr&_PKcP@OJI^3VYxo{)e(kcwbys_RugJ-#vhV!%Dv(8 z=;6@E=J?D$u9BB2C^lQK{0C_fl|an`d|6a(yKg2Qi4*Rxldte>rXYGvXZty$S`$Po z2}7oIBE(DB&!qjg`tX<<6hfHH^lc=QKxPCa7Mg!b7!H85iDmlbt%V7uP$9#?N;LOWw(tf6xV3sjGRcjU&WxdqoG zrJFe@I7FRBn9C72zO)BhI#`Psm62xM1aS^6=99*jR$N9m;=!kBQVFcyrgpdq>s81_(zACpWb%tgDN&V^f47*!tjzZbgM>hu2+1y z87e{N8cv@g8FH}SQ^eiX4ms^@jW85(>~m$&DmN~@i(Eq>qOFjD4>FM)=5z`@)Y=!3 z&#}c)GCqKTD)Cz|5?x;ldM4~B3_X6DSpc zl{gCj6P5Mmdim3)grP>}^kL@vKEdiXX&`l|h!a>-Z$M#zJsSqw00QR+?5;LnteR|W z=gDy7#!5_v`@rk+o06E7I4@$hmOuR)PB}er&gCGuGI~rcPyt8c0VG1AktArzftV&7 zTosWe1S5%b`Vt3WM+C@yV}>boy1*ZV7*MfHp$6g;vK4e`&-8w{}vh?wd|ZTKomvF-@)jDJ#8t4?)}a(jMF+Lx<~ zIhXVLAxWg0^tzljno;MzS+!-8yKP^OHQ1e?aUX1+p{ew&;8QLVKB0TbSJu0)04daogps6{+!<@#DSKe_cyn(* zwDKL?zOFYS2`#S(od)Mf-ggERi4&PO5$yGF=PC}V*iiT{g+~$ zj~NDw21?WIuw;Q&XwV%AX6dNerB^QH?W9fhMDs%#k+nXvYm_}9Av|2a4>j(J)YRs2G4rSgQo-UCPDhJ*C4 zGwkaYo{o{7jgbCm%j*MEee2w}aO_30M(Q{k1RY)DOu}z`56$}HJbhY`qQbp(!oiLh z%4)D>GXLm)j8|lC3ha{y4s~{R zuGgSF2yFwi4q`hYA6+d8&oab8bIL)M#v2(6oEoa5EYpYGy)$`cW=3l5#)ET;4qlWz z`r`$Rc$Db3YO^}d>v>l`8DiSsL5C}=+8f&H zGN@_tD#wKW>7JXL+tjMc?Z(#)ynsQHI2!`4$IaY!A$`ABLOTC&YesLjBj@|8P>bnl z{lYwYio-i>2oyytu*OU4bUD8yA}LZM-UMIJNLNm4gfYfT7E-%D9l_j)d>URN5j$Jyj&#V7iZD;Fp ztONqP^K$?n-S2UUm2)~388ZdwRl%7u=ge_9JJ|heGRcQqw%d6US$17tw!j(|X=KX# zn*%586(}Jc1U^KcG~G^^O27$uxpLXf^sm|W>ga*6>M^wVlYnffiC?qv5iI$CFMz-; zFPUTb=*ql07`G7E_`m#W%|dL?OG!L8v%C>yBt(~`5qJ4j>=`m6fO;ywV?obNMZ&uU3YLweaiB#|vtpO<9-($H6*?P8Ye4a96@v>Yga0 zK4kPU!F|K)j47^GLs^? zogQKUxy^9jjStrPwtH`+6igjB3lyz3 zA9+wBhVSfZV?LBJS%cJSXEI#pm*~q7F4woRy81f|Cj?^Vy88=?9R@Diw=A&JH{GR- zsxZB@D>g}Fts&4skS8Vj-p)`8F-Ff-m3ilWMULf~?lyKu{4Z%%WE}K^eK(Uje1zbW zeZaZ6Ja((uQ_Y#g!CChyuT5esSz5DynpHW=C8{Z<+RjQ*BuNFgyjpG6qj+$X17c6r z9e_M)2(A7lkBfH?#jx{?BU3$VM=H~dL+7~=@_t3L7WGa8^mJp;CJ|}jOw;mrrPpmX zi=P{=EIqb64~(pmOW zs!(OVe*%e%U+vW%foiMm9D6^IGQ+%=ddw4-50_jA8Z){=x6x;EPIaWW9FRl*Iq`Cc z`C_FO7wyG%b=pb9_rM?pty_6@Z{K~|m?(_EhVu5~fsZXd_pnP=n|We(o&O#|n@0^> z*KxD9(dvx00ZVk*iVs6iKL%X%A$YCE3(y%qw{M;gfO z#*?kGNm4uTkt8l-Nes+2< zzW=4L&F}1Avvf?@Q^rU6Is=^OQA1zsnuhtU{fKuZ_mS=qz^O*s6vva1=tza{ekn^z zk~>#7jw#XXe}o93Mki5fGjU&hsk%Hx!>gMWBu2zWd}Oppjl<-dx`t3D`Kj`Or!kW& zULom780N;z7o?2h{2!@qM=nJ&5dEj3)?7#B6K7st{`yZWh#NpgUfs9s+;7wW@p5u@ z3oQFb9u;<5^ah9LQhm6H`F-|uzU}awX*{_2U3_m#6b||DlE$)p&C!#4epeg9Za~*3 zKr~OqhgstBAUhPqy4ZB%vaDH%%0(97UKg0R4e0BIn)*%|?vc4)WJ?GII#7eLtD>M) zDB0GwQZ_{j6Vsu-_3=5>FF!Z4m)_P`S8=BL!!oP!#&w=D`296>e$4`Lf%KhaqpDm5 z<0?aP?WdO+`t;I5DY>=z+bG9!X57|)58j|Y=1jR6saXErm(9@mgG!6{vS8G6GaU*Q zR@GNLL>&5Zl6R*xBRhNFv6i=cVv4SG8qiP}xGXE7?Enu^gVrvin#omz52ZBc4pO(n zn=xMGIdiRtMK_NM{r|1knSHzTXggi}5|3VbcuD{t&%%`~0ayJivVp%iZx21oqAb6_^IyYAgJ!xU<*ji2Kr)B#%}JX+bRs+M;@mk7Ybk#E({ zOx#6l9&c;uN-5kas{1gGT0j|)JKbNSG_T@tBJpO&ICEs@m)M#7enpq4wO;jgT_}7w ze|kuN?dfHi(vd|KSj{d=n-H4r$TvFjGpaZ4FU{cA)C_-hB%B^kcitoRbji_Km0lY57lia{x)dnZS=Qkq>P;>v1)~% ze?x0gakVM7{8eH`XA1JAh$m+?IFvmPF&D7>=#s{zLB1dUl3Jm`zKKX6#0fbSkJDH> zo72TM=n!7%njqg}4e%sZbF-{JA;#?fk~WGYTJ03o$r=bUHu1n6mzLly$=k#E&juuG zbXFNni@xx@;3H18ckt`X%I)2qZ&J~aVlC;p_h&q-jW4oU zpeS%-CVE$UNAG(^*yWWEnj7`E3mVNQ;?5^eN;7m%CiSZhDx-Kuyo&WTM!~F}=<2r+ zcmAmPx7Q9`qcvZ)QZv#k`_>R@+~eqa;l_JwAcybb>R`^r&j*;bM9-)iQ$o%me6E6E zWI?=Ig|BL3wN-QdAHtO~%oFgB1O!RBcE#o=DI7(91is~gYDYuk_Ua_(;nbCF8{ZOs zSDKdV@n4&NuKPydhMJ4>AK_2BIZiK2Atk^dOc~#KcBTiVwW+gz{NgwMB(3UP*hZ>E z7vlb6BMk+q<+k}2-<7?i+!lpV#+Wd}Lx=Z?$Mii6Dtn zHA9o;rQ~UZES`W7gf1*xajisz?b5)eOk`A4Y*HpHI3$>?OgvE{MehAg48#=fdaZiS z6LY9HwEXo26oIp{PE01wn=twjL2q|dYG;oDco6JxHZ)KwHqFM6F)2Lx_|j6Z`SEHY zt;%PkC|(om%N_2X>kmvK-0OapcQ}tuY^QNKkuyqoQbT(5fSq+_*kUVyyu^IwaZzV& zC?;*y;V}CaW@KtTP#jw1I~=UT;~ekJroIpav4=`16R;@+MCxiOtE~)bYOkj!)zb`V zeR{lBk~`5dVjz_aN5*ACh=_4`^i}|EwsiQxfdSV{8a6Z1 z0Dyf#(C)Xlh}&hs2_mkiOiR@w*yY#Mz5Adsf~5+jS@C8u59T1WdIGc7WSL%ZuG%mC zR)bsmStm5lRxFP1zIjP7zFhZk;tzgKucO1e0|w(J_oYMnu%ze`n=+)sZt$HYHtA{t z0)qAon<3>(trt1Q$u;Kdm_%BMyIm+O_}~8dF{dJh=VpjC4hbx@N-Nh188EU4NFTV^ zNcB9nmc%fTHsDM+yyoOq(cpV-u~+tV8_P>x-ik+g?v58Np7Wc$w6M+;SJrp3{dQW( zc*Re28(0^co&NuH58aN~9C=j(?^2ew88t!tBUjF)i{Tb#oMy&KRFR8P%m>|+$~D&Z zOWj)k)Su8_MT>sfuz7oXkalydlB+G??_=51JswCoC=~R%GmE!Ga~^kaZ8U#mg`Xhgub~OrqrbX5{KKl(}UUN$|Dw7opzdr_=KFp&cq} z?~UlO5>9`owwB+jNraiqjL)E-;|oV0>@F;<>+c;|tKxK|!*_=XyI|#_Ju{6tz;m?M zOd%G#d=2?<5cUs=Iac%pMlq>xvF;~`yqK)r1Wln?RW7N%6@k>sfa=dvUhk9ybjtpi z6rkC$;T|1iN9I4h__ZafOz6V#%Wx2QMK+zZ3*63rfq`+{!R{hz^$L?DA#|S6?LM|d z^euv(YA(P>n!Yr@j*cv}8!?cUO0Tev)}9hnIUb}-8OkfVY|6yQA3=JSOxug`Ki!;qS)y8I-#N?iZN0F2ldg;LjND3W1Um@B&9#pFO^tvWc_NPttRXV(l zEsNktbNr!XG*q5>JIXQ z%9CIsZgwZrtY_I4#Di0?fgcfnlcncWsYxlEcD9pCoKJ&G|3ON4czA{Bv(E?8|1QPP zOUKsJ3{(o^5&w?Xf6eF1n!(&oH{KjvzW!3}A<=iCsFv@pxk`&bWhk?p&!qHmUh~Nc zps6tYwaIyK>1UNF)=Uje>6i28!h+V{jGYo8!`er=&0dDzb)Qv&L!9ex^SF4vvjof- zBLbyJlHUg~@x6GTzGF51`2ML3_5@@Z&x*r?*ccY>*++a%%Ems4BNp|PKf)XtrD1s98@TaJ1z zghiruc5uU6@5S9K^t)3yM$3Ow8~01cxP_u*;GhxdE?%i;=%S~1LIdd7m{lYZW%U+ z2dJ`Jzb2h3+I=s+G$x$w>4{5o&n!CR#7Fq{NJ^H%-Cr2kjk=X+*8sZy8gyr1cnYqA z_p~`(RG4R1p|dq|JZjSv0^EGVX3M_f8?!tojv^PLy-4-81jF<$RWCr1P=>xiI=4|V ze@|k1b5Ff%7H0WNa?6f}Ju*yU_Mf~Q%gLX~rnq%^i!UweoNRZJp43_zX$#zLaI(_0J++O% z)eZ7lqZC51svjjzCp`DX61P9k$ZGiMG9B*03Ixzj^X>1N(r6IRt<0`c{w0r$1v9lP zZ9&JE|Aaqa?xS?dfB9E`>ncly=IZi;Dfb1=4-ZA1_eI0+Ou>aV+2RMM>0Bj>5E?uJ z(gMTMYsng>7qdegFZnRf$BQ{sKOpc_F~EFaNXiK@lYbih@-+S9{W+y$;uWf;gyN@{ zKKnY5sB7x{N2H?n@OuZMg85sDtb&eLGq9j^a_4OO$0lQMq*-%Jf+lkZHs$o^1(0O+ z8C>4!0sGQ2nJpjuiPr(d&599aR1ZK+Z%}+ zsT(;wTwoyz=qxrI#%v4i^sGzc=xSOrZp;UPs>^iHV%vfXSQ5!27AW z28x{z?`Eb^$)ak>AJRCX0sNn?wkcG{IhnaCq3I-q9udDJK1?%{eqaZqKAmKLIgbf$ za_yz|zB%%3Wj#)|N#LVQHn=ZG`NC#L`s;(K4^S;C{bH97xX;A0{rqUt-K^B~mg|I{ z;4HPz-qz7Ov7I){z7k9<;WCvZjH~ekNnuKu%$^1YqWHM{bZ_t4Du%;%=Zrt&Qf18i zwl}1A;bQ+l-(SDp?13sn6V?HOfeTYB-dX2@$6uB8T^D{p&BesuW3 z(KBPxI$jWPt9gp9M))Fvr!-g4-dCqA_|f6yBg1e586CsbbkPT{;5N?$3IL%$%0X$E z7(CoewK`7>p{4;j1oEW7MrF~DrI&X(I|rg7oS`f}1CC7{Dw0?2TI({W;OKJ(W21rn z&|C_gT`v8@RCVv;<=dYjhw(4rQN|!@(a~}@A|S0)^8ur9*42&M)1))K+ts#>A!~}% zv_Yx0!rQ2;m)z6YdseCF*0D(jBsInVR+75LCGCY?O8MKRO4Qh+ZpDdy4LsZ}eM$PK z=w^jJ#{leOThxd$qe9 z{QkjVNd9!e8FXBKOuu;o?a$unXplh0l}7S*)Kl5{y?bhP<1`g@@`b%5iK<_@R-OF) zPGH2C#(A4~0D@yvhUv3?!+xqczpr@~y%RAXNdXp;;N@hLQ77-iL?)PbV3;_JIq_QL zmVLd7*3zTYsQM(lwX`Z=ox>`b*!S8&V&>-$L`un#(CPPUO1!l%u(lLt@?E3hc8M<>o?GI-& zOCHOssl+q?yN4dxr`yyg>p8l{O?KmN9*zD`RJ&JxdVOZZs_;2}14;Q;yXkA~@~n-A z$otuUFIvk}>6~Rv=-X^xHf~mnfAhYl=1U1#!;EH`SgZhy-HkuK9~;-}n%_N8yJp}x zbIbD1;jOv#o3qvf=E4_WtMLo}G!-w+5-F)jt z|9M%A3`wf+cXIskk=vFf0sR$`4u8)_S601Gf0zhV2L*%IXw4!`DycO6oCM|EZyL*d zwc?46%$nWV75}pXhEsW4BK&Q6tx?W=tr;KPyR*eI$0dhUF7~M#A76=HGNmV6T+ipZ z;B&e`5+_|1EV(oNxLt523Z2IO@a$jJt3fg_@#Sy_Z#89`PynRw@PsdY?i;|@bX`S^ z8bnq_g&VxcJ{dJECXJk?#%9}9LIY+>;aBYa0p&U0?Dfd-IIy30GcSE^Bd3bxOb)r12+VAG(h1)iNQZ7eO zxXEOOxG3l|E7l+5{I1#~8fLv5_3^a%@jG88H4Q1Y5+5ytLU?`YCw z8<+CfujwZmvXsz0Ew4Wq1a4;MYg>7&{Yzn%F^<&xa<7fX8F?Ix?y_tYz3}q>mMbB? z(xYHpYI2?Nl}ETYc>sx;bX6<<$c@}bkWJK_%*3nT;HoxdMwGxcoc_=Upj?c3w8&&{}8VmoK zE~3dg!AD zqt`zB!Cj8w_C{syrWSUYx64u03%R=$HqD#>4Hw)k$Q=JF?ewDJ+os~;uaoI}^^s>j z>G>~CVq_zZegSj+n!NRE``B2Ho#U;z1T{qsu5Pw5g5Px?OAg@}`&7%$p1T?CXsoRQyLPYMWx;n21Jmmp`8dtf2#fAQ@~xp&p%}$j7_sY@@nm~Ucs-hk_Ms*-!+@33e9un<>h?x z$<%5W_)lb7ZgOjR?ICI zves2gE5=JZovKPm`K~8FVb!?8$^TYr0M^h z;oZl(-GBa0eCg~(;PRW*TgD8M!`4jSCG0M#Jq`)(oBrNZ<7WBOCi?zdQGA;0v)#a0 zN)i)PlDoDx2c?4k6}uFo-;>(a>SBcFS3A$X?J5?Ak%ZKWm!9yA*yoPIaKZqm4*p9E zX~_vzR@UX!TdocKn#tT+lyx$^$<5jgo=d%cqd8J~E6o)q)laEj#RdfjZM=JBq&xkp zd?MY*?Ww+e$)}GM4s}u;9!uG?@##-0jP*T>2)fi+9AseYb@X?`jb74Uy%7znGCXH$ zU;LHw1mtP1EByX#V9;U0nCwzT&?W zm4UGj(zw{)GYIjVZc7=E&IT+(M&`4`mTkN7bfjGHxFa(`bbV$bZCy z$eUHEr+4Mu<1X70s!@3F6Fisl{p>|6_3>V8x*oMD=TGfwc~SpfpL{vd{0i2##C6ME zMZ#;2_7OZCsWgqZy8=#vmS>EuEl!PdT&>AU=O#8?#*23U4Ng7nO8x_cj@H)}pJM39 zWDVm7FC*MAHml1Qs2@D+k|&`;YxC1R0Kd#|xJP;4b??-Gr*A$u8{YFhUdM-nR4@x| z9ougCdV#2v?lL;}MKP5rtqlSp`|4Nxc~t2WH-d-z({k7E4vOUDYo+kfh%L^z94xJ^ zGD&Vpw@|%pa2Q^8mUuK^{|THJ96gA^uR{QTTTv?`A>S9p$3xr^bY@s9|N9|ZLFVV# zc5f=O=ciF-Sz8i5Nhp(h4KCDC$mE?xIq$`VHt~R8s#TwASj}sQa(q@lGpG^Vs7Y=* zaoM=0Gjlk%qniA_M~m2^T5vxHf* zJE9LOl{o%2(owKfNG~YA=yr?3tH@{0#OBPFW7a4Fy&>>(oNCY&BjXh9@Gc-N z(H}0i#HGRJh^x!KRrU{#*l>Is0Zu2m@_VIAUKtLO_J{EntD{;QLD%799^m{Hi zPJNhmP3GZvg)x-1^6}-={f`nMosN(>qAx^#eBO=RsN_Ljcg!SKp zsG`Be0SU?*`QKXF#}n6o+DLF~D2a^sQAyVP?M*q(P;<1DX3w5kneRw>Lw#i1`IfC> z=HP1gZtv6Z{~_wEqoQ8huMgu0Lr8abNQcr$w@4^0T`C{~N+aE!1JaTbQW6SM(ujnC zNDB%`3MwhTYdp`p-hYm3opaQgVZQf$#onK7SM}QBq>!fO(1G;V$xCKV-P6~2Pb^#q z-$G=8xPAS3<`ap1F2IX` z+0jUaYTj{T#Z?qGpmJ2pH#|$xr0A;-IV;AV;k$?`F4MfH2KL-&L7QJLcNZ2=Wq$OI z=gLkbY`=!YLaoL->ULX*-qigXi2r-=_kQ}P#*-UU+no#5qj=Xs&Z9r-T4|pDZ8Hcj zQe9{koK=X%j~K6}CMw{p&fK)9zh%FaD42ASAnwMn0I#{^n%mkF+V2&wRcwssCCRR} z)7w=3?l)$QC5+&sOxUN3SwC)&ygu+Ab4;Qr8Oc>%AA99`x%RUk|7ht8Pi|squeOpQ z*Ac*NB5%6^howV{;LI*nlEJU}YC4K!gmi^!vakIQ)^u)frj5^yhcR142fHCGz3 z2*Nkt#PuO~H>MKyjqiL}zCKAXP0KsFB4m)=)a3MmD2GQiH+1KMORkW1tQP6e5tVL( z@R5Sd$*1kIkpaQzSuE6Q43GF=)Y9edvXg_vui_6kZuXAqzMOG-v0+CAj^OG8*LR8r zD?Hbhcxu$X7=5o;k-Xh*#H*AaC&%YK{!CN5Zv#;*bL6DUN2c?QS6@LzREF*70*mNW z?=EUXq*6$cSN(nC=uv|~5x#04;qe%y`5Rxfyt>-m`5imy$7}ICVIQOp$+~$@$B#R_ zZvFgK!F!Rf)ld4c;~viU!)e`X_`boo9vUS-_sK{zdz82JdFYaG%vFZ8TH5|AI@+g>HNL5d{AqK3LH59MVPduNSl=~-^XG(1x{-K`&^%87 ze_@yS=I31bREF<=YUgRcULjW1IyBShW^=P>73>+$%=AbQU;i*Oyr3Ghzuvb`E#BT| z{qhkT`s)2zmHGMmIx-o~alWDmKP46(o@g*p=qv>6C)_dmyxQ{^RFf+}7K1pTlsJd# z0O9q$vp)-lAT+?sBy}wFNv#YPU-+F^_z;j8<|-4uEm@sI30-hqpb~>Rne&vTO2YkW zCok|GnOwFK;=Agz9+e&AO~+hiHyx5(7)|z-J7P;GOCap6sL0lv%CNd-;qG8NLHXO9 z_H1V*3VhFQ6-B0B_lvFCYz-nr>EwvV$nWe)y*MwbO5Z6|CM;cuzM2c(H;h%JGJNqpSKkW14K{abnO+YWL@R zZ}R1pUr%F-ibA4O?&Lo>MDw3H_Qka+_!;72+;8{TU;5_c?KVsG>6KZGQGKdZ^=Fos zK^yq4pPRDrDSYfc(xz3n7eIy!(wZ}*A`%@Up}kAm)=#YHE$TGJ&vkiqnU=l)Y}N+W z)`dPT%B^N%X&D~%_CsWM=iA#d0voaw4T^Vs)_E-1lF1Ia%9hUmK2sr&TxolBydZ9= z<@ji0g?AXhHmoPs6h+j4IAD~1luY&`gW~D|Z{U0fn!c2nzuccanDTi_&1=^C#6o5r z9#@`3w*GPV+;L$Mc9|B=kq?wMC0qZ@)APz!p%4&ZY}Zh10nb!HdCh5pD$&l;t>Jq3 zndrpAS)3oedhWX^Db2%)_vOz!-Gq{H<3_Y;{uLk5z?ol$M*KHv=td*A<{GoMZ?~%6 z{@IeQ^Y!Yp@yin3s5c2%2z{M(vHaJU7b5Q7e5QNyXWOZd&273hoSw}cEYCqq(o(g% zZF*mdWLQ|b4q`7xj%c;U$`&zcpWa<9G56l(|!16zF}TUpO+PIALtnZB*8}?j!n%XoP zyw7@x+x!&M>&6YtI}BeHlb`ioB@Jdq73)6~n9kt}xSAvVVoSp*Y>aG_4qmGmdlw(| zSdu*a!|wat>wK#{w;~;@lA?TjA7WxKcXBaHKD?XOx(}Mt!xyJlN$n|r3#M+qlF@K@JrRrZ1!gFF@eJj7$dr*JQ zmkrQ)e8WU1&qJcTU?%X!i_0HNAjSse@QKlg&r+)!R}h0AD7faG#rid~@;~)y^%|US$NNEwk4yQm*-bgsvak=2qse z6T42U_m+^P0r#a0TzkJ6c`gTp;o8(jn(`fI0kwr*{!hwNX~2 z)u|9`lgQ@&ZIqt;7LnUBkH`Jt{ox4D)*<~kc&Yk2={zaI3sMi3!_ye%pMx0BHAljm z>1=<%gN~Q;mH*$-GpCoy;#*JrIw~S4@(7FcKa>GX7G>CUvr*x1!^~Dko)mVDe(0zOR60utjHDMpfS7xSP zKCG$^_%#}zK|rmBJMm~G*FhPz`0%{;sq($w2Im`cD$9b@Z>C&tp;OPK*1YN1vlS24 z=hP)#o>7WjljbpdL4TV_?i^!OOkk4BQL2qX;ePSbJax7hV6JR??0WqA!L<}q`Xd80 zO~@LGMNE<+mWfkZ@6~3)onOzjD-{!nF(?eLm2uLInHN3Rg1smbjEDx37Mwv+LKp>rmBu6R1@Ows&c@9AG>VCiE(B?JY|Kj#fsBk;M9rGC zjV~1{aJ+H+yBsH^@-z2Y%{~1r5xGI`jso4%1ap3ShQIet*>X;jpuuK9u&}=C@3yB?2c? z<|YQA1d@7&=c89Fl)ALqrW>7z6TlDedAk)^6_5cgi|cZ)*A#79-1Msyw<>MkQKgIf z8XVE-g-rdu^2%9jXAd*`#yMbCz+kQUjYZqI5nxg%2f*4y|8;sy+|R+<68p~sUCpCm ziekhnzW%(yMP6@fd99RKPimSiLewRqB2U~7)X9ma`*T;7`O$qXUW1K4tAyW)l|}^*A8_T#P^es@ zyINQ6`yz1Q(M*R^i^=CgAC+tmha!s*UtaZz*>v{Bx0%DA zMr0S)TFYC5lsVGM;!=-_r-=&KReWAPK4I#MV@~=>J$Qq1_*Nn4x#I)?wIRKIDXt$y zLmUF16uHqE7?KqL$t7%w>&3DM{YHco7n^c_9Jibo`ld4cB)Y5>+UmmBZ(b*J5# zc@6VNSMvJRcjiP(0`&eW2}O;=v|()~n~x&kC);f~N}cXh_TPp>j}cndiMdidbtWv7 zd`3F$n-oHpxnhp=9!;js?5w*Wn8#0J;_!92#`#^%4LmFdOHs^ZT+W}(dZY;RY8*-} zBuAouR7Q2dr-9)wi~DZa<4aSjd?r{eX-MFMm3;?nYb+64mM~F4aJ}vr9Yd6P4kqC=%(okA!nV_GNc{2WqYz6Ij>}#yqdJcmb z*^}QiZmfIQmmElm>g80g^IXsLTFK(Q#Hlq}BwwQ+*!X=fOr7GI$bZf2@`BKE23Vo2>|Ooj!Mu%W8~aSP${BpC^r*dGqEY+ zGEz_R&InqjaZ~7>aDwCuZ9mf42kE+7lDbaBd0cPOYHw9RLopLiC*j5)#5ZX}n{DPM z8@(KCvJB)~tk?z6JD_4pNK#3^VN(mf{v0ZV+c|QP{cWvXU#~>iHQ)06qW8A@lm+tZ zyGP&rFJHT_mCI58T6#THd{E3oXj5>m!&iN#r_br|ymNuPvv>XX3q3y$UTP|>)h$&f z1C2K%ye&uyT*)|FPB!psgx6JKHo1kwNQ?$oX|9(ydk8F$#>F6m@;dqLnvyjtB{=+1 zi6|Znco_c}kkcHtt1Vhll9mC0+bz|mrj}|mVidB)cz`fcjgMPjoS(0tlS~)vnTB|^ zU%RAMY8nlrx#JEH-?%NC113*Wqq4X;wQ|s@9NJ1TC0Vt`LRJ&|gH8vh>teA16ub>0 z3zyoIeQerzKU-PJJG2Auza3_N=pgX#q`SJv){yN!g7Qc7KQ0o?iqzzAsu(Df5why zYFOY6_`k7oGQh!>WhO~~3Obu%@h*!wDr}C7&AC@C)3eQK_}(sHs|mNS1G90~74Ga@ z+sClyZgTl7TJKRH{qU}o>Ahj7Y^awC0Jargm?>#>N?qJMC2$8n^`#tm+QrO>~EG z`$T|H=K^*fN->kK{R!j+@E<8-9S-N*dm>9c!#@PF@vf#!x{y&|z2McHY3GfmCKM9zMa8WC+YReM_|1y{`~wO-s$4eQTk z@KTa4)02Da0G|x+6L{OBGq82))>4E&V(2Bb?XU|jRwvC%046y}R2Oh&8r z>4aJGfMayIxF>=#&s~&Vo5QjULp}u>Y7sc&Zdc1%|H2mHMZZ;%)NF6%NOp9dODW_4 z;dvM1tNy^_YX}X62!R{?6rD9Vek+Wh3~8tiA&g7m@U1?8Dp{NiqjKf3ik<2-E2I7EQ#{7UT z<}YrqSNeLYVcUn-W(ggII*B9{x+X=V5RJqBq18nk$)9$`&q$EPLqS17d??{u?DgKO zLRVs0S=kC$??qnn#37FZ*UVi4ww5teML3ob(WX9sE@e4j@f)u3z@?~;X^V_F$~SBt zk~a^#|Bf`|Nb^K>xd;dgkGBn5j5GmZ*>vb6-8A@0&v3-6#E9#wh_O_iZwerBcXxsE zm$jdZ$sg{8igImgf92W&*RM)&eSi0U9DdWmT_lgQ5$`r6(TkN($+;}ZQ#3a*|C z-~DfiKbL;~`yFdIArKvua;_wSXscw2W@d(QZdu1yHxa}JJ62i+0B%VFYS0$SU4wko z!s>a#Hlg>hoK3z!4+}l4LHNqFZ9{%oxbYuDK9&xA77HsNAZiuvm#oS1~zpV-B0+(v@- zSoCdd!c)N}2Ri+VEa1RbGMR1>Z6ihi8L)^^=25bxSi^9{0oY)9Q!OyS4#7;KeMKI( z#SZYOeb{%GAq3~eGKqCEw!9f&8< zH!(pg|H>8ETwmAJ@G|ZU3Uo4cmx~}p5fOdM(2o###Qj^+3T*oCh9gEnxTsQyZm;Lj z5LGUgl!12_ED1*pgf8%k7T;!eDZ}`nX!V4d2<)xhV5x9)bVPf@C)30m)#Z&#+qD;3 zNM)LN_Tlck&yR#-Y}9&?I35uo{`<`mJcMZ1fl6UIf7ybI2r21g&Va@1gO-c5M_{a} zq7MwRF6o3Omp;L072)f$JnkaW;+gQ|R~Qq_*gTKR#6-W|ohnNZw6|fU!DeSq2I>an+f-Fr z=5NsoRd3W83ddYFW$=JmwY~>{za0T zMjC<4-}sO7v_=^MK~jFl2fRloCqHhfWXAn_=w6X@Rnb(V08^q1d!NQCBI;O1?3E?O z?PfXu-_akYrnUF=rAX_{+Jb$Fd+4DN#}pmLND?!WA$gm-z4i%MN_&`p8~lJoLE`{w ziQVCdcxA_I8SnCpIOqtbAm2)mU2C|m!9XzmPGs9ZSPcs^0?I_rS$k+vgqRH_mc)Vk zOiD*zHLk{{@}=>xhDOsZGXrCyIyCRHsscQ}N1YuL8G>rHC$B4b>O9LTNE4p*m)n^c z9{SBLrZB3>u8nY9!dT5`Q31d&YqIIZ!6zgXmms<7mxOZ0v@W?qlq+M9TO?r7Itw-AIip9@FH92dO&Gf(BUH>{jDXc=k$R4q`NV6(*>LVp6R(Y6=8MKxrz2cJ(P> z&+bmNn>YIcCO<{z!yLnEfvm3*m}x)#LOcj|PA+ZeD4Q(aIZ9uTR)PLTz z6T51;4DUzb)=un2`zF!29$oPM2D6{S1HEqHP+N+J&<)x*BQL>U$Kn z%KE{<0R`THI9a#AlNZQn4RmsX*Lx;wcz9I+_rD!U@Kpx#wv>TN~W8UP<1+i^SCS@#h3Nr0eE16zQu*uC3pooQ-@LX1e&o|7xID2~ymS`SX zSmNiC277dK=?}*ztG2oS$sj2F1myufKK|r&T}HmuVtBUgV=h&Xx{DdBDOjPp1gBD6 z)G{lm!vx>GVkBSgl}NZFFVHbrjF1pId>w!-t1%5G`paQv?C#*yPI;4I zESOG ztOyLhU-$&G#Ap%1F+cbANZZVHK0dtl@&xn)6GVK}&$`Ym*{dzuaie}*!=y>*38Ujf zf}!qa4X+?o%A>oWKTsO3X$Du(L&p9O`Id44hsl7;vA&@%`1Ar&*hnjC6^>vbn@4~Q z0rXF*o9ze0>sp;iUY^(xgYeKL6{VBW#0U{T`cg2l8z&;{>`kg0fV`@3(<_vevQ?#2)9` zJd4%EA7H$W`6iYKu2`DRvj(giuuzsqemUMOHQ! z7}i@R+->6QEaV6jQ+?pcqtK)1iLdQn{X}h>{RihN^x4e-u&DF&F5y*R1ajD){soE& z<^J30mix@No?Fh*1lOfM!wiaPl@M}9g6Uz5eAMui+^WUS^HekF0A$u(Hcmcj(cVPU z%TL39UWeoJR;57%341m~DIl5AG9()k++(*+zF_g{ubu z?5mn65u6FGIRSPGM~}qiUkC%3jVl!!aH+9KBhWV$?IGSYR`uGOPI#_1hgBo+DOGBD zvKPIg6EZxoPn?KUe~?5*3dEcI!Gyk)VMlHu3EX^;@x}227lCbCQwe9^1Inq@2WXrn zPW38NK>`pk=a)fPO2uRdoG zRL2HF2b-hP+XR~yr!gIOt$%&NzdvI%UI8*RFu4mDDu=ZDVsLiR;_H!UEF*!%eG`BS z(*pQs4G{ZUypNx)x$f=!A&urfGCBS8SMYBi3Qd4LsteQ6^c;!%ZncS3v*xpF0QM9& zExy%OHJkf{H8|RA^U0E9*fSe%5?Snbj6AeD!>m}$t>6@%054C*y>O{7DqVM1dmMS^ z*M$+NygO!=-eMqifmgb}4V)Ti4`SvdrJ~n-Vz-Tdm z2&r6!&Tn48HWH*z@P$n%o78P*=L*DZcIhmJ&J#DwfzGpshF_B425c;oTSspfEAxh> zzizdC5%UzcUyjRrd$xX<+H0xj;$_SB)+Mob19Sd@ODF{N|K-4NFoc$ev9jMGPhk=8 zX>7C4$#1pA#-Zvwme^iP2dn-+7C>4r(WUgV>O8PYeBQT#;W+zq(iDy<1-8kyt+B+p=8IzzyghSYGME>hD0eG2=;UC%SNHHyu0Qm8rO-2x zy0i;`Vb11ysLK{{8#xF>f105ieCR0Ss=`cm(8}a2`x?&ihfs8uK1VUOrC2drdWXA6rbH z3$}oFYytd|et(cf!1~GyxPlM9CSAk#^g(~;RRz72LeoC=l?eViuejx*W z-bY;fdAm}J!O?=xn5umU1ajZuOLzU_y=_5u5*dVW1g)eyO9Jz?e3G)vAxKvmAeG9P z=FsYR;IyhFSN*ibzSJUJz&tZk@HSls!}&kLD~m3YB%~Vdx+X{>k{t1XDqIJ}aU(w$ zgMlCP)N69q7kij@a+%c~NWCuuPpDUZ?vL$M@t?f0ma4Pm;sk@;bWVJf;PY(^b%x^ z`;L!@eiSBoCcLNUr3kcHVDh421mkpKP3Ujc?xPqjZ3NY+jT*VK$h@mC=Dt+J!0(}Q zqSNvC8Vg0nnH?^pt#HET^|u9?jmCjzvDq&(9a!(`)z%%iT8@s^I`#`TF&# zz2WE+QuljEVX-#50iu+*Gc_{D=VPo#lhjrLHj%Z`bL!|s)}-X8;nd@p{j1YW^&cL- z@K74++dud&E4h)7)kXT2*>S z-oC+R`|1kPJx9zbG1|U=IKnmF=Xn^)+VN7+9!dAV{McM|tWP95rZBgz{v7CAdanHCVHR8D+? z+(F|tPaiL#58MR-O0dU%-;vAD!oKK+Iz8Qgm(G2I34W$jyi4)xZa#ND7XaH3weSQA zjyt@O>ofhs7oVuyk=O(e9oeZnf`1Dq9AcK@gTXpXa0lQlxrKwMus+e3j0hOwQ953Q z?xzgK0IzPJ&sHk$w(wZJmR;bx#dMR0dULc!bWJ~}(Lm7p$DR7VB!k4xe+~F9RS3MM zaaaxsE;o114O!_VVd*G9&KZ*Iix~8Bl6%sSHMRfuh?@pta>3&c{ z%%=#jSH3v3gx z7vdu*FW)5j^sc-h=$V%Pti~*gMO!lM5eie;tEBK5lte#LLN__szx?y_r|6xX7dvps z;3svXMeHgd%mu%tXLD5ntFg8awjm?kiM}vdRKoh!1h2aE`Rn81n`eoYjr0<3B@l4i z?`5)gCakY)83AQS^k>gL`W2jNxRmrEs4KKhD(xjq4Xo1?zYD7ym>9!@XiOUaRNgkj zPAymS9L18t(r{~-_J`?tha(>Rja(0f9}D}Bp@W05z+IcdkW80900o6gvullXs75db zyoqfFoT9=Enle`jsDUx*rRfAyp@lXBP}ai(PksoFu?WbW-cfn`r>f3lPoAmaTuCqn zz6<1*@&{^z<6ApBH=wlr_{2G9Xdhy(Vn~v5@VX$gH3SgmdO6~E)_@uwnO+c)$s7V& zl4z2WpPtQ0>`DokglEk96Vl$Y12bCFT~I7q6h`~Wu6dxrgz95!t0t%y=YIXoN&`%a zAvweHZPu~zEquR6?^RuX0P*jOzQGw=>mF-NK7+RPhW0xFQN*!gm#A+taK6q^eW}i| zUBH@qC{mdYYoF^6gztUT(1|2zVj#NpL@d}?Ft-;|r!41v_~2~b?yL^v^TSZI=z(CGkYODZeWq_`%6F&yqrXg6kuE!(1Aqm>& z(d;c`MpY7}gpN3dmmf~+&Gm^iSd*fd_}fU$1pd%;0%B9w2iiC4O*jIW{>o5IR+?{k`m{LL7xAg zkB1#$eA{Z7p zsSV|OModWTdx#-Z+9pz=v2RG|f_DZN*`#5PieILlME!16f zpRJ;6U6#RJ^*{reA=KZJCkg z^sOKge%7i`**915Q;XtaNQ^9ycHXj4{py$cc6W&8O$cT=>@#w+W?UI?)F(nvDL*)@ zh7N74lH>zJ>{T4S)%luFgQSBzqgR_elA8ApS$(;d=eRYJg9|N0q$05#`J`l8?9grg zcUGi@>A@;I+w`d$CSxeO#Kns`Gf-@Q{<`H*R34y)akc?aueT8;<3X)0Ki@rqO8@-fnz+ekO6nd0asT zyVW5C1HWB|!4E^M(bxTMt+sI!Cb#_mc3oX>NxQUQIUKkKBNw-M!~KWELFSGlBJMv| zG)Z5#Lr?yV-aYRZ4VS*~-m0_y3{iZBvIH9=%Mv|^93LS`8X1VSbR+G5i-nv#M$l3hMV+7-9(dh!vL5L}w$>OCNvPBPPMn2qK zMc|3mH37>5O&d~vqkzoz)pOIv{!wA~1(z=!p~b6AIp?i8e-pvawx{XJH>s&-~u^yu^+C0@g3spgi>gl9}nD2s!4l zqefs-wyT3gJCYP&MO_IR&z=^{Grz+uz9@9C1X&4hxb%-{WO=B8@lBc*cAPvYSAyAh zqKu&%Gij@%=A|8muR;>k60ID_4=r14%c)a8Ke(Y|A$=U<>KZs=su7QdAFvuEtEh(};+O0Cx(a7kl*x z1_cLj4Sng$!@Mz%1ts_iJcS6eKU*w+M)5L#BVE4dLIeuwr*`#D>Vt{_hU z&}~I-cYau_gE*(Tx4Y8$b9!w~iuO0Rz-i$BDAAvi9g#T8VQb%mJI{tmXKYzGit|KS zbOzm?joY=IuQcTTj&>Jl0XlOR@D;T%rIHjuVa0k1w4Pefv~lW8imYD%FFfoWK1B(0 zW%j@qS~~!i7-AwE-!}Z<+`((C{cri@9D~IW2zvt^SUY_%AapawMX}5f2h2m#qY7jO zOoga?WMeV?0*trAz#%%i>wn+`DBJCHorOQLQGL80!&b!%!J#i8J%p=4CG^UbFDuOl zahPm!FFuCQA`abLG~|7ho72AKnueLqI<$?Oo<(6HEe3*KEaY+jTT@#rA*U_gg@gIV0=oOhGg^H$VhCwPtg&rOl@Igc zAFwYC`|k|FLJ`u6sz@3#%Lka;0cqMh!lzY;M&SydiZzAkD450W9-IJ}cLJAg}K-tjHPV z{B8z)8`Xb=$-PjA+ficE$A*#&FF$!D0kbN7uZZ>MNW`xH%@LN7I^7@FQh?JmdGA=( zcjH+IglgV|+ioccX*e!x`scqp=k5}_e|S4bPuam?*fDZrl8?Z z76G`u3YcO_MNG_qIINCTefZu|e6}kZWD8+W^FVcdG=7_Hxa!xF3uXCG8N|dvam`>o z)6EX2)T8v&auh?P#QphE{o<7nLnA>wK^S@%Y1E**bJ*c~{y?|2!NcZaUV}`X{U6}^ z>ebu!!Q-gAJ?MzXtu^{r__JCUBx#D3D}EvS+}Q#*5hl6zvPEm%Sw?F~FUo!_HygfP z-`wSDNhA=$oLA^DdB4$wz&YO{O`b}k;L;y78s*ZTNxJ8SS7=cJH^Z^pUjZ=$iu^YG zRVHl>9;AG-!wjbfQ#UFB{5ve{oy?bdZq23k&Qy;3nlXN;3-=Eg8{&y2LbWrLdKL(AO>A1}VExP^ za~F9*vY0{eFd6bAJA?`1Ypxgx+A0qq2du@+O0_7L=}Yl&p1i6+A>1?7GyVA~#fIXr zEGKQ$Vs+lCvCZB9iRDo9f;5dd`oViR4Rjh{v9`b&Q#aX(3Hk)Ff_6Y_gDA?HEc9)0 zdiO{D+P#w1otkd( zI=C=e!i<5ckHyvruvZwmX&$bPD_VtS>(NzJ5q@ri>H1ikppK8Id)B|pY@8m`EPr^S z!JmXp8XQwm6~4%HiB8CNjL|dd?hrx?a`%2^xP#tGpf)Br@!=4|iS21LA#xJPVrPE^j zZ2lXjyHkcF$sb3PxLlOd0>hB&TiY?)G*Ey{=AOG-9o>&b27nA50+uS|6s#*xgc$4RMUEl2C z(M!X`-_4V0Z#oXZdEf?#>%qVsRrk57&dt#w=e0)iL`4->O}(?oV)t2u--U+9=Ru$& zzZZWAzM<^m!%STfi+4?A9XRc`CrB|v0th;hJ9e8pjU1v%FMwL;hZ+}EIH@o@0u^rn z9ktk_x$!`?X*2W0g+bR82(=+?o*QTMvRg83)AM!*ujO@kyo+F9@Yw~OLGYxGr;}V{ zk916z__LD;-vv*)vT0HUqhHXezp>Qled=x>W=Nm;C;PoJR{aiyEg1V9?iTqa^@TQ1=aXoI`)_tE!v~TcP}6q()v_?S1-?T)O1I%u&Nye1)-P;Ef-XhH zJ@Vm=y(7^~n-WfMbNWnkZ_#*O$$`wdTTf}-*zpn2WtM@`C$(`_y<27Ic_&2ovdV73 zF`ePk&p8kKeJAouStRdotirwuZ{!ie3ZHzZ z4$iTb&pdq8S8eozxXF&*Bt0iSG%VHX6H*%{mTFlnLzx&clXGgVl*zp}ZYdmOE$hgC ztM$rjT?rx#CaB%{6AV$-AK0L4zy#Q$+xPbOpJH;TfNzq!Jdm-Xjulf-Z#MXE^Y@0d z$_ISWB8+9>B1}sc$`rAhyE8cjr@V4xhEapzASesoeYm%`mlDI?7;`BEUhyPsR4QTB zP*3^QEp9)qQAmWIpUC~j5VwZ3#iiCf zHSHiT>^f?xs`S2ro*s!Q10lrlJrzneq5JpN3FEN>1g!5iLUCB`7ji1$E;)q+(qb~m(j!cCWf@BZGwJK3rj)@*Eh7qImMKLWNKLIAFl?nSz%MNJd zYDG(6xbp;JL#=&W-p*jJGBM!bT$2L@q6ZSSO>(O2pX*wlk-tekm?^v zFvY@`=T_UTAK!2;(Ww9mzfQi(AG7^1LXzNi!oC1Q?HOhbcA18s37KQ;@QY;{r|CIQ z1JwcHDZ_P`bP!m@fxM50>*LB$S|v=M*iKq(6VSmT6a?+F4IV{*t>H1xz@Qm3RT}g; z7dia&C&m~3Vd;0p`NPX07?(toV-}_#aeay5dUzAv1!E2=^ZW5@JdeA+e0k!|JlAxG zJP;H}!xGNw1i(OIAFU9jB@Tf+j43z{H1C`QwiEW=CmLd@Kc-6ajoBl)X>5yD34x=B z+PldJRwbnRZ;eK(EvA+F!cP_p1O9B^CjXuLY7{k{q@bdL#B@Jo+`9Z%M|HV%(8*t` zz7Q9&aSkNVtDAI>6G+j$zA5C<$iQLL1)-Uor=Qc`JO$?rrU?rb?Tw8H)Uad2eH|&~ z31Hi7QM@#39_rTLXJ=HRgbmS!)u%AS5P!63Vy^1T44=Uo2{!r@3#mD@%6E1byQR~|XW1A*T!FZ7;UWq> z4Q&R2%_`ZB5NNAdcp|13HQw!r&gApKjmeY`848VcHXn?{-SYmGw1KRAjxX&sNwDiRBi`a12Bnzb;*h}1v)v3@ z=uhB7*S2C5P7yaEnsZMyZTG2Go(4o3;=}kV%7!9Ud|8 zu!_2G8CFcTr4&2%=xJdY8&ydt{C2vrEDF6$CCrDSBHD$4LUs>}7Uq9b|IN z31o@sU-wa=rWLUbzq|E7`6CLT;Nc{fc(_7|)xMAA`I^de1^ZlMFH}Y*XW7F`dx_6_ z3T5?@Rj_?c8rStn*1H>V$i|zqc6MwGClEc0=c|TpQtle&$1heOxA(uYg%e?Zl?VZ+ zdl6>(2vQ%FW*1J*fnMU~5)2_aKSQ5vecBi1O*yBhr?!`ZF@%v}*c@%fA7Z3kYdF~G zFk(jObhr8T%Bn>yEL7q`bmYqVdL?~(6WI#%7}WA2%^rLTWsu=U!q7=t5~(SJbg8wd zvn|>V#gLOz*&XF?1w88%~| zR(pkVD%{Q+p^6pBQG2*P*|&A_{5z2n9yF}dklw5+CUOqxku#9~=D6kAo5<=8JHWkD zRReQxj_MNI7xY!NYTP_#BG-fceSF3t6wTp4kWTF{Y*WbdBL+W_~Ko!Bgcm(+4JRgRKZ*Gr=-1ms)7U zWyVJ*=hvjMQGV-W7QkZ)w4)FpWh5A!2qrfXf26!Dmguz)+n{;(plTaJ4*JVb(n!B^!90j#)nN zsc+LnBrIW(4YN+(f+)ahEe3d6U6Fbw8URHfd=@|Ps7qGzm_UHb85Rw0O|>*;mN2|b zX=d|73VFq55abaGkaat2jvqs%;$VClB(S>DOpD#Y61=)tp&N0yUF%5c*F9?~1v6b< z%jQi1A@8=%zsGSw!w3LgrL?aLYPO4K-XsuEX8vf%g4pcRH z@;Ua{54AG5N;;hcg8yU{rHaXOX<$k{AL!e1A-b!E?gg#D@H2`X;fshtcRce|xFpcU zowJ&1U6jbh(a2~H;4o6TfEHODj95N9Mc?rs|I2C{X2`ML9>=Mj*)HKMotE`q|DYfNn|Q=Gz3FK}HHqGyP+`O)5V;_cHz9y2 z|MqIaO;njLgt9gaTez-Y&?&K=!K`3M1bYK|o?i;NsW5nMW1n_)0#D+U+A~L4Vw2w+ zGNi~tVEof_sRI%M8$JiI;o>u4xl6veo~|i{T%5)uF9(lj`<(T0cr=Y3(=P3qOh1G6 z-r&6umDuRR$XkSx^k!E_b}%}?JW{U5nkdQEIbp!hcN4ZZUT zKBT_aa8pMI)9K0Au@+grrzE;^;`F<@IzUiZ1B@&F^tZbW@FQ zKCttz>N9f#dE)!$R@an5Rc9r$VJb#kfoY6k?mn2GP!|t{hyVRo{yTzmlqcJfqD&Wm%}s1zn|37ndZw?Uc#HIKe?jG zJ9OUSy^t1d7n917X~eQ@7;s0M2U zetK?setvRqkN%`URsN~djr`cH%GLe7CkxX_fk`{pilhFptxa@99hl7Q9_hJEzQ!fy zJ?@?6dm&M(`Sk{^n0*PxQFVN<-gm|h0%u!C;sP`E;y7up(>&5~0tBF+i_kZxTOT~N zR7q7OniZr5vH4>(liQ@IkDR3{DZGzJWO?|nr|0eHYBxx@2E z1>4%4%yU`WHTr`C@3KJrp^+`-Kt)eM#AAukD1$5-KY~;1!QZD@Woew(*2WdTqvch4 z;gW2gf~MCiSt6H8b$8fZU$3OiCmEFgVtp=NIW%IGvy~-ps7Wj;`(`#~cQQC?@yz_s zyo=4`@F+l{m^`AkBWE+^drRNRc%7J4ltjz=eR)WHV@O`g+-NwPoqBaJ|7=T{j95!n zd~VJKOYFVg7=S1asL21?x*>&QaQpmWF7Y0OTrJ28eCxtfZ{#THN3Yfw?VtydtUMP- zllaRFeIBUMIO!}aq)2*hS0DIhD!GNXXHO?@cmAcFOt$*gwDM#qDM0L4`;YCNk#x0y zKUwk*i2GIICl8j}(zUrBu$kuga@qu+Y}DMd@%nx&u+BuM)>3*SpwsiZ*~2zEtroZN zjy@LUenJDb&e?RZ`WLxF3U6?-6a#)vHfpC@vOMT?Prb^m5e9ZKk7R_W^Z@WF{b&;{ zssADkqohbz#L{{L4y(RuIyWuu8+j#$KN!gDcEFL>X(>SbpOhsv(;Mld1`!o4RRJ=g>hJcysQN3bKW_IeQyM|3bj%#ZoBi> zi(hn*s+goF5>ODmo4waRX=%;*QxAA zHGh;vs~RxYp8oh=8~g6b_fpDSvF-x}vooyH-@l5m?tI{>^T8N{ zy^s6dz{|k0BYvLkJdqUJUP?ujp@yux3y)AN0RCUEs;oE~?C%$1*@8>Gs#h2!-4z0u zl&fwisnDM5g(cLY9!9oUnM4#z0Q<^AU93eH&nFV|DD?m`_aew4syX!X|eA^TBUTE zR!aWU!`H|_IgglCL^U*D^urGKtzX~CLiW-0ABW1-T5 z{=XbtqlND2DO~i!nY`K{FDZms{L6$JxB+xaRkm@kIH$VIHILip2%Ch+>$P^vMN{oR zgdLRLr$7@nH8v-+eo#5J{0;x)i$&l6(R7w!QFd(?hM|TYy1S85y1P4+kQ5{&q(M5R zq`Nx>K|)HUB?L)nX$k3W`1U;S@%{0ahfdvlU$NG?PIWF2206+j-QCgz#J+l?$ehwO z;3HV;drO&$FlUxoh`Ppc<+jig%4FyhrCYBJrE{`aZ#)%!OBjgrRjcat14{XGR!gvV zDg#G{fyJS zt=%cj?ubJ#tAgCke%Z{YLc@C(lbSX@sF(u%fgBGtb6% zyVh|2L0A&D1D72t$J@-1wbfKn9-7k8)d$b}gJ)%5ZjSHf+}b$UC~a_a(x{VI*lb6Y z+vqaU608DEDxB%6UX+s4B_ImOb{whJ;VLbzvZ;NI$cGHGzY;D5!ZLqyp!J7H8w=T#bmP3@ya`oBAY6 zGgZso4WW45&CEq;*cypRmrT`PU&%D_VX*DjpI9Ws4Rs#OjDS=5I51cz7;m8H>guup;0qW&qn4D z2ev`tbU_tv-rvEpDaHs)eObnHl2BH^q;tMhP)+9~A`my%sgTiT*KWp2t@UWms1)Tsf?-B!nR*s}$_mKT`p6h{Hv-ft(5GKOD5T7$A$;r1 z1C|BHQm;CR0&5Du@Bv2n;cGBTh3yEw-d6>-A^kE~wqWKhA>OxmXrPp$098Q`#l>V- z;H669i*8o`A7@i5p{Q$gQO~g%xbIJ4?Pw6myCWnZ?lj%7;(4<~E9WJH+?WZZ!co*= zJzR#G&z?KzWvVFWv*~;u&B7aq{f+Y>Y|V7T0ed=jpFJz|Tb!7=^6#=rkgdK`&%bl0dCy*R%twN}qUH{(*Q zMH74<)m}yq0Tmdlt#=2A%>59}`E!ymk4dRY#Q%poJW~c`nnV5h!cf>-DL&OlHumBJKH>rL40$$&P49cZ4r z>DrxU-s?5^izn_XeiF!t55VhWKf1|$9LpLEM2~R(N^y2LlMjJF&YmnW#gZMe zNWh&CHn~{ji&`V~cdEn%WoChLAgo7+Njewr=xO!`rL*SUTE|BBVKI@0N5bEa1rpe| zE*Va4MZniSIj2UK4cEM6GY_BTw85_wQ zl4m;@WE9{PD~tgRd8Nuv@~HwFw;|4OW-Ab$tAIc@DdZ zD(~&-x;mblgZ9I1fM;Pb<=6H}Iq#uSUNgrJ=h)A<{>{6(wA^fFmgrU`mDxRYam%IG zSaqMQ>vKTylNlGHC_qynEL%2FDc)ZRS~EVMDcj!-p$t3pOZKlYjz@;V#Vk3WkgyUv zSHwp~I&YWiy`am;T%fP>K7K{cV~arNs&en7UU95nBR3$^ywBsMHUrIBatk5G%4QSh zJt%2A-yPR1?$`S6H^kcNO)FC=#gz}H+iW42erW~0=B}NQ%4kH0@|Igpn!tD*lf;^+P3 z7^drMrH_jne0Hw25HNmwqKela0Fe9v3zDHS)Zx*KWMI+!g0ZJ5A_9%hvN=f@2j=(` z2x!813f1Nrf>O=DB6u7u8a79xF#A-^R7;zkAIOi~G#5&04BPa{-0CV`;!9okwuZQ& zZsGi*%TawZ2Bxm?p6IDS-;n%=F2fto8|F?-6# z5S1#T=TA)OVs1B>`6Q<2H$!Tksw#8>xCO)OvovKs+hgaf23sy7b{!=vU$3~A!%YA_ z!)^W9l52Gy@9S{LnTYIx(cuSuinuYb1t|n=z&{;t)?)b>lG2sBCug^bb5n1md{r`7 z3%OpuEyBEyuz#+U+~p3hkRUs517d<}(!Yh`(s? z^8Nv5#=X!mkg>BrYKaR@{s6>og5eOAy+vQ#*dUzejo(|Lr3}?b>WN z8ZJI#3o_=x!2ux~_(R87#f23od`;_Xi|qKyLD&kHvUA|szT|3|a-{LxpLW+@myQSD z+8Jyf=7tY4Es0*fC=NS_vNJfBAmo3e2l!qezNx#26VUU3<;hUS)8b9!82B)uX1=LH z=4aJZfR0!B=%?_? zORVMHTpfhA^#95gSLA8Z&ko>;5dp%&-_?e?juI`B3Y|w#uu2gbUL@KY&1Zq4xN4me zj|^_b(%gS>i?&9_`~bwxN_wp$qZ@f_MDicbdQJ#7$3_ptl~v#GE`Wrj5KTk6hWVf>sP3tWCJW4Y@TN;YG8}T?3=Pr9?DNW30q+&ehR5-s8D2>Y%jWQ>( z?hEdB6o!knJ?XnbDcgt&0HhKLN6aj z_{^L=FTB_*UJ`BM*s@>F(~GE`*yP@vIGiG;*tkL*doiC37R0Rz-_e2M6F8*GXk{-> zPVl2nL3e_;@l{;%eLSVc->e75`nGx9 zd5ZyZJFYe*Gu);R=1XC1dApaB9&EQ2s@0@=O|qQq#x+9XZP!6JX$MMLe`pe)rQC@5 zNdFd@W|kxIS-;G}`820Wf|FB-W_sD1vG8G6X1w&KAmQp*!Z-J#c3%BBnW==aGI`>A zYWvPkt|FtU`K=(qJkgZ@^c=sO(N_(#(w^N5<$J~QJ4vF_n!r1C+)vBJ(Me>e2iTbY*LUF$dG#S&R3a>~JAtqK zO37b9=~LeSjxVL+m!QD5lW!+>!h>7^wcFHo((Tw&$ZUml$Y-Ddw0%Q3X{}aXq%#&W zWjI;&W2RAKeS3GS_LYCVdvufS-&v+^N(}CzC|#!W4#F;-kZxl$I)kt;0^wiMUK-*2 z!kres^7U5PHSe$d*4O6ga7y=h?&Qwms*1m?^L$8$>ZFZi!VN+;;>Ee7@)&Td4|P2c zv}4XABEiig*zdZm>8ssG|BkmZc=;JOwc=&k5MLGRC$m(1zXOvmp$8`IvQdnu!+sMt zW>o>#2&S~dd#3fVMQw7WjlvU?ZOe~EkklBhV0L+=p%u)eB@6NQWoUYB7Jam%iY_|A zk}dtwzuDDWwx%?wuY0B~z=gg86l54!$=QuWh#AsAr?_Ag`_rB<7)T{20j4hu+u51; z7$FDPaDf(2@QNurfZ^h-6f?a-<(6FFck;)hadotvJ!(6;RBC+U`383i>{N$MRaNeq z^^4(xmZ-JydwVaY)oz`T?If$ig^%8%D!C)F(YE}dNoC3k3~w$7AV{VOA62@Mp%D3Z z%KrJRuU{Sey7zQ7TCchOYqupme<`LW1}*a-=l-;+=^Q{Crsi~-?aj)Ss#Z-4l~1PT zS+Q9y5aw&xmD9dF-jA62=4@|qxa@3>8IrtIFeGl!_u@Y%?zcV%; z$jEZO?tZ`VoP5E%!s>)DSmA9xyIQ9w*DS|BDTB;;3(8n0AvrNI&MYWn;_bJ6+kelB zxv|Y8^A5~9RK02!@jWmejYD*-&f*VHx(b{<9=9oD-VY~+g{11WI%2b%wqw;~)}^!& zJ1BcwNSS=F{F~9&=(1@*#wT;THS;6O}4ez#$um zbbMu=|D|qvW^B5wZrZhx246DUrl!=6s$V%<70p&E{F4kq&?tfcLBQKviYjyrdvS~% z;lxVw7lYE`cT77eMm!Dr@r$=Wj7-^W%K1`xw z^wsnnnATE$72ZWl1Q>8_!?<;jsv7pW!QW4wuOut`YsFI0WK-pyop{{K_fD z0yL3eu)AJ24GW;s8njN?lgO1mFZpwtcZ#Z0EX^r@S?g~)j>2AGSLxt^v^Jy7)?F&5DznydZ;bQT-s4h}LiZv+eC6!{Lw4>}O4AbV zJxK;+?7gq0LrG~#HqPZACw{hthnyxCTT%bxX^m*fVOJ&3^02P-b_PV!pdzJq&4o=T zS~-o(1>dUe@;A3eDNRZ^Z^VB*GQA#O5iU9i`rDy%k@S#7X3LkhXr#%j!9^c$yc14L zt78>d%F~EzSaL(VK@^OTBB7~pyl`T3nN*V$Wq`aIivOF5oS$Op#on_upUsdt*0vIU zI%QZ-%kjc(PCAV8hMP)yt^|$6&%iZxkcE%HH_eGeXoY-$Kktcp>W}HbLFYG2`v{PA z)rfnq{WPp>7Q2^D+P>)V;8v6d#Yv z4_Gt6nfsg?#jBhT0ygwS_KtCs50Abomo|>KV@8%Hsw58Bbzi=V|1A)w`sR-jn^ZK} z=XpA_R!!ZJ;*|59S@_|CHp8xLI3)ertkoLDLU9&$RgK?V6R1Ru4YXnryJr`dQJvPw;VU1tTlYsd@O$KK ze{P*+$-K_iOKbf0JM0A-`SBi;D?0Y+FZq|OUYU1OnnwE4ho&9HlH9d~qlk>i*lM$T zJNjkG1DxUfq~tJu^vf*oG?nfzl*p3IF@qKc`{4Q}dSUUsj0>VvgvL1mdPz30s{iNt z>)Q@~FjxjglE}Z@v;IrTN^R;r*EIH>NOb4^qgTquvp{k(C@GBINriim_zho6Di2Ec zuZiF5>9#*}I{HetF7u6|uL4nZyb5yPO@tiK@7r3EP;*b?zFjQmrg@zFin@gsTOh_7 z%UEaNxuavH#OC?wLW%ugm*rC=Rbz&WCCU-hEWU(#Fg$-?D?Xo*-C)4KhO>XnmIrg}=xP)-L@ z>6FMY^MzWy<~)zepE_jCwe`Q5M1}uq)d%$?tM@JE9?a52-#m|FD9Hr z7lGvm?$ir>-0ygAV5WPW1gvKSxl$SW$uL4X9t(YmfRnH=k5QR4Y_^|9mLoUOZD}WI zp4EmwLr+87#yEmtdp$C2rTmx_O8JuhUmV3T&T@hRDH=BynD$4)Lv6yRS57Z&kcV{_ zG`5*D%N0sYV!q%{OTrq-z2lJMb5I&sp`tv?RkKBJI(ZSYmAsi5)mFKM#Lm8R&v!MH z_^t}@d5_qBe#f9ub=U7&J4nP~4gA>&F&#?P(kY{QbYpR^ktLAXf^};IyHofVhIfus zrdiNA{=C!d5G9mpvb-xPzsG03`4x#r=3M%avZ#5XHk-1ezx0W6SC8ZDs6X4=@Q|s% zxk!W#yeUkv1GJ<$LOw}eO-`JeLD(qTCc&3(p44b2bgf`?a*~+ozNG+2Gs~qH)M30N zqQzKQVK%Vc=>J&&TOctV^fvYN@3zP2x{)%%F%2!6+MY6As^p3^DdpIBFr{KJt7T}N zZQNd=^eMyiOHD&P*Dr_Dm#)5+Rrk4~wwfDSa^$zzj@*#9i2XBYPb+rtCiEVue=Uyj zi{S2(*4SJY<$KV_ADo55;SI`02deJw>(Za!mycwcPK2=FaTtan*`^@remTtO>cF*X zrOp`b{QK7INYFk4ys4gFw2St%Kfi53ae01Ax@}_d+fQ>WTF-K@8%O5oBeX|={VfA7 zF7EG4V9LO`zdH>S9joH)q?!+x0%GT0uA9Mq#r-O7FD47(Y65dMJ-BBRg{#L@3PkU|CDIv%g!r+k~E^D_kr2R_p`0UgAnf)I`=@>Np z-Xi5J)JDwZ4=c!Kc=k|k1lmOwvyQ9L#8T>Ex|MBCMaeXQzc` zgbf!J;6Y=nP0f&M)NOyxH;FX{$cn!G=|kw}AEY2A`!J0E_7VC}&`R3oL@6JQuY5Hw zos5LoE5l=fVj@9#)|yKDj^0JW6uf-0C7O+=gKT#DxYhHryX7?)wJr2Bg*9E`5x%3^ zGOXtS&ZPyG3O$a|;W5s1&ukE(e8BsZ+V^EH2P$GS<>cf9-!~YETD0=`yP%TrXxGEk z;-$*H^6PT&^SuinE`2w!aym8e_hdK|h3Y=ygk0kcoYY<6Z(Bq%%9k^C(Q95q5Wn>D z;MPy!5tT{?Uw_WQ+&TSP5}?T{94&i}O<^MUHiV!t9JXWW*RXn~rUD@)rz4-HN$NnA zLFnNwp7CSzN!i#!;P7=5=^{_$=tEZVpLbjd> zpXp_O-aYWj?lKR&lN)l4rO95p`BoVCFi+-;%}wa66nK1;$#IX&$I(Nw$4sAPaO=7M z+E%@l8AuMLvITENkDtt7HdEq5Fo`)}j|3p37H6k^a&+}?wdcM_2D1 zdQEmQgeQ&Gi}j7K&Sb{<=_#d~;;0JV-Io!V!d5%|)Q8M(cJ5h>MD1F~kPXyaRz3#h z)?Rm9buji=pMwau4d!oHp&AaNG6pL%8V^r8+59>PRfx3AtehJa~d~(85%s9vtptzdNsslQoz|_D{?5@(rSdA=Di) zi}C(&J)Fe;?};{MudqW{&YW9!)j9vwJo47xqv?}`E9w4#<(c75`)S^vSxhLXpRM5q zIvpz0J=^aBNM9s@ZWwB_+-|+?lYlq+43TA+U5c*hKe_35P~!Z&UHi48b7^r5j~c{~ zU@qJ|bW@&Q$x5k6dyihkz+MoQJ&CLe-d1on z{q^#5fp-wqANNR@D{LM`&MUPX^qSM6YoFN14k4Rvsj(Mio`7i;xe9oNSL97ayD{4%u+_IvmQSy+c6T7@TFE zTT+O@i~XW9UPy~2wIWSesj|#aW|h9@s*TgizM|#rbLqks@*Gd57q+LcD*w563w1#&k8v! z=Dr0xi@ona%LgmBsleqB33CEU;N(6;M(>EbY@q7B!!!8eK-OeC9#U^J zssVJYiTA+(Z?Bof>xF}Dbe|1H`bd0GTVj%(kVEvjZk>q)FK|WA*6@te&q5J1g2@MO zIOvE%TUBZ{vo|ElN;6nc()@x@Xx-yzx$8Q3vsm?kSm)q_(Ugya%`r?VjY~d3fKyDm z0g;X_lQ3!!-=oKsvqbX$YzQKAcjES;f#QAFrAhA;xCJ_o!t2=HwyN*+or-$P_@1+Pn_)_O$t?C`m8-pte+q898(z zNYs2#ZQH}276$8-Jmv`M8A8EE%J0bkojFx2(O8_<_SpxA$2c|I*eA+wD$5|CcQ6Z3 zu=SNoYGw;M;b)s-VKKn)A<&t)9Ae;|EWsdR57U!#+scy+)R2!RDhw=EEYV&7@?nH5 z%OtW1Du{%Rdqr2OuTB{5^7gwH>^Bnq}Z71SP3x!TZWO`K#$##!j z1+Y%g-75_o&Uo5ryGm~);!chIP+6|EEYev|SM^FC4S58TEPxl}=vHn#GH^KUCgQPH z!XDBG*jJ6{sBT1{`OAv16$0*0+~(>R80MBcM_oOHyfW_pOzWC>lBY1<4o67f1yyn$ zFfHn~G;cs9?YZ&6*aAp}i9Ay1PfxOcfdp*vdZ!<3mecbH-=yibjvqA>60694mAd;|m@mdwcV)+#f#gGhHJXi(o^boG3` zaAE>C@O>Nt<;0AJu?9tn!4bfX78>$eqn|F0*$?=lkmY{VtCZQZ2OP^cjRJrmnI+^> z6xl(;prBQ5%zu;q5x08eo6jY^7h8~gx}iT((Zt|yiDpYRUJ2wPIFXHh}PVlX_Zn8+M ztxv@96tk{B-Y24{$zdt&(!F0WW(bWnY4eMIDB8X7w=%6$KK`AntWdtg_;>C%8+Ol8 zFwH|Zl7Wq{p!x0N&+%8>)^L-oga-89mb=5}Q$$!e2qi26rmKWJ6wF~nQw(mCuX5B; zy1FwVoOVTo$NPi11#}wcV*11FU!f~Yo#G+BD3@3VR7}X2&fi}DBnHd2gx?`3|LQg& ztlL2=cbF9ZP3YXkM_p_{3O{e+7Kp)cbaiZb1Dv{c7c_2iWfRdgAGQB}k<>kLKft&g z9?2#{teD1A3|ye07y#39m2?TJ^TP$RFjYPoYkS7e?k+BcU{&&Sc(QtER=?VS?tsGK zYbo$vr%L?ZM&@?A57&1#Hd8ovwO-^sT6z80+wFhHs_+!-H%pDeO%808C*opOyAc%6XyCahBxU44EsbyOs34Cp8VZCp zV;gK8s=}B!$%=7jdeRfm(o^sLru>Sx&{I2q#w91P*zSk6pVg7+WZFXaS0Rz|(f6!` zoIk{xaAwWhpk-{W+BUNM@^E=~Debwe^ZP*zYI+n5!UEvD0m@ zJJ>O$r*v}C|7Fij$I#VHv?uU+udv^a`ha z5yZ_@g$bQ)m$(nzZeY(g2%MuD`4WyPbm5|KSiuC`%Xw|~bEl_2Ua!CvkNtO@7*SHa zIGSbviIb(VR5FydYvn21?d1beyS%{3c2d;qb%j{Cu`5N?%Sru&5?_}Ng9Jpx5M*){ zx&qM!DdIJrRMHSUIRdx=Lc%onet#sX0p=UvAz^z!`+GQdL2UNjkBvUnaj`KG+w!CRvFI9l=fS9cO^f`x| z{F^kw`As48wV@>z!3s*q0DgeqM;59-&OsXcVhRJ!aXFmo*?dGs7~-f;pxP}#Zcutc zI3q-uul2P;XD<}c{&L~C>n^u++NlLNraiJf{;0=@LCyvMULps=+Woh1L;??TBK`Lh z8IWE-NldOM9#J-o-YAeeIO&_6CP%g2MDtu}=JuXUEhZ@)p4-}<=yE#)QS;Gwyr|NV z6?&iXpH~|s0x6%Bb%ysI1_Oxp!7ViGWB$OarbI-Yr#`|k+7GOCcKdBjaNE1gQM%f7 zgU@h0E}@HYmu>naAjci>sDQI~jh zL}Zd%g|lwfO40Bz|HJJEAOk^~dh^?5VhNm+=1-R$c}qvLqh7W5X~#c3P$ouR3ETJh$NopiKlZDJDO0cBkm(&ivuRrloH^d&;?YCL1<#06=E!fHX&lQu=5%m#aao16{0Unn}6V`yaPobz58~Y ziRkv~eFUNS3#>tOvGT_2;<)aff@4~qPmJ?dtuf+Vl zZ}XDcS;|$2*rN)Ffi06DnATlNuOIrTzs#(_#~(HV>ZeNy7`g)~?+@(MuM2Sxw^sCgTOC$-6Ul%5DPl?^Ao z2SZ$C?IMNoJ@4V}*@g7C+Xtx&?w2Q=ZA^B|PWkCLgTY7pADfdp)B(v`n1E>5OzR36 zE{6c6?58CZH4?v_U+LcL6=-qPfvB<3cJ%6ySBW`PJoBw7P9F0=*eSF7FB zQ#l4`%=X@fJx<63aAv)P-<1?FMi6Q2>whvXw4W(8p{}*3A4Sz0D6kzb#w*fcQqKN> zU#cP#rL(4_hF&@v#)gl+8rnqt_y-ZJCz$dTxwo(H%g^?f2zIO^CH&Nk7m`^;{VrS)tlu%x7S!iSPu*{`RTC^BH{vNs}c$zKL6E|TMJ*St48 z@~M@U!FLx;#Uk)Jxv^EaVXFXm5_Eu;KipFgoVROjOAmf2^odN$Nnr`gSkl&ebi`bH z(j!qG8hK*MwPqd6LJt-41A#$(l%Aigz4CN1-5M@J`zR9|6I@8R?XJS!4(0lK^z6oIbp!mt@Gg}&A-w=P^$FnE~0r_|`6Ou7VgjbUC z#LEsr`Wt)+m#-K8^4$5?*EE{`JAZX0Pf|Tc3*H5BhlLll$`unHu(3WL(n}F}{)UcE z%DFT64&Mli*nIWRT)q-J8B5&#gEWs}AEq;iXU-KTls%8%f`yr9{2c-G2`$UXdGos9 zcP8^k!DUEg&u6~XUAyHTEPiL;qgo*`+G;^xQ_hwgWDE9{QK5CbqD@d->~(r&631CH z;)36cw_L2Uo0ztJ+OHV~Rj)PuS~RnES_-4jlk`^Lc3uoTc)Z>wyFc80MBW{fE73^K zdS*Sqij%=7O_2E1QUQd$x2C<{;^B^j2?Ib7;B>abp6%Hsgk$<@@fuR?@mOku3HgUl zYaH1QS!z#>uR>P4E&&NCNYhU-rG`bb)a1rSv(L+n#_WbsTq=Zs8V1ddVE`*qLQVy~ z9p}P|Wl0O_pk=P7_mag*aq)@t@+FZIp?p9iM5uie7r`#U5b#K)J%o6oUf*z^zcGMg zbMdG=ZgjNscpvyMQ-U^Cj+?)oT*B3l*wp%Xsd;vN&*JmAN#%ci6~1yCr1j~o**Cfy zLDEY+rP)sAgcF6%Lw4o0l8HnEjt5}vWuWvPSXIj4q03G|3DvC0@1y}75%Q;l{}EZ` z41NLJZq!zyAE%q@G<}eg-jPSwd)(oP1a~6CBD3#4%9jVKqPG+CADT$)&CFdB1w7VN zy5D~!oMP~)-rm69?tE*jq{UoSQuE{HjiKdzha!$pgurqAVW1yTewqjImV~N3hk#*$ z_SMk^l0TOF$|Z%vFQsm|l~~fosPje6@7V^Tx^3l*lmPSxqo|tIYoh$xiqTljK+IL$ zGdNYcQh=Pj3)G1O4kmCLq3EnqmR_B?H1VE87*&;tTpD^nr#7}Iud_siu6P_6m5;Yy zK1BSbl#mR3;E)kr3tUNEezJ;1_EZL0IU$JWSkeXiJA=2-Y8Mis9OYU&W290C=axx{ zl~SaB9E0_+0U<&D(^t{jt9|Hnoo*lzX4uYLC$#64Y3Ly^t`qIgL6J!G$qU_nvDNuE@IJT$xhb3`7r_yd!Zy0en91)zr|4Ss|LAwBc6fL)M>P$Zw?1*OSw zxzTQHNu4noC_BedZjIJZQr0=sp+zsEG8EAMSCY3Po2UK2tPPQh7(W9>u1est@1|5m zXA$2!v*`B)sRUVr!_=she!#g%6b#DfNg$nt+S4T;!=!ZPK>HIlLa`qED~AE&c?+qS zcU|2=xGWmn-aQbCuosS};tg&mf&ClWWG^tR`)d*M@-rr4#jT--6N$SqpyN{@hV_I^ za+pd0$bzMpsIm3}v=f>1!Cvi$6zx=|Tna)3EgS+RC4mgjP@VZ?LJ-o&vNXL*D9Fe(GD$I`hI)bgUl%72Wax6&2Q_UUzbr45ng0 z4vo{zRJxaQR0#jT5clbW5(b}R@UB!OI+ z`QBZ9HXhNgu-2|W@5E*cK_FfP1C6K+!D#o+*#CLlb&$;=5zuE)t8u{4N-kQtv%sYg z_+b4jhs|}7c8EM#1WLQ;(Ddeam^1bhVy3&{DKhlSSDX;gJC*}cX3V0FtL={LZ)1a> zuyi*ZNTeMunwc<@`qqaq-~YJqQZJz^t66};Bm$y*zL4_b2|`iC!G13>Apr%`gN3@# z8t=_5;Fob2RA7G7^^q;RfD;QpzNoP}ePXrR&8EBKT@L-J4?J0LnB#h^3ntJE7APZg znSNCQ7tJ)|TLqgcaBjdYLD}!GS9{PBjj@=YtHsfQU!_c9AnIvn2^VB+I#{$#2VS-a1c!J$0a6S6-(?`gYzzdD z$`c!F6jTV@T%4l?!@^oE>uG`kn>;G#8BhW@b>Mxfv_m#um-IR?RzDpWo{LAoB)PD( zY0H8}M6TK1<^7C2Ap)zvm6*JU@hGOLV|iMg<#qU&hHm3=4nXnTR?C#XO#L= z6fw9riU3nGmQvVNsL;#O9bGyAtc=zkaYiYa*Xa;+HEl}@3ST{AhBy$v9)1VR9yF2x zj3gu^ee+xIYZMWz-+&z;;gc5}yH8w{vtbqbwbWg4)Hrc)hFXCb1c<;3funjX^@+aR ziP&FXJ{w#xYalTkbv%EPgj54qllapwY?r`p_laWi;`<*ksBTMV%*Ofd3>#oKlUrub zSs(+swP!&xize6J_Idv|VPOS1fxS;etXiEp2uBrUh^cr3xuSv~PuDc8Pp{Q}(!Ci_ zatg^p6s8O*SfH02iUYcnYFWQf$;%80@hfO4mqCl_A;4jsjyFaP0niB;dSPQfnHwQF z|at;~*sVwNqv`_{H%!&DPO%?M)i?hJ-gH=$9|^@RPtR zFFjkk4A z8ME>*JLw=I7d#I!!}9F=@1ISGihEE?n>(R6C?)&1EO3e?6WFc7v#QfvpeKV zoTR^>A1f#?tHK$>AK|E!!9Ra;jZI8EKI9x50D{4HEw6()(B#*B5d4P7;B&f(-8JX8 zJytjcSVKXlck%(q5`hnD;3jCQ0t{nZT|oQ-*GzJeV!YFHDlR!V0TvLR=)h4BvYLR7 z$haamRRfHbgH!Z^Jy3&q1beRPew7BM#6^t}V>AGhViH2MD34Np32k)xlLdgx(qIg{ zr-%S)OhcEs2VQQ2IxUN&Y9fx#Xb^~@R7CQWUec&0Hw*mACPBY$Xm7!3{vstbXaP=) z<-)9i;eQ96pVX5*9vTdW&L;)k2o#^+eVv8F-n=sTL|Op~jgC?cV5ZF81N!>xau5dp zI~!w^1jjuHy22#D5P&?S&!5ZQ#l(~GzOM&-W1ipUNoa@;0-ubUqJ1t8I5k6YzCiYu z0pwZ;u{KobU!_R4{EpohzTPLqpMW`D3shkIy+jS&P@y;kdOKSCJABh<$NXa9^a8AM3TL^}4x+O}9dV87e@F#%@uMUt(9`6RYhT-_Y zFaL3sssMZA4~Qtc7&4aiK*ncOl8XER9vyc!! zhQ$B`Q;Zcwq*nKT{|ue;?lkB8*LS?~ag=jkqK&h_(MyULO3&l6Ca03YQwXhe7^6F> zBSloF4cg8-VhDR-%2}_{G5`|N>26R+ttPl2Ab^30Ov8frR|yp|*jRAMps=W>4OglG zq2^%az1!9h1CQf8-<#RG!V{{@YP9OgoL!mk%8CKR8|ynWwfVm-0{-rrJaT>ue9VL6 zfS~^14TeQ@g3oaqun9IcH;GNP=RUn;G6tVUNWnK&t%4v2DmU2^2868^KzDN`WVtT% zsF0VF?&|5x6zBuP2>hp`iH{+JEl>b)4dLW4Y8+?@b?+X4vH$Mr36%)A+YVcbongAm zgz+Itkf?p33(`7*M~8ut_WX-P)ogr3hY#kV1mn2Bu@W6qorB4u@EG2+u_$PU{sOK9 zC5QfNmPSGQHxIfId_K17M^fERGvG>>W$)g?3X+!7}1H_t{c$D2+3F0JX}H zIrHg%xGOy=^WI3jMxXOHGShZtGic7XkYgE#(-7x%}bTz#;B+0NCM!l)C);s^bp z29Ct9C2YNWr)gJ!A`GBnn#)+zEs*(Q5ganXq*L`s6F5-!q*uVBos%nywF1OaQlCD3 znga4_9+hLJZwxEz>#_hER|4APfBvk)9l6jtXA2f*;}IIf*<-iJSKlcBkpHt~KXmme zc-Ovo@MuWs?4M^0kTD~35{mD{4mjrw5?!O6{ff27t3@D-1EgCJe8UO8_Jkn{#JIww zKK%ku%nvDq)f-@78Xd%meVQwV5la_T*8t89yhk$*<1leyzz-wDX#wWjVmO)0B%}5j zgj}wZc?9Kz6);*-dXDX!=`)!e>4O&Wxy`;$F}n>vhasclP%44>HiqjjB}pO8&_rup zGt1y&(MDnzk3k*O_W&fP%PCzWqvLCV{E8l~VSTb-7);1@LkVj0Tl{shb1=*mE`L83c*C0WVL0dn-S2OmJZe88n3fNn{g0-O*v9&sH6cZV-)l@I!xP$saIWb_zVs}U*hR!v`!SG|5sC8a);SqEIe#S4$&gi_Zbr3ERHV5fv zZiets5qGIlJ@eX~Q`W<*W0=Us5 zbAydk;ltsdc16H+q_^7T(*Kkr^Ub*d9M7H5476Z)Ebdnc%J$_p;fQI7vI*F3YAEIX z$70=->SS(Ub(4DaLAx8T8eD>BfUZn#DJAwl_Fc{gglBIV8u*eupdYA2UtAfv|C<_Y z!(e8A-3U7X%ZRN@Y=S=>tJtahB&&42Gc__Rz$fYs@X}zzlK1>?D-65<9*B=Dg0d{$ zK5Jv7B9C||Iym`%p9%2IUHji%J$(m|NMI5nOyR}j4&0oop{UqJV4pYJx-Q+_f*f7UP5Qu1@}9DqbgUl5l68ZjKZKkXLd{ zOiZxN;zi*-V5WlLB8k-qd^#EA1&T5ASPsMb$fMRVQ$T{33K}W8l1RWt?9~Syh!9;P zTk=zwlxY}%MNWjEV6uYy;s>c-o%Y6Pem+PWR|BFCOwYb6Ny&gaR?h`+u)MwNs^XE! zh){^a@2k7ksSd9Lixv6|D1J90F5JScg^F0?WLvi>lX)%h`XeZwt-HF-dE@UWLH$FF z*Z(0a2wRvoVZG-AoKPR~4pmVy$>suYdafdhv_>9I2X6#z4~R`-#U!2%`SF(&Q4}`Y zWKRMI(I;Df^TZ?pr$r$+rREXQ^evEwgAw+wSk$xRBqSu-sCXK+L_PNk0E9mwjQ~*u z;tUEXIR#zC`7!%H;LS}0AtFIrp>;?JK3ZQg9yUJQb7+~}epg1lz3%Hh-do@{9 z8}lbC1{|2$;F000j6-)}R`UaVK_R*78^IuXOFYQ{zjM(oYBIzpc#)LC&oGH!yn4;{ zBl8!h67oGIh`R=PgM*FM@1@p3$+-3|hL+{X?iFwnOVL^nXYhgG+z}_^c~0Y%;IK$E zxC|f`f$|?nCzAzJ;c_KthZD3Qpr{=wAW^&c2pGWh!lt0a z!xnXA908PKvaP0Pdsw32+>8_K;shFxJ^ED(QZ^mN=LX^5*!Eh4kqg}4;Jg7R-<{j>@TWWiz?(}$$!_aH@-FpV5bt`dB(%<&GhF*c|ip}=6V!~KdIn% z%LzXQ9rEB@cdt9%o*@SFX4&SGY8PA|IfM`t;um|bnj9Bi#LJrJIZ7e4r$p{|09L`5 zg=R!St~YA%fJDw`I@z3!E?{lA4a$A@vu$ll4UTwrC}eB^{I|v#T_~-clBB_hP=NGU z#;B(cGI=6&Mg<5X)1IwQ9qD;q4-xv@-|z!!tVuT3`>yAJm}dvNH;WXW!%}d#YsHfD zhppI}5<1Wb-{An@okMNKIypQ87eom@>znUTte|Hil@ODX!$HM#u4^dxVpUwad@H00Xv7&+u z9GZXGb{175**Ck9H29jwI&mYpNxW{qWkCefa(n01rN8+ z1@GkY*-p|rpdO6D*O6e?*0yR!yt)QZ_j+&=<1Q0<1v>3{%+X3tEkU+{BM zYN-HtLl(3rNuQge-UA^DfJbILMeQwycN2zq3Gyunif@=~lReIu9XLSfR0^M+4qV8E zu2_4J5Kkq_JX|!j|6KH2YfB3>dk+w5UB%q@)iB-Yksx5Af!BTkmf(qn{QmsMn zo?k%8P_`sCK2t6HV;}HE?LgLE9DjF{dN_h&%(LI_$#q2XI2d7SaIAqGLgwnRRERiO z@AReaMK8R-L(I78`#?51m6`EbIy9^hYPWZA@QMEB*C7UX7Puw9l%S+ENK1*Nq@)sxG)kA0w2CxH3JOSy zh{U(&+zfs*9G7c-vIZ)G`3JzsUG2u>$(&{i1h*(}j zK)%s!_Ex!0VR*V{@3+?H36ZalzhwY|rz<^7WU6H6W`?-Solc^njH__8)B+gABFUH6 zUGKh12zURd%F*^Rum6ovbNBENS&;y&M_|uuFiU(SVY%j!9#Fm1Spw>(&zX#}#mT*pR zsm5K#tz4Q{tX0PRt9g1w#iDR1!MJH7^R)t0Yyv(%1#C`zb>j*|nFpm_OVceJDbmusX{vd6NEIpB{3#>w|aQRnc?60 z9(t7vF*&7j@Dd#V_$`(RccX;UVbD#S>10tNbi2%J9F8K&HN?erh`N6Lx<=6k!!q$bHfmb*Wi84ppfV*j8sHa zTzU7zXT>mC=lJVA9*eur&Q5C9uPGUlP&sr{tPFOe7yA zKnOM|{Gu%yh5o`D*vkn3|5|`hMv3};@W1==8uy{N#BB+Y3+V^#SYRNq6Ih{RU^Kk<1T zQH&WDQlirP6gJrWMzLB3G3PwUw06ocn%j+Zjf^5XJO1r7w>wPy-){&9xx-50Q35d| zqcA)@A|)JrM}FlLM&}|>>Q+bJMu{A6&4?@ZEdo~h#5Gk{2r-V%i~5d8WHYX;e2B<4 zA&kxgsUsVWsr{Z+S1UY68qlyIxHRem9gR__cH$j4E75mEmNYik->mYi@SZ@hzbf2K zFJVfMjKw$k*X>Wh_zrIJkD)4DeXLaXA)>EuVnRHHA|R6-#f+;WO1tPiz+M~L4nQLp z1e`i|7N!zd$zt~`y+%*R{8E_NF4J9ObXq8#s&~VDEzws>PgOK<5e;o{h9jjEMx!o* z)i|*x^s|eZuK{nQ6zc^u{}p$%EDsT)o!*qSF!HaFvIm-IZ#Ie>1-}Vp>JCKHU0B9$ z+G@{6yOCKwW;q>Pg^ltD>{CSq-*Icm8L{i*2-{Tq55V3~Zhs)L!%>Nk|Fu0b;fRJ{ zmdq<%!vtBRo2vuU6*(fZT1K+?(YU$9Mei@ar^_v*^Y364=RbOe@!m1xZW7zv_Q5s^ zh*Y-lSv`qbo|uWv`TaZL1-*2xs_RKz(AXJ!g?WP_kOBpO>um&`2u3S3pTgr%?P|60 zw0)H>#FebwG-TaL@WmA=PX~!tzkM^V(H>`u&$(HYn@dXh?y=dcj?WEBrY%BJ=qI4g zG1-Dli!UK!Wel`7YMBd-w^$M|Y9w=Q#%4l;WU=Oro*KTSly}gU!2hfjy zLwqTzcXb133!RTHMkM=^M=^-=L#wvNW@H8}{*?w9)Jx6O7~y+;mbymz7Z-y8DARG3 zfGXV-#XPv&ku`!XlwJm~0`cX{_%RFsGE@Rx5Q-N#rxk50!w6EIF9!1UH4Y6EmLd<`me~y8`|ma3i6P3kofD!K9UZ%kR`9) z6*uqot+$$erR|HGwShD8FX9}?o4KTAbz$eDG#-bFwcVb2d^iOxk%sa(^s;1XhX%OL zze33c1rae>D!9^JT6P_Z|Gf1f_16*7)28hWFEW;6oBHBE;l63KBhSB2t`Vcrgn|Pn zjLa)hV+JK}w)o@6#}S+dy2)j;fv3l*0Ds;9@k&aa#ltvqJ(YU-Br%RHOmJncPrINb zxQriQB)p~K!>joqo-P=UAYB+YIpyT!Y^9gSw-gtEAcQJ70VyaCviMzR{sWGi1BiU* zt8t)q5#)q)GdU<{Pv2V`aRDG1`Z{U&&AE_|kr>OH7qDFn6lIEos;^PBc6de=%Ma$8 zC4X;D8Km#8KO#0=^as#H6oAOLl{Ut*Fj}i)$4_j35>kp|3q9K6@6B!Yt_*dxOy(Ek zGK%24<>4D|#m;7s9ZEB%-q@B%fBM*A5@uSS6YC){uWLQAmaM1)%O1h?*GJ|hLeaBN zg2>wWKf({>x>aU;Y?UdArQMpygBNHe-S0JRIMpppR@o3_d?csVuL$Rz1qy+ZU_S`T z4u(ka&R8aq@S_?2U6hhA+o?L)S;UizW$F^D{fXkQ^!#xX1SX6y0yTR8t^xK?#*6{JE@%t3v9J3i;MYLi?Fhq9r0;H<`w~t2Z)5Yu%PrA4#tP_=XLHDQUI9RyskJ9f8Ho>04kIoCr%E}s_^q`mP8Mwb9%JuZCkQa4gLo&X?zwgvRD$NEDnZ1Sq zMxs2i)MNe&7vY<4rGqlVS>n%FSRf5j{rmG(7m}vu#*tuLa`{7t@MY!ZbL<6y zGPuCVL8^g9VoTCNc1%^IO85wERs)I-$|43BscqH#ru0@L|7Ro85sD=oMxKjtBJ_rC zzco!IqW~z)l?KswMFvm|DQrR;op6_lvum4_3Ja)kk#ZN_eu-z2b^tg{6c%Y3-db6c zL1s*z2h!LBWC&x@|6FH*vrhME`0~#<{V@PFJ2h|<7Q%Eo)kSuPjJ!Yuqz7VOmpi}1 zl2r|L(d7B@7Ut$C^8Q-Y$-WRf60tvU1$?3RAH=pFTqef7ab&)rf)jhU*5MQJ1p!jd z>&U!@dg%G_={}Oez!oy9xPae3?m96U0=Jm63XYwA9>`+#inKGZh4Amh@_l^oy;i&Y z8M=9{&foT7S}@sOTkDl|T*U33pu=UtA8pVVUYP!NUi z|MTk=2p&Iym_9Un;+S;S8_un9#w>tES=lO7xNh1Tfao=%h(3f85VRI_@Ke2ETdTP; z$Ii7Sc#N@2552S(FFVxDNDVinyhfcsa9u$gik!7%TEM#p<$xOkgG7w>H+98`(Zb5R z_BToXV^pyvWk8Q{O3aE(J;5nZMAQ8Qy+R30n}^p}ZQjD~DCZs4ipQf~{ zAm^~+0(;BoUJ2uress_`&VyHT0}K*HFp>5PYClvYMYUVae*J317VsIbZLrXb3~O4k zy66kRNLa>yORy)qFA`_`iStx7fyW0x-TKGN%`c&~SAi!l0WrM$HAe$!b;T^eNJ1-X zpzR~;r@IwQt9ijY6WHRw__!aFO!*o^_|-M6(MclNpBTfEouor?+!a}pdBK>(gK%Z- zKE+EW=CEN6{;Pse+KiJ6JT~+Q3%3KliA!ghNW&p988ywsvHxG%k0J>-M=$whXaEs( z3m>6Kwm~`E^aw$tKd=oF!wj%EiE0po<5CbouZR<>2V4G>XVwT=dS)qU505Qkt(pdc*j2i&$X z_V*(1;%ip`idig@64%S$$%0|{14x-KX58n?n+<>&UpQv5%rWt-J`{iex3tS1Ea&D0H6GKD;Dj*J&FjQ})Nrf%n=~TuE z!Tf?A>rj<+u3Z&-mi9~{`@HgfS@MY%xO7ATw8XYJ533at|MNi!nAht`L|y%Y_x`mv z5{OvU>|L|%nsxItK06`fCvXG4;u10blV9a9*LV%cWtC5@^=|O7j*26)^Uc2PuTlL< z45VJ1PFGZG@9tI+aobi}ORA8d#HHcQj&5xZ#85p5MG|lU@3$w$sN>{19|YW@dM2%o z{u2SS@zcJ2aA{X8)ZEUg471%NyGUVa*H-UipNlsxDZ}s`;Q`eBe_v(4!$_m;&syG?8kB@(F zf~+UG>SBMP$K?|uyz2SRj${{eMM76x9G2E# zRr)xMEB>7fAxQaaG#_tuFe4dG=LJ18yYjMbWVUKH=^Tm{r|t3inQAuP6)b2z8I3cj zKbY+Tx2Qmuosif3b>Ukd7~yPJ+AZ5qe|}+W5X=I~&%NoM$nR{0v@y6J?0k>U?vt9Q z`F=q|9Ein{(1>MMcOq_dFQFP5A{_V_8cnyuMgshOxK8PnO_0_anGCaW|ik zD+hzNWC5SjiB~%<9+Hd6S(OEUS^D0SV*xD#MvTI`H~#d)HQ5f7!zJ7~2~Vd>65o57 zLx80xP+oA=Rfi*C>_am|aYrmjEj9Rvj=Q6pz zRXT$0>;M3BY?$UF>d;geWb4U(CLqZZw|3}G+I>+tfL(KzJ$pw+vD_hf9j+eSua!=h zf))p*;p+mjun52%f|PL&1v2^2E1RNd6Vif4 zV0hz#k5Ne4X0pyY7%Ij9tD=_+YPKLoTa*4YQvxaGD<7wV<49&!BZCg zMA>1^3xCgA%|JImq@qU&r|CdqP<<2!xcO+ZR%%5RxWfqYxx}3(EyWq5N{}}qu3?8$ zrx^T{2LC_&3L6ABs1!Swx*gy&MJAVk)N_uz1Myo4Q%lNNSu@aux=fBcdk*2+EGw!u z9i6@+&U1u6uAg;o(&<|-sF$f8wF%NK#>TKF0Jc9jm4dMmNXmtdV@-W$I4W7LBQ5Qc zr5@cs-g^HHCH>cqbw$|}Xhrz&;}QQN<{$gx0* zcQ5+!MMhzm zygI+>BiT!I?auh!W*>9`uZb#tF0@onX|;=74}Fe2om3>_Unp@whezUDv<8@<)X7p5 z3xO|<_B}j2q_IPHoU0{>yaKqo(=dF$I6SgIY#0ua`G{T(XV;*i7G_?5H6)KnKrbqS@qzy#Z;mQew{%L zm6aD=JtLzrUuFR68g|2e`o10K$BK0Aef5+lFFQ~|5G%1xjyp$0Tlq=_fl1H*@8Ojs z3(mj-Z{2v4jF|8Grm;A}bRQOvVYN}HrS91H;7o8v3*wMVK_6d#gR6zYDp-j-E*oR@ zS2o;m4aB#|WS*58)KgyR>YX;MbWL6;T^B7(-NTqpR!Yd=s(q}0Bda(m2t?>TGQQ_Q zs_ogr2<1kx*iK|m40S9%QEM_CE+sm6ZppekhJ0`}eMM;jcy5Xy#l5=q?B^^#J#b3T z4lj;jb(^jO5w~z!$@2B#gH&vy`swTN?E?j`C4a=)97y`ZAdrwOR8^gxULwT>?(i|$ zzoCa<6p;JQTj`s9SnnyTc68V3vDw;)k^|%VoqE&*%Yb=Fl=IBH8ejz<;fG)359AN&&G-Dk;S@TgRTEAs~kvcpSstjI;@%%QSfg0`pd~-vx#KOZ5O2HAaJ7h~6V(4HdrAeV&8UOJjKl5}rkg}iP+;P}hy8mo6 z5@m?hLctm&;eylQr^;dDU~S17Q8|j!Lq2N!^h%tm8;B+|e9m#3$86gy3F0;bGxY0qvsCwM?-G z^mC1mc$Aa5w5)2MmaV{Hdg%-9+|3+0I^4IIVC~=VjN0%JT+&VX#ngB$j<3ef9SQd{ z+KZv?u+w(WadA;P3dd`}>gGMP1jRBt({Rry8A}`otB_;#PN)p9KUi{hfwE13ti*CT ze(te90S7OZ@A(>ntKEfIwz<(XdZ75v2E7pFVAu{HPtx-*3bLPyu`%Tz9UQ`UJ81Ey zv*7Zm3iMRTd=fiyYpKx_!5N#$#&bUPLVF--eZ$nv{w zI#`R4z>la%r2pd;qu{@n?pULJSke$)({;)|AE9=mGO7~~=Fpo9SgjICRZKz!O=x7- ztq#N^ytVf@6`-%Aw6n`6pecd zk(B&9OC}(+RJ6MV%KYFGF1_fVAqm~@frj<7O!d8oEK|e+jbl&|1~p{QqiVzTil5Uy z5)Dp!RMxSh609ok6kgWi`taS6raa4ZlXr#Ecg2t!g*%-tr0Dyp-RLGTg>)(tD(X2P zt&oW9S0w!=;q=M_^pfsub8U}vfnVj@{48nc@1QRA=L8Dg^Cb-w*H}AS81QkGGF3Wg zNJ(5>^#*ffn)JWN^rGS0FV032Du*X0`1d(H>R~wAZaaH1C{-)+!36LnT)9PFY>s!1 zl{=#@xT-UYKV-E1n4}W$7|JUXbj^FUu7?+m%8EajX8YORi`Pk0OWGmlM$&N2vH)P^ zIF{VeAeOZYj7G4nD1ie3IaJJEp<&o(mR?z2S0olOQ_5I?!kKYlE&*WDq<|53kRXNixpXGjfIijA3iN;vJjQS>r z(O3S#7_{u;xsTft@KXyL^5}B@PxU-GoID`t-?7}euG_E22R}Y=9v_@x0t5bp$hP+G z>T_>wpOd$L_#@yT9-m@3GQ^kDH$(o7Pj<0gVmAN}T_`U0Id4dXt+d_r<@V6d6IJrd z0KsC7SPsLyiUq1Bj|j~saf0nGZV)dor(AU{G5A18OOoH23i57w50rVcPog`R&pH{` z`ct($PBNnN0Zi5d0m=tYj&}9LTOJC04uQq9E(>D6-@M7bV zAqu%>L*+teKLii=VeBJuWXn$7H$uf#;^{N2>w6NyJF**_21c;Zpf z_oqt0LN*|tRVA92fSdWp#@e~NndNLW1t&!ib*Vv7kzwi0Xgs@{*gThuwH(^h3OLb> z`9s!(F*xJ2%Hm2d-@}4I{>zFZ5KU%scT@O17Mq8j*fnNy&&jb*f4$p50atct5Zpsh z^cqa^tQAP@P(@aWs1IXnz#bucci&8uf4;QM;JN)v=J>e#oL$QFz#&D#_NHb!HvxNp zdb(!Hfc8U;B_f4RzS7zn0VJWg)pM$w%=s_0lBTO(+Uggo)M-`X$T@nvBzpRmdARNI zetbc13^@x?2%EpY4U8t)z@$A`UVXQ55L9fi*=iPJCQ8 zBmJ>E^rSOjWAW*~gPmg;KNhA|-M|x}H0=&y`;Xd^)vILF9q=WjjIU2Jp`pYq5Q98C zJeML_mfUhtF?YX+q1?*lsXABG=zr4xV>O&kd@q{CwP3s;;^(>p-lz~%qopKi@j6b@ z3B7ufOo4K&qGPq6-cQCWDcnw`kX(H(Vilu|E4`2V=qQ#I)$ITK`7iTU74KKe!|Ye{ z7hcVH?q}1sJlC$2Fa7+oAoMTMO<<-865s8?3SuoRr;@&`iv4Q5hnqBiru56jW$2-# zHhFCIxl?-hI9=p>5_u&pt^=PX=8{LG(i76ewM5LpP4~P=U0fsqWagtd)UPyrHdy@0 z&Q-l4-TqPr39&u2)s9d#VSfEVc2D$?^e>}^0EVWaL zO4qEH08*|BQ*!)=L7Q!me#;8JjE3NACm}68d(bQMIy^WnjrPH}))!veQ+(ku?_K7T z%$AN)>Wp>zZ;DFWUQG)7y!NpxG+c8(-%va%>e1Bxbqh)N#B#<~`S%sGR6+E`qDlFVAmyu8lLrP*0?~rw!>!4y?Q~f3<(Jf6$R}Biza9N=Vws z>3U~~h$qBIdwNX}_;C?1m%CXTMC`4W+C9z0`uYy1670y)Mp~)dDkvEu?esIH1(;}9 zv-cj`A7$zP_mVEMI;$pTqfE3i4xY8c@JNt}%QwQA#750$ngV0e%g61$$RZV-AR18f z7h)A`-x$V|bDs&k8p??$yd|KDAH=PhL1<^YruAi>=?w3Q-SXJ5ji>V$wAA};(a&`T zK%188e^A8&io$RH8bTVb1MFtVfoP}z$UNcy>v9Bu8ppjtwW7ap8k~EFw9z4Ozo2N- z`6Q@6T<3(XG&22q4e1i}jHd|Pm9<*Fq^872VZDd>@(?UEwS8Ci!7l>ULY@3DuF>$B zD39b^FC4_L(cks6Ej507v(uY(us`5aEs90)E5x1tSjcSgbe|zlRIh}!WvtQ2>9t;d zXlduX4j`;~9p(Ckk&fF>7Vy;Ewb%lkVR$}0`?pRHZdqmvtICX*RJsid9a=k zuwjWWV}*n`5Pgj&zviULW51Pt)QlRPcLZ(z8J(H|Y)XkT=8mpP-%8<%j&{djr zKi1^C>OLwUp*qpO{F|;njZ0z8c{a$FlCf<@r9jW5K>PF1{s=L5SUWr`zBg`PFuhUR z-xYnWf?zFpf$DndrnwtS>X&rlJOso$eq93rR>!rD9h2`oqkn%zt=RS z#pfZN=^DpnTvp|L$VA86I`OFKQ=Wfq%ky*QeZ^$AT>$p0Apu`VtL%oAL_tKPavq56 zsYL9wu@Xmg@7kt9;MqwA2q2Z(&JKA3kM}ZOt0PpNmj9NpdQrpK(|(FsK8Dn1$GNVy z^GHXzq-VJTP)e3?|F?s@khx9&48i*zRCp+kVy)jp3HgD@A$i)&%GAt0mbj9u?%XL=kw5FyeGC|O}StaQ23SP!NMF$g4Z%x0)plFSx z#|rE)Gy2ZrI*~gNf$`3Xp>1DC;~I`3h2|H5fdi#Y zacPcm{S@ht5k@SsxE^f>ik7Zc7#8?wm^S%c>IS8GHvMp$dBq)>#Qb^aO$Sfli;)CM z$({XuN}c1r-S7aKoeUdcT13%=xurMq9MyJunAKo6uTgj{%X0VUS00e5rS>^&vh_8X zsVe&Gy7(T=G9weqX>M>eEgu75jV?5KQHOHr7fi_ zJnTSsP=zdx`VZG<^%q8QL5+m;BR`b#HhU6VpyAcaldHTXA+d_#x%L zb;T-FW6(vXV&2}o$d;;|CnjEZOON{ZH-Cr>GD%S@W&KuaLNHt38&Hr~^`Bkw-LhyQ z%3Zl1s`Pj(w(ji_@4?%tOLzPdgD)-O%g~5}DF7E;w;|W74PU>InL7G)u&840YYe zu>|l255)b|Vu(Xsgb+o#v^W0+68b2Y@8_i3buNrHGG=#u$b6WK>$0}-HUf+at{L>C zF*s?Z9ra;2uAkO21pctu+55Eq*XeQgbRZ*TQ@pUr;LPoZtfS{*E0^n(bKb}KuCAz< zOL@)bYey9fUu_(b40K;yn|r(f+58S)8&jX}%xp~RgFu;b9@`kX z5I{`}J<^69{_Yj)&j%$wlUX;J|;@ z;+V=_DhQPeSA9x9W#bU9fmq*v#Oy;oOzHOJjX2w06Hm9RsA?<8M9 zl7C)a5oCP&AYgCXMm<3gSJ-xh@l)5(2PXUh>gXfqeuih+IWC56%a4iVYL9hh7JUu! zHDAbHy7}tHsj7wjaYC`NY=Cfm;j}L$r5z0g3+^eUdf8+0t7wADYL=jkm_-Ycq$-Ua zuNOW8l0XLBF7xP>uZ0O`XJ=S3NMt#^&F7(}SKo!JX1JPt4iPQIm*Upg8Wk1)HepPia4onft!<_?9YNsW$M@^?X=n<*S!@ z<{zgp!yh-7S7T|@4~OnCo;k^#`TiyiI`<1rQlZM-sdSxf4WPuMAy%3u{^5F7$?PRC zQ$B>j?;ooOf7B+>``ZJzWTqT_|GjTZ80IP7@SW~=e;Lq(s;4?P-1a{|I(YlZD8oFO zxI=uqK!1WX;f?y0%?a)PcSGO8x1XPpSw-&go?N|k!xYgLSiE!a(O~83^V{sIg9+D? zllTrgFq>vg46T{Vo)ZLtW6g(e|Ngr+kT^H5p2s!(wVLKLhgObr$!I;d<^@VTa?2afo^Fi&?&)Xd zPqyX)jPuQREwmCAa?Tyuf^$yDvFQzpZc4!Cre;%-#5La^5%K_yirriXS6i^nLWRa`!gZqgAdMSnaxy% zGsLP#%dY0v{Yc~j59P9@eN^kdy|bi@e0;)3L!3)6^)`XEUtQ@&M#9ZJZS>eD?T<;t z+VKPys*XC#->$B+PG#&E{boeFlz=>XdeNWpF-udM%OLd^dr*&}}QbE%OOQSESs%a$9=CuEt9n4HC-_kn27h|Mp5n0|zcQZF$45#`NEyFJ)Q$XROY`9Rf=I((qV{{)FxT1faEw z@0ul9q>=CVs|N(#Kll*e6^F`?9!PX^Tih}6Jp0QNCHYKZYkXs;D6C<&GI!EV+5dj7 z$;T}tF4F4N5nQ<~)!Q-Ybg$G4BRIZ#CVIb4ixHHTYIe+>mh7__GgIm0HmC@7rx2g5 z&EgqR88R`Y3O)09QlS3ITd%@~lB&YQbW6fHqe)>4Mg3aOaLbxa<2f>dhej!}zgxdb zD}^Nsr*4sjZTJNw4CB~TvGMtmmDpgLM-p^(l=ul`bb z?<2+Lw>D;Qn|L%6=vluZPvErPlkQuZL~4%n|LZ}HpS&ZctF~1%)NUiRIn zp^6r^JcJyqOuK=Rj8y1O0x_%-dp}HFc!DPZ+z|$2IYW-&34w`Ev~oao25zTNP1kLz;^^y zEPtTE3y>%OevA#QgIezCcJkRhiI`jSliRs+1^-D2=XPR*5EnsYp?Nary0za}@qOA=d$cs8 zzShdI`wa?2%w73E!Vjvfrnyr}Y5#?xZB`q~GZ3$|vj~$(hvI#1{4tB0qD@;~ZhcS? zW4mW>P;gIUO@EEaxBVjhGUv0-`MnB_6bYe#vq!wN%+J#`4NYE)S3LEWa|)Ke?PBGc z+)VEAnL(*)tZJ~ zx5tK?;?AuA5|W3rPd?3XEYH2WlpxWly`-PBux;9CGiO?T7+j8adVucl%x>wxGdRs5??3n$dy>6|c z=AZrnO%CMK@!S7X-uz>o?dMl8E@0SVqSUefxr2&A)yy!E!Y<7Xt% znfM2Ojq$G5Z+YtKQMcUuf{IiGq~5ZpiBL6!q_Q^fygcIn7NV4CtzWG(g}Qr5NGT>; z`NqRacD6Ul_k~mB)Q0rGYekx0S>okmcbE295lY7$Vmz8*2-LXu8gl;`BHtf>$}_zF zOhqVpj$wQ0ZwfD`H&dWe(f*T@l&dLLvM%Oviys8$9(T6Pba2b{Z*zWs)2jRHI$>B? z5b+Rikl$*T-0sa-DHukjWB)wRe6oZ|zxu_AeJI7NObb!28r-kK%aa2z>HBwSHl@Q_ zQmibAydXKPAc|I0R2&mKhF_2;nl!?d4&UJSkNs8?|RZ4aG zXrnqRT85&Eo*ue4Mo5g%X`-;xC{-VSk0;;tvJ{Vt!)vB zb4W}b*D)zqDW`wsuH#AfCzW0)Xtss?W%jEumkTP{$(40C5qJ;Z6wa1tMQ^@wQyb{w zTm95R_9%t9+JKc^a6#@d`Jcxh`mPwaT`b_@WonZD8g2T1!1xBo&{vyPfmk%!@s;{m zsgtRXnZ{0<>dah%yBxg<8&7?TT1N$QcogFO{m<5q_}}_V*_y5zNxXOOxy|`tXBmnt z)5SgMRf(CwA}!7k*M|-d=30f#lY^K-Fjl?*Z7TGJodG+6YQK=8HYn0o0FmJq|0{{| z0WUv5EcC&s*EFDnYaSasn*g!|N~KoDm)a3*hHv;{(#83hM0Dp|wR#+*#SAMI$?H7a z3=LSthKvi{Wz}m7XEJZJg+Cm++n5&l*M=TBKLu4xydYVcuO!<2O!5|NOyrH?P|3K%iMRGfYc9&E$KK|W{(>&2yb%Q19 zZ8OzJ1G0uF-=rgabz`GajCiyDhWg8rzKr6+pdg<=A%w}?x?`7AytGzq*R=+VR%(>< zk|>ycSMI)ItD!Vu&&cl3{wVm4FWy>;qlqlZN3fiDsbCiW$ij$ZzM+oIFLK?msPC#Y za{*P1Fk6to58)#5SH8_ZHCa1C9?*XqrH3v5QSAOF}#5fd}~NUbsdczW5Bex}g<*fe}4( zvdYCmGDhL-|1`TkX)HWIBvGH(^Kq(ug_L5?U5ZI5h1W+P*|iR(oOfnEH}qscsdJWx z_oeD`A+2Nc`W~sK72a;D@a`($_#;5uy!3Z}A~Awd%kNZc2An?5V>yWJGY{52kf0UgObK5#1Tne2>)a`Zt5g{SnbT zd@~VAcwyapNYJ!AgVX@CR-40hL1aK+;8!^>sfVU6AK@*9ec{wCRL@ad*MG;v5xAQ? zRCsRe;An@8e^+ z8k73-QNXD}!1q(!@0YUTE7d9rsiyR(NLD+MUC&flgCFtCUuX;36=_|cWeO@jO?jLt zQyF#D5UdGRU?5N}s_sR&Y8RvBbBRQr?|spgQ#st6GD5P5WY%a9BO%Qh#+`mkVArr# z6XH6bOr&~y5;8}|zlinCB?cj4-CQ}Pu=1hN+TLF7<0ST8tGjHLEG#;QGqevotA&Ub zw!QHI8tfiLD}6mTQewLDR?8BOBnkgR-qy2Yrwx*>d5a{RRQR_o-nl+#v2cn^Cz(>t zxi^I&j8*C^7-h3mKrFROLJkj9D$;xZLKgI2yf&(5AR2S)s#S;nWGWA3LICqdad}sf zqm$v$oL6q0Qd`hz0;E>o?y=r)IN$j|dRfAi1uA`T2xf*A5zjf~S35r|PcaiD;1Ea% zhS0**5F&U0oT4j{hHW9-#A`h zCLd3u_g1{l3n{csPn=gmloG#5HIgD@8%7gOVv0&aSSN0E^y~aqW|5G%494o41izEm zG^}Yqtwi2+tH|JRQa6R$%Aoi_4kn0@+MxhZ5*H&ok#F-knxH&p4q5DRszmKGOn|8oPwH z$9~)t?zaLsu}BE7Zg79ZYDTph6Ge%6gK%?8i;(}JbCbqxAS!C_f7P67oW6k~(MIgD zvBdPiqE+d>s#$iYiT<|0U6r2)j(PydG#k`V#Y}KTWaB$3G3yRCx}34B%j#@i54D*g zSzNz+(N)QS|MN?&SnoQ$UP$m(fyXjYwq;A$FAL!eCbD(FhTR?PWZ4Y*s`vr-fY;-e z9rv1=p1!}VQ#G+V@D)g6Fo4T@Sukr5+Y8k2&QOX!=z`ItWOA>l&ia82S;9BI=$&`I z19q=GuM_$r{|wUU)$d7j8J2Pp-uAobt3@Th#1{RVh2K^%Ie1e$`%orc#9wD=@E2vh z`}ZVa7jBc+Y(K|dhy9uNCk4hqd8zC8&KkJR3qg;BRrf zx1G6~i=@Bi)ROLLB)s>*UEwhx!>>*A-aXmjPGN}l48r_;IY6~mi>R3EcvZOOdbVSd zE$4b+jr8y0;@m||1zwZaRIhK9hk}~=b=v&ki>2)BTULN-mw?|-$cU*r{^&B${}zAg zgAP8akw{)7+?s@Q$=Km^CHM7YTFm|qs38ARiRGBHvu)Yu21Wwe!sS2baaMYT#Hm#HBC zP>j7}0up-$9fmmK73CkwL)Azm4WB92KpD>}wknz&e4>*Jix`-%I>6lJcCtc{{h2C$ zA+PCm?@H-Shea0;Rx{kKS4=g2_DVF{o6|zll>ah1%vr^wHNL#n5+B>`iEyfS+!^(kJL<_>WLmpY3;%dvKPNXM&8^CquLkT~R8D(O*u%qqXCcy~j= zk@demoU=b|=ZnCnse{4$B~O4Bf^ESWiNM24{fu688F?Xnv8^Vk-gOs&IKg9~d+~}* zE0H+oj!A-0G3WJWVT?iiU|#||X13B4?B?f=Jf+Fr7MtyVpQgFWe$cKk|dl2gCdUR03tZ&mHC zoX7}_xt191nS{A*d61_7GCy;PtRVgwOD^-Af5{6X74=cPS9-H8)ZuHoxoS~Y_YeCv zLqPJ6zCCQdv$uCsfZ)RmPTecNfeA2D4s1o^0xar8p671GSG}2rgd;SF6H;LAmgTFtLiz}$31@+l#(~1n$PuFAO z(sYPce|~>{1*#ccy*<<}{2_+iT0HRfFZ}os4Y^cr(v&*~z^b;jfeFc$aASr1BGO%I zD|qdde7J$VaW#BI@!wgIUBhM%ud_`@zl{wyr_StJDy2bbm8OP2dKD!5&)5|bh zMC|OiI?p%L0Xy{UT`Y`EvlCSCqET*tc`Lwc+V&{rn+d@rT3|{gF>SGBk!y{DV?2eF zFEKCNI@M<7PoxI~a;bsJ8ZC_yVp?^vcIIFc{i(bC5d z>S+)I4(P%gb{{UVSrQ>;8!GW_&zZru`h^)e!s& z@+nAP9~Rv`6Z2$w5Lklqi%vbt$({#0Hh}&@(0Ni&!Xt;o-c0;<7HKLGLs@;-ue1lw zQw6qFa=6iMcbdE&tcqsJJr2quJlO4Je#4o&R0bD4n>_YU5!vLs2U*j=`#kH@k~UiGr~TMuh+U6I_FR zZo;Tjvp#}BbQx?}Pn;dA;eR%Bu-Fknw2K0y@I;6I_fTPL}#( zI{){B)a7|`!66b1s{J2&Qu`{?4IZ43Oi%dtq1HSNY%PX}g9g{J)WTWpZ+RgU35&cT z%Y|PTniiJMrELi~`7@^BP>zP20I5q+Aah(O&JF4W9eMWsJ32M;*-@Y1bGZC8hFasl zcMETL^Tq<`?-J&)@s!hMRPnlS-dw`XR8hg}eqId2g5AKP#4RdBl9e~`$J`<=DOxA$ z|9!-HN{FR5D&2}th?El57w*ClwRvPj_T-j}i;MGQWk>wY`oqzrkAK2QWwA~J=L<{V zQ5YP3ATrGu_5VMt=h&wr$t$G_^6TPny)`Yp?ds~9^5(>W2my`*c}T7nbeX?yMqJ!O zX5Y2l`fu27*^Pz5RTPU0cfwi6bi=t{3sFUpfGmgL+8!{tSikL!Wm{NBQb->o87M-4fA^(kf8}Es_B+`c$N$#z;c4?gCSJu5q~CxibZUKa zGzSTa@F&%_0}yviS7KWCT1I7Yl7k{0s^=piU{DC(Q+ai?>qm8CG;)PQyK`{bUHp?W zxyf8Vvdi4~OqTaf^JTy=YxW#AbKraP89QiXa{a5J!__EA!Q!8!eRg5)c|Md5Ah3-Y zt^;GH&!27*cw`_>7k=9bY#J17I@$vd*32x1`>0Vn;uF-jrZm{mY_ScDvE>PWk)awCx0A;CvD<0bld5W>R_FLIUG zV2M$k1@fp`ALVeuTj5obFOdIQWMD zmWB^s9fy#&(Ml^N>brB2_I)Oa!KbL^fWH)AF$BeujA57HKaI}BEfx7zJa}phB$?q^ zw-pfLl`2;jgB-+6!WT}T;-}~cB)D*o%_Y`5^_@4!5>AL<((i_w$w=FMBMuQ2_z=AA zhJzj&WnGGhaz%Mo+)q{$Mz{WL`L_D(Dy~*S#3nn~iuS$mbKuf)^+CkZtnO&_5f~@Q z!vkXEFauvh)9RV`$4Mt7N%GsE`*N{ZCZKS&Lm2XA`#xIE$qG-ifKZxQY7@YC+pP#j zdHb!>;zQNgSu!fNffe{&`!N?@Eg`f6C(mR|=iO=XgZvEfI=YSj`3NTyg4w*N3|awq znRYcKQ9;CO1>5PzLzU5W!jPrzSROSvFMCxRI-mKm?0n?R%>&2o&)nK8EBVCO(~OK3 zPU7Fg(%W2e*LU9}JkjNa|5^o4iOObx&({!aE-*bPc+~)k#nafLFNmQmmT-XycW<71h8F+UA%Zj-FbZp6!Y;P!SI_LCxvfr!1^okgUy2oN_R0u;XcIFKbT zx*q5(9+43{K$d=+87^_G24r<3PehQl2k-ZwpIV6WjpfmCGHp_g=W%s1ekb& zoFqYprpbZWlL^>J7p4a_223!V>77zaMMPhDuK1OQHk$~+*bv5b6!?7nSA&^Un>~o6>BEQa60xRj7AeiTH zKFgQCG?XJ+w7UoZkV-_3ID*fd!T( zSO-mDNMGJ~Ii)BuFqsT4&Sc)JrBqT_@JT}0sVCh@Keh)*!8R^}9!NG0ljJ~W+!ILe z!J3I*R!+`YfI(^Wau9R{ErJ7EOY$IX&{M+4C|qgTOQO$*30Wm(bR z3mh2->#^}vWUm>t$yQ)WN+f=6FzOZJ|G?}CwAG-O(^4Mvnqj!H4<#~3g!xS>-6PHV z+Vt^Zh;6f-n?DvD{!WM$(DHkJyuxH^pRM~+hCHGk7xCI8SB$57ggA#iY5e|_`=SeC z6C&<^^p38}Lygqc2nqDH#pyK7&=_n5Z9D_>Z~99d-g}}3l0~*ul)E7n%pOlmy&`7` z2_)y*OLiX+y4R_dZueATuY78lx2;VG%)wvcd%kh=*fC?4GIdz4 zs5j(DL)YZe?ruCdR)K_t(QS~WAbFdpdO9L7W5fr{$7`xDJ}iq>?djw+oOu?87s;yt zIh1b6k^k|5(TjWDN^odtFh84iD@IJgWr|i{xO$bCl%xzYf&I;hNB_eZv>~tydkxuC zRsMoQeKrRByVk1Rmo3VQ)-X_u_1GKlcIs~oMj2%Vo{TL3MG_nma%DmACo|>(G492S zy?`AUl_;l}7)0s2wc3GYNw6fm&+9op`4eAD(g0y#^bGR82xTIHNte~2-|w|7)`&6# zJ3B5YS2|&!v?Cx;`0&14@7YZel^Gp*m#95+H;0`*HeOP$fkh;<2#8)e2^BT)FEl^7MI>a(8plaPi;EkWDK7j} zt}v{@0%fzFs4#p)J5h}7D7Z+Ous1xcNMhqg`{71H@QfPB1`ANbru;PuufW(05{T}Z_Og__5Vwoaik#ngxtLT$@l8``5NF$_nPls3UIXPT*rDDxP6ztsGLoDq!YX{b1 zq}3FdDvtfXkMbl+x{m$!d%KS<%&ySPzbahgJSU`_#6r164Ca#QwF_w*#>h4Eoox?F zYyM}aht$w{0IqPMP?DRmc$1CC^2gk&i@Enc z1m)+`QxL>xKWG);+vhZ{-e?XS$VEH&4I0I)GZ2B1&RCV7rl%$pE0sfhS^4gVIa-|&SL(h{X3TA*bEk&2-^ zb!2~5=>GW6nz50%0&2~ox%*L>xOH=EN zyF!BUCmXy+PzJ7YvM!S1-RjGHzGwr~qJsY#RH z_s{IusNPN>aIV7q(HG6lqS4coi8?u^U~p%tZ$bKi1xjG{4UZ}l8RdC$FBKJadB6@B zCBenT?SRa_2E1|?&TA>>UKfN27Xb<_nWW!vPJ|ahJ-f5+_KL&_eJJST*PN*VRf3~D z!IpmFUd6%Nd(fIYc{%c>*p(mwhY?EeObT(AaVq@8Z(@kF`pVCfDDA#U?y}9 zT)gkhzaRls#-jpC4M0&Dstn@drVB4%%G5b@>*FS-_AeF24YJ@%!1&MxQh>4S$dm~9 zhT+IJl$(wdhp5t|dyPXW@0?u|PY~cuW^jgi3i4zx9P3@wqAX(PfET59*mY5A5rSJw zPIHDwG}`0%z>br$#gq|W0jrUvBbQ+Az`Jj>TdNup6v!kv;Ss+Hg)X4zMiS%glW#}1 z6GC?liLq;*F=U-ChU1q_a!;g-ViLm^v{05+YK)#H)b+)z>EtWQk(gWxg8D{DV% z3P=dO*kjP-b(hf#u_FKa&r68~Rs+&wnn46~f^3=shJ;k__r(d!!_tj5I-A)2yC|Zq zqpifupz>bw?8F1X0dcI?SG_c`z-F)m+!8M9-jBWs2l_Sw?rzQp^(H4&03G15c*)Sf zQ>z0tb_|vc5Xk-6@kuew#mK-6!Fl}-(PyuYg0tlW_b zA_3RciS_v+76vh5QtgRxrX{MWa-$H$>T)*an@R^e7J8a%v}=7hyEpWfBFWgjV&LAa zfUD_C<)VU)vO<`ke7r)oJ=YX}@up|y*#11h2-qtPHFFdTwUTrU6 z;(-wUJcu{mK-F!V^`*SoYjJ$)0^8NkNcpxyAs$laCkz*E#CEMncRex(S5! zpuUPhYCWbEv#lR_Q30No^Yt(&U6TT0urB*oiVDB{!Yr~_v ztI!RP)H{2CtY4m^m_u^?Kr=W9)m#sW=qM?}K}94hJ9*u&*>wpErdvF*3PjIht7K(xtz6dI~KF0?v^Yim}gm`e6kce;_9>3Lv=i6hB zSO*$U@u?@K0uNn@Px?;-4vQ0aqxwC)H}YvDdr){8DqorzG;433W6@R9@|>rfrxH>zm;(={`XSj1ACk)8{_4y zE-gDA{ir@YJ$<-$E$}W`!aOD1HU^2#rW2Tga6;jJ44@%;JDrNmYDsCo0p;>LoJy{) zSD_Ema*R)u8VLs*nUM5+ZM&XwLF(60k?OcNWLodvVPZnRjqN}RUgdMc$U>7EYlT=E zVRf7`8IsVzauuljr_lGb`F^=`-VRt_mm$Ir1Y?J%|pEMoED&I`Lj_W9Bk2CgLJsN~`TkEXsTTE35sYRz-KMLd|%N^$#Jr%_`A)H;?~6BdW-|82qm880*#8Z7R* zi1F%pjV4>7XJS-)PM#dk*A#{sPV+x`c9V7Oamckh)9*^6!z`0%S#`N-zY@sR07u~| z1NSdaT99nU4Qce;UBKh{{s&RbW+J++;5EGnR{-1#Z8ukmE?fvhUGrRH5~H-nXC6=h zpSc|0=PjApR_mksSk3@o(PXRZ>keg%qD08feL;(CvZj?0L92c-hW#}b`fx7t{$s%B zc-cyClWfBwzw>tLw#H|9#h*m`$X;vG%t=chwp|&&6U zyMmL5Vra|Nt_roNi;W_41I&5VV@<6zi;B&L9t#XV6rt;KAK*X{7#{TjNjLFNA}R-B znhcn4R7g_d{N5A>h#Du=Am5|u65^@*T;3Ot6cy>FrtycsBGEN*FL?+rU)S9+ zz2^9?!<@<0l#Pi&_=k1)8kA7w>(IK$6&Q#eiUC7fBp5Kc$Z!b>rnA^*jZEU&6f+J~9@dSbJn?_gQ?4`I_x=lGz;;5MJm9BUIs~Zp*0T zqy(atNFzL=4!{;TncBe!Y^5R3p#r1D_!=VK?)<>%`8vb&4v5hV!Y7UF)|SvJm)dI+j>^+4i8Q&^bJO0rq{vmMvsnAy7P$OA2mQRVQl2innrg zn|7IaP62T?7>Uf9F{Q&S3^NryQtM#ni>R2uNWsO$fVDx)XO97}zKu4G{-0E)nkcAy z@>AN&q(DjB$RbC;&m^?8gi$`WRZQ;nx2HzTyF5%ENkinom*d>h1Xl_E8mu4yQ$>K5 zp_3PsIn|xSquwe#Ovc>ezv(e=M%dY{mg|ojQ4AW-;L0gei@PIQ+0cuRkFV{$W!*kv zO^eAl!J$XvFW_!-f|!2qvo<5d>)^bfu!F02+{Aos8|mK)jQw+NE%dJP>?QAhkD zI*Icb=s_#4R&NI@r5>hVTpU_?ceJ3$7Y^v0ldKGkJ7%nv<79rbbe5P%$izrAO9-sM zTN%za*f9p+FgGdZAx_0oZQX;f3+C9zy3<%e@)}|=ZdChm&p1>)f5$~WKpU>HUWF;B zz4Ms;>5QYLsO}2En9#$Ny%*dlhNxYTwuJ)wZ9@14k_58b7LX>#e7nwzT$pg>$74L; z`P#&q(ieu?1{Ct-h8DoQu$O93?3C4ga%JD>)?|5RS2^O0wYamhbM@eQ^kcUN29I(h z{7YHZV{HAZ^vWnv5%>hiyCnpEA%;8WOF4^!HGCLxiCgbc0>*FJRp6NDy%@>3Z`|r# zF|c_GBw@yL!*7Ti3F8Rb8h@GH4z|?Z{{CwKIJ6435s72kj45_a)*XSEdtblSXGW!V zNtZlEmUZcP&u*+c+0;rPC%GkXTTciq0;(9S<< z*7!s8l7%-fDz=h2MJ|G<09@2KSE^BZHhgh`>{UoZWy@#)j8SuYgx2B$#~M!V>I|c( zE}_5Q$b-Z(k6_(cW8{rI7P=_`2EIN~&zcUr2Da4oH`@haFXH0HuOLdujC_Uyvzw9| z;!q4mzTP4*m`jTU%KHeT%OHsju7L!2#0&#>{0AUeL|nDGEnd+APV9!N`tsQ2xj)Yl zs#%}^RI`4gR_q{1JdF!!AhkLV2bEgTDMg!y`#p!)Z+Qr*s|XTZUa%A)Ni52e79lgZ z0-|B@-^|VTzaTM+`Lnks@ZJ^7O|)a?w0Dsu;Hn^~pzCedG#*fNL(|WB%;_G=b(2?k73xldT4%7!1Ry#>#vs zled861#fEsFsCjnykJyr!?yDj>hTbiX%OrMW5F^c1|efz%{c``1lDbr?GL-ckvEsd zszidx?Q#K!TdYBV$JpzV0JLV$gnY|Z5z%PIOeq~qV+Z?r1FdrNSN^x6K66h-*y5*G zwOfpbi+8 z?3tDDVg4rxQfzU*Bfle1^6-w=FEFwu4tqNhQ$7c`6r<|hAgq7TkK{<_RJz%JmqZ|X zMDik>e>%gQm;|N@s{=ugtaOQTqU=ngMz+w-g-UQC)BFAkCzfM3MmH?<3 zMxYW|3!$PDR<6L9-|O#7ZpJ`;?d7P(_(hm<5+qLmBPJAKG5H{xDcig96^&+FGuGE4c{!&t@P(gqdBujBKDETUj$Vhd0y}`izkL1Hl;;k=kxR!`XE*4ak|U z!VC;W=(@5gXVrLR!(W!TFTa$qzsjobt)QC5eaXh6#1x{d?wawn9=@=w)vbX;ZYxxWP>6|j&0g_miy=BUpvmfsOcdmxTNWSz0iY*a;y@epxBe^EMCAB{Oadt zF$zf`NsrXrDmWcoZ{PAxx;!=Pj*g)EQ{@?A06anHct;lNJQmvLvX0|8SZK3*Fxl*& zq0(IB($Yh&Lff?Z%zfN?$VFjA$c=*vZNQkBYQu%zyYl@sjT23OFl7-SL)wZbB}XD~ znQ!#g_|rspdEuOUsYT_!Pzq)EC4{bab`gE>qkfhG(p?I<-YkN|oj-?S2!S(qJntxD zNdqG>J|YWT=||ju{9uHk|H*!@(|Q3gy>5j+fI&>vX^?kHvW~i14Ye#;0J+PwVo;If znHn4pCdkxVFm}OP77VgTtfHCKSHSPlz^oifJMK2zj1E1Q7AC;cgsgZAas>o; z&Wur=(L{-`CN{Kq?>Ko&!H4+s_}7RZzYP-|pAN@nBEh|ILC>E1VB9QPeu+cxc?!Q3 zsQ^7P2uG`xbW`q{lbj8Vj$g85WnjZ zR3pj==_iR*i7l~OUi3v;5zVj{f;lm}``LG2y$0s)!=|EP6kh!Hi85NsfeZY(!?%f| z>Kbi_g_>~L_IrpeDEe{Fm-?&ys-03a;u ze&8-Zr>DioepxHGwI{Y;(_rY)3dbQRC6;M#!%=aBN?&(eaQ!e)y{Px8#qK7w;O{g- zW3A-~PGINvrTB*U)R!(l3AXi#zrvp$q84KPClV$|=OA|z8=ikkD(jMA+Sy)0cNmGfkV@ zHU|pAF9k1l9fcQ()bN4;9-Js&E~UuPhNXuR##MBe7)DwQK_E_j`$&Gs`cH6Wz*Is` zNTNY}?N+d~vNA5r&3){0wdgaeJf)^f9t-9Npn{q6s z9OR(xioVY=`xZdSG}zi9gE8F9$T8fQ&R}j5^GH99mMe;;$uynD*CsWlPh)~*Jxt!S zR@WEiV!~*W)A08;8zv%A&_aVtnx{{j#^RL1E}WQ(l6!E2&aPCY@P1FJ@~?~ic1)~x z`)=Lonmy9n9iU$zqiWl-9qKJ>>eUWkZ2UT#hcZ29C7NqJ%PSb`zjT-M{&N3P`yW5q2L$|OG ztVEHqjsL407yVRWQkp5Sf8Ls_kbU6aY6RRO_*MYXp9z#Rtv?pSN~*E~gtuw`acat7 z6&2}3iLz2zR!w6SeoES@@6ypDWI;LtGI7<+cgk4TeSf?H(n9&YBxt0S)5I@z`-+IL zQ@eb20ULy%#+ZFlUcoSV(&;F|_oefTH0DwDhXsuBDY0~UbeoC>-dBOoi>aUGtME>F z>rS@4wpNltIYYtMCLa~WGk6GvONQw5ST39XX%N{tQ7PtqUmwaGE7@XgRfL&Mkyow2 z!uK=Hu|#N$%%zl;S{oF<>aPnPs=)K=edV=6v~a+t4CJ`L_4((Hr;UcE5@F1PzZD6j z=u_Jd(6U>?e@ZfUzj-O`axiEZIK=z{0s`b8n(em-2L@uyUucPe9*0xm9c<|=&s)TF zlyUP4Uznhc9(5y?Ha*@VP)S{byj&BTL%X!YLSU*uajV63a67JBg_KzfEl*MvnkD)k z9FU1bU-|sP+InaabZ~)-*=|-BH{b-@D!!ALj**C-YhXxBU%Ya`rE?^&69^G_Hq3fzW+TBe*N}t0`fID@Mz!`285$65>*F zF@(;s*DtHnjs9L0j_i+S8sf-60Rv)B=Bu52CgilcZ6DZmtE<0rKJ`AgQexu$Px-05 zMWGA0-xzX`CfR8l1|G0LU{=dV_bBJ8ZGgPq|x(tzGJF`0ac@rD<}R z*FJ?dqv$pk0tO2XUyAXejJAf{NHx~@rPvF$rK@jxwxI7qoQGC2=7v)Ja$+6sgFRe4 zG8XxQ&M?gecRh-*G5|oFA0s$uZ4H!DLLp_PSy1!lw`G%MlJ3#(CJ_fqb^?vJh$at1b{V}|#`icZz}lewT)ul)V%3w2 z@9mY>T|MebI|`pJwD`+$(3BqL1m^Fmn2LL=A4jYl_Qzju*nFCO2D;21CsnVVSwXw= zUNFPBf!S&xCyDjub0#;$Z9K&unvws+VALK``a0oE2qeMoK2bOzE;p{jcTmqA^}m#~ zl)G8Hr+#xsuZa90jlH9ETG91d!$9)8tBB`KZ{y|8nkzVNGCD%tjIZDqI?g`f0N2xK zP#P(CauLnY`|n|bJWS8?c_aaA8+du(p=nAcLzfIw|6U$B$mLOLtgikh2^;l(v@?vL z#&Q&E{)P9sysR#dV^%%QMj00JGGi>2hUzNrMi$pI^{YhAvk?z&doRCx^T6jogm85r zU1=+=Lifc75@tntk;H7~Om=W^^6CQSVEERE(BJR4cz`6BCkBBSOk@cO#gJ5XjepXa zAW{&5{@nL%LeC%S68Off$D5|^?x-!!j5&zZ9%D4}PKScA3+ES(83tTsOJ2 zw|3gMop~wDAKwa6DiYr-YMI{vxG(MOIIEIPviw(ue+NX(;#5a5Uf=NgULtd~*B8o_ zu@lyRovf^G*O$kva6B5kxb%L{^ZKz#dX>%BQn{t3-TD&4Hu?7`mDFGo(Ow1HQP69I z7NowbN9*$75d|EtQu#wkA+c;<;&*gH0u%{0DUDWy9vCFxD$_;(I``^zob#Mki;HjU z>~%aAr!=<~-xhRe?Mi=~TWjfa`GA01VwVQraCewpDX=&kSxA)%JJJJX95Ev!<0kuV z(ZjebvMvfy_mRIVZb=0BC?W!+P3r))!Dv;0)KIP%6^o!<;m+R3wFmCg6W7#T`=9Mk zZF^-%d0y|N53|`=WCX+$Fh@{xmJAAM-@%2 z4f}kxC|*i7BJQ$gyNQmPC?5z?ZFrv&}tOalCSV|FAFHU}mPm z;t>o9`~Dh3m)(S}OutgL)>bXnky80T+#VDFs;pp(e@aoVP`66qFraL{vDR~#WzERS z$BiPs9K^-Oi_V^v&}{Z+DL1VlCCy6v4@fC@h-01bI?)L?zUK>qo|tQn;}~?l;$Fpu z$|BSJ* ztZF{?Za~leP6Q^+j(PXBJU}P68ES9mJBNFAzmo8CJF0$@{{OA4EmqV`m)GY}k8Q99 z4S1Bk>F>^Va~yunBg+stx>*0K@?5mum4c`Lzm8D@!cY4vLyoT8F{#E|iqC&+zjdft z)YD4h<<0xC@&_IS9HRqUxv)2S$T{tM^b4)!q4zRhELQr>Hl3qbJsINh@o3DTXzR$_ z@OaSLRKg1noU7zZwlf*se^gEfdElrsH?t~r@eFGgXr)HhpOpLp$=b#MY z99Cc&dq)(viRWW?{aB3avMk1{@^>Tv|K0_RBnaCYgYD82w;Kd+=Z)N)4*9k%wqkJZ zeU=$|G_oxb<(8{xy>?uzoX078UU2(SxdRW^YN2fMbK;&ZSGl}v3jDDyV&rpFC&fQ5 z625qpuoy8wkDiy2njbx3`k}iMD=F|wPV6Sf(aS?0!Uyg2CAr6BGhf!bmlHJYtW(={ zWe5$gsy#Y&Uf`{{yWn%hz)k=k&|KNe`R`zymr?11E)FWKC{Yu6uV9pmibHnFb|x! zPk*fu<~`qWH&tA(v0${z(q%t&0Ss({`>T{!&i_gwO_hCFi<9u1t5jWX#%C%{y(?Rp zA8#$MDkQ4zKHe?g-9M6He^XBrUOpQqeby|e=cRRxbvwHtrSdy-E5{{;{v`L_v$RIJEG1$K15*%bo*?7vWt_;W8_qGPS(!wojFmH&tCW zd#*Vwq)==a7hY(&x$)>A3ojXZlS#g<-VDah@+NskJru_&SW%+Zd63TYw6gKvar1Ay zqX{SA%G8SM&ZsOPmV~QGQ&K6vpH-YFz8c^w{pP2--kMh87YX^xyehS*L`AB@_<-s! zZ?CvcotQEGv?j06Hr;tOKQ0paEUney`~(klzbY5FC871$o32aZwpGQwH~03mzmQe9 za`H7Ge|avfYh2Le#E10X^IiA)DVN;{|2u}P2>V|$;kn;zJCs4q!#YZR*8tD0<^|(nm0R{TL@%UwO1m-4~~_Lh9AlH??va z(&6V*m>Hm;ue{Rsb+u@xQkjH4WkXdr)2>`n;QZ_1F|#lIhC$xPlHGZFt%bLpQaubb zOl2AKr`C-0F9qiQWqJb1faO~1j@gRVDbr~c`d(ST@W|2j4f=`1$@1M)k8c~!$@`V| zg(-%u&B7(@I&2lzjsBwJm9M7++IyQ~!kOh7)kIFF9uod^?8sh_pK12_f(B3cD+|w4 z$Y!iQNq8~1ANeSllK03ByuRSKk3PO#$JM34w@<3H8%f&h^Gxt8F*J(o*#ec8F%wm0 z2)WJhM5xW{1BI)rNB-mQa=vt3`}ipTT6|3=sm zM3GciRUI?D`$au}`32>({zVa3M(K}Zdxrl=j3+e~ zy8U5WwfU&{r^btWVuo|CpN4$Y7@ATmJXl&8DI$)z#c^PJmg;@(*FjGr%IeosV$FB6SDo>o~Fg3wPP=7kW(b;4D_2RO^og> zpD;>AF8k_^@pOHAs-!Y>=$DVjX`FhL{54Nf^VoLVs9C^CFDAfT@*xSo{Xk^+1sdbF zyWanCvX#>C)ws%Q35IK+2kWWv%YPs4?AK`tf83X;(gyXM#-Wu z6y1iuJ~@>B{;9`6JDT1ygz~=ka_q$36qAa?_|UT_^N>tkz92=YK8kKJ|AIx4D?##d_2~M#C}PL{jPV3xMQ>) zc2uv86=dH;t7wfr@6lUfeJgI{2JQx{U)*HO=(m!hAvfS z0VWW6i+b~X2(HK)Yx=ssQ%J(DRToS8ZP#wD+UtX&^Wkbee^k=tP<5$q@@oOflPX_J z7q}X20Kui6vpJiU5UGBB_%ZTEZz8uHf8@C)a^c~iABeTl{7%s#G2(5ssdJ+3PB|2I z@qUwbD}L#N_~kar7X8jnp`961g%18BBY8UBvU}dc5zOQs5$ZZ(bZ9Cj$;+Lhbq16x z6K@vy9VEPOd63Z)XgOtl2fHA_UiX>Aqfd2bj7Mu`I}}g6y}FOhI>%J$g?Y?Fj>?s# z(6?*M2z>pP(O!45Y7|8qV#?2Fj<0YZ$>qGjnb-;o{_qdjNTSLf*~lc$Q2brdjU;KT zVR2c%^PmQUhASZFjy9I#-#xIVzjlnaDZBX@j3JcM`A%t0W1i_guRjx2Q99*LU7b?T z+bng{_^D{t%&KwPQ(z3-oddJenYPlKRM&>{U${i6bVvg5eJ?S|Mv12Sr)}tmGp*a= z$S?`2P%k{~N!jl%=j_;h?!Grt!7?f!9~M39pq9^qU5WZaHdfUt9GrqhF`*@1(zupG z^+7J{YuB*AlV8da)0m2RQHV7Ng*QeB!TMa@eYpLU zykTxUg3+eoRdK0j2{G;~FRH>cM3_g$Z+O5Sh%XIVw=Dn;)uGh@E8C;j>e>sWxZgv_Mvxogf!VM{m-0NP} z?&4G@Jgx(OfLtTeOa)LmiwF;?i9^Y9;)9jv9LCBql4 zj1TjF;C$a*z|pv(KzSBks?R1SOWY;*Xs;3sWK`ZRW zY%v!|CDBjn*6RPht#muQ?Z!Q4_RPz8N5{ujP~FXFca_AdJkQ|wD(C6DdQQ%3&!U4@ zV;I1y(K}_NAtEhyJwoVn7kH<-TITY~HoQ&cGX%ZUo6z;#PE)jZjtJ?wj}2x0 zs2fUem;2JriIj6t0B6<#`YKH$9rmo39|>!9K+iz5h1Zeyze5s>6lNTC%aySLw;jtZ z+Ud50%Ok3)c=N)g6eh)IwCauB$SY5X5EmR#d>;}$aa?fsAVe%>>UZ68W*%UHXQ0AH zm!|F4zQ`7@%|cKrJcZ$SprIs=*P2fG-xK&3c>*DvKRxlV&_#^+Z$PeB{bkoo#B=Yl zwvcwIMuyR&bT4A7VPl3Tsh-vf!y0U>ZPu(PPbEkjLKs(nGT}> z(<$?*lgdtupC^z!qHd;hyo@@qT;-r z+jXp@>Rq7dM8J50|Jn7Odx~OtGVgL31gB8_NetQdh`RR# z@k^v^D&-ukQNR37e;RqKn%`1?Z+#!tdY%N>uL!A!!PQDuK1@~bsv{4Rl+aqPxOCVH zyN@gzlGGUO53Nfz&(Jbdbvfj)HE_gb?{5Oat z1SUiG+LA57z$X#OAed?_T^oUejlBq+W4QSEvX+*X-COFKkG*+_Yq<_KwAkrxN1ZXH zkZ`FG-^^Jv10d2Plc-lN-}WtOv2ccn@b(CGY3MDANcz(+wgFy?q0Y5KYznbAbtV&r6Yx212zWy Or=p-PUny%D{Qm&kjp_3M literal 51442 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 F{{!l18Mpud diff --git a/fastlane/Fastfile b/fastlane/Fastfile index ce5b3e9..43c06ce 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -50,9 +50,29 @@ platform :android do run_detail_tests() end - desc "Runs tests in repository module" - lane :test_repository do - run_repository_tests() + desc "Runs tests in abstraction module" + lane :test_abstractions do + run_abstractions_tests() + end + + desc "Runs tests in definitions module" + lane :test_definitions do + run_definitions_tests() + end + + desc "Runs tests in interactors module" + lane :test_interactors do + run_interactors_tests() + end + + desc "Runs tests in network module" + lane :test_network do + run_network_tests() + end + + desc "Runs tests in persistence module" + lane :test_persistence do + run_persistence_tests() end # ================ Gradle tasks ================ @@ -81,7 +101,23 @@ platform :android do gradle(task: "features:detail:test --continue") end - def run_repository_tests - gradle(task: "repository:test --continue") + def run_abstractions_tests + gradle(task: "abstractions:test --continue") + end + + def run_definitions_tests + gradle(task: "data:definitions:test --continue") + end + + def run_interactors_tests + gradle(task: "data:interactors:test --continue") + end + + def run_network_tests + gradle(task: "data:network:test --continue") + end + + def run_persistence_tests + gradle(task: "data:persistence:test --continue") end end diff --git a/features/detail/build.gradle b/features/detail/build.gradle index 43a02bd..cea8317 100644 --- a/features/detail/build.gradle +++ b/features/detail/build.gradle @@ -14,7 +14,5 @@ android { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation project(':repository') - testImplementation testLibraries.coroutinesTest } diff --git a/features/detail/src/main/kotlin/com/melih/detail/data/LaunchDetailItem.kt b/features/detail/src/main/kotlin/com/melih/detail/data/LaunchDetailItem.kt new file mode 100644 index 0000000..e6676f4 --- /dev/null +++ b/features/detail/src/main/kotlin/com/melih/detail/data/LaunchDetailItem.kt @@ -0,0 +1,10 @@ +package com.melih.launches.data + +import com.melih.abstractions.data.ViewEntity + +data class LaunchDetailItem( + val id: Long, + val imageUrl: String, + val rocketName: String, + val missionDescription: String +) : ViewEntity diff --git a/features/detail/src/main/kotlin/com/melih/detail/data/LaunchDetailMapper.kt b/features/detail/src/main/kotlin/com/melih/detail/data/LaunchDetailMapper.kt new file mode 100644 index 0000000..32f61c0 --- /dev/null +++ b/features/detail/src/main/kotlin/com/melih/detail/data/LaunchDetailMapper.kt @@ -0,0 +1,18 @@ +package com.melih.launches.data + +import com.melih.abstractions.mapper.Mapper +import com.melih.definitions.entities.LaunchEntity +import javax.inject.Inject + +class LaunchDetailMapper @Inject constructor() : Mapper() { + + override fun convert(launchEntity: LaunchEntity) = + with(launchEntity) { + LaunchDetailItem( + id, + rocket.imageURL, + rocket.name, + if (!missions.isNullOrEmpty()) missions[0].description else "" + ) + } +} diff --git a/features/detail/src/main/kotlin/com/melih/detail/di/modules/DetailFragmentModule.kt b/features/detail/src/main/kotlin/com/melih/detail/di/modules/DetailFragmentModule.kt index c4a58a2..946e852 100644 --- a/features/detail/src/main/kotlin/com/melih/detail/di/modules/DetailFragmentModule.kt +++ b/features/detail/src/main/kotlin/com/melih/detail/di/modules/DetailFragmentModule.kt @@ -2,11 +2,15 @@ package com.melih.detail.di.modules import androidx.lifecycle.ViewModel import androidx.navigation.fragment.navArgs +import com.melih.abstractions.mapper.Mapper import com.melih.core.di.keys.ViewModelKey +import com.melih.definitions.entities.LaunchEntity import com.melih.detail.ui.DetailFragment import com.melih.detail.ui.DetailFragmentArgs import com.melih.detail.ui.DetailViewModel -import com.melih.repository.interactors.GetLaunchDetails +import com.melih.interactors.GetLaunchDetails +import com.melih.launches.data.LaunchDetailItem +import com.melih.launches.data.LaunchDetailMapper import dagger.Binds import dagger.Module import dagger.Provides @@ -21,6 +25,9 @@ abstract class DetailFragmentModule { @IntoMap @ViewModelKey(DetailViewModel::class) abstract fun detailViewModel(detailViewModel: DetailViewModel): ViewModel + + @Binds + abstract fun detailMapper(mapper: LaunchDetailMapper): Mapper //endregion @Module diff --git a/features/detail/src/main/kotlin/com/melih/detail/ui/DetailViewModel.kt b/features/detail/src/main/kotlin/com/melih/detail/ui/DetailViewModel.kt index f63ee29..8897dbc 100644 --- a/features/detail/src/main/kotlin/com/melih/detail/ui/DetailViewModel.kt +++ b/features/detail/src/main/kotlin/com/melih/detail/ui/DetailViewModel.kt @@ -1,34 +1,31 @@ package com.melih.detail.ui import androidx.lifecycle.Transformations.map +import com.melih.abstractions.deliverable.handle import com.melih.core.base.viewmodel.BaseViewModel -import com.melih.repository.entities.LaunchEntity -import com.melih.repository.interactors.GetLaunchDetails -import com.melih.repository.interactors.base.handle +import com.melih.interactors.GetLaunchDetails +import com.melih.launches.data.LaunchDetailItem +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collect import javax.inject.Inject class DetailViewModel @Inject constructor( - private val getLaunchDetails: GetLaunchDetails, + private val getLaunchDetails: GetLaunchDetails, private val getLaunchDetailsParams: GetLaunchDetails.Params -) : BaseViewModel() { +) : BaseViewModel() { //region Properties val rocketName = map(successData) { - it.rocket.name + it.rocketName } val description = map(successData) { - if (it.missions.isEmpty()) { - "" - } else { - it.missions[0].description - } + it.missionDescription } val imageUrl = map(successData) { - it.rocket.imageURL + it.imageUrl } //endregion diff --git a/features/detail/src/main/res/layout/fragment_detail.xml b/features/detail/src/main/res/layout/fragment_detail.xml index dde2a8f..e58cded 100644 --- a/features/detail/src/main/res/layout/fragment_detail.xml +++ b/features/detail/src/main/res/layout/fragment_detail.xml @@ -1,69 +1,69 @@ + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> - + - - + + - + - + - + - - + + diff --git a/features/detail/src/test/java/com/melih/detail/DetailViewModelTest.kt b/features/detail/src/test/java/com/melih/detail/DetailViewModelTest.kt index 69ad7c9..d4cc572 100644 --- a/features/detail/src/test/java/com/melih/detail/DetailViewModelTest.kt +++ b/features/detail/src/test/java/com/melih/detail/DetailViewModelTest.kt @@ -1,7 +1,8 @@ package com.melih.detail import com.melih.detail.ui.DetailViewModel -import com.melih.repository.interactors.GetLaunchDetails +import com.melih.interactors.GetLaunchDetails +import com.melih.launches.data.LaunchDetailItem import io.mockk.mockk import io.mockk.slot import io.mockk.spyk @@ -19,7 +20,7 @@ import org.junit.jupiter.api.Test @UseExperimental(ExperimentalCoroutinesApi::class) class DetailViewModelTest : BaseTestWithMainThread() { - private val getLaunchDetails: GetLaunchDetails = mockk(relaxed = true) + private val getLaunchDetails: GetLaunchDetails = mockk(relaxed = true) private val getLaunchDetailsParams = GetLaunchDetails.Params(1013) private val viewModel = spyk(DetailViewModel(getLaunchDetails, getLaunchDetailsParams)) diff --git a/features/launches/build.gradle b/features/launches/build.gradle index 78a3446..740d414 100644 --- a/features/launches/build.gradle +++ b/features/launches/build.gradle @@ -7,8 +7,6 @@ apply from: "$rootProject.projectDir/scripts/feature_module.gradle" dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation project(':repository') - implementation libraries.paging implementation libraries.swipeRefreshLayout diff --git a/features/launches/src/main/kotlin/com/melih/launches/data/LaunchItem.kt b/features/launches/src/main/kotlin/com/melih/launches/data/LaunchItem.kt new file mode 100644 index 0000000..8d50cb4 --- /dev/null +++ b/features/launches/src/main/kotlin/com/melih/launches/data/LaunchItem.kt @@ -0,0 +1,10 @@ +package com.melih.launches.data + +import com.melih.abstractions.data.ViewEntity + +data class LaunchItem( + val id: Long, + val imageUrl: String, + val rocketName: String, + val missionDescription: String +) : ViewEntity diff --git a/features/launches/src/main/kotlin/com/melih/launches/data/LaunchMapper.kt b/features/launches/src/main/kotlin/com/melih/launches/data/LaunchMapper.kt new file mode 100644 index 0000000..77aadd1 --- /dev/null +++ b/features/launches/src/main/kotlin/com/melih/launches/data/LaunchMapper.kt @@ -0,0 +1,18 @@ +package com.melih.launches.data + +import com.melih.abstractions.mapper.Mapper +import com.melih.definitions.entities.LaunchEntity +import javax.inject.Inject + +class LaunchMapper @Inject constructor() : Mapper() { + + override fun convert(launchEntity: LaunchEntity) = + with(launchEntity) { + LaunchItem( + id, + rocket.imageURL, + rocket.name, + if (!missions.isNullOrEmpty()) missions[0].description else "" + ) + } +} diff --git a/features/launches/src/main/kotlin/com/melih/launches/di/modules/LaunchesFragmentModule.kt b/features/launches/src/main/kotlin/com/melih/launches/di/modules/LaunchesFragmentModule.kt index 207eaf3..8841558 100644 --- a/features/launches/src/main/kotlin/com/melih/launches/di/modules/LaunchesFragmentModule.kt +++ b/features/launches/src/main/kotlin/com/melih/launches/di/modules/LaunchesFragmentModule.kt @@ -2,10 +2,14 @@ package com.melih.launches.di.modules import androidx.lifecycle.ViewModel import androidx.paging.Config +import com.melih.abstractions.mapper.Mapper import com.melih.core.di.keys.ViewModelKey +import com.melih.definitions.entities.LaunchEntity +import com.melih.interactors.DEFAULT_LAUNCHES_AMOUNT +import com.melih.interactors.GetLaunches +import com.melih.launches.data.LaunchItem +import com.melih.launches.data.LaunchMapper import com.melih.launches.ui.vm.LaunchesViewModel -import com.melih.repository.interactors.DEFAULT_LAUNCHES_AMOUNT -import com.melih.repository.interactors.GetLaunches import dagger.Binds import dagger.Module import dagger.Provides @@ -14,12 +18,15 @@ import dagger.multibindings.IntoMap @Module abstract class LaunchesFragmentModule { - //region ViewModels + //region Binds @Binds @IntoMap @ViewModelKey(LaunchesViewModel::class) - abstract fun listViewModel(listViewModel: LaunchesViewModel): ViewModel + abstract fun launchesViewModel(listViewModel: LaunchesViewModel): ViewModel + + @Binds + abstract fun launchMapper(mapper: LaunchMapper): Mapper //endregion @Module diff --git a/features/launches/src/main/kotlin/com/melih/launches/ui/LaunchesFragment.kt b/features/launches/src/main/kotlin/com/melih/launches/ui/LaunchesFragment.kt index e29d29c..e5e7a85 100644 --- a/features/launches/src/main/kotlin/com/melih/launches/ui/LaunchesFragment.kt +++ b/features/launches/src/main/kotlin/com/melih/launches/ui/LaunchesFragment.kt @@ -4,18 +4,18 @@ import android.os.Bundle import android.view.View import androidx.fragment.app.viewModels import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import com.melih.abstractions.deliverable.State import com.melih.core.actions.openDetail import com.melih.core.base.lifecycle.BaseDaggerFragment import com.melih.core.extensions.observe +import com.melih.interactors.error.PersistenceEmptyError import com.melih.launches.R -import com.melih.launches.databinding.ListBinding +import com.melih.launches.data.LaunchItem +import com.melih.launches.databinding.LaunchesBinding import com.melih.launches.ui.adapters.LaunchesAdapter import com.melih.launches.ui.vm.LaunchesViewModel -import com.melih.repository.entities.LaunchEntity -import com.melih.repository.interactors.base.PersistenceEmpty -import com.melih.repository.interactors.base.State -class LaunchesFragment : BaseDaggerFragment(), SwipeRefreshLayout.OnRefreshListener { +class LaunchesFragment : BaseDaggerFragment(), SwipeRefreshLayout.OnRefreshListener { //region Properties @@ -67,7 +67,7 @@ class LaunchesFragment : BaseDaggerFragment(), SwipeRefreshLayout.O // Observing error to show toast with retry action observe(viewModel.errorData) { - if (it !is PersistenceEmpty) { + if (it !is PersistenceEmptyError) { showSnackbarWithAction(it) { viewModel.retry() } @@ -79,7 +79,7 @@ class LaunchesFragment : BaseDaggerFragment(), SwipeRefreshLayout.O } } - private fun onItemSelected(item: LaunchEntity) { + private fun onItemSelected(item: LaunchItem) { openDetail(item.id) } diff --git a/features/launches/src/main/kotlin/com/melih/launches/ui/adapters/LaunchesAdapter.kt b/features/launches/src/main/kotlin/com/melih/launches/ui/adapters/LaunchesAdapter.kt index d9e88ec..7f8f423 100644 --- a/features/launches/src/main/kotlin/com/melih/launches/ui/adapters/LaunchesAdapter.kt +++ b/features/launches/src/main/kotlin/com/melih/launches/ui/adapters/LaunchesAdapter.kt @@ -5,10 +5,10 @@ import android.view.ViewGroup import com.melih.core.base.recycler.BasePagingListAdapter import com.melih.core.base.recycler.BaseViewHolder import com.melih.core.extensions.createDiffCallback +import com.melih.launches.data.LaunchItem import com.melih.launches.databinding.LaunchRowBinding -import com.melih.repository.entities.LaunchEntity -class LaunchesAdapter(itemClickListener: (LaunchEntity) -> Unit) : BasePagingListAdapter( +class LaunchesAdapter(itemClickListener: (LaunchItem) -> Unit) : BasePagingListAdapter( createDiffCallback { oldItem, newItem -> oldItem.id == newItem.id }, itemClickListener ) { @@ -19,21 +19,18 @@ class LaunchesAdapter(itemClickListener: (LaunchEntity) -> Unit) : BasePagingLis inflater: LayoutInflater, parent: ViewGroup, viewType: Int - ): BaseViewHolder = + ): BaseViewHolder = LaunchesViewHolder(LaunchRowBinding.inflate(inflater, parent, false)) //endregion } -class LaunchesViewHolder(private val binding: LaunchRowBinding) : BaseViewHolder(binding) { +class LaunchesViewHolder(private val binding: LaunchRowBinding) : + BaseViewHolder(binding) { //region Functions - override fun bind(item: LaunchEntity) { + override fun bind(item: LaunchItem) { binding.entity = item - - val missions = item.missions - binding.tvDescription.text = if (!missions.isNullOrEmpty()) missions[0].description else "" - binding.executePendingBindings() } //endregion diff --git a/features/launches/src/main/kotlin/com/melih/launches/ui/paging/LaunchesPagingSource.kt b/features/launches/src/main/kotlin/com/melih/launches/ui/paging/LaunchesPagingSource.kt index 6dc3056..7e1424b 100644 --- a/features/launches/src/main/kotlin/com/melih/launches/ui/paging/LaunchesPagingSource.kt +++ b/features/launches/src/main/kotlin/com/melih/launches/ui/paging/LaunchesPagingSource.kt @@ -1,25 +1,23 @@ package com.melih.launches.ui.paging import com.melih.core.base.paging.BasePagingDataSource -import com.melih.repository.entities.LaunchEntity -import com.melih.repository.interactors.GetLaunches -import com.melih.repository.interactors.base.Result +import com.melih.interactors.GetLaunches +import com.melih.launches.data.LaunchItem import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.Flow import javax.inject.Inject /** * Uses [GetLaunches] to get data for pagination */ class LaunchesPagingSource @Inject constructor( - private val getLaunches: GetLaunches, + private val getLaunches: GetLaunches, private val getLaunchesParams: GetLaunches.Params -) : BasePagingDataSource() { +) : BasePagingDataSource() { //region Functions @UseExperimental(ExperimentalCoroutinesApi::class) - override fun loadDataForPage(page: Int): Flow>> = + override fun loadDataForPage(page: Int) = getLaunches( getLaunchesParams.copy( page = page diff --git a/features/launches/src/main/kotlin/com/melih/launches/ui/paging/LaunchesPagingSourceFactory.kt b/features/launches/src/main/kotlin/com/melih/launches/ui/paging/LaunchesPagingSourceFactory.kt index 98b3485..7a6cfcf 100644 --- a/features/launches/src/main/kotlin/com/melih/launches/ui/paging/LaunchesPagingSourceFactory.kt +++ b/features/launches/src/main/kotlin/com/melih/launches/ui/paging/LaunchesPagingSourceFactory.kt @@ -2,16 +2,16 @@ package com.melih.launches.ui.paging import com.melih.core.base.paging.BasePagingDataSource import com.melih.core.base.paging.BasePagingFactory -import com.melih.repository.entities.LaunchEntity +import com.melih.launches.data.LaunchItem import javax.inject.Inject import javax.inject.Provider class LaunchesPagingSourceFactory @Inject constructor( private val sourceProvider: Provider -) : BasePagingFactory() { +) : BasePagingFactory() { //region Functions - override fun createSource(): BasePagingDataSource = sourceProvider.get() + override fun createSource(): BasePagingDataSource = sourceProvider.get() //endregion } diff --git a/features/launches/src/main/kotlin/com/melih/launches/ui/vm/LaunchesViewModel.kt b/features/launches/src/main/kotlin/com/melih/launches/ui/vm/LaunchesViewModel.kt index 39133a7..d026a54 100644 --- a/features/launches/src/main/kotlin/com/melih/launches/ui/vm/LaunchesViewModel.kt +++ b/features/launches/src/main/kotlin/com/melih/launches/ui/vm/LaunchesViewModel.kt @@ -3,18 +3,18 @@ package com.melih.launches.ui.vm import androidx.paging.PagedList import com.melih.core.base.paging.BasePagingFactory import com.melih.core.base.viewmodel.BasePagingViewModel +import com.melih.launches.data.LaunchItem import com.melih.launches.ui.paging.LaunchesPagingSourceFactory -import com.melih.repository.entities.LaunchEntity import javax.inject.Inject class LaunchesViewModel @Inject constructor( private val launchesPagingSourceFactory: LaunchesPagingSourceFactory, private val launchesPagingConfig: PagedList.Config -) : BasePagingViewModel() { +) : BasePagingViewModel() { //region Properties - override val factory: BasePagingFactory + override val factory: BasePagingFactory get() = launchesPagingSourceFactory override val config: PagedList.Config diff --git a/features/launches/src/main/res/layout/fragment_launches.xml b/features/launches/src/main/res/layout/fragment_launches.xml index f9f368d..967e940 100644 --- a/features/launches/src/main/res/layout/fragment_launches.xml +++ b/features/launches/src/main/res/layout/fragment_launches.xml @@ -4,7 +4,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> - + + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> - + - - + + - + - + - + - + - - - + + + diff --git a/repository/.gitignore b/repository/.gitignore deleted file mode 100644 index 796b96d..0000000 --- a/repository/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/repository/src/main/AndroidManifest.xml b/repository/src/main/AndroidManifest.xml deleted file mode 100644 index efd4c29..0000000 --- a/repository/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/repository/src/main/kotlin/com/melih/repository/Repository.kt b/repository/src/main/kotlin/com/melih/repository/Repository.kt deleted file mode 100644 index af1e3d8..0000000 --- a/repository/src/main/kotlin/com/melih/repository/Repository.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.melih.repository - -import com.melih.repository.entities.LaunchEntity -import com.melih.repository.interactors.base.Result - -/** - * Contract for sources to seperate low level business logic from build and return type - */ -abstract class Repository { - - //region Abstractions - - internal abstract suspend fun getNextLaunches(count: Int, page: Int): Result> - internal abstract suspend fun getLaunchById(id: Long): Result - //endregion -} diff --git a/repository/src/main/kotlin/com/melih/repository/interactors/GetLaunchDetails.kt b/repository/src/main/kotlin/com/melih/repository/interactors/GetLaunchDetails.kt deleted file mode 100644 index 5f9de0d..0000000 --- a/repository/src/main/kotlin/com/melih/repository/interactors/GetLaunchDetails.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.melih.repository.interactors - -import com.melih.repository.entities.LaunchEntity -import com.melih.repository.interactors.base.BaseInteractor -import com.melih.repository.interactors.base.Failure -import com.melih.repository.interactors.base.InteractorParameters -import com.melih.repository.interactors.base.Result -import com.melih.repository.interactors.base.Success -import com.melih.repository.sources.NetworkSource -import com.melih.repository.sources.PersistenceSource -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.FlowCollector -import javax.inject.Inject - -/** - * Gets next given number of launches - */ -@UseExperimental(ExperimentalCoroutinesApi::class) -class GetLaunchDetails @Inject constructor() : BaseInteractor() { - - //region Properties - - @field:Inject - internal lateinit var networkSource: NetworkSource - - @field:Inject - internal lateinit var persistenceSource: PersistenceSource - //endregion - - //region Functions - - override suspend fun FlowCollector>.run(params: Params) { - val result = persistenceSource.getLaunchById(params.id) - - if (result !is Success) { - when (val response = networkSource.getLaunchById(params.id)) { - // Save result and return again from persistence - is Success -> { - persistenceSource.saveLaunch(response.successData) - emit(persistenceSource.getLaunchById(params.id)) - } - - // Redirect failure as it is - is Failure -> emit(response) - } - } else { - emit(result) - } - } - //endregion - - data class Params( - val id: Long - ) : InteractorParameters -} diff --git a/repository/src/main/kotlin/com/melih/repository/interactors/GetLaunches.kt b/repository/src/main/kotlin/com/melih/repository/interactors/GetLaunches.kt deleted file mode 100644 index 775d8c9..0000000 --- a/repository/src/main/kotlin/com/melih/repository/interactors/GetLaunches.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.melih.repository.interactors - -import com.melih.repository.entities.LaunchEntity -import com.melih.repository.interactors.base.BaseInteractor -import com.melih.repository.interactors.base.InteractorParameters -import com.melih.repository.interactors.base.Result -import com.melih.repository.interactors.base.Success -import com.melih.repository.sources.NetworkSource -import com.melih.repository.sources.PersistenceSource -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.FlowCollector -import javax.inject.Inject - -const val DEFAULT_LAUNCHES_AMOUNT = 15 - -/** - * Gets next given number of launches - */ -@UseExperimental(ExperimentalCoroutinesApi::class) -class GetLaunches @Inject constructor() : BaseInteractor, GetLaunches.Params>() { - - //region Properties - - @field:Inject - internal lateinit var networkSource: NetworkSource - - @field:Inject - internal lateinit var persistenceSource: PersistenceSource - //endregion - - //region Functions - - override suspend fun FlowCollector>>.run(params: Params) { - - // Start network fetch - we're not handling state here to ommit them - networkSource - .getNextLaunches(params.count, params.page) - .also { - if (it is Success) { - persistenceSource.saveLaunches(it.successData) - emit(persistenceSource.getNextLaunches(params.count, params.page)) - } else { - emit(it) - emit(persistenceSource.getNextLaunches(params.count, params.page)) - } - } - } - //endregion - - data class Params( - val count: Int = DEFAULT_LAUNCHES_AMOUNT, - val page: Int - ) : InteractorParameters -} diff --git a/repository/src/main/kotlin/com/melih/repository/interactors/base/Reason.kt b/repository/src/main/kotlin/com/melih/repository/interactors/base/Reason.kt deleted file mode 100644 index fa14e9a..0000000 --- a/repository/src/main/kotlin/com/melih/repository/interactors/base/Reason.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.melih.repository.interactors.base - -import androidx.annotation.StringRes -import com.melih.repository.R - - -/** - * [Failure] reasons - */ -sealed class Reason(@StringRes val messageRes: Int) - -//region Subclasses - -class NetworkError : Reason(R.string.reason_network) -class EmptyResultError : Reason(R.string.reason_empty_body) -class GenericError : Reason(R.string.reason_generic) -class ResponseError : Reason(R.string.reason_response) -class TimeoutError : Reason(R.string.reason_timeout) -class PersistenceEmpty : Reason(R.string.reason_persistance_empty) -class NoNetworkPersistenceEmpty : Reason(R.string.reason_no_network_persistance_empty) -//endregion diff --git a/repository/src/main/kotlin/com/melih/repository/sources/NetworkSource.kt b/repository/src/main/kotlin/com/melih/repository/sources/NetworkSource.kt deleted file mode 100644 index 785e0a2..0000000 --- a/repository/src/main/kotlin/com/melih/repository/sources/NetworkSource.kt +++ /dev/null @@ -1,118 +0,0 @@ -package com.melih.repository.sources - -import android.net.NetworkInfo -import com.melih.repository.Repository -import com.melih.repository.entities.LaunchEntity -import com.melih.repository.interactors.DEFAULT_LAUNCHES_AMOUNT -import com.melih.repository.interactors.base.EmptyResultError -import com.melih.repository.interactors.base.Failure -import com.melih.repository.interactors.base.NetworkError -import com.melih.repository.interactors.base.Reason -import com.melih.repository.interactors.base.ResponseError -import com.melih.repository.interactors.base.Result -import com.melih.repository.interactors.base.Success -import com.melih.repository.interactors.base.TimeoutError -import com.melih.repository.network.ApiImpl -import retrofit2.Response -import java.io.IOException -import javax.inject.Inject -import javax.inject.Provider - -private const val DEFAULT_IMAGE_SIZE = 480 - -/** - * NetworkSource for fetching results using api and wrapping them as contracted in [repository][Repository], - * returning either [failure][Failure] with proper [reason][Reason] or [success][Success] with data - */ -internal class NetworkSource @Inject constructor( - private val apiImpl: ApiImpl, - private val networkInfoProvider: Provider -) : Repository() { - - //region Properties - - private val isNetworkConnected: Boolean - get() { - val networkInfo = networkInfoProvider.get() - return networkInfo != null && networkInfo.isConnected - } - //endregion - - //region Functions - - override suspend fun getNextLaunches(count: Int, page: Int): Result> = - safeExecute({ - apiImpl.getNextLaunches(count, page * DEFAULT_LAUNCHES_AMOUNT) - }) { entity -> - entity.launches.map { launch -> - if (!launch.rocket.imageURL.isNotBlank()) { - launch.copy( - rocket = launch.rocket.copy( - imageURL = transformImageUrl( - launch.rocket.imageURL, - launch.rocket.imageSizes - ) - ) - ) - } else { - launch - } - } - } - - override suspend fun getLaunchById(id: Long): Result = - safeExecute({ - apiImpl.getLaunchById(id) - }) { - if (!it.rocket.imageURL.isNotBlank()) { - it.copy( - rocket = it.rocket.copy( - imageURL = transformImageUrl(it.rocket.imageURL, it.rocket.imageSizes) - ) - ) - } else { - it - } - } - - private inline fun safeExecute( - block: () -> Response, - transform: (T) -> R - ) = - if (isNetworkConnected) { - try { - block().extractResponseBody(transform) - } catch (e: IOException) { - Failure(TimeoutError()) - } - } else { - Failure(NetworkError()) - } - - private inline fun Response.extractResponseBody(transform: (T) -> R) = - if (isSuccessful) { - body()?.let { - Success(transform(it)) - } ?: Failure(EmptyResultError()) - } else { - Failure(ResponseError()) - } - - private fun transformImageUrl(imageUrl: String, supportedSizes: IntArray) = - try { - val urlSplit = imageUrl.split("_") - val url = urlSplit[0] - val format = urlSplit[1].split(".")[1] - - val requestedSize = if (!supportedSizes.contains(DEFAULT_IMAGE_SIZE)) { - supportedSizes.last { it < DEFAULT_IMAGE_SIZE } - } else { - DEFAULT_IMAGE_SIZE - } - - "${url}_$requestedSize.$format" - } catch (e: Exception) { - imageUrl - } - //endregion -} diff --git a/repository/src/main/kotlin/com/melih/repository/sources/PersistenceSource.kt b/repository/src/main/kotlin/com/melih/repository/sources/PersistenceSource.kt deleted file mode 100644 index c49881d..0000000 --- a/repository/src/main/kotlin/com/melih/repository/sources/PersistenceSource.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.melih.repository.sources - -import android.content.Context -import com.melih.repository.Repository -import com.melih.repository.entities.LaunchEntity -import com.melih.repository.interactors.base.Failure -import com.melih.repository.interactors.base.PersistenceEmpty -import com.melih.repository.interactors.base.Result -import com.melih.repository.interactors.base.Success -import com.melih.repository.persistence.LaunchesDatabase -import javax.inject.Inject - -/** - * Persistance source using Room database to save / read objects for SST - offline usage - */ -internal class PersistenceSource @Inject constructor( - ctx: Context -) : Repository() { - - //region Functions - - private val launchesDatabase = LaunchesDatabase.getInstance(ctx) - - override suspend fun getNextLaunches(count: Int, page: Int): Result> = - launchesDatabase - .launchesDao - .getLaunches(count, page) - .takeIf { it.isNotEmpty() } - ?.run { - Success(this) - } ?: Failure(PersistenceEmpty()) - - override suspend fun getLaunchById(id: Long): Result = - launchesDatabase - .launchesDao - .getLaunchById(id) - .takeIf { it != null } - ?.run { - Success(this) - } ?: Failure(PersistenceEmpty()) - - internal suspend fun saveLaunches(launches: List) { - launchesDatabase.launchesDao.saveLaunches(launches) - } - - internal suspend fun saveLaunch(launch: LaunchEntity) { - launchesDatabase.launchesDao.saveLaunch(launch) - } - //endregion -} diff --git a/repository/src/test/kotlin/com/melih/repository/sources/NetworkSourceTest.kt b/repository/src/test/kotlin/com/melih/repository/sources/NetworkSourceTest.kt deleted file mode 100644 index 343aac6..0000000 --- a/repository/src/test/kotlin/com/melih/repository/sources/NetworkSourceTest.kt +++ /dev/null @@ -1,104 +0,0 @@ -package com.melih.repository.sources - -import android.net.NetworkInfo -import com.melih.repository.R -import com.melih.repository.entities.LaunchEntity -import com.melih.repository.entities.LaunchesEntity -import com.melih.repository.interactors.base.EmptyResultError -import com.melih.repository.interactors.base.Failure -import com.melih.repository.interactors.base.NetworkError -import com.melih.repository.interactors.base.ResponseError -import com.melih.repository.interactors.base.Success -import com.melih.repository.interactors.base.onFailure -import com.melih.repository.interactors.base.onSuccess -import com.melih.repository.network.ApiImpl -import io.mockk.coEvery -import io.mockk.every -import io.mockk.mockk -import io.mockk.spyk -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.runBlockingTest -import org.amshove.kluent.shouldBeInstanceOf -import org.amshove.kluent.shouldEqualTo -import org.junit.jupiter.api.Nested -import org.junit.jupiter.api.Test -import javax.inject.Provider - -@UseExperimental(ExperimentalCoroutinesApi::class) -class NetworkSourceTest { - - private val apiImpl = mockk(relaxed = true) - private val networkInfoProvider = mockk>(relaxed = true) { - every { get() } returns mockk(relaxed = true) - } - - private val source = spyk(NetworkSource(apiImpl, networkInfoProvider)) - - @Nested - inner class GetNextLaunches { - - @Test - fun `should return network error when internet is not connected`() { - every { networkInfoProvider.get().isConnected } returns false - - runBlockingTest { - val result = source.getNextLaunches(1, 0) - - result shouldBeInstanceOf Failure::class - result.onFailure { - it shouldBeInstanceOf NetworkError::class - } - } - } - - @Test - fun `should return response error when it is not successful`() { - every { networkInfoProvider.get().isConnected } returns true - coEvery { apiImpl.getNextLaunches(any(), any()).isSuccessful } returns false - - runBlockingTest { - val result = source.getNextLaunches(1, 0) - - result shouldBeInstanceOf Failure::class - result.onFailure { - it shouldBeInstanceOf ResponseError::class - (it as ResponseError).messageRes shouldEqualTo R.string.reason_response - } - } - } - - @Test - fun `should return empty result error when body is null`() { - every { networkInfoProvider.get().isConnected } returns true - coEvery { apiImpl.getNextLaunches(any(), any()).isSuccessful } returns true - coEvery { apiImpl.getNextLaunches(any(), any()).body() } returns null - - runBlockingTest { - val result = source.getNextLaunches(1, 0) - - result shouldBeInstanceOf Failure::class - result.onFailure { - it shouldBeInstanceOf EmptyResultError::class - } - } - } - - @Test - fun `should return success with data if execution is successful`() { - every { networkInfoProvider.get().isConnected } returns true - coEvery { apiImpl.getNextLaunches(any(), any()).isSuccessful } returns true - coEvery { apiImpl.getNextLaunches(any(), any()).body() } returns LaunchesEntity(launches = listOf(LaunchEntity(id = 1013))) - - runBlockingTest { - val result = source.getNextLaunches(1, 0) - - result shouldBeInstanceOf Success::class - result.onSuccess { - it shouldBeInstanceOf List::class - it.size shouldEqualTo 1 - it[0].id shouldEqualTo 1013 - } - } - } - } -} diff --git a/repository/src/test/kotlin/com/melih/repository/sources/PersistanceSourceTest.kt b/repository/src/test/kotlin/com/melih/repository/sources/PersistanceSourceTest.kt deleted file mode 100644 index e40fa14..0000000 --- a/repository/src/test/kotlin/com/melih/repository/sources/PersistanceSourceTest.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.melih.repository.sources - -import android.content.Context -import com.melih.repository.entities.LaunchEntity -import com.melih.repository.interactors.base.Failure -import com.melih.repository.interactors.base.PersistenceEmpty -import com.melih.repository.interactors.base.Success -import com.melih.repository.interactors.base.onFailure -import com.melih.repository.interactors.base.onSuccess -import com.melih.repository.persistence.LaunchesDatabase -import io.mockk.coEvery -import io.mockk.every -import io.mockk.mockk -import io.mockk.mockkObject -import io.mockk.spyk -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import org.amshove.kluent.shouldBe -import org.amshove.kluent.shouldBeInstanceOf -import org.amshove.kluent.shouldEqualTo -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Nested -import org.junit.jupiter.api.Test - -class PersistanceSourceTest { - - private val ctx = mockk(relaxed = true) - private val dbImplementation = mockk(relaxed = true) - private val source = spyk(PersistenceSource(ctx)) - - private val scope = CoroutineScope(Dispatchers.IO) - - @BeforeEach - fun setup() { - mockkObject(LaunchesDatabase) - every { LaunchesDatabase.getInstance(ctx) } returns dbImplementation - } - - @Nested - inner class GetNextLaunches { - - @Test - fun `should return persistance empty error when db is empty`() { - coEvery { dbImplementation.launchesDao.getLaunches(any(), any()) } returns emptyList() - - scope.launch { - val result = source.getNextLaunches(10, 0) - - result shouldBeInstanceOf Failure::class - result.onFailure { - it shouldBeInstanceOf PersistenceEmpty::class - } - } - } - - @Test - fun `should return success with data if db is not empty`() { - coEvery { dbImplementation.launchesDao.getLaunches(any(), any()) } returns listOf(LaunchEntity(id = 1013)) - - scope.launch { - val result = source.getNextLaunches(10, 0) - - result shouldBeInstanceOf Success::class - result.onSuccess { - it.isEmpty() shouldBe false - it.size shouldEqualTo 1 - it[0].id shouldEqualTo 1013 - } - } - } - } -} diff --git a/scripts/detekt.gradle b/scripts/cq/detekt.gradle similarity index 100% rename from scripts/detekt.gradle rename to scripts/cq/detekt.gradle diff --git a/scripts/dokka.gradle b/scripts/cq/dokka.gradle similarity index 100% rename from scripts/dokka.gradle rename to scripts/cq/dokka.gradle diff --git a/scripts/cq/jacoco.gradle b/scripts/cq/jacoco.gradle new file mode 100644 index 0000000..0493b26 --- /dev/null +++ b/scripts/cq/jacoco.gradle @@ -0,0 +1,53 @@ +apply plugin: 'jacoco' + +jacoco { + toolVersion = "0.8.1" + reportsDir = file("$rootProject.projectDir/reports/jacoco/$project.name") +} + +task jacocoTestReport(type: JacocoReport, dependsOn: "testDebugUnitTest") { + group = "Reporting" + description = "Generate Jacoco coverage reports for Debug build" + + reports { + xml.enabled = true + html.enabled = true + } + + // what to exclude from coverage report + // UI, "noise", generated classes, platform classes, etc. + def excludes = [ + '**/R.class', + '**/R$*.class', + '**/*$ViewInjector*.*', + '**/BuildConfig.*', + '**/Manifest*.*', + '**/*Test*.*', + 'android/**/*.*', + '**/*Fragment.*', + '**/*Activity.*' + ] + + // generated classes + getClassDirectories().setFrom( + fileTree( + dir: "$buildDir/intermediates/classes/debug", + excludes: excludes + ) + fileTree( + dir: "$buildDir/tmp/kotlin-classes/debug", + excludes: excludes + ) + ) + + // sources + getSourceDirectories().setFrom( + files([ + android.sourceSets.main.java.srcDirs, + "src/main/kotlin" + ]) + ) + + getExecutionData().setFrom( + files("$buildDir/jacoco/testDebugUnitTest.exec") + ) +} \ No newline at end of file diff --git a/scripts/default_android_config.gradle b/scripts/default_android_config.gradle index 4546de2..c81a51b 100644 --- a/scripts/default_android_config.gradle +++ b/scripts/default_android_config.gradle @@ -1,4 +1,6 @@ -apply from: "$rootProject.projectDir/scripts/default_dependencies.gradle" +apply from: "$rootProject.projectDir/scripts/cq/detekt.gradle" +apply from: "$rootProject.projectDir/scripts/cq/dokka.gradle" +apply from: "$rootProject.projectDir/scripts/cq/jacoco.gradle" android { compileSdkVersion versions.compileSdkVersion diff --git a/scripts/default_dependencies.gradle b/scripts/default_dependencies.gradle index b9ee1c9..9e6003a 100644 --- a/scripts/default_dependencies.gradle +++ b/scripts/default_dependencies.gradle @@ -1,11 +1,10 @@ apply plugin: "de.mannodermaus.android-junit5" -apply from: "$rootProject.projectDir/scripts/detekt.gradle" -apply from: "$rootProject.projectDir/scripts/dokka.gradle" - dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation project(':abstractions') + implementation libraries.kotlin implementation libraries.dagger implementation libraries.timber @@ -18,57 +17,3 @@ dependencies { testRuntimeOnly testLibraries.jUnitEngine } - -apply plugin: 'jacoco' - -jacoco { - toolVersion = "0.8.1" - reportsDir = file("$rootProject.projectDir/reports/jacoco/$project.name") -} - -task jacocoTestReport(type: JacocoReport, dependsOn: "testDebugUnitTest") { - group = "Reporting" - description = "Generate Jacoco coverage reports for Debug build" - - reports { - xml.enabled = true - html.enabled = true - } - - // what to exclude from coverage report - // UI, "noise", generated classes, platform classes, etc. - def excludes = [ - '**/R.class', - '**/R$*.class', - '**/*$ViewInjector*.*', - '**/BuildConfig.*', - '**/Manifest*.*', - '**/*Test*.*', - 'android/**/*.*', - '**/*Fragment.*', - '**/*Activity.*' - ] - - // generated classes - getClassDirectories().setFrom( - fileTree( - dir: "$buildDir/intermediates/classes/debug", - excludes: excludes - ) + fileTree( - dir: "$buildDir/tmp/kotlin-classes/debug", - excludes: excludes - ) - ) - - // sources - getSourceDirectories().setFrom( - files([ - android.sourceSets.main.java.srcDirs, - "src/main/kotlin" - ]) - ) - - getExecutionData().setFrom( - files("$buildDir/jacoco/testDebugUnitTest.exec") - ) -} diff --git a/scripts/dependencies.gradle b/scripts/dependencies.gradle index 21ff897..49b7aed 100644 --- a/scripts/dependencies.gradle +++ b/scripts/dependencies.gradle @@ -5,28 +5,28 @@ ext { compileSdkVersion : 29, targetSdkVersion : 29, buildToolsVersion : "29.0.2", - appCompatVersion : "1.1.0-rc01", - lifecycleVersion : "2.2.0-alpha03", - fragmentVersion : "1.2.0-alpha02", - workManagerVersion : "2.3.0-alpha01", - constraintLayoutVesion : "2.0.0-beta2", + appCompatVersion : "1.1.0", + lifecycleVersion : "2.2.0-alpha05", + fragmentVersion : "1.2.0-rc01", + workManagerVersion : "2.3.0-alpha03", + constraintLayoutVesion : "2.0.0-beta3", cardViewVersion : "1.0.0", - recyclerViewVersion : "1.1.0-beta03", + recyclerViewVersion : "1.1.0-rc01", pagingVersion : "2.1.0", - viewPagerVersion : "1.0.0-beta03", + viewPagerVersion : "1.0.0-rc01", materialVersion : "1.1.0-alpha09", - swipeRefreshLayoutVersion: "1.1.0-alpha02", + swipeRefreshLayoutVersion: "1.1.0-alpha03", collectionVersion : "1.1.0", - roomVersion : "2.2.0-rc01", - daggerVersion : "2.24", - okHttpVersion : "4.0.1", - retrofitVersion : "2.6.1", + roomVersion : "2.2.0", + daggerVersion : "2.25.2", + okHttpVersion : "4.2.1", + retrofitVersion : "2.6.2", picassoVersion : "2.71828", moshiVersion : "1.8.0", - coroutinesVersion : "1.3.0-RC2", - leakCanaryVersion : "2.0-beta-2", + coroutinesVersion : "1.3.2", + leakCanaryVersion : "2.0-beta-3", timberVersion : "4.7.1", - jUnitVersion : "5.5.1", + jUnitVersion : "5.5.2", espressoVersion : "3.2.0", mockkVersion : "1.9.3", kluentVersion : "1.53", diff --git a/scripts/feature_module.gradle b/scripts/feature_module.gradle index 981efc5..89eae3a 100644 --- a/scripts/feature_module.gradle +++ b/scripts/feature_module.gradle @@ -1,5 +1,7 @@ apply plugin: "androidx.navigation.safeargs" + apply from: "$rootProject.projectDir/scripts/module.gradle" +apply from: "$rootProject.projectDir/scripts/default_dependencies.gradle" android { dataBinding { @@ -9,6 +11,8 @@ android { dependencies { implementation project(':core') + implementation project(':data:interactors') + implementation project(':data:definitions') implementation libraries.fragment implementation libraries.lifecycle diff --git a/settings.gradle b/settings.gradle index 7a766a4..ad1f600 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,11 @@ -include ':app', ':repository', ':core', ':features:launches', ':features:detail' -rootProject.name = 'Rocket Science' +rootProject.name = 'RocketScience' + +include ':abstractions', + ':core', + 'app', + ':features:launches', + ':features:detail', + ':data:interactors', + ':data:network', + ':data:persistence', + ':data:definitions'