Skip to content

Commit

Permalink
MBX-3390 Added filter for innaps by operation (#466)
Browse files Browse the repository at this point in the history
Co-authored-by: Akylbek Utekeshev <[email protected]>
  • Loading branch information
Vailence and Akylbek Utekeshev authored Nov 22, 2024
1 parent 38e9b02 commit 0ff2518
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 54 deletions.
15 changes: 11 additions & 4 deletions Mindbox/InAppMessages/InAppConfigurationMapper/InappMapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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()
Expand Down Expand Up @@ -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)
Expand All @@ -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] = []

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down Expand Up @@ -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] {
Expand Down Expand Up @@ -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)
}
Expand Down

0 comments on commit 0ff2518

Please sign in to comment.