<commit_before>var CallbackTimer = (function () {
    "use strict";

    function CallbackTimer() {
        this.todos = [];
    }

    CallbackTimer.prototype.update = function () {

        for (var i = this.todos.length - 1; i >= 0; i--) {
            var toAdd = this.todos[i];

            if (toAdd.duration < toAdd.time) {
                toAdd.callback();

                this.todos.splice(i, 1);

            } else {
                toAdd.time++;
            }
        }
    };

    CallbackTimer.prototype.doLater = function (callback, duration) {
        this.todos.push({
            duration: duration,
            time: 0,
            callback: callback
        });
    };

    CallbackTimer.prototype.pause = function () {
        if (this.paused) {
            this.paused.push.apply(this.paused, this.todos.splice(0, this.todos.length));
        } else {
            this.paused = this.todos.splice(0, this.todos.length);
        }
    };

    CallbackTimer.prototype.resume = function () {
        this.todos.push.apply(this.todos, this.paused);
        delete this.paused;
    };

    return CallbackTimer;
})();<commit_msg>shop tutorial refs #74 #core (cherry picked from commit b985cbc)<commit_after>var CallbackTimer = (function () {
    "use strict";

    function CallbackTimer() {
        this.todos = [];
    }

    CallbackTimer.prototype.update = function () {
        if (this.todos.length == 0)
            return;
        for (var i = this.todos.length - 1; i >= 0; i--) {
            var toAdd = this.todos[i];
            if (!toAdd)
                continue;
            if (toAdd.duration < toAdd.time) {
                toAdd.callback();

                this.todos.splice(i, 1);

            } else {
                toAdd.time++;
            }
        }
    };

    CallbackTimer.prototype.doLater = function (callback, duration) {
        this.todos.push({
            duration: duration,
            time: 0,
            callback: callback
        });
    };

    CallbackTimer.prototype.pause = function () {
        if (this.paused) {
            this.paused.push.apply(this.paused, this.todos.splice(0, this.todos.length));
        } else {
            this.paused = this.todos.splice(0, this.todos.length);
        }
    };

    CallbackTimer.prototype.resume = function () {
        this.todos.push.apply(this.todos, this.paused);
        delete this.paused;
    };

    return CallbackTimer;
})();<|endoftext|>


<commit_before>const path = require("path"),
	{haro} = require(path.join(__dirname, "dist", "haro.cjs.js")),
	precise = require("precise"),
	data = require(path.join(__dirname, "data.json"));

let indexes;

function second () {
	const timer = precise().start(),
		store = haro(null, {id: "test", key: "_id", index: ["name", "eyeColor", "age", "gender", "isActive"]}),
		deferreds = [];

	deferreds.push(store.override(data, "records"));
	deferreds.push(store.override(indexes, "indexes"));

	Promise.all(deferreds).then(function () {
		let i = -1,
			nth = 5;

		timer.stop();
		console.log("time to override data: " + (timer.diff() / 1000000) + "ms");
		console.log("testing time to 'search(regex, index)' on overridden data for a record (first one is cold):");

		while (++i < nth) {
			(function () {
				const timer2 = precise().start();
				const record = store.search(/Carly Conway/, "name");
				timer2.stop();
				console.log((timer2.diff() / 1000000) + "ms");

				if (!record) {
					console.log("Couldn't find record");
				}
			}());
		}
	});
}

function first () {
	const timer = precise().start(),
		store = haro(null, {id: "test", key: "_id", index: ["name", "eyeColor", "age", "gender", "isActive"]});

	store.batch(data, "set").then(function () {
		timer.stop();
		console.log("time to batch insert data: " + (timer.diff() / 1000000) + "ms");
		console.log("datastore record count: " + store.total);
		console.log("name indexes: " + store.indexes.get("name").size + "\n");
	}).then(function () {
		let i = -1,
			nth = 5;

		console.log("testing time to 'find()' a record (first one is cold):");
		indexes = store.dump("indexes");

		while (++i < nth) {
			(function () {
				const timer2 = precise().start();
				const record = store.find({name: "Muriel Osborne"});
				timer2.stop();
				console.log((timer2.diff() / 1000000) + "ms");

				if (!record) {
					console.log("Couldn't find record");
				}
			}());
		}

		console.log("");
	}).then(function () {
		let i = -1,
			nth = 5;

		console.log("testing time to 'search(regex, index)' for a record (first one is cold):");

		while (++i < nth) {
			(function () {
				const timer2 = precise().start();
				const record = store.search(/Lizzie Clayton/, "name");
				timer2.stop();
				console.log((timer2.diff() / 1000000) + "ms");

				if (!record) {
					console.log("Couldn't find record");
				}
			}());
		}

		console.log("");

		second();
	});
}

first();
<commit_msg>Fixing lint errors in benchmark.js<commit_after>const path = require("path"),
	{haro} = require(path.join(__dirname, "dist", "haro.cjs.js")),
	precise = require("precise"),
	data = require(path.join(__dirname, "data.json"));

let indexes;

function second () {
	const timer = precise().start(),
		store = haro(null, {id: "test", key: "_id", index: ["name", "eyeColor", "age", "gender", "isActive"]}),
		deferreds = [];

	deferreds.push(store.override(data, "records"));
	deferreds.push(store.override(indexes, "indexes"));

	Promise.all(deferreds).then(function () {
		let i = -1,
			nth = 5;

		timer.stop();
		console.log("time to override data: " + timer.diff() / 1000000 + "ms");
		console.log("testing time to 'search(regex, index)' on overridden data for a record (first one is cold):");

		while (++i < nth) {
			(function () {
				const timer2 = precise().start();
				const record = store.search(/Carly Conway/, "name");
				timer2.stop();
				console.log(timer2.diff() / 1000000 + "ms");

				if (!record) {
					console.log("Couldn't find record");
				}
			}());
		}
	});
}

function first () {
	const timer = precise().start(),
		store = haro(null, {id: "test", key: "_id", index: ["name", "eyeColor", "age", "gender", "isActive"]});

	store.batch(data, "set").then(function () {
		timer.stop();
		console.log("time to batch insert data: " + timer.diff() / 1000000 + "ms");
		console.log("datastore record count: " + store.total);
		console.log("name indexes: " + store.indexes.get("name").size + "\n");
	}).then(function () {
		let i = -1,
			nth = 5;

		console.log("testing time to 'find()' a record (first one is cold):");
		indexes = store.dump("indexes");

		while (++i < nth) {
			(function () {
				const timer2 = precise().start();
				const record = store.find({name: "Muriel Osborne"});
				timer2.stop();
				console.log(timer2.diff() / 1000000 + "ms");

				if (!record) {
					console.log("Couldn't find record");
				}
			}());
		}

		console.log("");
	}).then(function () {
		let i = -1,
			nth = 5;

		console.log("testing time to 'search(regex, index)' for a record (first one is cold):");

		while (++i < nth) {
			(function () {
				const timer2 = precise().start();
				const record = store.search(/Lizzie Clayton/, "name");
				timer2.stop();
				console.log(timer2.diff() / 1000000 + "ms");

				if (!record) {
					console.log("Couldn't find record");
				}
			}());
		}

		console.log("");

		second();
	});
}

first();
<|endoftext|>


<commit_before>const Benchmark = require('benchmark')
const suite = new Benchmark.Suite()
const { inspect } = require('util')
const jsonStringifySafe = require('json-stringify-safe')
const fastSafeStringify = require('./')

const array = new Array(10).fill(0).map((_, i) => i)
const obj = { foo: array }
const circ = JSON.parse(JSON.stringify(obj))
circ.o = { obj: circ, array }
const circGetters = JSON.parse(JSON.stringify(obj))
Object.assign(circGetters, { get o () { return { obj: circGetters, array } } })

const deep = require('./package.json')
deep.deep = JSON.parse(JSON.stringify(deep))
deep.deep.deep = JSON.parse(JSON.stringify(deep))
deep.deep.deep.deep = JSON.parse(JSON.stringify(deep))
deep.array = array

const deepCirc = JSON.parse(JSON.stringify(deep))
deepCirc.deep.deep.deep.circ = deepCirc
deepCirc.deep.deep.circ = deepCirc
deepCirc.deep.circ = deepCirc
deepCirc.array = array

const deepCircGetters = JSON.parse(JSON.stringify(deep))
for (let i = 0; i < 10; i++) {
  deepCircGetters[i.toString()] = {
    deep: {
      deep: {
        get circ () { return deep.deep },
        deep: { get circ () { return deep.deep.deep } }
      },
      get circ () { return deep }
    },
    get array () { return array }
  }
}

suite.add('util.inspect:          simple object            ', function () {
  inspect(obj, { showHidden: false, depth: null })
})
suite.add('util.inspect:          circular                 ', function () {
  inspect(circ, { showHidden: false, depth: null })
})
suite.add('util.inspect:          circular getters         ', function () {
  inspect(circGetters, { showHidden: false, depth: null })
})
suite.add('util.inspect:          deep                     ', function () {
  inspect(deep, { showHidden: false, depth: null })
})
suite.add('util.inspect:          deep circular            ', function () {
  inspect(deepCirc, { showHidden: false, depth: null })
})
suite.add('util.inspect:          10+ deep circular getters', function () {
  inspect(deepCircGetters, { showHidden: false, depth: null })
})

suite.add('\njson-stringify-safe:   simple object            ', function () {
  jsonStringifySafe(obj)
})
suite.add('json-stringify-safe:   circular                 ', function () {
  jsonStringifySafe(circ)
})
suite.add('json-stringify-safe:   circular getters         ', function () {
  jsonStringifySafe(circGetters)
})
suite.add('json-stringify-safe:   deep                     ', function () {
  jsonStringifySafe(deep)
})
suite.add('json-stringify-safe:   deep circular            ', function () {
  jsonStringifySafe(deepCirc)
})
suite.add('json-stringify-safe:   10+ deep circular getters', function () {
  jsonStringifySafe(deepCircGetters)
})

suite.add('\nfast-safe-stringify:   simple object            ', function () {
  fastSafeStringify(obj)
})
suite.add('fast-safe-stringify:   circular                 ', function () {
  fastSafeStringify(circ)
})
suite.add('fast-safe-stringify:   circular getters         ', function () {
  fastSafeStringify(circGetters)
})
suite.add('fast-safe-stringify:   deep                     ', function () {
  fastSafeStringify(deep)
})
suite.add('fast-safe-stringify:   deep circular            ', function () {
  fastSafeStringify(deepCirc)
})
suite.add('fast-safe-stringify:   10+ deep circular getters', function () {
  fastSafeStringify(deepCircGetters)
})

// add listeners
suite.on('cycle', function (event) {
  console.log(String(event.target))
})

suite.on('complete', function () {
  console.log('\nFastest is ' + this.filter('fastest').map('name'))
})

suite.run({ delay: 1, minSamples: 150 })
<commit_msg>Rename large benchmarks to 'large deep circular getters'<commit_after>const Benchmark = require('benchmark')
const suite = new Benchmark.Suite()
const { inspect } = require('util')
const jsonStringifySafe = require('json-stringify-safe')
const fastSafeStringify = require('./')

