-
Notifications
You must be signed in to change notification settings - Fork 12
/
thisorthat.js
58 lines (53 loc) · 1.8 KB
/
thisorthat.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
function randomByte() {
if (crypto && crypto.getRandomValues) {
// decent browsers
let byte = new Uint8Array(1);
crypto.getRandomValues(byte);
return byte[0];
} else if (crypto && crypto.randomBytes) {
// nodejs
let byte = crypto.randomBytes(1);
return byte[0];
} else {
// crippled browsers
return Math.floor(Math.random() * 1000 % 256);
}
}
function choose(n) {
while (true) {
let byte = randomByte();
let bucketSize = Math.floor(256/n);
if (byte <= bucketSize * n) {
return Math.ceil(byte / bucketSize);
}
}
}
/*
* thisorthat
* A method to help A/B/...n test in javascript by choosing between n config objects
* and persisting it locally.
* @param {string} name - This is a key used when storing values. It's purpose is to allow you to use multiple thisorthat's on the same page
* @param {Array} arrConfs - Array of possible configurations
* @param {Method} modifier - Method which modifies the chosen object to include the specified index
*/
function thisorthat(name, arrConfs, modifier) {
modifier = modifier || function defaultModifier(obj, idx) { obj['thisorthat'] = idx; };
let idx;
if (typeof(Storage) !== "undefined") {
let key = 'thisorthat.' + name;
idx = window.localStorage.getItem(key);
if (idx instanceof String) {
idx = parseInt(idx);
} else {
idx = choose(arrConfs.length);
window.localStorage.setItem(key, idx);
}
obj = arr_confs[idx];
modifier(obj, idx);
return obj;
} else {
// If we cannot remember the same user past page-refreshes,
// then don't include in A/B test, just use the default conf
return arr_confs[0];
}
}