{"size": 8791, "ext": "js", "max_stars_repo_path": "static/src/javascripts/projects/common/modules/experiments/ab.js", "max_stars_repo_name": "lootnath/frontend", "max_stars_repo_stars_event_min_datetime": "2021-08-21T00:15:06.000Z", "max_stars_repo_stars_event_max_datetime": "2021-11-17T10:53:30.000Z", "max_issues_repo_path": "static/src/javascripts/projects/common/modules/experiments/ab.js", "max_issues_repo_name": "lootnath/frontend", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "static/src/javascripts/projects/common/modules/experiments/ab.js", "max_forks_repo_name": "lootnath/frontend", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": 3, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 30.8456140351, "max_line_length": 109, "alphanum_fraction": 0.5297463315}
define([
    'raven',
    'lodash/collections/filter',
    'lodash/collections/forEach',
    'lodash/collections/map',
    'lodash/collections/some',
    'lodash/objects/assign',
    'lodash/objects/keys',
    'common/utils/_',
    'common/utils/storage',
    'common/utils/mediator',
    'common/utils/config',
    'common/modules/analytics/mvt-cookie',
    'common/modules/experiments/tests/high-commercial-component'
], function (
    raven,
    filter,
    forEach,
    map,
    some,
    assign,
    keys,
    _,
    store,
    mediator,
    globalConfig,
    mvtCookie,
    HighCommercialComponent
    ) {

    var TESTS = [
            new HighCommercialComponent()
        ],
        participationsKey = 'gu.ab.participations';

    function getParticipations() {
        return store.local.get(participationsKey) || {};
    }

    function isParticipating(test) {
        var participations = getParticipations();
        return participations[test.id];
    }

    function addParticipation(test, variantId) {
        var participations = getParticipations();
        participations[test.id] = {
            variant: variantId
        };
        store.local.set(participationsKey, participations);
    }

    function removeParticipation(test) {
        var participations = getParticipations();
        delete participations[test.id];
        store.local.set(participationsKey, participations);
    }

    function cleanParticipations(config) {
        // Removes any tests from localstorage that have been
        // renamed/deleted from the backend
        var participations = getParticipations();
        forEach(keys(participations), function (k) {
            if (typeof(assign({}, globalConfig, config).switches['ab' + k]) === 'undefined') {
                removeParticipation({ id: k });
            } else {
                var testExists = some(TESTS, function(element) {
                    return element.id === k;
                });

                if (!testExists) {
                    removeParticipation({ id: k });
                }
            }
        });
    }

    function getActiveTests() {
        return filter(TESTS, function(test) {
            var expired = (new Date() - new Date(test.expiry)) > 0;
            if (expired) {
                removeParticipation(test);
                return false;
            }
            return true;
        });
    }

    function getExpiredTests() {
        return filter(TESTS, function(test) {
            return (new Date() - new Date(test.expiry)) > 0;
        });
    }

    function testCanBeRun(test, config) {
        var expired = (new Date() - new Date(test.expiry)) > 0;
        return (test.canRun(config) && !expired && isTestSwitchedOn(test, config));
    }

    function getTest(id) {
        var test = filter(TESTS, function (test) {
            return (test.id === id);
        });
        return (test) ? test[0] : '';
    }

    function makeOmnitureTag (config) {
        var participations = getParticipations(),
            tag = [];

        forEach(keys(participations), function (k) {
            if (testCanBeRun(getTest(k), config)) {
                tag.push(['AB', k, participations[k].variant].join(' | '));
            }
        });

        return tag.join(',');
    }

    // Finds variant in specific tests and runs it
    function run(test, config) {
        if (isParticipating(test) && testCanBeRun(test, config)) {
            var participations = getParticipations(),
                variantId = participations[test.id].variant;
            some(test.variants, function(variant) {
                if (variant.id === variantId) {
                    variant.test(config);
                    return true;
                }
            });
            if (variantId === 'notintest' && test.notInTest) {
                test.notInTest();
            }
        }
    }

    function allocateUserToTest(test, config) {

        // Skip allocation if the user is already participating, or the test is invalid.
        if (!testCanBeRun(test, config) || isParticipating(test)) {
            return;
        }

        // Determine whether the user is in the test or not. The test population is just a subset of mvt ids.
        // A test population must begin from a specific value. Overlapping test ranges are permitted.
        var smallestTestId = mvtCookie.getMvtNumValues() * test.audienceOffset;
        var largestTestId  = smallestTestId + mvtCookie.getMvtNumValues() * test.audience;

        // Get this browser's mvt test id.
        var mvtCookieId = mvtCookie.getMvtValue();

        if (smallestTestId <= mvtCookieId && largestTestId > mvtCookieId) {
            // This mvt test id is in the test range, so allocate it to a test variant.
            var variantIds = map(test.variants, function(variant) {
                return variant.id;
            });
            var testVariantId = mvtCookieId % variantIds.length;

            addParticipation(test, variantIds[testVariantId]);

        } else {
            addParticipation(test, 'notintest');
        }
    }

    function isTestSwitchedOn(test, config) {
        return assign({}, globalConfig, config).switches['ab' + test.id];
    }

    function getTestVariant(testId) {
        var participation = getParticipations()[testId];
        return participation && participation.variant;
    }

    var ab = {

        addTest: function(test) {
            TESTS.push(test);
        },

        clearTests: function() {
            TESTS = [];
        },

        segment: function(config) {
            forEach(getActiveTests(), function(test) {
                allocateUserToTest(test, config);
            });
        },

        forceSegment: function(testId, variant) {
            _(getActiveTests())
                .filter(function (test) {
                    return (test.id === testId);
                })
                .forEach(function (test) {
                    addParticipation(test, variant);
                })
                .valueOf();
        },

        segmentUser: function(config) {
            mvtCookie.generateMvtCookie();

            var forceUserIntoTest = /^#ab/.test(window.location.hash);
            if (forceUserIntoTest) {
                var tokens = window.location.hash.replace('#ab-','').split('=');
                var test = tokens[0], variant = tokens[1];
                ab.forceSegment(test, variant);
            } else {
                ab.segment(config);
            }

            cleanParticipations(config);
        },

        run: function(config) {
            forEach(getActiveTests(), function(test) {
                run(test, config);
            });
        },

        isEventApplicableToAnActiveTest: function(event) {
            var participations = keys(getParticipations());
            return some(participations, function(id) {
                var listOfEventStrings = getTest(id).events;
                return some(listOfEventStrings, function(ev) {
                    return event.indexOf(ev) === 0;
                });
            });
        },

        getActiveTestsEventIsApplicableTo: function (event) {

            function startsWith(string, prefix) {
                return string.indexOf(prefix) === 0;
            }

            var eventTag = event.tag;
            return eventTag && _(getActiveTests())
                .filter(function (test) {
                    var testEvents = test.events;
                    return testEvents && some(testEvents, function(testEvent) {
                        return startsWith(eventTag, testEvent);
                    });
                })
                .map(function (test) {
                    return test.id;
                })
                .valueOf();
        },

        getAbLoggableObject: function(config) {
            var abLogObject = {};

            try {
                forEach(getActiveTests(), function (test) {

                    if (isParticipating(test) && testCanBeRun(test, config)) {
                        var variant = getTestVariant(test.id);
                        if (variant && variant !== 'notintest') {
                            abLogObject['ab' + test.id] = variant;
                        }
                    }
                });
            } catch (error) {
                // Encountering an error should invalidate the logging process.
                abLogObject = {};
                raven.captureException(error);
            }

            return abLogObject;
        },

        getParticipations: getParticipations,
        makeOmnitureTag: makeOmnitureTag,
        getExpiredTests: getExpiredTests,
        getActiveTests: getActiveTests,
        getTestVariant: getTestVariant
    };

    return ab;

});