const array = new Array(10).fill(0).map((_, i) => i)
const obj = { foo: array }
const circ = JSON.parse(JSON.stringify(obj))
circ.o = { obj: circ, array }
const circGetters = JSON.parse(JSON.stringify(obj))
Object.assign(circGetters, { get o () { return { obj: circGetters, array } } })

const deep = require('./package.json')
deep.deep = JSON.parse(JSON.stringify(deep))
deep.deep.deep = JSON.parse(JSON.stringify(deep))
deep.deep.deep.deep = JSON.parse(JSON.stringify(deep))
deep.array = array

const deepCirc = JSON.parse(JSON.stringify(deep))
deepCirc.deep.deep.deep.circ = deepCirc
deepCirc.deep.deep.circ = deepCirc
deepCirc.deep.circ = deepCirc
deepCirc.array = array

const deepCircGetters = JSON.parse(JSON.stringify(deep))
for (let i = 0; i < 10; i++) {
  deepCircGetters[i.toString()] = {
    deep: {
      deep: {
        get circ () { return deep.deep },
        deep: { get circ () { return deep.deep.deep } }
      },
      get circ () { return deep }
    },
    get array () { return array }
  }
}

suite.add('util.inspect:          simple object              ', function () {
  inspect(obj, { showHidden: false, depth: null })
})
suite.add('util.inspect:          circular                   ', function () {
  inspect(circ, { showHidden: false, depth: null })
})
suite.add('util.inspect:          circular getters           ', function () {
  inspect(circGetters, { showHidden: false, depth: null })
})
suite.add('util.inspect:          deep                       ', function () {
  inspect(deep, { showHidden: false, depth: null })
})
suite.add('util.inspect:          deep circular              ', function () {
  inspect(deepCirc, { showHidden: false, depth: null })
})
suite.add('util.inspect:          large deep circular getters', function () {
  inspect(deepCircGetters, { showHidden: false, depth: null })
})

suite.add('\njson-stringify-safe:   simple object              ', function () {
  jsonStringifySafe(obj)
})
suite.add('json-stringify-safe:   circular                   ', function () {
  jsonStringifySafe(circ)
})
suite.add('json-stringify-safe:   circular getters           ', function () {
  jsonStringifySafe(circGetters)
})
suite.add('json-stringify-safe:   deep                       ', function () {
  jsonStringifySafe(deep)
})
suite.add('json-stringify-safe:   deep circular              ', function () {
  jsonStringifySafe(deepCirc)
})
suite.add('json-stringify-safe:   large deep circular getters', function () {
  jsonStringifySafe(deepCircGetters)
})

suite.add('\nfast-safe-stringify:   simple object              ', function () {
  fastSafeStringify(obj)
})
suite.add('fast-safe-stringify:   circular                   ', function () {
  fastSafeStringify(circ)
})
suite.add('fast-safe-stringify:   circular getters           ', function () {
  fastSafeStringify(circGetters)
})
suite.add('fast-safe-stringify:   deep                       ', function () {
  fastSafeStringify(deep)
})
suite.add('fast-safe-stringify:   deep circular              ', function () {
  fastSafeStringify(deepCirc)
})
suite.add('fast-safe-stringify:   large deep circular getters', function () {
  fastSafeStringify(deepCircGetters)
})

// add listeners
suite.on('cycle', function (event) {
  console.log(String(event.target))
})

suite.on('complete', function () {
  console.log('\nFastest is ' + this.filter('fastest').map('name'))
})

suite.run({ delay: 1, minSamples: 150 })
<|endoftext|>


