@ninetailed/experience.js 2.0.0-beta.6 → 2.0.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.esm.js CHANGED
@@ -6,6 +6,7 @@ import flatten from 'lodash/flatten';
6
6
  import find from 'lodash/find';
7
7
  import includes from 'lodash/includes';
8
8
  import pickBy from 'lodash/pickBy';
9
+ import { murmur3 } from 'murmurhash-js';
9
10
 
10
11
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
11
12
 
@@ -883,14 +884,14 @@ var isCallable$a = isCallable$j;
883
884
  var replacement = /#|\.prototype\./;
884
885
 
885
886
  var isForced$2 = function (feature, detection) {
886
- var value = data[normalize(feature)];
887
+ var value = data[normalize$1(feature)];
887
888
  return value == POLYFILL ? true
888
889
  : value == NATIVE ? false
889
890
  : isCallable$a(detection) ? fails$a(detection)
890
891
  : !!detection;
891
892
  };
892
893
 
893
- var normalize = isForced$2.normalize = function (string) {
894
+ var normalize$1 = isForced$2.normalize = function (string) {
894
895
  return String(string).replace(replacement, '.').toLowerCase();
895
896
  };
896
897
 
@@ -4572,6 +4573,20 @@ const selectEglibleExperiences = ({
4572
4573
  }));
4573
4574
  };
4574
4575
 
4576
+ const LOWER_BOUND = 0;
4577
+ const UPPER_BOUND = 4294967295;
4578
+
4579
+ const normalize = (val, min, max) => (val - min) / (max - min);
4580
+
4581
+ const getRandom = text => {
4582
+ const hash = murmur3(text, 0);
4583
+ const random = normalize(hash, LOWER_BOUND, UPPER_BOUND);
4584
+ return random;
4585
+ };
4586
+
4587
+ const getTrafficRandom = (profile, experience) => getRandom(`traffic-${experience.id}-${profile.id}`);
4588
+ const getDistributionRandom = (profile, experience) => getRandom(`distribution-${experience.id}-${profile.id}`);
4589
+
4575
4590
  const selectExperience = ({
4576
4591
  experiences,
4577
4592
  activeExperiments,
@@ -4581,11 +4596,13 @@ const selectExperience = ({
4581
4596
  experiences,
4582
4597
  activeExperiments
4583
4598
  });
4584
- const selectedExperience = eglibleExperiences.find(experience => // TODO check traffic allocation
4585
- includes(profile.audiences, experience.audience.id) || // if the expriment is active already then it's selectible without further contraints to be fullfilled
4586
- find(activeExperiments, {
4587
- id: experience.id
4588
- }));
4599
+ const selectedExperience = eglibleExperiences.find(experience => {
4600
+ const trafficRandom = getTrafficRandom(profile, experience);
4601
+ return experience.trafficAllocation > trafficRandom && (includes(profile.audiences, experience.audience.id) || // if the expriment is active already then it's selectible without further contraints to be fullfilled
4602
+ find(activeExperiments, {
4603
+ id: experience.id
4604
+ }));
4605
+ });
4589
4606
  return selectedExperience;
4590
4607
  };
4591
4608
 
@@ -4605,13 +4622,14 @@ const selectVariant = ({
4605
4622
  // TODO check holdout
4606
4623
  // Personalization Expriences can have only one variant.
4607
4624
  return variants[0];
4608
- } // Experiment
4625
+ }
4609
4626
 
4627
+ const distributionRandom = getDistributionRandom(profile, experience); // Experiment
4610
4628
 
4611
4629
  const distribution = find(experience.distribution, ({
4612
4630
  start,
4613
4631
  end
4614
- }) => profile.random > start && profile.random < end);
4632
+ }) => distributionRandom > start && distributionRandom < end);
4615
4633
 
4616
4634
  if (!distribution) {
4617
4635
  return null;
package/index.umd.js CHANGED
@@ -1,8 +1,8 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('lodash/get'), require('lodash/unionBy'), require('@ninetailed/experience.js-shared'), require('analytics'), require('lodash/flatten'), require('lodash/find'), require('lodash/includes'), require('lodash/pickBy')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'lodash/get', 'lodash/unionBy', '@ninetailed/experience.js-shared', 'analytics', 'lodash/flatten', 'lodash/find', 'lodash/includes', 'lodash/pickBy'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Javascript = {}, global.get$2, global.unionBy, global.experience_jsShared, global.Analytics, global.flatten, global.find, global.includes, global.pickBy));
5
- })(this, (function (exports, get$2, unionBy, experience_jsShared, Analytics, flatten, find, includes, pickBy) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('lodash/get'), require('lodash/unionBy'), require('@ninetailed/experience.js-shared'), require('analytics'), require('lodash/flatten'), require('lodash/find'), require('lodash/includes'), require('lodash/pickBy'), require('murmurhash-js')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'lodash/get', 'lodash/unionBy', '@ninetailed/experience.js-shared', 'analytics', 'lodash/flatten', 'lodash/find', 'lodash/includes', 'lodash/pickBy', 'murmurhash-js'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Javascript = {}, global.get$2, global.unionBy, global.experience_jsShared, global.Analytics, global.flatten, global.find, global.includes, global.pickBy, global.murmurhashJs));
5
+ })(this, (function (exports, get$2, unionBy, experience_jsShared, Analytics, flatten, find, includes, pickBy, murmurhashJs) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
@@ -890,14 +890,14 @@
890
890
  var replacement = /#|\.prototype\./;
891
891
 
892
892
  var isForced$2 = function (feature, detection) {
893
- var value = data[normalize(feature)];
893
+ var value = data[normalize$1(feature)];
894
894
  return value == POLYFILL ? true
895
895
  : value == NATIVE ? false
896
896
  : isCallable$7(detection) ? fails$8(detection)
897
897
  : !!detection;
898
898
  };
899
899
 
900
- var normalize = isForced$2.normalize = function (string) {
900
+ var normalize$1 = isForced$2.normalize = function (string) {
901
901
  return String(string).replace(replacement, '.').toLowerCase();
902
902
  };
903
903
 
@@ -4478,6 +4478,26 @@
4478
4478
  });
4479
4479
  };
