Skip to content

Commit 987ff6c

Browse files
wip: holdout config struct added
1 parent fd6535a commit 987ff6c

File tree

4 files changed

+174
-56
lines changed

4 files changed

+174
-56
lines changed

OptimizelySwiftSDK.xcodeproj/project.pbxproj

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,6 +2034,22 @@
20342034
984FE51E2CC8AA88004F6F41 /* UserProfileTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 984FE5102CC8AA88004F6F41 /* UserProfileTracker.swift */; };
20352035
984FE51F2CC8AA88004F6F41 /* UserProfileTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 984FE5102CC8AA88004F6F41 /* UserProfileTracker.swift */; };
20362036
984FE5202CC8AA88004F6F41 /* UserProfileTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 984FE5102CC8AA88004F6F41 /* UserProfileTracker.swift */; };
2037+
98AC97E22DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
2038+
98AC97E32DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
2039+
98AC97E42DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
2040+
98AC97E52DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
2041+
98AC97E62DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
2042+
98AC97E72DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
2043+
98AC97E82DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
2044+
98AC97E92DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
2045+
98AC97EA2DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
2046+
98AC97EB2DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
2047+
98AC97EC2DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
2048+
98AC97ED2DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
2049+
98AC97EE2DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
2050+
98AC97EF2DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
2051+
98AC97F02DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
2052+
98AC97F12DAE4579001405DD /* HoldoutConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AC97E12DAE4579001405DD /* HoldoutConfig.swift */; };
20372053
BD1C3E8524E4399C0084B4DA /* SemanticVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B97DD93249D327F003DE606 /* SemanticVersion.swift */; };
20382054
BD64853C2491474500F30986 /* Optimizely.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E75167A22C520D400B2B157 /* Optimizely.h */; settings = {ATTRIBUTES = (Public, ); }; };
20392055
BD64853E2491474500F30986 /* Audience.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E75169822C520D400B2B157 /* Audience.swift */; };
@@ -2477,6 +2493,7 @@
24772493
982C071E2D8C82AE0068B1FF /* HoldoutTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoldoutTests.swift; sourceTree = "<group>"; };
24782494
984FE5102CC8AA88004F6F41 /* UserProfileTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserProfileTracker.swift; sourceTree = "<group>"; };
24792495
987F11D92AF3F56F0083D3F9 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
2496+
98AC97E12DAE4579001405DD /* HoldoutConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoldoutConfig.swift; sourceTree = "<group>"; };
24802497
BD6485812491474500F30986 /* Optimizely.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Optimizely.framework; sourceTree = BUILT_PRODUCTS_DIR; };
24812498
C78CAF572445AD8D009FE876 /* OptimizelyJSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimizelyJSON.swift; sourceTree = "<group>"; };
24822499
C78CAF652446DB91009FE876 /* OptimizelyClientTests_OptimizelyJSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptimizelyClientTests_OptimizelyJSON.swift; sourceTree = "<group>"; };
@@ -2857,6 +2874,7 @@
28572874
6E75169022C520D400B2B157 /* Variation.swift */,
28582875
6E75169122C520D400B2B157 /* TrafficAllocation.swift */,
28592876
6E75169222C520D400B2B157 /* Project.swift */,
2877+
98AC97E12DAE4579001405DD /* HoldoutConfig.swift */,
28602878
6E75169322C520D400B2B157 /* Experiment.swift */,
28612879
980CC9072D833F2800E07D24 /* ExperimentCore.swift */,
28622880
980CC8F62D833F0D00E07D24 /* Holdout.swift */,
@@ -4181,6 +4199,7 @@
41814199
845945C3287758A100D13E11 /* OdpConfig.swift in Sources */,
41824200
6E14CD832423F9A100010234 /* DataStoreQueueStackImpl.swift in Sources */,
41834201
848617F12863E21200B7F41B /* OdpEventApiManager.swift in Sources */,
4202+
98AC97E52DAE4579001405DD /* HoldoutConfig.swift in Sources */,
41844203
6E14CD812423F9A100010234 /* DataStoreUserDefaults.swift in Sources */,
41854204
6E14CD802423F9A100010234 /* DataStoreMemory.swift in Sources */,
41864205
6E14CDA02423F9C300010234 /* OptimizelyClient+Extension.swift in Sources */,
@@ -4369,6 +4388,7 @@
43694388
6E424CB926324B1D0081004A /* Constants.swift in Sources */,
43704389
6E424CBA26324B1D0081004A /* Notifications.swift in Sources */,
43714390
6E424CBB26324B1D0081004A /* MurmurHash3.swift in Sources */,
4391+
98AC97EC2DAE4579001405DD /* HoldoutConfig.swift in Sources */,
43724392
8464087628130D3200CCF97D /* Integration.swift in Sources */,
43734393
848617CE2863DC2700B7F41B /* OdpSegmentManager.swift in Sources */,
43744394
848617F02863E21200B7F41B /* OdpEventApiManager.swift in Sources */,
@@ -4410,6 +4430,7 @@
44104430
845945BD2877589E00D13E11 /* OdpConfig.swift in Sources */,
44114431
984FE51C2CC8AA88004F6F41 /* UserProfileTracker.swift in Sources */,
44124432
6E75171322C520D400B2B157 /* OptimizelyClient+ObjC.swift in Sources */,
4433+
98AC97EF2DAE4579001405DD /* HoldoutConfig.swift in Sources */,
44134434
6E75191922C520D500B2B157 /* OPTNotificationCenter.swift in Sources */,
44144435
6E7518A122C520D400B2B157 /* FeatureFlag.swift in Sources */,
44154436
6E994B3525A3E6EA00999262 /* DecisionResponse.swift in Sources */,
@@ -4494,6 +4515,7 @@
44944515
845945C7287758A300D13E11 /* OdpConfig.swift in Sources */,
44954516
6E75175622C520D400B2B157 /* LogMessage.swift in Sources */,
44964517
848617F62863E21200B7F41B /* OdpEventApiManager.swift in Sources */,
4518+
98AC97EB2DAE4579001405DD /* HoldoutConfig.swift in Sources */,
44974519
6E75193822C520D500B2B157 /* OPTDataStore.swift in Sources */,
44984520
6E75191422C520D500B2B157 /* BackgroundingCallbacks.swift in Sources */,
44994521
6E75172622C520D400B2B157 /* OptimizelyResult.swift in Sources */,
@@ -4596,6 +4618,7 @@
45964618
6EF8DE2024BD1BB2008B9488 /* OptimizelyDecideOption.swift in Sources */,
45974619
6E7517D822C520D400B2B157 /* DefaultNotificationCenter.swift in Sources */,
45984620
6E75177622C520D400B2B157 /* SDKVersion.swift in Sources */,
4621+
98AC97E32DAE4579001405DD /* HoldoutConfig.swift in Sources */,
45994622
84518B1F287665020023F104 /* OptimizelyClientTests_ODP.swift in Sources */,
46004623
6E7516FE22C520D400B2B157 /* OptimizelyLogLevel.swift in Sources */,
46014624
6E75173A22C520D400B2B157 /* MurmurHash3.swift in Sources */,
@@ -4720,6 +4743,7 @@
47204743
6EC6DD4A24ABF89B0017D296 /* OptimizelyUserContext.swift in Sources */,
47214744
6E75170122C520D400B2B157 /* OptimizelyLogLevel.swift in Sources */,
47224745
8464087B28130D3200CCF97D /* Integration.swift in Sources */,
4746+
98AC97EA2DAE4579001405DD /* HoldoutConfig.swift in Sources */,
47234747
84E2E96C28540B5E001114AB /* OptimizelySdkSettings.swift in Sources */,
47244748
6EF8DE3A24BF7D69008B9488 /* DecisionReasons.swift in Sources */,
47254749
6E7516B922C520D400B2B157 /* DefaultUserProfileService.swift in Sources */,
@@ -4866,6 +4890,7 @@
48664890
6E7517C522C520D400B2B157 /* DefaultDatafileHandler.swift in Sources */,
48674891
6E75190922C520D500B2B157 /* Attribute.swift in Sources */,
48684892
6E75177B22C520D400B2B157 /* SDKVersion.swift in Sources */,
4893+
98AC97F12DAE4579001405DD /* HoldoutConfig.swift in Sources */,
48694894
84E7ABC827D2A1F100447CAE /* ThreadSafeLogger.swift in Sources */,
48704895
6E7E9B562523F8C6009E4426 /* OptimizelyUserContextTests_Decide_Legacy.swift in Sources */,
48714896
6EC6DD3C24ABF6990017D296 /* OptimizelyClient+Decide.swift in Sources */,
@@ -5035,6 +5060,7 @@
50355060
84E7ABC927D2A1F100447CAE /* ThreadSafeLogger.swift in Sources */,
50365061
6E9B119122C5488300C22D81 /* EventForDispatchTests.swift in Sources */,
50375062
6E7517EA22C520D400B2B157 /* DefaultDecisionService.swift in Sources */,
5063+
98AC97F02DAE4579001405DD /* HoldoutConfig.swift in Sources */,
50385064
6E75171C22C520D400B2B157 /* OptimizelyClient+ObjC.swift in Sources */,
50395065
6E7516B022C520D400B2B157 /* DefaultLogger.swift in Sources */,
50405066
0B97DD9C249D3735003DE606 /* SemanticVersion.swift in Sources */,
@@ -5159,6 +5185,7 @@
51595185
6E7516B522C520D400B2B157 /* DefaultUserProfileService.swift in Sources */,
51605186
6E7516A922C520D400B2B157 /* DefaultLogger.swift in Sources */,
51615187
6E7517D722C520D400B2B157 /* DefaultNotificationCenter.swift in Sources */,
5188+
98AC97E72DAE4579001405DD /* HoldoutConfig.swift in Sources */,
51625189
6E75181F22C520D400B2B157 /* BatchEventBuilder.swift in Sources */,
51635190
84F6BADD27FD011B004BE62A /* OptimizelyUserContextTests_ODP_Decide.swift in Sources */,
51645191
84E2E9472852A378001114AB /* VuidManager.swift in Sources */,
@@ -5309,6 +5336,7 @@
53095336
84E7ABC427D2A1F100447CAE /* ThreadSafeLogger.swift in Sources */,
53105337
6E9B117B22C5488100C22D81 /* EventForDispatchTests.swift in Sources */,
53115338
6E7517E522C520D400B2B157 /* DefaultDecisionService.swift in Sources */,
5339+
98AC97E92DAE4579001405DD /* HoldoutConfig.swift in Sources */,
53125340
6E75171722C520D400B2B157 /* OptimizelyClient+ObjC.swift in Sources */,
53135341
6E7516AB22C520D400B2B157 /* DefaultLogger.swift in Sources */,
53145342
0B97DD9B249D3733003DE606 /* SemanticVersion.swift in Sources */,
@@ -5433,6 +5461,7 @@
54335461
84E7ABC527D2A1F100447CAE /* ThreadSafeLogger.swift in Sources */,
54345462
6E7518BE22C520D400B2B157 /* Variable.swift in Sources */,
54355463
6E7518CA22C520D400B2B157 /* Audience.swift in Sources */,
5464+
98AC97E62DAE4579001405DD /* HoldoutConfig.swift in Sources */,
54365465
848617E42863E21200B7F41B /* OdpSegmentApiManager.swift in Sources */,
54375466
6E75187622C520D400B2B157 /* Variation.swift in Sources */,
54385467
6E7517F222C520D400B2B157 /* DataStoreMemory.swift in Sources */,
@@ -5537,6 +5566,7 @@
55375566
84E7ABCA27D2A1F100447CAE /* ThreadSafeLogger.swift in Sources */,
55385567
6E7518C322C520D400B2B157 /* Variable.swift in Sources */,
55395568
6E7518CF22C520D400B2B157 /* Audience.swift in Sources */,
5569+
98AC97E42DAE4579001405DD /* HoldoutConfig.swift in Sources */,
55405570
848617E92863E21200B7F41B /* OdpSegmentApiManager.swift in Sources */,
55415571
6E75187B22C520D400B2B157 /* Variation.swift in Sources */,
55425572
6E7517F722C520D400B2B157 /* DataStoreMemory.swift in Sources */,
@@ -5592,6 +5622,7 @@
55925622
845945BC2877589D00D13E11 /* OdpConfig.swift in Sources */,
55935623
984FE5192CC8AA88004F6F41 /* UserProfileTracker.swift in Sources */,
55945624
6E75184022C520D400B2B157 /* Event.swift in Sources */,
5625+
98AC97EE2DAE4579001405DD /* HoldoutConfig.swift in Sources */,
55955626
6E7516E222C520D400B2B157 /* OPTEventDispatcher.swift in Sources */,
55965627
6E7517D422C520D400B2B157 /* DefaultNotificationCenter.swift in Sources */,
55975628
6E994B3425A3E6EA00999262 /* DecisionResponse.swift in Sources */,
@@ -5676,6 +5707,7 @@
56765707
845945C02877589F00D13E11 /* OdpConfig.swift in Sources */,
56775708
6E75175022C520D400B2B157 /* LogMessage.swift in Sources */,
56785709
848617EE2863E21200B7F41B /* OdpEventApiManager.swift in Sources */,
5710+
98AC97E82DAE4579001405DD /* HoldoutConfig.swift in Sources */,
56795711
6E75193222C520D500B2B157 /* OPTDataStore.swift in Sources */,
56805712
6E75190E22C520D500B2B157 /* BackgroundingCallbacks.swift in Sources */,
56815713
6E75172022C520D400B2B157 /* OptimizelyResult.swift in Sources */,
@@ -5841,6 +5873,7 @@
58415873
75C71A3125E454460084187E /* Group.swift in Sources */,
58425874
75C71A3225E454460084187E /* Variable.swift in Sources */,
58435875
848617DD2863E21200B7F41B /* OdpSegmentApiManager.swift in Sources */,
5876+
98AC97E22DAE4579001405DD /* HoldoutConfig.swift in Sources */,
58445877
75C71A3325E454460084187E /* Attribute.swift in Sources */,
58455878
75C71A3425E454460084187E /* BackgroundingCallbacks.swift in Sources */,
58465879
75C71A3525E454460084187E /* OPTNotificationCenter.swift in Sources */,
@@ -5890,6 +5923,7 @@
58905923
845945BE2877589E00D13E11 /* OdpConfig.swift in Sources */,
58915924
984FE51A2CC8AA88004F6F41 /* UserProfileTracker.swift in Sources */,
58925925
BD6485462491474500F30986 /* Event.swift in Sources */,
5926+
98AC97ED2DAE4579001405DD /* HoldoutConfig.swift in Sources */,
58935927
BD6485472491474500F30986 /* OPTEventDispatcher.swift in Sources */,
58945928
BD6485482491474500F30986 /* DefaultNotificationCenter.swift in Sources */,
58955929
6E994B3625A3E6EA00999262 /* DecisionResponse.swift in Sources */,
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//
2+
// Copyright 2022, Optimizely, Inc. and contributors
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
17+
import Foundation
18+
19+
struct HoldoutConfig {
20+
var allHoldouts: [Holdout] {
21+
didSet {
22+
updateHoldoutProperties()
23+
}
24+
}
25+
private(set) var holdoutIdMap: [String: Holdout] = [:]
26+
private(set) var global: [Holdout] = []
27+
private(set) var others: [Holdout] = []
28+
private(set) var includedHoldouts: [String: [Holdout]] = [:]
29+
private(set) var excludedHoldouts: [String: [Holdout]] = [:]
30+
private(set) var flagHoldoutsMap: [String: [Holdout]] = [:]
31+
32+
init(allholdouts: [Holdout] = []) {
33+
self.allHoldouts = allholdouts
34+
updateHoldoutProperties()
35+
}
36+
37+
mutating func updateHoldoutProperties() {
38+
holdoutIdMap = {
39+
var map = [String: Holdout]()
40+
allHoldouts.forEach { map[$0.id] = $0 }
41+
return map
42+
}()
43+
flagHoldoutsMap = [:]
44+
global = []
45+
others = []
46+
includedHoldouts = [:]
47+
excludedHoldouts = [:]
48+
49+
for holdout in allHoldouts {
50+
switch (holdout.includedFlags.isEmpty, holdout.excludedFlags.isEmpty) {
51+
case (true, true):
52+
global.append(holdout)
53+
case (false, _):
54+
holdout.includedFlags.forEach { flagId in
55+
if var existing = includedHoldouts[flagId] {
56+
existing.append(holdout)
57+
includedHoldouts[flagId] = existing
58+
} else {
59+
includedHoldouts[flagId] = [holdout]
60+
}
61+
}
62+
case (_, false):
63+
others.append(holdout)
64+
holdout.excludedFlags.forEach { flagId in
65+
if var existing = excludedHoldouts[flagId] {
66+
existing.append(holdout)
67+
excludedHoldouts[flagId] = existing
68+
} else {
69+
excludedHoldouts[flagId] = [holdout]
70+
}
71+
}
72+
}
73+
}
74+
}
75+
76+
mutating func getHoldoutForFlag(id: String) -> [Holdout] {
77+
guard !allHoldouts.isEmpty else { return [] }
78+
79+
if let holdouts = flagHoldoutsMap[id] {
80+
return holdouts
81+
}
82+
83+
if let included = includedHoldouts[id], !included.isEmpty {
84+
flagHoldoutsMap[id] = global + included
85+
} else {
86+
let excluded = excludedHoldouts[id] ?? []
87+
let filteredHoldouts = others.filter { holdout in
88+
return !excluded.contains(holdout)
89+
}
90+
flagHoldoutsMap[id] = global + filteredHoldouts
91+
}
92+
return flagHoldoutsMap[id] ?? []
93+
}
94+
95+
func getHoldout(id: String) -> Holdout? {
96+
return holdoutIdMap[id]
97+
}
98+
}
99+

0 commit comments

Comments
 (0)