<commit_before>
(function(){
    // Simple bar chart
    // ----------------

    var BarChart = Datawrapper.Visualizations.BarChart = function() {

    };

    _.extend(BarChart.prototype, Datawrapper.Visualizations.RaphaelChart.prototype, {

        render: function(el) {
            el = $(el);

            this.setRoot(el);

            var me = this, row = 0,
            sortBars = me.get('sort-values', false),
            reverse = me.get('reverse-order'),
            useNegativeColor = me.get('negative-color', false);

            if (!_.isUndefined(me.get('selected-row'))) {
                row = me.get('selected-row', 0);
                row = row > me.chart.numRows() ? 0 : row;
            }

            var filterUI = me.getFilterUI(row);
            if (filterUI) $('#header').append(filterUI);

            var c = me.initCanvas({
                h: Math.max(
                    me.getSize()[1] - me.theme.padding.top - me.theme.padding.bottom - me.theme.vpadding,
                    18 * 1.35 * me.chart.dataSeries().length + 5
                )
            });

            var
            chart_width = c.w - c.lpad - c.rpad,
            series_gap = 0.05, // pull from theme
            row_gap = 0.01,
            labelsInsideBars = me.get('labels-inside-bars', false);

            if (me.chart.numRows() > 1) me.chart.filterRow(row);

            me.init();
            me.initDimensions(0);

            $('.tooltip').hide();

            c.lastBarY = 0;

            _.each(me.chart.dataSeries(sortBars, reverse), function(series, s) {
                _.each(series.data, function(val, r) {
                    var d = me.barDimensions(series, s, r),
                        lpos = me.labelPosition(series, s, r),
                        fill = me.getSeriesColor(series, r, useNegativeColor),
                        stroke = d3.cie.lch(d3.rgb(fill)).darker(0.6).toString();

                    if (labelsInsideBars) d.x -= 10;

                    // draw bar
                    me.registerSeriesElement(c.paper.rect(d.x, d.y, d.width, d.height).attr({
                        'stroke': stroke,
                        'fill': fill
                    }).data('strokeCol', stroke), series);

                    if (lpos.show_val) {
                        me.registerSeriesLabel(me.label(lpos.val_x, lpos.top, me.chart.formatValue(series.data[r], true),{
                            w: 40,
                            align: lpos.val_align,
                            cl: 'value' + lpos.lblClass
                        }), series);
                    }

                    if (lpos.show_lbl) {
                        me.registerSeriesLabel(me.label(lpos.lbl_x , lpos.top, series.name,{
                            w: 160,
                            align: lpos.lbl_align,
                            cl: 'series' + lpos.lblClass
                        }), series);
                    }

                    c.lastBarY = Math.max(c.lastBarY, d.y + d.height);
                });
            });

            if (me.__domain[0] < 0) {
                var x = c.lpad + c.zero ;
                if (labelsInsideBars) x -= 10;
                // add y-axis
                me.__yaxis = me.path('M' + [x, c.tpad] + 'V' + c.lastBarY, 'axis')
                    .attr(me.theme.yAxis);
            }

            // enable mouse events
            el.mousemove(_.bind(me.onMouseMove, me));

        },

        update: function(row) {
            var me = this;
            // re-filter dataset
            me.chart.filterRow(row);

            // update scales
            me.initDimensions(0);

            // update bar heights and labels
            _.each(me.chart.dataSeries(me.get('sort-values', false)), function(series, s) {
                _.each(me.__seriesElements[series.name], function(rect) {
                    var dim = me.barDimensions(series, s, 0);
                    rect.animate(dim, me.theme.duration, me.theme.easing);
                });

                _.each(me.__seriesLabels[series.name], function(lbl) {
                    var pos = me.labelPosition(series, s, 0), lpos;
                    if (lbl.hasClass('value')) {
                        // update value
                        $('span', lbl).html(me.chart.formatValue(series.data[0]));
                        lpos = { halign: pos.val_align, left: pos.val_x, top: pos.top };
                    } else if (lbl.hasClass('series')) {
                        // update series label position
                        lpos = { halign: pos.lbl_align, left: pos.lbl_x, top: pos.top };
                    }
                    if (lpos) {
                        lbl.animate({
                            align: lpos.halign,
                            x: lpos.left,
                            y: lpos.top
                        }, me.theme.duration, me.theme.easing);
                    }
                });
            });
            if (me.__domain[0] < 0) {
                var c = me.__canvas,
                    x = c.lpad + c.zero - (me.get('labels-inside-bars', false) ? 10 : 0),
                    p = 'M' + [x, c.tpad] + 'V' + c.lastBarY;
                // add y-axis
                if (me.__yaxis) {
                    me.__yaxis.animate({ path: p, opacity: 1 }, me.theme.duration, me.theme.easing);
                } else {
                    me.__yaxis = me.path(p, 'axis').attr(me.theme.yAxis);
                }
            } else if (me.__yaxis) {
                me.__yaxis.animate({ opacity: 0 }, me.theme.duration * 0.5, me.theme.easing);
            }
        },

        initDimensions: function(r) {
            //
            var me = this, c = me.__canvas,
                dMin = 0, dMax = 0, w = c.w - c.lpad - c.rpad - 30;
            _.each(me.chart.dataSeries(), function(series) {
                dMin = Math.min(dMin, series._min());
                dMax = Math.max(dMax, series._max());
            });
            me.__domain = [dMin, dMax];
            me.__scales = {
                y: d3.scale.linear().domain([dMin, dMax])
            };
            /* how maxw works:
             *
             * maxw[0] .. max series name label width      \
             * maxw[1] .. max formatted value label width   } positive
             * largestVal[0] .. max absolute value               /
             * maxw[2] .. max series name label width      \
             * maxw[3] .. max formatted value label width   } negative
             * largestVal[1] .. max absolute value               /
             */
            var maxw = [0, 0, 0, 0], ratio, largestVal = [0, 0];
            _.each(me.chart.dataSeries(), function(series, s) {
                var neg = series.data[r] < 0;
                largestVal[neg ? 1 : 0] = Math.max(largestVal[neg ? 1 : 0], Math.abs(series.data[r]));
            });
            _.each(me.chart.dataSeries(), function(series, s) {
                var val = series.data[r],
                    neg = val < 0,
                    t = neg ? 2 : 0,
                    bw;
                bw = Math.abs(val) / (largestVal[0] + largestVal[1]) * w;
                maxw[t] = Math.max(maxw[t], me.labelWidth(series.name, 'series') + 20);
                maxw[t+1] = Math.max(maxw[t+1], me.labelWidth(me.chart.formatValue(series.data[r], true), 'value') + 20 + bw);
            });

            c.left = 0;
            c.right = 0;
            c.zero = largestVal[1] / (largestVal[0] + largestVal[1]) * w;

            if (!me.get('labels-inside-bars', false) && w > 300) {

                var maxNegBar = c.zero;
                //console.log('c.left', );
                c.left = Math.max(maxw[0], maxw[3]) - c.zero;
                c.right = Math.max(maxw[1], maxw[2]) - (w - c.zero); // Math.max((maxw[2] + maxw[1]) - (w - c.zero), 0);

                w -= c.left + c.right;

                c.zero = c.left + largestVal[1] / (largestVal[0] + largestVal[1]) * w;
            } else {
                c.zero += 15;
            }

            c.maxSeriesLabelWidth = [maxw[0], maxw[2]];
            c.maxValueLabelWidth = [maxw[1], maxw[3]];

            me.__scales.y.rangeRound([c.lpad, w]);
        },

        barDimensions: function(series, s, r) {
            var me = this, w, h, x, y, i, cw, n = me.chart.dataSeries().length,
                sc = me.__scales, c = me.__canvas, bw, pad = 0.35, vspace = 0.1,
                val = series.data[r];
            //
            cw = c.h - c.bpad - c.tpad;
            //
            bw = Math.max(18, Math.min(50, cw / (n + (n-1) * pad)));
            w = sc.y(val) - sc.y(0);
            h = bw;
            if (w > 0) {
                x = c.lpad + c.zero;
            } else {
                x = c.lpad + c.zero + w;
                w *= -1;
            }
            y = Math.round(c.tpad + s * (bw + bw * pad));
            return { width: w, height: h, x: x, y: y };
        },

        labelPosition: function(series, s, r) {
            var me = this,
                d = me.barDimensions(series, s, r),
                c = me.__canvas,
                val = series.data[r],
                lbl_x = val >= 0 ?
                    c.zero - 10
                    : c.zero + 10,
                lbl_align = val >= 0 ? 'right' : 'left',
                val_x = val >= 0 ?
                    d.x + d.width + 10
                    : d.x - 10,
                val_align = val >= 0 ? 'left' : 'right',
                show_lbl = true,
                show_val = true,
                lblClass = me.chart.hasHighlight() && me.chart.isHighlighted(series) ? ' highlighted' : '';

            if (me.get('labels-inside-bars', false)) {
                lbl_x = val >= 0 ? d.x + 10 : d.x + d.width - 10;
                val_x = val >= 0 ? d.x + d.width - 10 : d.x + 10;
                lbl_align = val >= 0 ? 'left' : 'right';
                val_align = val >= 0 ? 'right' : 'left';

                // check if the label is bigger than the bar
                var slblw = me.labelWidth(series.name, 'series')+10,
                    vlblw = me.labelWidth(me.chart.formatValue(val, true), 'value')+20;
                if (slblw + vlblw > d.width) {
                    show_val = false;
                    if (slblw > d.width) show_lbl = false;
                }
                if (me.invertLabel(me.getSeriesColor(series, r, useNegativeColor))) lblClass += ' inverted';
            }

            return { lblClass: lblClass, val_align: val_align, show_lbl: show_lbl,
                show_val: show_val, lbl_align: lbl_align, lbl_x: lbl_x, val_x: val_x,
                top: d.y + d.height * 0.5 };
        },

        getDataRowByPoint: function(x, y) {
            return 0;
        },

        showTooltip: function() {

        },

        hideTooltip: function() {

        },

        hoverSeries: function(series) {
            var me = this;
            _.each(me.chart.dataSeries(), function(s) {
                _.each(me.__seriesLabels[s.name], function(lbl) {
                    if (series !== undefined && s.name == series.name) {
                        lbl.addClass('hover');
                    } else {
                        lbl.removeClass('hover');
                    }
                    _.each(me.__seriesElements[s.name], function(el) {
                        var fill = me.getSeriesColor(s, 0, me.get('negative-color', false)), stroke;
                        if (series !== undefined && s.name == series.name) fill = d3.cie.lch(d3.rgb(fill)).darker(0.6).toString();
                        stroke = d3.cie.lch(d3.rgb(fill)).darker(0.6).toString();
                        if (el.attrs.fill != fill || el.attrs.stroke != stroke)
                            el.animate({ fill: fill, stroke: stroke }, 50);
                    });
                });
            });
        },

        unhoverSeries: function() {
            this.hoverSeries();
        }
    });

    var Slice = function(paper, cx, cy, or, ir, startAngle, endAngle, label) {
        var me = this;
        me.cx = cx;
        me.cy = cy;
        me.or = or;
        me.ir = ir;
        me.startAngle = startAngle;
        me.endAngle = endAngle;
        me.path = paper.path(me.arcPath());
        me.label = label;
        me.updateLabelPos();
    };

}).call(this);
<commit_msg>Looking for fill<commit_after>
(function(){
    // Simple bar chart
    // ----------------

    var BarChart = Datawrapper.Visualizations.BarChart = function() {

    };

    _.extend(BarChart.prototype, Datawrapper.Visualizations.RaphaelChart.prototype, {

        render: function(el) {
            el = $(el);

            this.setRoot(el);

            var me = this, row = 0,
            sortBars = me.get('sort-values', false),
            reverse = me.get('reverse-order'),
            useNegativeColor = me.get('negative-color', false);

            if (!_.isUndefined(me.get('selected-row'))) {
                row = me.get('selected-row', 0);
                row = row > me.chart.numRows() ? 0 : row;
            }

            var filterUI = me.getFilterUI(row);
            if (filterUI) $('#header').append(filterUI);

            var c = me.initCanvas({
                h: Math.max(
                    me.getSize()[1] - me.theme.padding.top - me.theme.padding.bottom - me.theme.vpadding,
                    18 * 1.35 * me.chart.dataSeries().length + 5
                )
            });

            var
            chart_width = c.w - c.lpad - c.rpad,
            series_gap = 0.05, // pull from theme
            row_gap = 0.01,
            labelsInsideBars = me.get('labels-inside-bars', false);

            if (me.chart.numRows() > 1) me.chart.filterRow(row);

            me.init();
            me.initDimensions(0);

            $('.tooltip').hide();

            c.lastBarY = 0;

            _.each(me.chart.dataSeries(sortBars, reverse), function(series, s) {
                _.each(series.data, function(val, r) {
                    var d = me.barDimensions(series, s, r),
                        lpos = me.labelPosition(series, s, r),
                        fill = me.getSeriesColor(series, r, useNegativeColor),
                        stroke = d3.cie.lch(d3.rgb(fill)).darker(0.6).toString();

                    if (labelsInsideBars) d.x -= 10;

                    // draw bar
                    me.registerSeriesElement(c.paper.rect(d.x, d.y, d.width, d.height).attr({
                        'stroke': stroke,
                        'fill': fill
                    }).data('strokeCol', stroke), series);

                    if (lpos.show_val) {
                        me.registerSeriesLabel(me.label(lpos.val_x, lpos.top, me.chart.formatValue(series.data[r], true),{
                            w: 40,
                            align: lpos.val_align,
                            cl: 'value' + lpos.lblClass
                        }), series);
                    }

                    if (lpos.show_lbl) {
                        me.registerSeriesLabel(me.label(lpos.lbl_x , lpos.top, series.name,{
                            w: 160,
                            align: lpos.lbl_align,
                            cl: 'series' + lpos.lblClass
                        }), series);
                    }

                    c.lastBarY = Math.max(c.lastBarY, d.y + d.height);
                });
            });

            if (me.__domain[0] < 0) {
                var x = c.lpad + c.zero ;
                if (labelsInsideBars) x -= 10;
                // add y-axis
                me.__yaxis = me.path('M' + [x, c.tpad] + 'V' + c.lastBarY, 'axis')
                    .attr(me.theme.yAxis);
            }

            // enable mouse events
            el.mousemove(_.bind(me.onMouseMove, me));

        },

        update: function(row) {
            var me = this;
            // re-filter dataset
            me.chart.filterRow(row);

            // update scales
            me.initDimensions(0);

            // update bar heights and labels
            _.each(me.chart.dataSeries(me.get('sort-values', false)), function(series, s) {
                _.each(me.__seriesElements[series.name], function(rect) {
                    var dim = me.barDimensions(series, s, 0);
                    rect.animate(dim, me.theme.duration, me.theme.easing);
                });

                _.each(me.__seriesLabels[series.name], function(lbl) {
                    var pos = me.labelPosition(series, s, 0), lpos;
                    if (lbl.hasClass('value')) {
                        // update value
                        $('span', lbl).html(me.chart.formatValue(series.data[0]));
                        lpos = { halign: pos.val_align, left: pos.val_x, top: pos.top };
                    } else if (lbl.hasClass('series')) {
                        // update series label position
                        lpos = { halign: pos.lbl_align, left: pos.lbl_x, top: pos.top };
                    }
                    if (lpos) {
                        lbl.animate({
                            align: lpos.halign,
                            x: lpos.left,
                            y: lpos.top
                        }, me.theme.duration, me.theme.easing);
                    }
                });
            });
            if (me.__domain[0] < 0) {
                var c = me.__canvas,
                    x = c.lpad + c.zero - (me.get('labels-inside-bars', false) ? 10 : 0),
                    p = 'M' + [x, c.tpad] + 'V' + c.lastBarY;
                // add y-axis
                if (me.__yaxis) {
                    me.__yaxis.animate({ path: p, opacity: 1 }, me.theme.duration, me.theme.easing);
                } else {
                    me.__yaxis = me.path(p, 'axis').attr(me.theme.yAxis);
                }
            } else if (me.__yaxis) {
                me.__yaxis.animate({ opacity: 0 }, me.theme.duration * 0.5, me.theme.easing);
            }
        },

        initDimensions: function(r) {
            //
            var me = this, c = me.__canvas,
                dMin = 0, dMax = 0, w = c.w - c.lpad - c.rpad - 30;
            _.each(me.chart.dataSeries(), function(series) {
                dMin = Math.min(dMin, series._min());
                dMax = Math.max(dMax, series._max());
            });
            me.__domain = [dMin, dMax];
            me.__scales = {
                y: d3.scale.linear().domain([dMin, dMax])
            };
            /* how maxw works:
             *
             * maxw[0] .. max series name label width      \
             * maxw[1] .. max formatted value label width   } positive
             * largestVal[0] .. max absolute value               /
             * maxw[2] .. max series name label width      \
             * maxw[3] .. max formatted value label width   } negative
             * largestVal[1] .. max absolute value               /
             */
            var maxw = [0, 0, 0, 0], ratio, largestVal = [0, 0];
            _.each(me.chart.dataSeries(), function(series, s) {
                var neg = series.data[r] < 0;
                largestVal[neg ? 1 : 0] = Math.max(largestVal[neg ? 1 : 0], Math.abs(series.data[r]));
            });
            _.each(me.chart.dataSeries(), function(series, s) {
                var val = series.data[r],
                    neg = val < 0,
                    t = neg ? 2 : 0,
                    bw;
                bw = Math.abs(val) / (largestVal[0] + largestVal[1]) * w;
                maxw[t] = Math.max(maxw[t], me.labelWidth(series.name, 'series') + 20);
                maxw[t+1] = Math.max(maxw[t+1], me.labelWidth(me.chart.formatValue(series.data[r], true), 'value') + 20 + bw);
            });

            c.left = 0;
            c.right = 0;
            c.zero = largestVal[1] / (largestVal[0] + largestVal[1]) * w;

            if (!me.get('labels-inside-bars', false) && w > 300) {

                var maxNegBar = c.zero;
                //console.log('c.left', );
                c.left = Math.max(maxw[0], maxw[3]) - c.zero;
                c.right = Math.max(maxw[1], maxw[2]) - (w - c.zero); // Math.max((maxw[2] + maxw[1]) - (w - c.zero), 0);

                w -= c.left + c.right;

                c.zero = c.left + largestVal[1] / (largestVal[0] + largestVal[1]) * w;
            } else {
                c.zero += 15;
            }

            c.maxSeriesLabelWidth = [maxw[0], maxw[2]];
            c.maxValueLabelWidth = [maxw[1], maxw[3]];

            me.__scales.y.rangeRound([c.lpad, w]);
        },

        barDimensions: function(series, s, r) {
            var me = this, w, h, x, y, i, cw, n = me.chart.dataSeries().length,
                sc = me.__scales, c = me.__canvas, bw, pad = 0.35, vspace = 0.1,
                val = series.data[r];
            //
            cw = c.h - c.bpad - c.tpad;
            //
            bw = Math.max(18, Math.min(50, cw / (n + (n-1) * pad)));
            w = sc.y(val) - sc.y(0);
            h = bw;
            if (w > 0) {
                x = c.lpad + c.zero;
            } else {
                x = c.lpad + c.zero + w;
                w *= -1;
            }
            y = Math.round(c.tpad + s * (bw + bw * pad));
            return { width: w, height: h, x: x, y: y };
        },

        labelPosition: function(series, s, r) {
            var me = this,
                d = me.barDimensions(series, s, r),
                c = me.__canvas,
                val = series.data[r],
                lbl_x = val >= 0 ?
                    c.zero - 10
                    : c.zero + 10,
                lbl_align = val >= 0 ? 'right' : 'left',
                val_x = val >= 0 ?
                    d.x + d.width + 10
                    : d.x - 10,
                val_align = val >= 0 ? 'left' : 'right',
                show_lbl = true,
                show_val = true,
                lblClass = me.chart.hasHighlight() && me.chart.isHighlighted(series) ? ' highlighted' : '';

            if (me.get('labels-inside-bars', false)) {
                lbl_x = val >= 0 ? d.x + 10 : d.x + d.width - 10;
                val_x = val >= 0 ? d.x + d.width - 10 : d.x + 10;
                lbl_align = val >= 0 ? 'left' : 'right';
                val_align = val >= 0 ? 'right' : 'left';

                // check if the label is bigger than the bar
                var slblw = me.labelWidth(series.name, 'series')+10,
                    vlblw = me.labelWidth(me.chart.formatValue(val, true), 'value')+20;
                if (slblw + vlblw > d.width) {
                    show_val = false;
                    if (slblw > d.width) show_lbl = false;
                }
                if (me.invertLabel(fill)) lblClass += ' inverted';
            }

            return { lblClass: lblClass, val_align: val_align, show_lbl: show_lbl,
                show_val: show_val, lbl_align: lbl_align, lbl_x: lbl_x, val_x: val_x,
                top: d.y + d.height * 0.5 };
        },

        getDataRowByPoint: function(x, y) {
            return 0;
        },

        showTooltip: function() {

        },

        hideTooltip: function() {

        },

        hoverSeries: function(series) {
            var me = this;
            _.each(me.chart.dataSeries(), function(s) {
                _.each(me.__seriesLabels[s.name], function(lbl) {
                    if (series !== undefined && s.name == series.name) {
                        lbl.addClass('hover');
                    } else {
                        lbl.removeClass('hover');
                    }
                    _.each(me.__seriesElements[s.name], function(el) {
                        var fill = me.getSeriesColor(s, 0, me.get('negative-color', false)), stroke;
                        if (series !== undefined && s.name == series.name) fill = d3.cie.lch(d3.rgb(fill)).darker(0.6).toString();
                        stroke = d3.cie.lch(d3.rgb(fill)).darker(0.6).toString();
                        if (el.attrs.fill != fill || el.attrs.stroke != stroke)
                            el.animate({ fill: fill, stroke: stroke }, 50);
                    });
                });
            });
        },

        unhoverSeries: function() {
            this.hoverSeries();
        }
    });

    var Slice = function(paper, cx, cy, or, ir, startAngle, endAngle, label) {
        var me = this;
        me.cx = cx;
        me.cy = cy;
        me.or = or;
        me.ir = ir;
        me.startAngle = startAngle;
        me.endAngle = endAngle;
        me.path = paper.path(me.arcPath());
        me.label = label;
        me.updateLabelPos();
    };

}).call(this);
<|endoftext|>