4480
4480
 
4481
+ var LOWER_BOUND = 0;
4482
+ var UPPER_BOUND = 4294967295;
4483
+
4484
+ var normalize = function normalize(val, min, max) {
4485
+ return (val - min) / (max - min);
4486
+ };
4487
+
4488
+ var getRandom = function getRandom(text) {
4489
+ var hash = murmurhashJs.murmur3(text, 0);
4490
+ var random = normalize(hash, LOWER_BOUND, UPPER_BOUND);
4491
+ return random;
4492
+ };
4493
+
4494
+ var getTrafficRandom = function getTrafficRandom(profile, experience) {
4495
+ return getRandom("traffic-".concat(experience.id, "-").concat(profile.id));
4496
+ };
4497
+ var getDistributionRandom = function getDistributionRandom(profile, experience) {
4498
+ return getRandom("distribution-".concat(experience.id, "-").concat(profile.id));
4499
+ };
4500
+
4481
4501
  var selectExperience = function selectExperience(_a) {
4482
4502
  var experiences = _a.experiences,
4483
4503
  activeExperiments = _a.activeExperiments,
@@ -4487,11 +4507,11 @@
4487
4507
  activeExperiments: activeExperiments
4488
4508
  });
4489
4509
  var selectedExperience = eglibleExperiences.find(function (experience) {
4490
- // TODO check traffic allocation
4491
- return includes__default["default"](profile.audiences, experience.audience.id) || // if the expriment is active already then it's selectible without further contraints to be fullfilled
4510
+ var trafficRandom = getTrafficRandom(profile, experience);
4511
+ return experience.trafficAllocation > trafficRandom && (includes__default["default"](profile.audiences, experience.audience.id) || // if the expriment is active already then it's selectible without further contraints to be fullfilled
4492
4512
  find__default["default"](activeExperiments, {
4493
4513
  id: experience.id
4494
- });
4514
+ }));
4495
4515
  });
4496
4516
  return selectedExperience;
4497
4517
  };
@@ -4511,13 +4531,14 @@
4511
4531
  // TODO check holdout
4512
4532
  // Personalization Expriences can have only one variant.
4513
4533
  return variants[0];
4514
- } // Experiment
4534
+ }
4515
4535
 
4536
+ var distributionRandom = getDistributionRandom(profile, experience); // Experiment
4516
4537
 
4517
4538
  var distribution = find__default["default"](experience.distribution, function (_a) {
4518
4539
  var start = _a.start,
4519
4540
  end = _a.end;
4520
- return profile.random > start && profile.random < end;
4541
+ return distributionRandom > start && distributionRandom < end;
4521
4542
  });
4522
4543
 
4523
4544
  if (!distribution) {
@@ -0,0 +1,4 @@
1
+ import { Profile } from '@ninetailed/experience.js-shared';
2
+ import { ExperienceConfiguration } from './types';
3
+ export declare const getTrafficRandom: (profile: Profile, experience: ExperienceConfiguration) => number;
4
+ export declare const getDistributionRandom: (profile: Profile, experience: ExperienceConfiguration) => number;
package/package.json CHANGED
@@ -1,17 +1,18 @@
1
1
  {
2
2
  "name": "@ninetailed/experience.js",
3
- "version": "2.0.0-beta.6",
3
+ "version": "2.0.0-beta.7",
4
4
  "main": "./index.umd.js",
5
5
  "module": "./index.esm.js",
6
6
  "typings": "./index.d.ts",
7
7
  "dependencies": {
8
8
  "analytics": "^0.8.0",
9
- "@ninetailed/experience.js-shared": "2.0.0-beta.6",
9
+ "@ninetailed/experience.js-shared": "2.0.0-beta.7",
10
10
  "uuid": "^8.3.2",
11
11
  "ts-toolbelt": "^9.6.0",
12
12
  "locale-enum": "^1.1.1",
13
13
  "i18n-iso-countries": "^7.3.0",
14
- "lodash": "^4.17.21"
14
+ "lodash": "^4.17.21",
15
+ "murmurhash-js": "^1.0.0"
15
16
  },
16
17
  "peerDependencies": {}
17
18
  }