Skip to content

Commit

Permalink
impl experiment, remote-config, embedding, user propoerties
Browse files Browse the repository at this point in the history
  • Loading branch information
RyosukeCla committed Aug 28, 2023
1 parent 11b7691 commit 4ac3889
Show file tree
Hide file tree
Showing 9 changed files with 353 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,18 @@ Morondava is a charming coastal town located on the western coast of Madagascar.
Text("Loading")
}
}.frame(width: nil, height: 270)

nativebrik
.experiment
.remoteConfigAsView(id: "cjm5piq23akg008u0km0") { phase in
switch phase {
case .failure:
Text("error")
case .loading:
Text("loading")
case .completed(let variant):
Text(variant.getAsString("text") ?? "Not Found")
}
}
ForEach(self.items, id: \.title) { item in
item.padding()
}
Expand Down
5 changes: 4 additions & 1 deletion ios/Nativebrik/Classes/component.swift
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ struct ComponentSwiftView: View {
}
}
self.data = ComponentSwiftViewModel()
self.data.fetchComponentAndUpdatePhase(experimentId: experimentId, componentId: componentId, config: config, repositories: repositories, modalViewController: modalViewController)
}

init<V: View>(
Expand All @@ -243,6 +244,7 @@ struct ComponentSwiftView: View {
AnyView(content(phase))
}
self.data = ComponentSwiftViewModel()
self.data.fetchComponentAndUpdatePhase(experimentId: experimentId, componentId: componentId, config: config, repositories: repositories, modalViewController: modalViewController)
}

init<I: View, P: View>(
Expand All @@ -263,9 +265,10 @@ struct ComponentSwiftView: View {
}
}
self.data = ComponentSwiftViewModel()
self.data.fetchComponentAndUpdatePhase(experimentId: experimentId, componentId: componentId, config: config, repositories: repositories, modalViewController: modalViewController)
}

public var body: some View {
var body: some View {
self.content(data.phase)
}
}
31 changes: 24 additions & 7 deletions ios/Nativebrik/Classes/embedding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,20 @@ import YogaKit