<commit_before>;(function($) {
    $.fn.formset = function(opts){
        var $$ = $(this);

        var options = $.extend({
            prefix: $$.data('prefix')
        }, $.fn.formset.styles[$$.data('style')], opts),

            updateElementIndex = function(elem, prefix, ndx) {
                var idRegex = new RegExp(prefix + '-(\\d+|__prefix__)-'),
                    replacement = prefix + '-' + ndx + '-';
                if (elem.attr("for")) elem.attr("for", elem.attr("for").replace(idRegex, replacement));
                if (elem.attr('id')) elem.attr('id', elem.attr('id').replace(idRegex, replacement));
                if (elem.attr('name')) elem.attr('name', elem.attr('name').replace(idRegex, replacement));
                if (elem.attr('href')) elem.attr('href', elem.attr('href').replace(idRegex, replacement));
                elem.find('.formset-num').html(ndx + 1);
            },

            hasChildElements = function(row) {
                return row.find('input,select,textarea,label,div,a').length > 0;
            },

            updateRowIndex = function(row, i){
                if (options.update) options.update(row, (function(elem){
                    updateElementIndex(elem, options.prefix, i);
                }));
                updateElementIndex(row, options.prefix, i);
                row.find('input,select,textarea,label,div,a').each(function() {
                    updateElementIndex($(this), options.prefix, i);
                });
                row.data('row-index', i);
            },

            insertDeleteLink = function(row) {
                row.find('a.delete-row').click(function() {
                    var row = $(this).parents(".formset-row"),
                        del = row.find('input[id $= "-DELETE"]');

                    if (options.removed) options.removed(row, del, $$);

                    if (del.length) {
                        if(del.val() == 'on'){
                            row.removeClass('row-deleted');
                        } else {
                            row.addClass('row-deleted');
                        }
                        del.val(del.val() == 'on'?'':'on');
                    } else {
                        var parent = row.parent();
                        row.remove();
                        var forms = parent.find('.formset-row');
                        $('#id_' + options.prefix + '-TOTAL_FORMS').val(forms.length);
                        for (var i=0, formCount=forms.length; i<formCount; i++) {
                            updateRowIndex(forms.eq(i), i);
                        }
                    }
                    return false;
                });
            };

        $$.find(".formset-row").each(function(i) {
            insertDeleteLink($(this));
        });

        if ($$.length) {
            var template, el = $('#' + options.prefix + '-empty');
            if(el.is('textarea')) {
                template = el.val();
            } else if(el.is('span')) {
                template = el.html();
            }else if(el.is('script')) {
                template = el.html();
            }

            template = el.html(template).text(); // decoded
            template = $($.parseHTML(template));

            template.removeAttr('id');
            if(template.data("replace-id")){
                template.attr('id', template.data("replace-id"));
                template.removeAttr('data-replace-id');
            }
            options.formTemplate = template;

            $('#' + options.prefix + '-add-row').click(function() {
                var formCount = parseInt($('#id_' + options.prefix + '-TOTAL_FORMS').val()),
                    row = options.formTemplate.clone(true).removeClass('empty-form');
                updateRowIndex(row, formCount);
                row.appendTo($$);
                insertDeleteLink(row);
                row.exform();
                $('#id_' + options.prefix + '-TOTAL_FORMS').val(formCount + 1);
                // If a post-add callback was supplied, call it with the added form:
                if (options.added) options.added(row, $$);
                return false;
            });
        }

        return $$;
    }

    $.fn.formset.styles = {
        'tab': {
            added: function(row, $$){
                var new_tab = $('
#'+ (row.data('row-index') + 1) +'
');
                $$.parent().find('.nav-tabs').append(new_tab);
                new_tab.find('a').tab('show');
            },
            update: function(row, update){
                var rowId = row.attr('id');
                if(rowId){
                    $('a[href=#'+rowId+']').each(function(){
                        update($(this));
                    })
                }
            },
            removed: function(row, del, $$){
                var rowId = row.attr('id');
                if(rowId){
                    var tab = $('a[href=#'+rowId+']');
                    if (del.length) {
                        if(del.val() == 'on'){
                            tab.removeClass('row-deleted');
                        } else {
                            tab.addClass('row-deleted');
                        }
                    } else {
                        if(tab.parent().next().length){
                            tab.parent().next().find('a').tab('show');
                        } else {
                            tab.parent().prev().find('a').tab('show');
                        }
                        tab.parent().remove();
                    }
                }
            }
        }
    };

    $(function(){
        $('.formset-content').each(function(){
            $(this).formset();
        });
    });
})(jQuery);
<commit_msg>fix formset js<commit_after>;(function($) {
    $.fn.formset = function(opts){
        var $$ = $(this);

        var options = $.extend({
            prefix: $$.data('prefix')
        }, $.fn.formset.styles[$$.data('style')], opts),

            updateElementIndex = function(elem, prefix, ndx) {
                var idRegex = new RegExp(prefix + '-(\\d+|__prefix__)-'),
                    replacement = prefix + '-' + ndx + '-';
                if (elem.attr("for")) elem.attr("for", elem.attr("for").replace(idRegex, replacement));
                if (elem.attr('id')) elem.attr('id', elem.attr('id').replace(idRegex, replacement));
                if (elem.attr('name')) elem.attr('name', elem.attr('name').replace(idRegex, replacement));
                if (elem.attr('href')) elem.attr('href', elem.attr('href').replace(idRegex, replacement));
                elem.find('.formset-num').html(ndx + 1);
            },

            hasChildElements = function(row) {
                return row.find('input,select,textarea,label,div,a').length > 0;
            },

            updateRowIndex = function(row, i){
                if (options.update) options.update(row, (function(elem){
                    updateElementIndex(elem, options.prefix, i);
                }));
                updateElementIndex(row, options.prefix, i);
                row.find('input,select,textarea,label,div,a').each(function() {
                    updateElementIndex($(this), options.prefix, i);
                });
                row.data('row-index', i);
            },

            insertDeleteLink = function(row) {
                row.find('a.delete-row').click(function() {
                    var row = $(this).parents(".formset-row"),
                        del = row.find('input[id $= "-DELETE"]');

                    if (options.removed) options.removed(row, del, $$);

                    if (del.length) {
                        if(del.val() == 'on'){
                            row.removeClass('row-deleted');
                        } else {
                            row.addClass('row-deleted');
                        }
                        del.val(del.val() == 'on'?'':'on');
                    } else {
                        var parent = row.parent();
                        row.remove();
                        var forms = parent.find('.formset-row');
                        $('#id_' + options.prefix + '-TOTAL_FORMS').val(forms.length);
                        for (var i=0, formCount=forms.length; i<formCount; i++) {
                            updateRowIndex(forms.eq(i), i);
                        }
                    }
                    return false;
                });
            };

        $$.find(".formset-row").each(function(i) {
            insertDeleteLink($(this));
        });

        if ($$.length) {
            var template, el = $('#' + options.prefix + '-empty');
            if(el.is('textarea')) {
                template = el.val();
            } else if(el.is('span')) {
                template = el.html();
            }else if(el.is('script')) {
                template = el.html();
            }

            template = el.html(template).text(); // decoded
            template.replace(/(^[ \t]*\n)/gm, ""); // delete empty lines
            template = $($.parseHTML(template)[1]);

            template.removeAttr('id');
            if(template.data("replace-id")){
                template.attr('id', template.data("replace-id"));
                template.removeAttr('data-replace-id');
            }
            options.formTemplate = template;

            $('#' + options.prefix + '-add-row').click(function() {
                var formCount = parseInt($('#id_' + options.prefix + '-TOTAL_FORMS').val()),
                    row = options.formTemplate.clone(true).removeClass('empty-form');
                updateRowIndex(row, formCount);
                row.appendTo($$);
                insertDeleteLink(row);
                row.exform();
                $('#id_' + options.prefix + '-TOTAL_FORMS').val(formCount + 1);
                // If a post-add callback was supplied, call it with the added form:
                if (options.added) options.added(row, $$);
                return false;
            });
        }

        return $$;
    }

    $.fn.formset.styles = {
        'tab': {
            added: function(row, $$){
                var new_tab = $('
#'+ (row.data('row-index') + 1) +'
');
                $$.parent().find('.nav-tabs').append(new_tab);
                new_tab.find('a').tab('show');
            },
            update: function(row, update){
                var rowId = row.attr('id');
                if(rowId){
                    $('a[href=#'+rowId+']').each(function(){
                        update($(this));
                    })
                }
            },
            removed: function(row, del, $$){
                var rowId = row.attr('id');
                if(rowId){
                    var tab = $('a[href=#'+rowId+']');
                    if (del.length) {
                        if(del.val() == 'on'){
                            tab.removeClass('row-deleted');
                        } else {
                            tab.addClass('row-deleted');
                        }
                    } else {
                        if(tab.parent().next().length){
                            tab.parent().next().find('a').tab('show');
                        } else {
                            tab.parent().prev().find('a').tab('show');
                        }
                        tab.parent().remove();
                    }
                }
            }
        }
    };

    $(function(){
        $('.formset-content').each(function(){
            $(this).formset();
        });
    });
})(jQuery);
<|endoftext|>


<commit_before>"use strict";

var NetworkTables = new function () {

	if (!("WebSocket" in window)) {
		alert("Your browser does not support websockets, this will fail!");
		return;
	}

	//
	// javascript map implementation
	// map functions copied from d3 (BSD license: Mike Bostock)
	//

	var d3_map_proto = "__proto__", d3_map_zero = "\x00";

	// we use encodeURIComponent/decodeURIComponent to allow weird values
	// into the maps we create

	function d3_map_escape(key) {
		return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + encodeURIComponent(key) : encodeURIComponent(key);
	}

	function d3_map_unescape(key) {
		return (key += "")[0] === d3_map_zero ? decodeURIComponent(key.slice(1)) : decodeURIComponent(key);
	}

	var d3_map = function() {

		this._ = Object.create(null);

		this.forEach = function(f) {
			for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]);
		};

		this.get = function(key) {
			return this._[d3_map_escape(key)];
		};

		this.getKeys = function() {
			var keys = [];
			for(var key in this._) keys.push(d3_map_unescape(key));
			return keys;
		};

		this.has = function(key) {
			return d3_map_escape(key) in this._;
		};

		this.set = function(key, value) {
			return this._[d3_map_escape(key)] = value;
		};
	};

	//
	// Utility functions
	//

	/**
		Creates a new empty map (or hashtable) object and returns it. The map
    	is safe to store NetworkTables keys in.
    */
	this.create_map = function() {
		return new d3_map();
	};

	/**
		Escapes NetworkTables keys so that they're valid HTML identifiers.

		:param key: A networktables key
    	:returns: Escaped value
    */
	this.keyToId = encodeURIComponent;

	/**
		Escapes special characters and returns a valid jQuery selector. Useful as
    	NetworkTables does not really put any limits on what keys can be used.

    	:param key: A networktables key
    	:returns: Escaped value
    */
	this.keySelector = function(str) {
	    return encodeURIComponent(str).replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1');
	};

	//
	// NetworkTables internal variables
	//

	// functions that listen for connection changes
	var connectionListeners = [];
	var robotConnectionListeners = [];

	// functions that listen for everything
	var globalListeners = [];

	// functions that listen for specific keys
	var keyListeners = new d3_map();

	// contents of everything in NetworkTables that we know about
	var ntCache = new d3_map();

	//
	// NetworkTables JS API
	//

	/**
		Sets a function to be called when the websocket connects/disconnects

	    :param f: a function that will be called with a single boolean parameter
	              that indicates whether the websocket is connected
	    :param immediateNotify: If true, the function will be immediately called
	                            with the current status of the websocket
    */
	this.addWsConnectionListener = function(f, immediateNotify) {
		connectionListeners.push(f);

		if (immediateNotify == true) {
			f(socketOpen);
		}

		return function() {
			const index = connectionListeners.indexOf(f);
			if (index !== -1) {
				connectionListeners.splice(index, 1);
			}
		}
	};

	/**
		Sets a function to be called when the robot connects/disconnects to the
	    pynetworktables2js server via NetworkTables. It will also be called when
	    the websocket connects/disconnects.

	    :param f: a function that will be called with a single boolean parameter
	              that indicates whether the robot is connected
	    :param immediateNotify: If true, the function will be immediately called
	                            with the current robot connection state
	*/
	this.addRobotConnectionListener = function(f, immediateNotify) {
		robotConnectionListeners.push(f);

		if (immediateNotify == true) {
			f(robotConnected);
		}

		return function() {
			const index = robotConnectionListeners.indexOf(f);
			if (index !== -1) {
				robotConnectionListeners.splice(index, 1);
			}
		}
	}

	/**
		Set a function that will be called whenever any NetworkTables value is changed

	    :param f: When any key changes, this function will be called with the following parameters; key: key name
	              for entry, value: value of entry, isNew: If true, the entry has just been created
	    :param immediateNotify: If true, the function will be immediately called
	                            with the current value of all keys
    */
	this.addGlobalListener = function(f, immediateNotify) {
		globalListeners.push(f);

		if (immediateNotify == true) {
			ntCache.forEach(function(k, v){
				f(k, v, true);
			});
		}

		return function() {
			const index = globalListeners.indexOf(f);
			if (index !== -1) {
				globalListeners.splice(index, 1);
			}
		}
	};

	/**
	    Set a function that will be called whenever a value for a particular key is changed in NetworkTables

	    :param key: A networktables key to listen for
	    :param f: When the key changes, this function will be called with the following parameters; key: key name
	              for entry, value: value of entry, isNew: If true, the entry has just been created
	    :param immediateNotify: If true, the function will be immediately called
	                            with the current value of the specified key
	*/
	this.addKeyListener = function(key, f, immediateNotify) {
		var listeners = keyListeners.get(key);
		if (listeners === undefined) {
			keyListeners.set(key, [f]);
		} else {
			listeners.push(f);
		}

		if (immediateNotify == true) {
			var v = ntCache.get(key);
			if (v !== undefined) {
				f(key, v, true);
			}
		}

		return function() {
			const index = keyListeners.get(key).indexOf(f);
			if (index !== -1) {
				keyListeners.get(key).splice(index, 1);
			}
		}
	};

	/**
		Returns true/false if key is in NetworkTables

		.. warning:: This may not return correct results when the websocket is not
                 	 connected
    */
	this.containsKey = function(key) {
		return ntCache.has(key);
	};

	/**
		Returns all the keys in the NetworkTables

		.. warning:: This may not return correct results when the websocket is not
                 	 connected
    */
	this.getKeys = function() {
		return ntCache.getKeys();
	};

	/**
		Returns the value that the key maps to. If the websocket is not
	    open, this will always return the default value specified.

	    :param key: A networktables key
	    :param defaultValue: If the key isn't present in the table, return this instead
	    :returns: value of key if present, ``undefined`` or ``defaultValue`` otherwise

	    .. warning:: This may not return correct results when the websocket is not
                 	 connected

	    .. note:: To make a fully dynamic webpage that updates when the robot
	              updates values, it is recommended (and simpler) to use
	              :func:`addKeyListener` or :func:`addGlobalListener` to listen
	              for changes to values, instead of using this function.
    */
	this.getValue = function(key, defaultValue) {
		var val = ntCache.get(key);
		if (val === undefined)
			return defaultValue;
		else
			return val;
	};

	// returns null if robot is not connected, string otherwise
	this.getRobotAddress = function() {
		return robotAddress;
	};

	// returns true if robot is connected
	this.isRobotConnected = function() {
		return robotConnected;
	};

	// returns true if websocket is connected
	this.isWsConnected = function() {
		return socketOpen;
	};

	/**
		Sets the value in NetworkTables. If the websocket is not connected, the
	    value will be discarded.

	    :param key: A networktables key
	    :param value: The value to set (see warnings)
	    :returns: True if the websocket is open, False otherwise

	    .. note:: When you put a value, it will not be immediately available
	              from ``getValue``. The value must be sent to the NetworkTables
	              server first, which will then send the change notification
	              back up to the javascript NetworkTables key/value cache.

	    .. warning:: NetworkTables is type sensitive, whereas Javascript is loosely
	                 typed. This function will **not** check the type of the value
	                 that you are trying to put, so you must be careful to only put
	                 the correct values that are expected. If your robot tries to
	                 retrieve the value and it is an unexpected type, an exception
	                 will be thrown and your robot may crash. You have been warned.
    */
	this.putValue = function(key, value) {
		if (!socketOpen)
			return false;

		if (value === undefined)
			throw new Error(key + ": 'undefined' passed to putValue");

		socket.send(JSON.stringify({'k': key, 'v': value}));
		return true;
	};

	// backwards compatibility; deprecated
	this.setValue = this.putValue;

	//
	// NetworkTables socket code
	//

	var socket;
	var socketOpen = false;
	var robotConnected = false;
	var robotAddress = null;

	// construct the websocket URI
	var loc = window.location;
	var host;

	if (loc.protocol === "https:") {
		host = "wss:";
	} else {
		host = "ws:";
	}

	// If the websocket is being served from a different host allow users
	// to add a data-nt-host="" attribute to the script tag loading
	// Networktables.
	var ntHostElement = document.querySelector('[data-nt-host]');
	if (ntHostElement) {
		var ntHost = ntHostElement.getAttribute('data-nt-host');
		host += "//" + ntHost;
	} else {
		host += "//" + loc.host;
	}

	host += "/networktables/ws";

	function createSocket() {

		socket = new WebSocket(host);
		if (socket) {

			socket.onopen = function() {
				console.log("Socket opened");

				socketOpen = true;

				for (var i in connectionListeners) {
					connectionListeners[i](true);
				}
			};

			socket.onmessage = function(msg) {
				var data = JSON.parse(msg.data);

				// robot connection event
				if (data.r !== undefined) {
					robotConnected = data.r;
					robotAddress = data.a;
					for (var i in robotConnectionListeners) {
						robotConnectionListeners[i](robotConnected);
					}
				} else {

					// data changed on websocket
					var key = data['k'];
					var value = data['v'];
					var isNew = data['n'];

					ntCache.set(key, value);

					// notify global listeners
					for (var i in globalListeners) {
						globalListeners[i](key, value, isNew);
					}

					// notify key-specific listeners
					var listeners = keyListeners.get(key);
					if (listeners !== undefined) {
						for (var i in listeners) {
							listeners[i](key, value, isNew);
						}
					}
				}
			};

			socket.onclose = function() {

				if (socketOpen) {

					for (var i in connectionListeners) {
						connectionListeners[i](false);
					}

					for (var i in robotConnectionListeners) {
						robotConnectionListeners[i](false);
					}

					// clear ntCache, it's no longer valid
					// TODO: Is this true?
					ntCache = new d3_map();

					socketOpen = false;
					robotConnected = false;
					robotAddress = null;
					console.log("Socket closed");
				}

				// respawn the websocket
				setTimeout(createSocket, 300);
			};
		}
	}

	createSocket();
}

