From 0ff2518355bbd7950777f61950f2414a30645034 Mon Sep 17 00:00:00 2001 From: Akylbek Utekeshev Date: Fri, 22 Nov 2024 13:27:26 +0500 Subject: [PATCH] MBX-3390 Added filter for innaps by operation (#466) Co-authored-by: Akylbek Utekeshev --- .../InappMapper.swift | 15 ++- .../InappFilterService/InappFilter.swift | 101 +++++++++--------- 2 files changed, 62 insertions(+), 54 deletions(-) diff --git a/Mindbox/InAppMessages/InAppConfigurationMapper/InappMapper.swift b/Mindbox/InAppMessages/InAppConfigurationMapper/InappMapper.swift index 401bd6a1..f322a6b4 100644 --- a/Mindbox/InAppMessages/InAppConfigurationMapper/InappMapper.swift +++ b/Mindbox/InAppMessages/InAppConfigurationMapper/InappMapper.swift @@ -24,6 +24,7 @@ class InappMapper: InappMapperProtocol { private let dataFacade: InAppConfigurationDataFacadeProtocol private var shownInappIDWithHashValue: [String: Int] = [:] + private var abTests: [ABTest]? init(targetingChecker: InAppTargetingCheckerProtocol, inappFilterService: InappFilterProtocol, @@ -37,7 +38,7 @@ class InappMapper: InappMapperProtocol { _ response: ConfigResponse, _ completion: @escaping (InAppFormData?) -> Void) { setupEnvironment(event: event) - + abTests = response.abtests let filteredInapps = getFilteredInapps(inappsDTO: response.inapps?.elements, abTests: response.abtests) prepareTargetingChecker(for: filteredInapps) prepareForRemainingTargeting() @@ -70,9 +71,8 @@ class InappMapper: InappMapperProtocol { private func chooseInappToShow(filteredInapps: [InApp], completion: @escaping (InAppFormData?) -> Void) { dataFacade.fetchDependencies(model: applicationEvent?.model) { - let inapps = self.applicationEvent == nil ? filteredInapps : self.getOperationInappsByEvent() - let filteredByAlreadyShown = self.inappFilterService.filterInappsByAlreadyShown(inapps) - let suitableInapps = self.filterByInappsEvents(inapps: filteredByAlreadyShown) + let inapps = self.applicationEvent == nil ? filteredInapps : self.getOperationInappsByEventForShow() + let suitableInapps = self.filterByInappsEvents(inapps: inapps) if suitableInapps.isEmpty { completion(nil) @@ -94,6 +94,13 @@ class InappMapper: InappMapperProtocol { return [] } + private func getOperationInappsByEventForShow() -> [InApp] { + let inapps = getOperationInappsByEvent() + let filteredByABTest = inappFilterService.filterInappsByABTests(abTests, responseInapps: inapps) + let filteredByAlreadyShown = self.inappFilterService.filterInappsByAlreadyShown(filteredByABTest) + return filteredByAlreadyShown + } + private func filterByInappsEvents(inapps: [InApp]) -> [InAppTransitionData] { var filteredInAppsByEvent: [InAppTransitionData] = [] diff --git a/Mindbox/InAppMessages/InAppConfigurationMapper/Services/InappFilterService/InappFilter.swift b/Mindbox/InAppMessages/InAppConfigurationMapper/Services/InappFilterService/InappFilter.swift index 629c9cb7..87ab117e 100644 --- a/Mindbox/InAppMessages/InAppConfigurationMapper/Services/InappFilterService/InappFilter.swift +++ b/Mindbox/InAppMessages/InAppConfigurationMapper/Services/InappFilterService/InappFilter.swift @@ -11,6 +11,7 @@ import MindboxLogger protocol InappFilterProtocol { func filter(inapps: [InAppDTO]?, abTests: [ABTest]?) -> [InApp] + func filterInappsByABTests(_ abTests: [ABTest]?, responseInapps: [InApp]?) -> [InApp] func filterInappsByAlreadyShown(_ inapps: [InApp]) -> [InApp] var validInapps: [InApp] { get } var shownInAppDictionary: [String: Date] { get } @@ -46,56 +47,6 @@ final class InappsFilterService: InappFilterProtocol { return filteredByAlreadyShown } - func filterInappsByAlreadyShown(_ inapps: [InApp]) -> [InApp] { - let shownInAppDictionary = persistenceStorage.shownInappsDictionary ?? [:] - Logger.common(message: "Shown in-apps ids: [\(shownInAppDictionary.keys)]", level: .info, category: .inAppMessages) - let filteredInapps = inapps.filter { - Logger.common(message: "[Inapp frequency] Start checking frequency of inapp with id = \($0.id)", level: .debug, category: .inAppMessages) - let frequencyValidator = self.createFrequencyValidator() - let result = frequencyValidator.isValid(item: $0) - Logger.common(message: "[Inapp frequency] Finish checking frequency of inapp with id = \($0.id)", level: .debug, category: .inAppMessages) - return result - } - - return filteredInapps - } -} - -// MARK: - Private methods -private extension InappsFilterService { - func filterInappsBySDKVersion(_ inapps: [InAppDTO]) -> [InAppDTO] { - let inapps = inapps - let filteredInapps = inapps.filter { - sdkVersionValidator.isValid(item: $0.sdkVersion) - } - - return filteredInapps - } - - func filterValidInAppMessages(_ inapps: [InAppDTO]) -> [InApp] { - var filteredInapps: [InApp] = [] - for inapp in inapps { - do { - let variants = try variantsFilter.filter(inapp.form.variants) - if !variants.isEmpty { - let formModel = InAppForm(variants: variants) - let inappModel = InApp(id: inapp.id, - sdkVersion: inapp.sdkVersion, - targeting: inapp.targeting, - frequency: inapp.frequency, - form: formModel) - filteredInapps.append(inappModel) - } - } catch { - Logger.common(message: "In-app [ID:] \(inapp.id)\n[Error]: \(error)", level: .error, category: .inAppMessages) - } - } - - Logger.common(message: "Filtering process completed. \(filteredInapps.count) valid in-app(s) found.", level: .debug, category: .inAppMessages) - validInapps = filteredInapps - return filteredInapps - } - // FIXME: Rewrite this func in the future // swiftlint:disable:next cyclomatic_complexity func filterInappsByABTests(_ abTests: [ABTest]?, responseInapps: [InApp]?) -> [InApp] { @@ -167,6 +118,56 @@ private extension InappsFilterService { return result } + func filterInappsByAlreadyShown(_ inapps: [InApp]) -> [InApp] { + let shownInAppDictionary = persistenceStorage.shownInappsDictionary ?? [:] + Logger.common(message: "Shown in-apps ids: [\(shownInAppDictionary.keys)]", level: .info, category: .inAppMessages) + let filteredInapps = inapps.filter { + Logger.common(message: "[Inapp frequency] Start checking frequency of inapp with id = \($0.id)", level: .debug, category: .inAppMessages) + let frequencyValidator = self.createFrequencyValidator() + let result = frequencyValidator.isValid(item: $0) + Logger.common(message: "[Inapp frequency] Finish checking frequency of inapp with id = \($0.id)", level: .debug, category: .inAppMessages) + return result + } + + return filteredInapps + } +} + +// MARK: - Private methods +private extension InappsFilterService { + func filterInappsBySDKVersion(_ inapps: [InAppDTO]) -> [InAppDTO] { + let inapps = inapps + let filteredInapps = inapps.filter { + sdkVersionValidator.isValid(item: $0.sdkVersion) + } + + return filteredInapps + } + + func filterValidInAppMessages(_ inapps: [InAppDTO]) -> [InApp] { + var filteredInapps: [InApp] = [] + for inapp in inapps { + do { + let variants = try variantsFilter.filter(inapp.form.variants) + if !variants.isEmpty { + let formModel = InAppForm(variants: variants) + let inappModel = InApp(id: inapp.id, + sdkVersion: inapp.sdkVersion, + targeting: inapp.targeting, + frequency: inapp.frequency, + form: formModel) + filteredInapps.append(inappModel) + } + } catch { + Logger.common(message: "In-app [ID:] \(inapp.id)\n[Error]: \(error)", level: .error, category: .inAppMessages) + } + } + + Logger.common(message: "Filtering process completed. \(filteredInapps.count) valid in-app(s) found.", level: .debug, category: .inAppMessages) + validInapps = filteredInapps + return filteredInapps + } + private func createFrequencyValidator() -> InappFrequencyValidator { InappFrequencyValidator(persistenceStorage: persistenceStorage) }