<commit_before><template>
    <div class="ab-testing">
        <div class="row">
            <div class="col-md-12">

                <div id="slider" class="m-b-25 m-t-25"></div>

                <table class="table table-striped">
                    <thead>
                        <tr>
                            <th></th>
                            <th>Banner</th>
                            <th></th>
                            <th></th>
                        </tr>
                    </thead>

                    <tbody>
                        <ab-testing-variant
                            v-for="(variant, index) in variants"
                            :index="index"
                            :variant="variant"
                            :key="variant.index"
                        ></ab-testing-variant>
                    </tbody>
                </table>

                <input type="hidden" v-for="variant in variantsToRemove" :value="variant.id" :key="variant.id" name="variants_to_remove[]">
            </div>
        </div><!-- .row -->

    </div>
</template>

<script type="text/javascript">
    import AbTestingVariant from "./AbTestingVariant";

    export default {
        components: {
            AbTestingVariant
        },
        props: {
            variantOptions: null,
            variants: {
                default: [
                    {
                        name: "Variant B",
                        val: 30
                    }
                ]
            },
            bannerId: {
                default: null
            }
        },
        data() {
            return {
                sliderEl: null,
                dontRunSliderUpdate: true,
                variantsToRemove: [],
                variantNumber: 0
            };
        },
        created() {
            if (!this.variants.length) {
                this.variants.push({
                    id: null,
                    variant: "Primary banner",
                    proportion: 100,
                    control_group: 0,
                    banner_id: this.bannerId
                });

                this.variants.push({
                    id: null,
                    variant: 'Control Group',
                    proportion: 0,
                    control_group: 1,
                    banner_id: null
                })
            }

            this.variantNumber = this.variants.length;
        },
        mounted() {
            // calculate slider starts
            var starts = this.calculateStarts();

            // get slider element
            this.sliderEl = document.getElementById('slider');

            // render slider ui
            this.renderSlider(starts);
        },
        methods: {
            calculateStarts() {
                var starts  = [],
                    sum     = 0;

                // calc slider handle starts from variants data
                for(var ii = 0; ii < this.variants.length - 1; ii++) {
                    sum += this.variants[ii].proportion;
                    starts.push(sum);
                }

                return starts;
            },
            renderSlider(starts) {
                // destroy slider if exists
                if (this.sliderEl.noUiSlider) {
                    this.sliderEl.noUiSlider.destroy();
                }

                // bind noUiSlider
                noUiSlider.create(this.sliderEl, {
                    start: starts,
                    range: {
                        min: 0,
                        max: 100
                    },
                    step: 1,
                    connect: Array(this.variants.length).fill(true)
                });

                // set slider connects color
                var connects = slider.querySelectorAll('.noUi-connect');
                for (var i = 0; i < connects.length; i++) {
                    connects[i].classList.add('color-' + i);
                }

                this.$children[0].renderProportionInputValues();

                // bind events
                this.sliderEl.noUiSlider.on('update', this.handleSliderUpdate);
            },
            handleSliderUpdate(values, handle) {
                var sum = 0;

                // update variants proportions
                for (var ii = 0; ii < values.length; ii++) {
                    var val = parseInt(values[ii]);

                    if (ii == 0) {
                        this.variants[ii].proportion = val;
                        sum += val;
                    } else {
                        this.variants[ii].proportion = parseInt(val-values[ii-1]);
                        sum += parseInt(val-values[ii-1]);
                    }
                }

                // update control group proportion
                this.variants[this.variants.length-1].proportion = 100-sum;
            },
            // noUiSlider needs exact position to set slider handle
            // so we have to calculate it using our percentual variant proportions
            // -> this means set handle to sum of all previous + this variant proporion
            // control group doesn't have handle so its treated independently
            handleInputUpdate(event, i) {
                let a = Array(this.variants.length).fill(null),
                    prevInputsSum = 0,
                    sum = 0;


                // sum all previous inputs & all inputs
                for(let ii = 0; ii < this.variants.length; ii++) {
                    var els = document.getElementsByClassName('ab-testing-input-' + ii);

                    if (els.length) {
                        sum += parseInt(els[0].value);
                        prevInputsSum += (ii < i) ? parseInt(els[0].value) : 0;
                    }
                }

                // handle control group input
                if (this.variants.length - 1 === i) {
                    a[i-1] = prevInputsSum + (100 - prevInputsSum - parseInt(event.srcElement.value));

                // handle regular variant input
                } else {
                    a[i] = prevInputsSum+parseInt(event.srcElement.value)
                }

                // set slider positions
                this.sliderEl.noUiSlider.set(a)
            },
            addEmptyVariant: function (event) {
                let i = this.variants.length - 1;

                while (!this.variants[i].proportion) i--;

                this.variants[i].proportion = this.variants[i].proportion-10;

                // add empty variant before control group
                this.variants.splice(i, 0, {
                    id: null,
                    variant: "Variant " + this.variantNumber,
                    proportion: 10,
                    control_group: 0,
                    banner_id: null
                });
<commit_msg>fix add ab variant after last variant row instead of before last variant row<commit_after><template>
    <div class="ab-testing">
        <div class="row">
            <div class="col-md-12">

                <div id="slider" class="m-b-25 m-t-25"></div>

                <table class="table table-striped">
                    <thead>
                        <tr>
                            <th></th>
                            <th>Banner</th>
                            <th></th>
                            <th></th>
                        </tr>
                    </thead>

                    <tbody>
                        <ab-testing-variant
                            v-for="(variant, index) in variants"
                            :index="index"
                            :variant="variant"
                            :key="variant.index"
                        ></ab-testing-variant>
                    </tbody>
                </table>

                <input type="hidden" v-for="variant in variantsToRemove" :value="variant.id" :key="variant.id" name="variants_to_remove[]">
            </div>
        </div><!-- .row -->

    </div>
</template>

<script type="text/javascript">
    import AbTestingVariant from "./AbTestingVariant";

    export default {
        components: {
            AbTestingVariant
        },
        props: {
            variantOptions: null,
            variants: {
                default: [
                    {
                        name: "Variant B",
                        val: 30
                    }
                ]
            },
            bannerId: {
                default: null
            }
        },
        data() {
            return {
                sliderEl: null,
                dontRunSliderUpdate: true,
                variantsToRemove: [],
                variantNumber: 0
            };
        },
        created() {
            if (!this.variants.length) {
                this.variants.push({
                    id: null,
                    variant: "Primary banner",
                    proportion: 100,
                    control_group: 0,
                    banner_id: this.bannerId
                });

                this.variants.push({
                    id: null,
                    variant: 'Control Group',
                    proportion: 0,
                    control_group: 1,
                    banner_id: null
                })
            }

            this.variantNumber = this.variants.length;
        },
        mounted() {
            // calculate slider starts
            var starts = this.calculateStarts();

            // get slider element
            this.sliderEl = document.getElementById('slider');

            // render slider ui
            this.renderSlider(starts);
        },
        methods: {
            calculateStarts() {
                var starts  = [],
                    sum     = 0;

                // calc slider handle starts from variants data
                for(var ii = 0; ii < this.variants.length - 1; ii++) {
                    sum += this.variants[ii].proportion;
                    starts.push(sum);
                }

                return starts;
            },
            renderSlider(starts) {
                // destroy slider if exists
                if (this.sliderEl.noUiSlider) {
                    this.sliderEl.noUiSlider.destroy();
                }

                // bind noUiSlider
                noUiSlider.create(this.sliderEl, {
                    start: starts,
                    range: {
                        min: 0,
                        max: 100
                    },
                    step: 1,
                    connect: Array(this.variants.length).fill(true)
                });

                // set slider connects color
                var connects = slider.querySelectorAll('.noUi-connect');
                for (var i = 0; i < connects.length; i++) {
                    connects[i].classList.add('color-' + i);
                }

                this.$children[0].renderProportionInputValues();

                // bind events
                this.sliderEl.noUiSlider.on('update', this.handleSliderUpdate);
            },
            handleSliderUpdate(values, handle) {
                var sum = 0;

                // update variants proportions
                for (var ii = 0; ii < values.length; ii++) {
                    var val = parseInt(values[ii]);

                    if (ii == 0) {
                        this.variants[ii].proportion = val;
                        sum += val;
                    } else {
                        this.variants[ii].proportion = parseInt(val-values[ii-1]);
                        sum += parseInt(val-values[ii-1]);
                    }
                }

                // update control group proportion
                this.variants[this.variants.length-1].proportion = 100-sum;
            },
            // noUiSlider needs exact position to set slider handle
            // so we have to calculate it using our percentual variant proportions
            // -> this means set handle to sum of all previous + this variant proporion
            // control group doesn't have handle so its treated independently
            handleInputUpdate(event, i) {
                let a = Array(this.variants.length).fill(null),
                    prevInputsSum = 0,
                    sum = 0;


                // sum all previous inputs & all inputs
                for(let ii = 0; ii < this.variants.length; ii++) {
                    var els = document.getElementsByClassName('ab-testing-input-' + ii);

                    if (els.length) {
                        sum += parseInt(els[0].value);
                        prevInputsSum += (ii < i) ? parseInt(els[0].value) : 0;
                    }
                }

                // handle control group input
                if (this.variants.length - 1 === i) {
                    a[i-1] = prevInputsSum + (100 - prevInputsSum - parseInt(event.srcElement.value));

                // handle regular variant input
                } else {
                    a[i] = prevInputsSum+parseInt(event.srcElement.value)
                }

                // set slider positions
                this.sliderEl.noUiSlider.set(a)
            },
            addEmptyVariant: function (event) {
                let i = this.variants.length - 1;

                while (!this.variants[i].proportion) i--;

                this.variants[i].proportion = this.variants[i].proportion-10;

                // add empty variant before control group
                this.variants.splice(i + 1, 0, {
                    id: null,
                    variant: "Variant " + this.variantNumber,
                    proportion: 10,
                    control_group: 0,
                    banner_id: null
                });

{'fraction_non_alphanumeric': 0.10070427648297393, 'fraction_numerical': 0.007623611413635374, 'mean_word_length': 0.9632269099201825, 'pattern_counts': {'":': 0, '<': 75, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7315962', 'n_tokens_mistral': 3527, 'n_tokens_neox': 3143, 'n_words': 728}