<commit_msg>Document return values for listener functions<commit_after>"use strict";

var NetworkTables = new function () {

	if (!("WebSocket" in window)) {
		alert("Your browser does not support websockets, this will fail!");
		return;
	}

	//
	// javascript map implementation
	// map functions copied from d3 (BSD license: Mike Bostock)
	//

	var d3_map_proto = "__proto__", d3_map_zero = "\x00";

	// we use encodeURIComponent/decodeURIComponent to allow weird values
	// into the maps we create

	function d3_map_escape(key) {
		return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + encodeURIComponent(key) : encodeURIComponent(key);
	}

	function d3_map_unescape(key) {
		return (key += "")[0] === d3_map_zero ? decodeURIComponent(key.slice(1)) : decodeURIComponent(key);
	}

	var d3_map = function() {

		this._ = Object.create(null);

		this.forEach = function(f) {
			for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]);
		};

		this.get = function(key) {
			return this._[d3_map_escape(key)];
		};

		this.getKeys = function() {
			var keys = [];
			for(var key in this._) keys.push(d3_map_unescape(key));
			return keys;
		};

		this.has = function(key) {
			return d3_map_escape(key) in this._;
		};

		this.set = function(key, value) {
			return this._[d3_map_escape(key)] = value;
		};
	};

	//
	// Utility functions
	//

	/**
		Creates a new empty map (or hashtable) object and returns it. The map
    	is safe to store NetworkTables keys in.
    */
	this.create_map = function() {
		return new d3_map();
	};

	/**
		Escapes NetworkTables keys so that they're valid HTML identifiers.

		:param key: A networktables key
    	:returns: Escaped value
    */
	this.keyToId = encodeURIComponent;

	/**
		Escapes special characters and returns a valid jQuery selector. Useful as
    	NetworkTables does not really put any limits on what keys can be used.

    	:param key: A networktables key
    	:returns: Escaped value
    */
	this.keySelector = function(str) {
	    return encodeURIComponent(str).replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1');
	};

	//
	// NetworkTables internal variables
	//

	// functions that listen for connection changes
	var connectionListeners = [];
	var robotConnectionListeners = [];

	// functions that listen for everything
	var globalListeners = [];

	// functions that listen for specific keys
	var keyListeners = new d3_map();

	// contents of everything in NetworkTables that we know about
	var ntCache = new d3_map();

	//
	// NetworkTables JS API
	//

	/**
		Sets a function to be called when the websocket connects/disconnects

	    :param f: a function that will be called with a single boolean parameter
	              that indicates whether the websocket is connected
	    :param immediateNotify: If true, the function will be immediately called
	                            with the current status of the websocket
	 	:returns: a function that will unsubscribe
    */
	this.addWsConnectionListener = function(f, immediateNotify) {
		connectionListeners.push(f);

		if (immediateNotify == true) {
			f(socketOpen);
		}

		return function() {
			const index = connectionListeners.indexOf(f);
			if (index !== -1) {
				connectionListeners.splice(index, 1);
			}
		}
	};

	/**
		Sets a function to be called when the robot connects/disconnects to the
	    pynetworktables2js server via NetworkTables. It will also be called when
	    the websocket connects/disconnects.

	    :param f: a function that will be called with a single boolean parameter
	              that indicates whether the robot is connected
	    :param immediateNotify: If true, the function will be immediately called
	                            with the current robot connection state
	 	:returns: a function that will unsubscribe
	*/
	this.addRobotConnectionListener = function(f, immediateNotify) {
		robotConnectionListeners.push(f);

		if (immediateNotify == true) {
			f(robotConnected);
		}

		return function() {
			const index = robotConnectionListeners.indexOf(f);
			if (index !== -1) {
				robotConnectionListeners.splice(index, 1);
			}
		}
	}

	/**
		Set a function that will be called whenever any NetworkTables value is changed

	    :param f: When any key changes, this function will be called with the following parameters; key: key name
	              for entry, value: value of entry, isNew: If true, the entry has just been created
	    :param immediateNotify: If true, the function will be immediately called
	                            with the current value of all keys
	 	:returns: a function that will unsubscribe
    */
	this.addGlobalListener = function(f, immediateNotify) {
		globalListeners.push(f);

		if (immediateNotify == true) {
			ntCache.forEach(function(k, v){
				f(k, v, true);
			});
		}

		return function() {
			const index = globalListeners.indexOf(f);
			if (index !== -1) {
				globalListeners.splice(index, 1);
			}
		}
	};

	/**
	    Set a function that will be called whenever a value for a particular key is changed in NetworkTables

	    :param key: A networktables key to listen for
	    :param f: When the key changes, this function will be called with the following parameters; key: key name
	              for entry, value: value of entry, isNew: If true, the entry has just been created
	    :param immediateNotify: If true, the function will be immediately called
	                            with the current value of the specified key
	 	:returns: a function that will unsubscribe
	*/
	this.addKeyListener = function(key, f, immediateNotify) {
		var listeners = keyListeners.get(key);
		if (listeners === undefined) {
			keyListeners.set(key, [f]);
		} else {
			listeners.push(f);
		}

		if (immediateNotify == true) {
			var v = ntCache.get(key);
			if (v !== undefined) {
				f(key, v, true);
			}
		}

		return function() {
			const index = keyListeners.get(key).indexOf(f);
			if (index !== -1) {
				keyListeners.get(key).splice(index, 1);
			}
		}
	};

	/**
		Returns true/false if key is in NetworkTables

		.. warning:: This may not return correct results when the websocket is not
                 	 connected
    */
	this.containsKey = function(key) {
		return ntCache.has(key);
	};

	/**
		Returns all the keys in the NetworkTables

		.. warning:: This may not return correct results when the websocket is not
                 	 connected
    */
	this.getKeys = function() {
		return ntCache.getKeys();
	};

	/**
		Returns the value that the key maps to. If the websocket is not
	    open, this will always return the default value specified.

	    :param key: A networktables key
	    :param defaultValue: If the key isn't present in the table, return this instead
	    :returns: value of key if present, ``undefined`` or ``defaultValue`` otherwise

	    .. warning:: This may not return correct results when the websocket is not
                 	 connected

	    .. note:: To make a fully dynamic webpage that updates when the robot
	              updates values, it is recommended (and simpler) to use
	              :func:`addKeyListener` or :func:`addGlobalListener` to listen
	              for changes to values, instead of using this function.
    */
	this.getValue = function(key, defaultValue) {
		var val = ntCache.get(key);
		if (val === undefined)
			return defaultValue;
		else
			return val;
	};

	// returns null if robot is not connected, string otherwise
	this.getRobotAddress = function() {
		return robotAddress;
	};

	// returns true if robot is connected
	this.isRobotConnected = function() {
		return robotConnected;
	};

	// returns true if websocket is connected
	this.isWsConnected = function() {
		return socketOpen;
	};

	/**
		Sets the value in NetworkTables. If the websocket is not connected, the
	    value will be discarded.

	    :param key: A networktables key
	    :param value: The value to set (see warnings)
	    :returns: True if the websocket is open, False otherwise

	    .. note:: When you put a value, it will not be immediately available
	              from ``getValue``. The value must be sent to the NetworkTables
	              server first, which will then send the change notification
	              back up to the javascript NetworkTables key/value cache.

	    .. warning:: NetworkTables is type sensitive, whereas Javascript is loosely
	                 typed. This function will **not** check the type of the value
	                 that you are trying to put, so you must be careful to only put
	                 the correct values that are expected. If your robot tries to
	                 retrieve the value and it is an unexpected type, an exception
	                 will be thrown and your robot may crash. You have been warned.
    */
	this.putValue = function(key, value) {
		if (!socketOpen)
			return false;

		if (value === undefined)
			throw new Error(key + ": 'undefined' passed to putValue");

		socket.send(JSON.stringify({'k': key, 'v': value}));
		return true;
	};

	// backwards compatibility; deprecated
	this.setValue = this.putValue;

	//
	// NetworkTables socket code
	//

	var socket;
	var socketOpen = false;
	var robotConnected = false;
	var robotAddress = null;

	// construct the websocket URI
	var loc = window.location;
	var host;

	if (loc.protocol === "https:") {
		host = "wss:";
	} else {
		host = "ws:";
	}

	// If the websocket is being served from a different host allow users
	// to add a data-nt-host="" attribute to the script tag loading
	// Networktables.
	var ntHostElement = document.querySelector('[data-nt-host]');
	if (ntHostElement) {
		var ntHost = ntHostElement.getAttribute('data-nt-host');
		host += "//" + ntHost;
	} else {
		host += "//" + loc.host;
	}

	host += "/networktables/ws";

	function createSocket() {

		socket = new WebSocket(host);
		if (socket) {

			socket.onopen = function() {
				console.log("Socket opened");

				socketOpen = true;

				for (var i in connectionListeners) {
					connectionListeners[i](true);
				}
			};

			socket.onmessage = function(msg) {
				var data = JSON.parse(msg.data);

				// robot connection event
				if (data.r !== undefined) {
					robotConnected = data.r;
					robotAddress = data.a;
					for (var i in robotConnectionListeners) {
						robotConnectionListeners[i](robotConnected);
					}
				} else {

					// data changed on websocket
					var key = data['k'];
					var value = data['v'];
					var isNew = data['n'];

					ntCache.set(key, value);

					// notify global listeners
					for (var i in globalListeners) {
						globalListeners[i](key, value, isNew);
					}

					// notify key-specific listeners
					var listeners = keyListeners.get(key);
					if (listeners !== undefined) {
						for (var i in listeners) {
							listeners[i](key, value, isNew);
						}
					}
				}
			};

			socket.onclose = function() {

				if (socketOpen) {

					for (var i in connectionListeners) {
						connectionListeners[i](false);
					}

					for (var i in robotConnectionListeners) {
						robotConnectionListeners[i](false);
					}

					// clear ntCache, it's no longer valid
					// TODO: Is this true?
					ntCache = new d3_map();

					socketOpen = false;
					robotConnected = false;
					robotAddress = null;
					console.log("Socket closed");
				}

				// respawn the websocket
				setTimeout(createSocket, 300);
			};
		}
	}

	createSocket();
}

