Skip to content

Commit

Permalink
addressed #40 issue and changed the way choosing recipe with sampleRate
Browse files Browse the repository at this point in the history
  • Loading branch information
allmywant committed Dec 20, 2019
1 parent fb42045 commit efec23b
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 107 deletions.
142 changes: 43 additions & 99 deletions lib/mojito.js
Original file line number Diff line number Diff line change
Expand Up @@ -297,72 +297,44 @@ Mojito = (function ()
chooseRecipe: function ()
{
var recipes = this.options.recipes;
var chosen_recipe, partitions, chosen_partition, sameRecipes;
var chosenRecipe, partitions, chosenPartition;

// check if sample property was set in recipe objects
var samplesWasSet = true;
var samplesSet = true;
for (var p in recipes)
{
if (recipes[p].sampleRate == null)
{
samplesWasSet = false;
samplesSet = false;
break;
}
}

// No sample set, just use pure random
if (!samplesWasSet)
// no sample was set, just use pure random
if (!samplesSet)
{
partitions = 1.0 / this.recipes.length;
chosen_partition = Math.floor(this.getRandom() / partitions);
chosen_recipe = this.recipes[chosen_partition];
chosenPartition = Math.floor(this.getRandom() / partitions);
chosenRecipe = this.recipes[chosenPartition];
}
else
{
var orderedRecipes = this.getOrderedBySampleRecipes();
var sameSimpleRateRecipes = this.getSameSimpleRateValueRecipes(orderedRecipes);

var weight = 0;
var lastSample = orderedRecipes[orderedRecipes.length - 1].sampleRate;

while (!chosen_recipe)
{
var orderedRecipes = this.getOrderedBySampleRecipes(),
checkedRecipeSamples = 0,
weight = this.getRandom();

for (var i = 0; i < orderedRecipes.length; i++)
{
if (weight <= orderedRecipes[i].sampleRate)
{
chosen_recipe = orderedRecipes[i].key;
sameRecipes = sameSimpleRateRecipes[orderedRecipes[i].sampleRate];

if (sameRecipes)
{
partitions = 1.0 / sameRecipes.length;
chosen_partition = Math.floor(this.getRandom() / partitions);
chosen_recipe = sameRecipes[chosen_partition].key;
}

break;
}
}

if (!chosen_recipe && (weight - lastSample) <= (1 - lastSample))
for (var i = 0; i < orderedRecipes.length; i++)
{
checkedRecipeSamples += orderedRecipes[i].sampleRate;
if (weight <= checkedRecipeSamples)
{
chosen_recipe = orderedRecipes[orderedRecipes.length - 1].key;
sameRecipes = sameSimpleRateRecipes[orderedRecipes[orderedRecipes.length - 1].sampleRate];

if (sameRecipes)
{
partitions = 1.0 / sameRecipes.length;
chosen_partition = Math.floor(this.getRandom() / partitions);
chosen_recipe = sameRecipes[chosen_partition].key;
}
chosenRecipe = orderedRecipes[i].key;
break;
}
}
}

return chosen_recipe;
return chosenRecipe;
},
/**
* Get random value from decisionAdapter
Expand Down Expand Up @@ -410,60 +382,38 @@ Mojito = (function ()

return orderedRecipes;
},
getSameSimpleRateValueRecipes: function (orderedRecipes)
getStoredDecision: function()
{
var tempRecipes = {}, simpleRate;
for (var i = 0, c = orderedRecipes.length; i < c; i++)
if (!this.options.storedDecision)
{
simpleRate = orderedRecipes[i].sampleRate;
if (!tempRecipes[simpleRate])
{
tempRecipes[simpleRate] = [];
tempRecipes[simpleRate].push(orderedRecipes[i]);
}
else
{
tempRecipes[simpleRate].push(orderedRecipes[i]);
}
}
this.options.storedDecision = {inTest: null, recipe: null};
var cookie = this.getCookie();

for (var p in tempRecipes)
{
if (tempRecipes[p].length <= 1)
if (cookie != null)
{
delete tempRecipes[p];
values = cookie.split('.');
this.options.storedDecision.inTest = values[0] == 1;
this.options.storedDecision.recipe = values[1]||null;
}
}

return tempRecipes;
return this.options.storedDecision;
},
inTest: function ()
{
var cookie = this.getCookie(),
inTest,
values;

if (cookie != null)
{
values = cookie.split('.');
inTest = values[0];
}

return inTest == null ? null : inTest == 1;
return this.getStoredDecision().inTest;
},
setInTest: function (val)
{
var cookie = this.getCookie(),
inTest,
values;

if (cookie != null)
{
values = cookie.split('.');
inTest = values[0];

// Return if inTest value is unchanged
if (inTest == val)
if (values[0] == val)
{
return;
}
Expand All @@ -472,33 +422,27 @@ Mojito = (function ()
{
this.setCookie('', val + '.' + values[1]);
}
else
{
this.setCookie('', val);
}
}
else
{
// Cookie doesn't exist yet
this.setCookie('', val);
}
},
getRecipe: function ()
{
var cookie = this.getCookie(),
values;

if (this.inTest())
if (!this.options.storedDecision)
{
values = cookie.split('.');

if (values.length == 2)
{
return values[1];
}

return null;
}
else
{
return null;
this.options.storedDecision = {};
}

this.options.storedDecision.inTest = val == 1;
},
getRecipe: function ()
{
return this.getStoredDecision().recipe;
},
setRecipe: function (recipe)
{
Expand All @@ -507,21 +451,21 @@ Mojito = (function ()

if (Utils.arrayIndexOf(this.recipes, recipe) == -1)
{
return false;
return;
}
else
{
values = cookie.split('.');
// Return if recipe value is unchanged
if (values[1] == recipe)
{
return false;
return;
}

this.setCookie('', values[0] + '.' + recipe);

return true;
}

this.options.storedDecision.recipe = recipe;
},
setCookie: function (name, value)
{
Expand Down
99 changes: 91 additions & 8 deletions tests/test_suite.html
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,90 @@
w12PreviewModeWorking.should.equal(true);
});

var w13T1Chosen = false,
w13T3Chosen = false,
w13T5Chosen = false;

w13Test = {
id: 'w13',
state: 'live',
name: 'recipe_simple_rate_test',
sampleRate: 1,
options: {},
trigger: function (e) {
e.activate();
},
recipes: {
'1': {
name: 'treatment1',
sampleRate: 0.4,
js: function()
{
w13T1Chosen = true;
}
},
'2': {
name: 'treatment2',
sampleRate: 0.1
},
'3': {
name: 'treatment3',
sampleRate: 0.1,
js: function()
{
w13T3Chosen = true;
}
},
'4': {
name: 'treatment4',
sampleRate: 0.2
},
'5': {
name: 'treatment5',
sampleRate: 0.2,
js: function()
{
w13T5Chosen = true;
}
}
}
};

// T3 should be chosen
w13Test.options.decisionAdapter = function (testObject) {
if (testObject.decisionIdx === 0)
return 0.8;

return 0.15;
};

Mojito.addTest(w13Test);

// T5 should be chosen
w13Test.id = 'w13-2';
w13Test.options.decisionAdapter = function (testObject) {
if (testObject.decisionIdx === 0)
return 0.8;

return 0.55;
};

Mojito.addTest(w13Test);

// T1 should be chosen
w13Test.id = 'w13-3';
w13Test.options.decisionAdapter = function (testObject) {
if (testObject.decisionIdx === 0)
return 0.8;

return 0.65;
};

Mojito.addTest(w13Test);

it('Recipes with different and same sample rates', function () {
w13T1Chosen.should.equal(true)&&w13T3Chosen.should.equal(true)&&w13T5Chosen.should.equal(true);
});

});

Expand All @@ -608,14 +691,14 @@
testDiv.className = 'observe-existing';
document.body.appendChild(testDiv);

it('observeSelector on existing elements', function () {
it('ObserveSelector on existing elements', function () {
Mojito.utils.observeSelector('.observe-existing', function (element)
{
element.id.should.equal('observe-existing');
});
});

it('observeSelector on dynamic elements', function (done) {
it('ObserveSelector on dynamic elements', function (done) {
Mojito.utils.observeSelector('.observe-dynamic', function ()
{
done();
Expand All @@ -627,7 +710,7 @@
document.body.appendChild(testDiv);
});

it('observeSelector timeout', function (done) {
it('ObserveSelector timeout', function (done) {
Mojito.utils.observeSelector('.timeout', function ()
{
done('error');
Expand All @@ -641,14 +724,14 @@
});
});

it('waitForElement on existing elements', function () {
it('WaitForElement on existing elements', function () {
Mojito.utils.waitForElement('.observe-existing', function (element)
{
element.id.should.equal('observe-existing');
});
});

it('waitForElement on dynamic elements', function (done) {
it('WaitForElement on dynamic elements', function (done) {
Mojito.utils.observeSelector('.observe-dynamic-wait', function (element)
{
done();
Expand All @@ -659,7 +742,7 @@
document.body.appendChild(testDiv);
});

it('waitUntil', function (done) {
it('WaitUntil', function (done) {
var waitSignal = 0;
Mojito.utils.waitUntil(function ()
{
Expand All @@ -675,7 +758,7 @@
}, 1000);
});

it('waitUntil timeout', function (done) {
it('WaitUntil timeout', function (done) {
var waitSignal = 0;
var waitUntilState = 0;
Mojito.utils.waitUntil(function ()
Expand All @@ -695,7 +778,7 @@
}, 1500);
});

it('watchElement changes', function (done) {
it('WatchElement changes', function (done) {
testDiv = document.createElement('div');
testDiv.className = 'watch-changes';
document.body.appendChild(testDiv);
Expand Down

0 comments on commit efec23b

Please sign in to comment.