Skip to content

Commit 83cbf92

Browse files
authored
Merge pull request #4543 from EdgeApp/jon/fix/experiment-config-init
Jon/fix/experiment-config-init
2 parents f0cfad4 + ad8fdb9 commit 83cbf92

File tree

2 files changed

+33
-18
lines changed

2 files changed

+33
-18
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
- changed: Change FlipInput styling to make the edit functionality more obvious
1010
- changed: Enable max spend for Filecoin
1111
- changed: Move asset-specific settings into their own settings page
12+
- changed: Experiment config probability distribution support percentage based values
13+
- fixed: Write updated experiment configs to disk
1214
- removed: Moonpay sell via ACH
1315
- removed: Banxa buy via Pix
1416

src/experimentConfig.ts

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,45 @@ const DEFAULT_EXPERIMENT_CONFIG: ExperimentConfig = {
2626

2727
const experimentConfigDisklet = makeReactNativeDisklet()
2828

29-
// The probability (0-1) of a feature config being set to the first value(s):
30-
// the configuration that differs from the default feature configuration.
29+
// The probability of an experiment config feature being set for a given key
3130
const experimentDistribution = {
32-
swipeLastUsp: [0.5],
33-
createAccountType: [0.5],
34-
legacyLanding: [0],
35-
createAccountText: [0.33, 0.33],
36-
signupCaptcha: [0.5]
31+
swipeLastUsp: [50, 50],
32+
createAccountType: [50, 50],
33+
legacyLanding: [100],
34+
createAccountText: [33.33, 33.33, 33.33],
35+
signupCaptcha: [50, 50]
3736
}
3837

3938
/**
4039
* Generate a random index value according to the experiment distribution to
4140
* determine which variant gets used.
4241
*/
4342
const generateExperimentConfigVal = <T>(key: keyof typeof experimentDistribution, configVals: T[]): T => {
44-
const variantProbability = experimentDistribution[key]
43+
const variantNominations = experimentDistribution[key]
4544

46-
if (variantProbability.length !== configVals.length - 1) {
45+
if (variantNominations.length !== configVals.length) {
4746
console.error(`Misconfigured experimentDistribution for: '${key}'`)
4847
} else {
48+
// Distribute the probability of each config value
49+
const variantDenomination = variantNominations.reduce((sum, probability) => sum + probability, 0)
50+
if (variantDenomination === 0) {
51+
throw new Error(`Config values for '${key}' do not add up to 100%`)
52+
} else if (variantDenomination > 101 || variantDenomination < 99) {
53+
console.warn(`Config values for '${key}' do not add up to 100% +/- 1%`)
54+
}
55+
const distributedProbabilities = variantNominations.map(variantNomination => variantNomination / variantDenomination)
56+
4957
// Generate a random number between 0 and 1
5058
const random = Math.random()
5159

5260
// Check which index the random number falls into and return the configVal:
5361
let lowerBound = 0
54-
for (let i = 0; i < variantProbability.length; i++) {
55-
if (random >= lowerBound && random < variantProbability[i]) return configVals[i]
56-
lowerBound += variantProbability[i]
62+
let upperBound = distributedProbabilities[0]
63+
for (let i = 0; i < distributedProbabilities.length; i++) {
64+
if (random >= lowerBound && random < upperBound) return configVals[i]
65+
66+
lowerBound = upperBound
67+
upperBound += distributedProbabilities[i]
5768
}
5869
}
5970

@@ -81,17 +92,19 @@ const asExperimentConfig: Cleaner<ExperimentConfig> = asObject({
8192
* This config value is available through the module's getter functions.
8293
*/
8394
const experimentConfigPromise: Promise<ExperimentConfig> = (async (): Promise<ExperimentConfig> => {
95+
let currentConfig: ExperimentConfig
8496
try {
8597
const experimentConfigJson = await experimentConfigDisklet.getText(LOCAL_EXPERIMENT_CONFIG)
86-
return asExperimentConfig(JSON.parse(experimentConfigJson))
98+
currentConfig = asExperimentConfig(JSON.parse(experimentConfigJson))
8799
} catch (err) {
88-
console.debug('Experiment config not found/out of date. Regenerating...')
100+
console.log('Experiment config not found/out of date. Regenerating...')
89101
// Not found or incompatible. Re-generate with random values according to
90102
// the defined distribution.
91-
const generatedExperimentConfig = asExperimentConfig({})
92-
await experimentConfigDisklet.setText(LOCAL_EXPERIMENT_CONFIG, JSON.stringify(generatedExperimentConfig))
93-
return generatedExperimentConfig
103+
currentConfig = asExperimentConfig({})
94104
}
105+
106+
await experimentConfigDisklet.setText(LOCAL_EXPERIMENT_CONFIG, JSON.stringify(currentConfig))
107+
return currentConfig
95108
})()
96109

97110
/**
@@ -106,7 +119,7 @@ export const getExperimentConfig = async (): Promise<ExperimentConfig> => {
106119
if (isMaestro()) return DEFAULT_EXPERIMENT_CONFIG // Test with forced defaults
107120
else if (ENV.EXPERIMENT_CONFIG_OVERRIDE != null && Object.keys(ENV.EXPERIMENT_CONFIG_OVERRIDE).length > 0) {
108121
try {
109-
console.debug('exp cfg override')
122+
console.log('ENV.EXPERIMENT_CONFIG_OVERRIDE set')
110123
return asExperimentConfig(ENV.EXPERIMENT_CONFIG_OVERRIDE)
111124
} catch (err) {
112125
console.error('Error applying ENV.EXPERIMENT_CONFIG_OVERRIDE: ', String(err))

0 commit comments

Comments
 (0)