<|endoftext|>


<commit_before>/*exported Hungarian*/
var Hungarian = (function() {
  'use strict';

  var Type = {
    NONE:  0,
    STAR:  1,
    PRIME: 2
  };

  /**
   * Array minima mutation functions.
   */
  function subtractRowMinima( row ) {
    var min = Math.min.apply( Math, row );

    for ( var i = 0, il = row.length; i < il; i++ ) {
      row[i] -= min;
    }

    return row;
  }

  function subtractRowsMinima( array ) {
    var i, il;
    for ( i = 0, il = array.length; i < il; i++ ) {
      subtractRowMinima( array[i] );
    }
  }

  /**
   * Takes a two-dimensional n by m matrix.
   */
  function subtractColMinima( array, colIndex ) {
    var min = Number.POSITIVE_INFINITY;
    var value;
    var i, il;
    // Create col array and find min.
    for ( i = 0, il = array.length; i < il; i++ ) {
      value = array[i][ colIndex ];
      if ( value < min ) {
        min = value;
      }
    }

    for ( i = 0, il = array.length; i < il; i++ ) {
      array[i][ colIndex ] -= min;
    }

    return array;
  }

  function subtractColsMinima( array ) {
    var i, il;
    for ( i = 0, il = array[0].length; i < il; i++ ) {
      subtractColMinima( array, i );
    }
  }

  function calculate( costMatrix ) {
    var coveredRows = [],
        coveredCols = [];

    subtractRowsMinima( costMatrix );
    subtractColsMinima( costMatrix );

    var marked = [];
    var i, il;
    for ( i = 0, il = costMatrix[0].length; i < il; i++ ) {
      marked.push( [] );
    }

    var j, jl;
    var row;
    for ( i = 0, il = costMatrix.length; i < il; i++ ) {
      row = costMatrix[i];
      for ( j = 0, jl = row.length; j < jl; j++ ) {
        // Mark uncovered zeros.
        if ( !costMatrix && !coveredRows[i] && !coveredCols[j] ) {
          marked[i][j] = true;
          coveredRows[i] = true;
          coveredCols[j] = true;
        }
      }
    }

    // Empty covers.
    coveredRows = [];
    coveredCols = [];

    // Cover each column containing a starred zero.
    for ( i = 0, il = costMatrix.length; i < il; i++ ) {
      for ( j = 0, jl = costMatrix[i].length; j < jl; j++ ) {
        if ( marked[i][j] === Type.STAR ) {
          coveredCols[j] = true;
        }
      }
    }

    // Count covered columns.
    var count = 0;
    for ( i = 0, il = coveredCols.length; i < il; i++ ) {
      if ( coveredCols[i] ) {
        count++;
      }
    }

    // Finished.
    if ( count >= costMatrix[0].length ) {
      return;
    }

    function step3() {

    }

    // Step 4 helper functions.
    function findUncoveredZero( costMatrix, coveredRows, coveredCols ) {
      var row = -1,
          col = -1;

      var i, il;
      var j, jl;
      for ( i = 0, il = costMatrix.length; i < il; i++ ) {
        for ( j = 0, jl = costMatrix[i].length; j < jl; j++ ) {
          if ( !costMatrix[i][j] && !coveredRows[i] && !coveredCols[j] ) {
            // TODO: Out variable these.
            row = i;
            col = j;
            break;
          }
        }
      }

      return {
        row: row,
        col: col
      };
    }

    function isRowStarred( row ) {
      for ( var i = 0, il = row.length; i < il; i++ ) {
        if ( row[i] === Type.STAR ) {
          return true;
        }
      }

      return false;
    }

    function indexOfStar( row ) {
      for ( var i = 0, il = row.length; i < il; i++ ) {
        if ( row[i] === Type.STAR ) {
          return i;
        }
      }

      return -1;
    }

    function step4() {
      var index;
      var starIndex;
      while ( true ) {
        index = findUncoveredZero( costMatrix, coveredRows, coveredCols );
        if ( index.row === -1 ) {
          return step6();
        } else {
          marked[ index.row ][ index.col ] = 2;

          starIndex = indexOfStar( marked, index.row );
          if ( starIndex !== -1 ) {
            coveredRows[ index.row ] = true;
            coveredCols[ index.col ] = false;
          } else {
            return step5( index.row, index.col );
          }
        }
      }
    }

    function step5( row, col ) {
      function indexOfStarCol( costMatrix, col ) {
        for ( var i = 0, il = costMatrix.length; i < il; i++ ) {
          if ( costMatrix[i][ col ] === Type.STAR ) {
            return i;
          }
        }

        return -1;
      }

      function indexOfPrimeRow( row ) {
        for ( var i = 0, il = costMatrix.length; i < il; i++ ) {
          if ( row[i] === Type.PRIME ) {
            return i;
          }
        }

        return -1;
      }

      function augmentPath( marked, path, lastIndex ) {
        var row, col;
        for ( var i = 0; i < lastIndex; i++ ) {
          row = path[i][0];
          col = path[i][1];
          if ( marked[ row ][ col ] === 1 ) {
            marked[ row ][ col ] = 0;
          } else {
            marked[ row ][ col ] = 1;
          }
        }
      }

      function clearCovers() {
        coveredRows = [];
        coveredCols = [];
      }

      function removePrimes( marked ) {
        var i, j;
        for ( i = 0; i < marked.length; i++ ) {
          for ( j = 0; j < marked[i].length; j++ ) {
            if ( marked[i][j] === Type.PRIME ) {
              marked[i][j] = 0;
            }
          }
        }
      }

      var pathIndex = 0;
      var path = [
        [ row, col ]
      ];
      var index;
      while ( true ) {
        index = indexOfStarCol( path[ pathIndex ][1] );
        if ( index > -1 ) {
          pathIndex++;
          path[ pathIndex ] = [
            index,
            path[ pathIndex - 1 ][1]
          ];

          index = indexOfPrimeRow( path[ pathIndex ][0] );
          pathIndex++;
          path[ pathIndex ] = [
            path[ pathIndex - 1 ][0],
            index
          ];
        } else {
          break;
        }
      }

      augmentPath( marked, path, pathIndex );
      clearCovers();
      removePrimes( marked );
      step3();
    }

    function uncoveredMinima( costMatrix, coveredRows, coveredCols ) {
      var min = Number.POSITIVE_INFINITY;

      var value;
      var i, il;
      var j, jl;
      for ( i = 0, i = costMatrix.length; i < il; i++ ) {
        for ( j = 0, j = costMatrix[i].length; j < jl; j++ ) {
          value = costMatrix[i][j];
          if ( value < min && !coveredRows[i] && !coveredCols[j] ) {
            min = value;
          }
        }
      }

      return value;
    }

    function step6() {
      var min = uncoveredMinima( costMatrix, coveredRows, coveredCols );
      var i, il;
      var j, jl;
      for ( i = 0, il = costMatrix.length; i < il; i++ ) {
        for ( j = 0, jl = costMatrix[i].length; j < jl; j++ ) {
          // Add min to every element of each covered row.
          if ( coveredRows[i] ) {
            costMatrix[i][j] += min;
          }

          // Subtract min from every element of each uncoverd column.
          if ( !coveredCols[j] ) {
            costMatrix[i][j] -= min;
          }
        }
      }

      step4();
    }
  }

  return {
    calculate: calculate
  };

}) ();
<commit_msg>registration[points]: Wrap Hungarian steps 1, 2, and 3 in functions.<commit_after>/*exported Hungarian*/
var Hungarian = (function() {
  'use strict';

  var Type = {
    NONE:  0,
    STAR:  1,
    PRIME: 2
  };

  /**
   * Array minima mutation functions.
   */
  function subtractRowMinima( row ) {
    var min = Math.min.apply( Math, row );

    for ( var i = 0, il = row.length; i < il; i++ ) {
      row[i] -= min;
    }

    return row;
  }

  function subtractRowsMinima( array ) {
    var i, il;
    for ( i = 0, il = array.length; i < il; i++ ) {
      subtractRowMinima( array[i] );
    }
  }

  /**
   * Takes a two-dimensional n by m matrix.
   */
  function subtractColMinima( array, colIndex ) {
    var min = Number.POSITIVE_INFINITY;
    var value;
    var i, il;
    // Create col array and find min.
    for ( i = 0, il = array.length; i < il; i++ ) {
      value = array[i][ colIndex ];
      if ( value < min ) {
        min = value;
      }
    }

    for ( i = 0, il = array.length; i < il; i++ ) {
      array[i][ colIndex ] -= min;
    }

    return array;
  }

  function subtractColsMinima( array ) {
    var i, il;
    for ( i = 0, il = array[0].length; i < il; i++ ) {
      subtractColMinima( array, i );
    }
  }

  function calculate( costMatrix ) {
    var coveredRows = [],
        coveredCols = [];

    var marked = [];

    function init() {
      var i, il;
      for ( i = 0, il = costMatrix[0].length; i < il; i++ ) {
        marked.push( [] );
      }

      step1();
    }

    init();

    function step1() {
      subtractRowsMinima( costMatrix );
      step2();
    }

    function step2() {
      var i, il;
      var j, jl;
      var row;
      for ( i = 0, il = costMatrix.length; i < il; i++ ) {
        row = costMatrix[i];
        for ( j = 0, jl = row.length; j < jl; j++ ) {
          // Mark uncovered zeros.
          if ( !costMatrix && !coveredRows[i] && !coveredCols[j] ) {
            marked[i][j] = true;
            coveredRows[i] = true;
            coveredCols[j] = true;
          }
        }
      }

      // Empty covers.
      coveredRows = [];
      coveredCols = [];
    }

    function step3() {
      var i, il;
      var j, jl;
      // Cover each column containing a starred zero.
      for ( i = 0, il = costMatrix.length; i < il; i++ ) {
        for ( j = 0, jl = costMatrix[i].length; j < jl; j++ ) {
          if ( marked[i][j] === Type.STAR ) {
            coveredCols[j] = true;
          }
        }
      }

      // Count covered columns.
      var count = 0;
      for ( i = 0, il = coveredCols.length; i < il; i++ ) {
        if ( coveredCols[i] ) {
          count++;
        }
      }

      if ( count >= costMatrix[0].length ) {
        // Finished.
        return;
      } else {
        step4();
      }
    }

    // Step 4 helper functions.
    function findUncoveredZero( costMatrix, coveredRows, coveredCols ) {
      var row = -1,
          col = -1;

      var i, il;
      var j, jl;
      for ( i = 0, il = costMatrix.length; i < il; i++ ) {
        for ( j = 0, jl = costMatrix[i].length; j < jl; j++ ) {
          if ( !costMatrix[i][j] && !coveredRows[i] && !coveredCols[j] ) {
            // TODO: Out variable these.
            row = i;
            col = j;
            break;
          }
        }
      }

      return {
        row: row,
        col: col
      };
    }

    function isRowStarred( row ) {
      for ( var i = 0, il = row.length; i < il; i++ ) {
        if ( row[i] === Type.STAR ) {
          return true;
        }
      }

      return false;
    }

    function indexOfStar( row ) {
      for ( var i = 0, il = row.length; i < il; i++ ) {
        if ( row[i] === Type.STAR ) {
          return i;
        }
      }

      return -1;
    }

    function step4() {
      var index;
      var starIndex;
      while ( true ) {
        index = findUncoveredZero( costMatrix, coveredRows, coveredCols );
        if ( index.row === -1 ) {
          return step6();
        } else {
          marked[ index.row ][ index.col ] = 2;

          starIndex = indexOfStar( marked, index.row );
          if ( starIndex !== -1 ) {
            coveredRows[ index.row ] = true;
            coveredCols[ index.col ] = false;
          } else {
            return step5( index.row, index.col );
          }
        }
      }
    }

    function step5( row, col ) {
      function indexOfStarCol( costMatrix, col ) {
        for ( var i = 0, il = costMatrix.length; i < il; i++ ) {
          if ( costMatrix[i][ col ] === Type.STAR ) {
            return i;
          }
        }

        return -1;
      }

      function indexOfPrimeRow( row ) {
        for ( var i = 0, il = costMatrix.length; i < il; i++ ) {
          if ( row[i] === Type.PRIME ) {
            return i;
          }
        }

        return -1;
      }

      function augmentPath( marked, path, lastIndex ) {
        var row, col;
        for ( var i = 0; i < lastIndex; i++ ) {
          row = path[i][0];
          col = path[i][1];
          if ( marked[ row ][ col ] === 1 ) {
            marked[ row ][ col ] = 0;
          } else {
            marked[ row ][ col ] = 1;
          }
        }
      }

      function clearCovers() {
        coveredRows = [];
        coveredCols = [];
      }

      function removePrimes( marked ) {
        var i, j;
        for ( i = 0; i < marked.length; i++ ) {
          for ( j = 0; j < marked[i].length; j++ ) {
            if ( marked[i][j] === Type.PRIME ) {
              marked[i][j] = 0;
            }
          }
        }
      }

      var pathIndex = 0;
      var path = [
        [ row, col ]
      ];
      var index;
      while ( true ) {
        index = indexOfStarCol( path[ pathIndex ][1] );
        if ( index > -1 ) {
          pathIndex++;
          path[ pathIndex ] = [
            index,
            path[ pathIndex - 1 ][1]
          ];

          index = indexOfPrimeRow( path[ pathIndex ][0] );
          pathIndex++;
          path[ pathIndex ] = [
            path[ pathIndex - 1 ][0],
            index
          ];
        } else {
          break;
        }
      }

      augmentPath( marked, path, pathIndex );
      clearCovers();
      removePrimes( marked );
      step3();
    }

    function uncoveredMinima( costMatrix, coveredRows, coveredCols ) {
      var min = Number.POSITIVE_INFINITY;

      var value;
      var i, il;
      var j, jl;
      for ( i = 0, i = costMatrix.length; i < il; i++ ) {
        for ( j = 0, j = costMatrix[i].length; j < jl; j++ ) {
          value = costMatrix[i][j];
          if ( value < min && !coveredRows[i] && !coveredCols[j] ) {
            min = value;
          }
        }
      }

      return value;
    }

    function step6() {
      var min = uncoveredMinima( costMatrix, coveredRows, coveredCols );
      var i, il;
      var j, jl;
      for ( i = 0, il = costMatrix.length; i < il; i++ ) {
        for ( j = 0, jl = costMatrix[i].length; j < jl; j++ ) {
          // Add min to every element of each covered row.
          if ( coveredRows[i] ) {
            costMatrix[i][j] += min;
          }

          // Subtract min from every element of each uncoverd column.
          if ( !coveredCols[j] ) {
            costMatrix[i][j] -= min;
          }
        }
      }

      step4();
    }

    return;
  }

  return {
    calculate: calculate
  };

}) ();
<|endoftext|>


