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

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,28 @@ 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
+
4590
+ const getTrafficAllocation = experience => {
4591
+ if (experience.type === 'nt_personalization') {
4592
+ return 1 - experience.trafficAllocation;
4593
+ }
4594
+
4595
+ return experience.trafficAllocation;
4596
+ };
4597
+
4575
4598
  const selectExperience = ({
4576
4599
  experiences,
4577
4600
  activeExperiments,
@@ -4581,11 +4604,13 @@ const selectExperience = ({
4581
4604
  experiences,
4582
4605
  activeExperiments
4583
4606
  });
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
- }));
4607
+ const selectedExperience = eglibleExperiences.find(experience => {
4608
+ const trafficRandom = getTrafficRandom(profile, experience);
4609
+ return getTrafficAllocation(experience) > trafficRandom && (includes(profile.audiences, experience.audience.id) || // if the expriment is active already then it's selectible without further contraints to be fullfilled
4610
+ find(activeExperiments, {
4611
+ id: experience.id
4612
+ }));
4613
+ });
4589
4614
  return selectedExperience;
4590
4615
  };
4591
4616
 
@@ -4598,20 +4623,19 @@ const selectVariant = ({
4598
4623
 
4599
4624
  if (!variants.length) {
4600
4625
  return null;
4601
- } // Personalization
4602
-
4626
+ }
4603
4627
 
4604
4628
  if (experience.type === 'nt_personalization') {
4605
- // TODO check holdout
4606
4629
  // Personalization Expriences can have only one variant.
4607
4630
  return variants[0];
4608
- } // Experiment
4631
+ }
4609
4632
 
4633
+ const distributionRandom = getDistributionRandom(profile, experience); // Experiment
4610
4634
 
4611
4635
  const distribution = find(experience.distribution, ({
4612
4636
  start,
4613
4637
  end
4614
- }) => profile.random > start && profile.random < end);
4638
+ }) => distributionRandom > start && distributionRandom < end);
4615
4639
 
4616
4640
  if (!distribution) {
4617
4641
  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,34 @@
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
+
4501
+ var getTrafficAllocation = function getTrafficAllocation(experience) {
4502
+ if (experience.type === 'nt_personalization') {
4503
+ return 1 - experience.trafficAllocation;
4504
+ }
4505
+
4506
+ return experience.trafficAllocation;
4507
+ };
4508
+
4481
4509
  var selectExperience = function selectExperience(_a) {
4482
4510
  var experiences = _a.experiences,
4483
4511
  activeExperiments = _a.activeExperiments,
@@ -4487,11 +4515,11 @@
4487
4515
  activeExperiments: activeExperiments
4488
4516
  });
4489
4517
  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
4518
+ var trafficRandom = getTrafficRandom(profile, experience);
4519
+ return getTrafficAllocation(experience) > 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
4520
  find__default["default"](activeExperiments, {
4493
4521
  id: experience.id
4494
- });
4522
+ }));
4495
4523
  });
4496
4524
  return selectedExperience;
4497
4525
  };
@@ -4504,20 +4532,19 @@
4504
4532
 
4505
4533
  if (!variants.length) {
4506
4534
  return null;
4507
- } // Personalization
4508
-
4535
+ }
4509
4536
 
4510
4537
  if (experience.type === 'nt_personalization') {
4511
- // TODO check holdout
4512
4538
  // Personalization Expriences can have only one variant.
4513
4539
  return variants[0];
4514
- } // Experiment
4540
+ }
4515
4541
 
4542
+ var distributionRandom = getDistributionRandom(profile, experience); // Experiment
4516
4543
 
4517
4544
  var distribution = find__default["default"](experience.distribution, function (_a) {
4518
4545
  var start = _a.start,
4519
4546
  end = _a.end;
4520
- return profile.random > start && profile.random < end;
4547
+ return distributionRandom > start && distributionRandom < end;
4521
4548
  });
4522
4549
 
4523
4550
  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.9",
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.9",
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
  }