class EmbeddingUIView: ComponentUIView {
private let user: NativebrikUser
required init?(coder: NSCoder) {
self.user = NativebrikUser()
super.init(coder: coder)
}
init(
experimentId: String,
user: NativebrikUser,
config: Config,
repositories: Repositories,
modalViewController: ModalComponentViewController?,
fallback: ((_ phase: ComponentPhase) -> UIView)?
) {
self.user = user
super.init(
config: config,
repositories: repositories,
Expand All @@ -36,15 +40,18 @@ class EmbeddingUIView: ComponentUIView {
self?.renderFallback(phase: .failure)
return
}
guard let config = extractExperimentConfigMatchedToProperties(configs: configs, properties: []) else {
guard let config = extractExperimentConfigMatchedToProperties(configs: configs, properties: { seed in
return self?.user.toEventProperties(seed: seed) ?? []
}) else {
self?.renderFallback(phase: .failure)
return
}
if config.kind != .EMBED {
self?.renderFallback(phase: .failure)
return
}
guard let variant = extractExperimentVariant(config: config, normalizedUsrRnd: 1.0) else {
let normalizedUsrRnd = self?.user.getSeededNormalizedUserRnd(seed: config.seed ?? 0) ?? 0.0
guard let variant = extractExperimentVariant(config: config, normalizedUsrRnd: normalizedUsrRnd) else {
self?.renderFallback(phase: .failure)
return
}
Expand All @@ -61,6 +68,10 @@ class EmbeddingUIView: ComponentUIView {
}

class EmbeddingSwiftViewModel: ComponentSwiftViewModel {
private let user: NativebrikUser
init(user: NativebrikUser) {
self.user = user
}
func fetchAndUpdatePhase(
experimentId: String,
config: Config,
Expand All @@ -75,15 +86,18 @@ class EmbeddingSwiftViewModel: ComponentSwiftViewModel {
self?.phase = .failure
return
}
guard let experimentConfig = extractExperimentConfigMatchedToProperties(configs: configs, properties: []) else {
guard let experimentConfig = extractExperimentConfigMatchedToProperties(configs: configs, properties: { seed in
return self?.user.toEventProperties(seed: seed) ?? []
}) else {
self?.phase = .failure
return
}
if experimentConfig.kind != .EMBED {
self?.phase = .failure
return
}
guard let variant = extractExperimentVariant(config: experimentConfig, normalizedUsrRnd: 1.0) else {
let normalizedUsrRnd = self?.user.getSeededNormalizedUserRnd(seed: experimentConfig.seed ?? 0) ?? 0.0
guard let variant = extractExperimentVariant(config: experimentConfig, normalizedUsrRnd: normalizedUsrRnd) else {
self?.phase = .failure
return
}
Expand Down Expand Up @@ -112,6 +126,7 @@ struct EmbeddingSwiftView: View {

init(
experimentId: String,
user: NativebrikUser,
config: Config,
repositories: Repositories,
modalViewController: ModalComponentViewController?
Expand All @@ -124,7 +139,7 @@ struct EmbeddingSwiftView: View {
return AnyView(ProgressView())
}
}
self.data = EmbeddingSwiftViewModel()
self.data = EmbeddingSwiftViewModel(user: user)
self.data.fetchAndUpdatePhase(
experimentId: experimentId,
config: config,
Expand All @@ -135,6 +150,7 @@ struct EmbeddingSwiftView: View {

init<V: View>(
experimentId: String,
user: NativebrikUser,
config: Config,
repositories: Repositories,
modalViewController: ModalComponentViewController?,
Expand All @@ -143,7 +159,7 @@ struct EmbeddingSwiftView: View {
self.content = { phase in
AnyView(content(phase))
}
self.data = EmbeddingSwiftViewModel()
self.data = EmbeddingSwiftViewModel(user: user)
self.data.fetchAndUpdatePhase(
experimentId: experimentId,
config: config,
Expand All @@ -154,6 +170,7 @@ struct EmbeddingSwiftView: View {

init<I: View, P: View>(
experimentId: String,
user: NativebrikUser,
config: Config,
repositories: Repositories,
modalViewController: ModalComponentViewController?,
Expand All @@ -168,7 +185,7 @@ struct EmbeddingSwiftView: View {
return AnyView(placeholder())
}
}
self.data = EmbeddingSwiftViewModel()
self.data = EmbeddingSwiftViewModel(user: user)
self.data.fetchAndUpdatePhase(
experimentId: experimentId,
config: config,
Expand Down
13 changes: 9 additions & 4 deletions ios/Nativebrik/Classes/experiment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ func extractExperimentVariant(config: ExperimentConfig, normalizedUsrRnd: Double
return baseline
}

if variants.count == 0 {
return baseline
}

let baselineWeight = baseline.weight ?? 1
var weights = [baselineWeight]
var weightSum = baselineWeight
Expand All @@ -40,15 +44,16 @@ func extractExperimentVariant(config: ExperimentConfig, normalizedUsrRnd: Double
}

// here is calculation of the picking from the probability.
// X is selected when p_X(x) < F_X(x)
// X is selected when p_X(x) >= F_X(x)
// where F_X(x) := Integral p_X(t)dt, the definition of comulative distribution function
var comulativeDistributionValue: Double = 0.0
var selectedVariantIndex: Int = 0
for (index, weight) in weights.enumerated() {
let probability: Double = Double(weight) / Double(weightSum)
comulativeDistributionValue += probability
print(comulativeDistributionValue, index)

if comulativeDistributionValue < normalizedUsrRnd {
if comulativeDistributionValue >= normalizedUsrRnd {
selectedVariantIndex = index
break
}
Expand All @@ -61,7 +66,7 @@ func extractExperimentVariant(config: ExperimentConfig, normalizedUsrRnd: Double
return variants[selectedVariantIndex - 1]
}

func extractExperimentConfigMatchedToProperties(configs: ExperimentConfigs, properties: [EventProperty]) -> ExperimentConfig? {
func extractExperimentConfigMatchedToProperties(configs: ExperimentConfigs, properties: (_ seed: Int) -> [EventProperty]) -> ExperimentConfig? {
guard let configs = configs.configs else {
return nil
}
Expand All @@ -72,7 +77,7 @@ func extractExperimentConfigMatchedToProperties(configs: ExperimentConfigs, prop
guard let distribution = config.distribution else {
return true
}
return isInDistribution(distribution: distribution, properties: properties)
return isInDistribution(distribution: distribution, properties: properties(config.seed ?? 0))
}
}

Expand Down
4 changes: 2 additions & 2 deletions ios/Nativebrik/Classes/overlay.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ class OverlayViewController: UIViewController {
let modalForTriggerViewController: ModalComponentViewController = ModalComponentViewController()
let triggerViewController: TriggerViewController

init(config: Config, repositories: Repositories) {
self.triggerViewController = TriggerViewController(config: config, repositories: repositories, modalViewController: self.modalForTriggerViewController)
init(user: NativebrikUser, config: Config, repositories: Repositories) {
self.triggerViewController = TriggerViewController(user: user, config: config, repositories: repositories, modalViewController: self.modalForTriggerViewController)
super.init(nibName: nil, bundle: nil)

self.addChild(self.modalViewController)
Expand Down
Loading

0 comments on commit 4ac3889

Please sign in to comment.