<commit_before>'use strict';

const path = require('path');
const sequelize = require(path.resolve('src/utils/connection'));
const Sequelize = require('sequelize');

const pokemon = sequelize.define('pokemon', {
	name: {
		type: Sequelize.STRING,
		allowNull: false,
		validate: {
            isAlpha: true
		}
	},
	price: {
		type: Sequelize.INTEGER,
		allowNull: false
	},
	stock: {
		type: Sequelize.INTEGER,
		allowNull: true,
		defaultValue: 1
	}
});

module.exports = pokemon;<commit_msg>ADJUST model to more persistence .<commit_after>'use strict';

const path = require('path');
const sequelize = require(path.resolve('src/utils/connection'));
const Sequelize = require('sequelize');

const pokemon = sequelize.define('pokemon', {
	name: {
		type: Sequelize.STRING,
		allowNull: false,
		unique: true
	},
	price: {
		type: Sequelize.FLOAT(2),
		allowNull: false
	},
	stock: {
		type: Sequelize.INTEGER,
		allowNull: true,
		defaultValue: 1
	}
});

module.exports = pokemon;<|endoftext|>


<commit_before>const GitHubAuth = require('./GitHubAuth')

class GitHub {
  constructor(token) {
    this.token = token
  }

  getTasks(filter) {
    const extraParams = filter.updatedAt ? ` updated:>${filter.updatedAt}` : ' is:open'
    const search = `${filter.query} ${extraParams}`
    return this.getIssuesFromSearch(search)
  }

  getCurrentUser() {
    const query = `{
      viewer {
        login
      }
    }`

    return this.graphql(query).then(result => result.viewer)
  }

  getIssuesFromSearch(search, endCursor, edges = []) {
    return this.graphql(this.taskQuery(), { search, endCursor }).then(results => {
      const allEdges = edges.concat(results.search.edges)

      if (results.search.pageInfo.hasNextPage) {
        const nextEndCursor = results.search.pageInfo.endCursor
        return this.getIssuesFromSearch(search, nextEndCursor, allEdges)
      }

      return { tasks: allEdges.map(edge => this.transformEdgeToTask(edge)) }
    })
  }

  graphql(query, variables = {}) {
    const url = 'https://api.github.com/graphql'
    const options = {
      body: JSON.stringify({ query, variables }),
      method: 'POST',
      headers: this.getHeaders(),
    }

    return fetch(url, options).then(response => {
      console.log(`${response.status} ${JSON.stringify(variables)}`)

      if (!response.ok) {
        return response.json().then(json => {
          throw new Error(`${response.status}: ${JSON.stringify(json)}`)
        })
      }

      return response.json().then(result => {
        if (result.errors) {
          throw new Error(`GraphQL Error: ${result.errors.map(e => e.message)}`)
        }

        return result.data
      })
    })
  }

  getHeaders() {
    if (!this.token) {
      this.token = GitHubAuth.getToken()
    }
    return {
      Authorization: `bearer ${this.token}`,
    }
  }

  transformEdgeToTask(edge) {
    const node = edge.node
    const type = node.type === 'PullRequest' ? 'pull' : 'issue'
    return {
      storageKey: `${type}-${node.id}`,
      id: node.id,
      type: node.type,
      title: node.title,
      body: node.body,
      state: node.state,
      createdAt: node.createdAt,
      updatedAt: node.updatedAt,
      isPullRequest: node.type === 'PullRequest',
      url: node.url,
      number: node.number,
      repository: `${node.repository.owner.login}/${node.repository.name}`,
      repositoryOwner: node.repository.owner.login,
      repositoryOwnerUrl: node.repository.owner.url,
      repositoryOwnerAvatar: node.repository.owner.avatarURL,
      user: node.author.login,
      userUrl: node.author.url,
      userAvatar: node.author.avatarURL,
      comments: node.comments ? node.comments.totalCount : 0,
    }
  }

  taskQuery() {
    return `query($search: String!, $endCursor: String) {
      search(first: 30, query: $search, after: $endCursor, type: ISSUE) {
        pageInfo {
         endCursor,
          hasNextPage
        }
        edges {
          node {
            ... on Issueish {
              body,
              id,
              title,
              number,
              type: __typename,

              author {
                login,
                url,
                avatarURL
              },

              repository {
                name,
                owner {
                  login
                  url,
                  avatarURL
                },
              },
            },
            ... on Issue {
              url,
              state,
              updatedAt,
              createdAt,
              comments(last: 1) {
                totalCount,
                edges {
                  node {
                    author {
                      login
                    }
                  }
                }
              }
            },
            ... on PullRequest {
              url,
              state,
              updatedAt,
              createdAt
            }
          }
        }
      }
    }`
  }
}

module.exports = GitHub
<commit_msg>Changes<commit_after>const GitHubAuth = require('./GitHubAuth')

class GitHub {
  TASKS_PER_PAGE = 30

  constructor(token) {
    this.token = token
  }

  getTasks(filter) {
    const extraParams = filter.updatedAt ? ` updated:>${filter.updatedAt}` : ' is:open'
    const search = `${filter.query} ${extraParams}`
    return this.getIssuesFromSearch(search)
  }

  getCurrentUser() {
    const query = `{
      viewer {
        login
      }
    }`

    return this.graphql(query).then(result => result.viewer)
  }

  getIssuesFromSearch(search, endCursor, edges = []) {
    const limit = TASKS_PER_PAGE
    return this.graphql(this.taskQuery(), { search, endCursor, limit }).then(results => {
      const allEdges = edges.concat(results.search.edges)

      if (results.search.pageInfo.hasNextPage) {
        const nextEndCursor = results.search.pageInfo.endCursor
        return this.getIssuesFromSearch(search, nextEndCursor, allEdges)
      }

      return { tasks: allEdges.map(edge => this.transformEdgeToTask(edge)) }
    })
  }

  graphql(query, variables = {}) {
    const url = 'https://api.github.com/graphql'
    const options = {
      body: JSON.stringify({ query, variables }),
      method: 'POST',
      headers: this.getHeaders(),
    }

    return fetch(url, options).then(response => {
      console.log(`${response.status} ${JSON.stringify(variables)}`)

      if (!response.ok) {
        return response.json().then(json => {
          throw new Error(`${response.status}: ${JSON.stringify(json)}`)
        })
      }

      return response.json().then(result => {
        if (result.errors) {
          throw new Error(`GraphQL Error: ${result.errors.map(e => e.message).join(', ')}`)
        }

        return result.data
      })
    })
  }

  getHeaders() {
    if (!this.token) {
      this.token = GitHubAuth.getToken()
    }
    return {
      Authorization: `bearer ${this.token}`,
    }
  }

  transformEdgeToTask(edge) {
    const node = edge.node
    const type = node.type === 'PullRequest' ? 'pull' : 'issue'
    return {
      storageKey: `${type}-${node.id}`,
      id: node.id,
      type: node.type,
      title: node.title,
      body: node.body,
      state: node.state,
      createdAt: node.createdAt,
      updatedAt: node.updatedAt,
      isPullRequest: node.type === 'PullRequest',
      url: node.url,
      number: node.number,
      repository: `${node.repository.owner.login}/${node.repository.name}`,
      repositoryOwner: node.repository.owner.login,
      repositoryOwnerUrl: node.repository.owner.url,
      repositoryOwnerAvatar: node.repository.owner.avatarURL,
      user: node.author.login,
      userUrl: node.author.url,
      userAvatar: node.author.avatarURL,
      comments: node.comments ? node.comments.totalCount : 0,
    }
  }

  // A GraphQL query using GitHubs GraphQL API https://developer.github.com/early-access/graphql/
  taskQuery() {
    return `query($limit: Integer, $search: String!, $endCursor: String) {
      search(first: $limit, query: $search, after: $endCursor, type: ISSUE) {
        pageInfo {
         endCursor,
          hasNextPage
        }
        edges {
          node {
            ... on Issueish {
              body,
              id,
              title,
              number,
              type: __typename,

              author {
                login,
                url,
                avatarURL
              },

              repository {
                name,
                owner {
                  login
                  url,
                  avatarURL
                },
              },
            },
            ... on Issue {
              url,
              state,
              updatedAt,
              createdAt,
              comments(last: 1) {
                totalCount,
                edges {
                  node {
                    author {
                      login
                    }
                  }
                }
              }
            },
            ... on PullRequest {
              url,
              state,
              updatedAt,
              createdAt
            }
          }
        }
      }
    }`
  }
}

module.exports = GitHub
<|endoftext|>